From d4535394eeb0fc9efbf4aac7c2db189ef2e2ece3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Walter?= Date: Sun, 10 Nov 2002 10:38:54 +0000 Subject: [PATCH] Many bugfixes and improvements, especially related to sparse matrices. Thanks namely to Kresimir Fresl and Michael Stevens this time. --- bench1/Jamfile | 1 - bench1/bench1.cpp | 18 +- bench1/bench1.hpp | 4 +- bench1/bench11.cpp | 10 +- bench1/bench12.cpp | 10 +- bench1/bench13.cpp | 10 +- bench2/Jamfile | 1 - bench2/bench2.cpp | 16 + bench2/bench2.hpp | 13 +- bench2/bench21.cpp | 46 +- bench2/bench22.cpp | 80 +- bench2/bench23.cpp | 50 +- bench3/Jamfile | 1 - bench3/bench3.cpp | 18 +- bench3/bench3.hpp | 4 +- bench3/bench31.cpp | 10 +- bench3/bench32.cpp | 10 +- bench3/bench33.cpp | 10 +- doc/matrix_proxy.htm | 82 +- doc/overview.htm | 6 +- doc/vector_proxy.htm | 20 +- include/boost/numeric/ublas/banded.hpp | 154 +- include/boost/numeric/ublas/concepts.hpp | 7 - include/boost/numeric/ublas/config.hpp | 67 +- include/boost/numeric/ublas/exception.hpp | 30 +- include/boost/numeric/ublas/functional.hpp | 108 +- include/boost/numeric/ublas/hermitian.hpp | 179 +- include/boost/numeric/ublas/iterator.hpp | 20 - include/boost/numeric/ublas/matrix.hpp | 270 +- include/boost/numeric/ublas/matrix_assign.hpp | 2638 ++-------------- .../boost/numeric/ublas/matrix_expression.hpp | 428 +-- include/boost/numeric/ublas/matrix_proxy.hpp | 1290 +++----- include/boost/numeric/ublas/matrix_sparse.hpp | 2778 +++++++++++------ include/boost/numeric/ublas/storage.hpp | 188 +- .../boost/numeric/ublas/storage_sparse.hpp | 395 +-- include/boost/numeric/ublas/symmetric.hpp | 174 +- include/boost/numeric/ublas/triangular.hpp | 185 +- include/boost/numeric/ublas/vector.hpp | 26 +- include/boost/numeric/ublas/vector_assign.hpp | 433 +-- include/boost/numeric/ublas/vector_proxy.hpp | 172 +- include/boost/numeric/ublas/vector_sparse.hpp | 972 +++++- test1/Jamfile | 2 +- test1/test1.hpp | 4 + test1/test11.cpp | 30 + test1/test12.cpp | 60 + test1/test13.cpp | 60 + test2/Jamfile | 2 +- test2/test2.cpp | 27 + test2/test2.hpp | 6 +- test2/test21.cpp | 10 + test2/test22.cpp | 20 +- test2/test23.cpp | 10 + test3/Jamfile | 2 +- test3/test3.hpp | 10 +- test3/test31.cpp | 54 + test3/test32.cpp | 71 + test3/test33.cpp | 76 +- test4/Jamfile | 2 +- test4/test4.hpp | 4 + test4/test41.cpp | 30 + test4/test42.cpp | 30 + test4/test43.cpp | 32 +- test5/Jamfile | 2 +- test5/test5.hpp | 4 + test5/test51.cpp | 30 + test5/test52.cpp | 26 + test5/test53.cpp | 32 +- test6/Jamfile | 2 +- test6/test6.hpp | 4 + test6/test61.cpp | 30 + test6/test62.cpp | 30 + test6/test63.cpp | 30 + 72 files changed, 5430 insertions(+), 6236 deletions(-) diff --git a/bench1/Jamfile b/bench1/Jamfile index 70c04529..d13718af 100644 --- a/bench1/Jamfile +++ b/bench1/Jamfile @@ -5,7 +5,6 @@ SOURCES = bench1 bench11 bench12 bench13 ; exe bench1 : $(SOURCES).cpp : $(BOOST_ROOT) - BOOST_UBLAS_TYPE_CHECK <*>"-w-8026 -w-8027 -w-8057 -w-8084 -w-8092" ; diff --git a/bench1/bench1.cpp b/bench1/bench1.cpp index f4afef6b..2fcffd73 100644 --- a/bench1/bench1.cpp +++ b/bench1/bench1.cpp @@ -96,24 +96,33 @@ int main (int argc, char *argv []) { _set_new_handler (std_new_handler); #endif +#ifdef USE_FLOAT header ("float"); peak () (100000000); +#endif +#ifdef USE_DOUBLE header ("double"); peak () (100000000); +#endif -#ifdef USE_COMPLEX +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT header ("std:complex"); peak > () (100000000); +#endif +#ifdef USE_DOUBLE header ("std:complex"); peak > () (100000000); +#endif #endif int scale = 1; if (argc > 1) scale = atoi (argv [1]); +#ifdef USE_FLOAT header ("float, 3"); bench_1 () (1000000 * scale); @@ -137,7 +146,9 @@ int main (int argc, char *argv []) { bench_1 () (30000 * scale); bench_2 () (300 * scale); bench_3 () (3 * scale); +#endif +#ifdef USE_DOUBLE header ("double, 3"); bench_1 () (1000000 * scale); @@ -161,8 +172,10 @@ int main (int argc, char *argv []) { bench_1 () (30000 * scale); bench_2 () (300 * scale); bench_3 () (3 * scale); +#endif #ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT header ("std::complex, 3"); bench_1, 3> () (1000000 * scale); @@ -186,7 +199,9 @@ int main (int argc, char *argv []) { bench_1, 100> () (30000 * scale); bench_2, 100> () (300 * scale); bench_3, 100> () (3 * scale); +#endif +#ifdef USE_DOUBLE header ("std::complex, 3"); bench_1, 3> () (1000000 * scale); @@ -210,6 +225,7 @@ int main (int argc, char *argv []) { bench_1, 100> () (30000 * scale); bench_2, 100> () (300 * scale); bench_3, 100> () (3 * scale); +#endif #endif return 0; diff --git a/bench1/bench1.hpp b/bench1/bench1.hpp index c58a910a..08d65b63 100644 --- a/bench1/bench1.hpp +++ b/bench1/bench1.hpp @@ -143,6 +143,8 @@ struct bench_3 { struct safe_tag {}; struct fast_tag {}; +// #define USE_FLOAT +#define USE_DOUBLE // #define USE_STD_COMPLEX #define USE_C_ARRAY @@ -151,6 +153,6 @@ struct fast_tag {}; // #define USE_STD_VALARRAY #define USE_STD_VECTOR -#endif +#endif diff --git a/bench1/bench11.cpp b/bench1/bench11.cpp index 8668ec44..59c5b437 100644 --- a/bench1/bench11.cpp +++ b/bench1/bench11.cpp @@ -280,28 +280,34 @@ void bench_1::operator () (int 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/bench1/bench12.cpp b/bench1/bench12.cpp index ec269c7f..05297630 100644 --- a/bench1/bench12.cpp +++ b/bench1/bench12.cpp @@ -497,28 +497,34 @@ void bench_2::operator () (int 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/bench1/bench13.cpp b/bench1/bench13.cpp index a7fef89a..8e48a781 100644 --- a/bench1/bench13.cpp +++ b/bench1/bench13.cpp @@ -178,28 +178,34 @@ void bench_3::operator () (int 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/bench2/Jamfile b/bench2/Jamfile index ed8b7fa6..a4ace07d 100644 --- a/bench2/Jamfile +++ b/bench2/Jamfile @@ -5,7 +5,6 @@ SOURCES = bench2 bench21 bench22 bench23 ; exe bench2 : $(SOURCES).cpp : $(BOOST_ROOT) - BOOST_UBLAS_TYPE_CHECK <*>"-w-8026 -w-8027 -w-8057 -w-8084 -w-8092" ; diff --git a/bench2/bench2.cpp b/bench2/bench2.cpp index 98fe7fb8..ccb2f6c8 100644 --- a/bench2/bench2.cpp +++ b/bench2/bench2.cpp @@ -98,24 +98,33 @@ int main (int argc, char *argv []) { _set_new_handler (std_new_handler); #endif +#ifdef USE_FLOAT header ("float"); peak () (100000000); +#endif +#ifdef USE_DOUBLE header ("double"); peak () (100000000); +#endif #ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT header ("std:complex"); peak > () (100000000); +#endif +#ifdef USE_DOUBLE header ("std:complex"); peak > () (100000000); +#endif #endif int scale = 1; if (argc > 1) scale = atoi (argv [1]); +#ifdef USE_FLOAT header ("float, 3"); bench_1 () (1000000 * scale); @@ -139,7 +148,9 @@ int main (int argc, char *argv []) { bench_1 () (30000 * scale); bench_2 () (300 * scale); bench_3 () (3 * scale); +#endif +#ifdef USE_DOUBLE header ("double, 3"); bench_1 () (1000000 * scale); @@ -163,8 +174,10 @@ int main (int argc, char *argv []) { bench_1 () (30000 * scale); bench_2 () (300 * scale); bench_3 () (3 * scale); +#endif #ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT header ("std::complex, 3"); bench_1, 3> () (1000000 * scale); @@ -188,7 +201,9 @@ int main (int argc, char *argv []) { bench_1, 100> () (30000 * scale); bench_2, 100> () (300 * scale); bench_3, 100> () (3 * scale); +#endif +#ifdef USE_DOUBLE header ("std::complex, 3"); bench_1, 3> () (1000000 * scale); @@ -212,6 +227,7 @@ int main (int argc, char *argv []) { bench_1, 100> () (30000 * scale); bench_2, 100> () (300 * scale); bench_3, 100> () (3 * scale); +#endif #endif return 0; diff --git a/bench2/bench2.hpp b/bench2/bench2.hpp index 64b788c7..f4bfb702 100644 --- a/bench2/bench2.hpp +++ b/bench2/bench2.hpp @@ -159,12 +159,23 @@ struct bench_3 { 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 -#endif +#define USE_SPARSE_VECTOR +#define USE_COMPRESSED_VECTOR +#define USE_COORDINATE_VECTOR + +#define USE_SPARSE_MATRIX +// #define USE_SPARSE_VECTOR_OF_SPARSE_VECTOR +#define USE_COMPRESSED_MATRIX +#define USE_COORDINATE_MATRIX + +#endif diff --git a/bench2/bench21.cpp b/bench2/bench21.cpp index 08ee6e1e..99fe296f 100644 --- a/bench2/bench21.cpp +++ b/bench2/bench21.cpp @@ -201,6 +201,7 @@ void bench_1::operator () (int runs) { header ("C array"); bench_c_inner_prod () (runs); +#ifdef USE_SPARSE_VECTOR #ifdef USE_MAP_ARRAY header ("sparse_vector"); bench_my_inner_prod >, N> () (runs); @@ -210,17 +211,29 @@ void bench_1::operator () (int runs) { header ("sparse_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 ("sparse_vector + sparse_vector"); + header ("vector + vector"); header ("C array"); bench_c_vector_add () (runs); +#ifdef USE_SPARSE_VECTOR #ifdef USE_MAP_ARRAY header ("sparse_vector safe"); bench_my_vector_add >, N> () (runs, safe_tag ()); @@ -236,6 +249,27 @@ void bench_1::operator () (int runs) { header ("sparse_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"); @@ -243,28 +277,34 @@ void bench_1::operator () (int 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/bench2/bench22.cpp b/bench2/bench22.cpp index 64ab76f8..6d22d775 100644 --- a/bench2/bench22.cpp +++ b/bench2/bench22.cpp @@ -333,6 +333,7 @@ void bench_2::operator () (int runs) { 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 >, @@ -352,24 +353,46 @@ void bench_2::operator () (int runs) { 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 (sparse_matrix, sparse_vector)"); + 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 >, + bench_my_matrix_vector_prod >, ublas::sparse_vector >, N> () (runs, fast_tag ()); #endif @@ -379,20 +402,42 @@ void bench_2::operator () (int runs) { ublas::sparse_vector >, N> () (runs, safe_tag ()); header ("sparse_matrix, sparse_vector fast"); - bench_my_matrix_vector_prod >, + 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 ("sparse_matrix + sparse_matrix"); + 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 ()); @@ -408,6 +453,23 @@ void bench_2::operator () (int runs) { 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"); @@ -415,28 +477,34 @@ void bench_2::operator () (int 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/bench2/bench23.cpp b/bench2/bench23.cpp index 2b874019..c1f9d520 100644 --- a/bench2/bench23.cpp +++ b/bench2/bench23.cpp @@ -131,30 +131,52 @@ template void bench_3::operator () (int runs) { header ("bench_3"); - header ("prod (sparse_matrix, sparse_matrix)"); + 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 >, + 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 >, + 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 >, + 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 >, + 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"); @@ -162,28 +184,34 @@ void bench_3::operator () (int 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/bench3/Jamfile b/bench3/Jamfile index b7c4e5c2..5bb3ec30 100644 --- a/bench3/Jamfile +++ b/bench3/Jamfile @@ -5,7 +5,6 @@ SOURCES = bench3 bench31 bench32 bench33 ; exe bench3 : $(SOURCES).cpp : $(BOOST_ROOT) - BOOST_UBLAS_TYPE_CHECK <*>"-w-8026 -w-8027 -w-8057 -w-8084 -w-8092" ; diff --git a/bench3/bench3.cpp b/bench3/bench3.cpp index 2f340e8d..b5473b20 100644 --- a/bench3/bench3.cpp +++ b/bench3/bench3.cpp @@ -96,24 +96,33 @@ int main (int argc, char *argv []) { _set_new_handler (std_new_handler); #endif +#ifdef USE_FLOAT header ("float"); peak () (100000000); +#endif +#ifdef USE_DOUBLE header ("double"); peak () (100000000); +#endif -#ifdef USE_COMPLEX +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT header ("std:complex"); peak > () (100000000); +#endif +#ifdef USE_DOUBLE header ("std:complex"); peak > () (100000000); +#endif #endif int scale = 1; if (argc > 1) scale = atoi (argv [1]); +#ifdef USE_FLOAT header ("float, 3"); bench_1 () (1000000 * scale); @@ -137,7 +146,9 @@ int main (int argc, char *argv []) { bench_1 () (30000 * scale); bench_2 () (300 * scale); bench_3 () (3 * scale); +#endif +#ifdef USE_DOUBLE header ("double, 3"); bench_1 () (1000000 * scale); @@ -161,8 +172,10 @@ int main (int argc, char *argv []) { bench_1 () (30000 * scale); bench_2 () (300 * scale); bench_3 () (3 * scale); +#endif #ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT header ("std::complex, 3"); bench_1, 3> () (1000000 * scale); @@ -186,7 +199,9 @@ int main (int argc, char *argv []) { bench_1, 100> () (30000 * scale); bench_2, 100> () (300 * scale); bench_3, 100> () (3 * scale); +#endif +#ifdef USE_DOUBLE header ("std::complex, 3"); bench_1, 3> () (1000000 * scale); @@ -210,6 +225,7 @@ int main (int argc, char *argv []) { bench_1, 100> () (30000 * scale); bench_2, 100> () (300 * scale); bench_3, 100> () (3 * scale); +#endif #endif return 0; diff --git a/bench3/bench3.hpp b/bench3/bench3.hpp index e94c62d4..a0e2eee1 100644 --- a/bench3/bench3.hpp +++ b/bench3/bench3.hpp @@ -143,6 +143,8 @@ struct bench_3 { struct safe_tag {}; struct fast_tag {}; +// #define USE_FLOAT +#define USE_DOUBLE // #define USE_STD_COMPLEX #define USE_C_ARRAY @@ -151,6 +153,6 @@ struct fast_tag {}; // #define USE_STD_VALARRAY #define USE_STD_VECTOR -#endif +#endif diff --git a/bench3/bench31.cpp b/bench3/bench31.cpp index 190cdb67..99be327b 100644 --- a/bench3/bench31.cpp +++ b/bench3/bench31.cpp @@ -309,28 +309,34 @@ void bench_1::operator () (int 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/bench3/bench32.cpp b/bench3/bench32.cpp index b7a50d04..183e6e62 100644 --- a/bench3/bench32.cpp +++ b/bench3/bench32.cpp @@ -541,28 +541,34 @@ void bench_2::operator () (int 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/bench3/bench33.cpp b/bench3/bench33.cpp index 584df7ab..814524b4 100644 --- a/bench3/bench33.cpp +++ b/bench3/bench33.cpp @@ -196,28 +196,34 @@ void bench_3::operator () (int 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/doc/matrix_proxy.htm b/doc/matrix_proxy.htm index db5a5590..e1b7cd03 100644 --- a/doc/matrix_proxy.htm +++ b/doc/matrix_proxy.htm @@ -281,11 +281,11 @@ href="expression.htm#vector_expression">Vector Expression.

public container_const_reference<matrix_row>, public random_access_iterator_base<const_iterator, value_type> { public: - typedef typename M::const_iterator2::iterator_category iterator_category; - typedef typename M::const_iterator2::difference_type difference_type; - typedef typename M::const_iterator2::value_type value_type; - typedef typename M::const_iterator2::reference reference; - typedef typename M::const_iterator2::pointer pointer; + typedef typename const_iterator_type::iterator_category iterator_category; + typedef typename const_iterator_type::difference_type difference_type; + typedef typename const_iterator_type::value_type value_type; + typedef typename const_iterator_type::reference reference; + typedef typename const_iterator_type::pointer pointer; // Construction and destruction const_iterator (); @@ -320,11 +320,11 @@ href="expression.htm#vector_expression">Vector Expression.

public container_reference<matrix_row>, public random_access_iterator_base<iterator, value_type> { public: - typedef typename M::iterator2::iterator_category iterator_category; - typedef typename M::iterator2::difference_type difference_type; - typedef typename M::iterator2::value_type value_type; - typedef typename M::iterator2::reference reference; - typedef typename M::iterator2::pointer pointer; + typedef typename iterator_type::iterator_category iterator_category; + typedef typename iterator_type::difference_type difference_type; + typedef typename iterator_type::value_type value_type; + typedef typename iterator_type::reference reference; + typedef typename iterator_type::pointer pointer; // Construction and destruction iterator (); @@ -685,11 +685,11 @@ href="expression.htm#vector_expression">Vector Expression.

public container_const_reference<matrix_column>, public random_access_iterator_base<const_iterator, value_type> { public: - typedef typename M::const_iterator1::iterator_category iterator_category; - typedef typename M::const_iterator1::difference_type difference_type; - typedef typename M::const_iterator1::value_type value_type; - typedef typename M::const_iterator1::reference reference; - typedef typename M::const_iterator1::pointer pointer; + typedef typename const_iterator_type::iterator_category iterator_category; + typedef typename const_iterator_type::difference_type difference_type; + typedef typename const_iterator_type::value_type value_type; + typedef typename const_iterator_type::reference reference; + typedef typename const_iterator_type::pointer pointer; // Construction and destruction const_iterator (); @@ -709,7 +709,7 @@ href="expression.htm#vector_expression">Vector Expression.

// Index size_type index () const; - // Assignment + // Assignment const_iterator &operator = (const const_iterator &it); // Comparison @@ -724,11 +724,11 @@ href="expression.htm#vector_expression">Vector Expression.

public container_reference<matrix_column>, public random_access_iterator_base<iterator, value_type> { public: - typedef typename M::iterator1::iterator_category iterator_category; - typedef typename M::iterator1::difference_type difference_type; - typedef typename M::iterator1::value_type value_type; - typedef typename M::iterator1::reference reference; - typedef typename M::iterator1::pointer pointer; + typedef typename iterator_type::iterator_category iterator_category; + typedef typename iterator_type::difference_type difference_type; + typedef typename iterator_type::value_type value_type; + typedef typename iterator_type::reference reference; + typedef typename iterator_type::pointer pointer; // Construction and destruction iterator (); @@ -1885,11 +1885,11 @@ href="expression.htm#matrix_expression">Matrix Expression.

public container_const_reference<matrix_range>, public random_access_iterator_base<const_iterator1, value_type> { public: - typedef typename M::const_iterator1::iterator_category iterator_category; - typedef typename M::const_iterator1::difference_type difference_type; - typedef typename M::const_iterator1::value_type value_type; - typedef typename M::const_iterator1::reference reference; - typedef typename M::const_iterator1::pointer pointer; + typedef typename const_iterator1_type::iterator_category iterator_category; + typedef typename const_iterator1_type::difference_type difference_type; + typedef typename const_iterator1_type::value_type value_type; + typedef typename const_iterator1_type::reference reference; + typedef typename const_iterator1_type::pointer pointer; typedef const_iterator2 dual_iterator_type; typedef const_reverse_iterator2 dual_reverse_iterator_type; @@ -1932,11 +1932,11 @@ href="expression.htm#matrix_expression">Matrix Expression.

public container_reference<matrix_range>, public random_access_iterator_base<iterator1, value_type> { public: - typedef typename M::iterator1::iterator_category iterator_category; - typedef typename M::iterator1::difference_type difference_type; - typedef typename M::iterator1::value_type value_type; - typedef typename M::iterator1::reference reference; - typedef typename M::iterator1::pointer pointer; + typedef typename iterator1_type::iterator_category iterator_category; + typedef typename iterator1_type::difference_type difference_type; + typedef typename iterator1_type::value_type value_type; + typedef typename iterator1_type::reference reference; + typedef typename iterator1_type::pointer pointer; typedef iterator2 dual_iterator_type; typedef reverse_iterator2 dual_reverse_iterator_type; @@ -1978,11 +1978,11 @@ href="expression.htm#matrix_expression">Matrix Expression.

public container_const_reference<matrix_range>, public random_access_iterator_base<const_iterator2, value_type> { public: - typedef typename M::const_iterator2::iterator_category iterator_category; - typedef typename M::const_iterator2::difference_type difference_type; - typedef typename M::const_iterator2::value_type value_type; - typedef typename M::const_iterator2::reference reference; - typedef typename M::const_iterator2::pointer pointer; + typedef typename const_iterator2_type::iterator_category iterator_category; + typedef typename const_iterator2_type::difference_type difference_type; + typedef typename const_iterator2_type::value_type value_type; + typedef typename const_iterator2_type::reference reference; + typedef typename const_iterator2_type::pointer pointer; typedef const_iterator1 dual_iterator_type; typedef const_reverse_iterator1 dual_reverse_iterator_type; @@ -2025,11 +2025,11 @@ href="expression.htm#matrix_expression">Matrix Expression.

public container_reference<matrix_range>, public random_access_iterator_base<iterator2, value_type> { public: - typedef typename M::iterator2::iterator_category iterator_category; - typedef typename M::iterator2::difference_type difference_type; - typedef typename M::iterator2::value_type value_type; - typedef typename M::iterator2::reference reference; - typedef typename M::iterator2::pointer pointer; + typedef typename iterator2_type::iterator_category iterator_category; + typedef typename iterator2_type::difference_type difference_type; + typedef typename iterator2_type::value_type value_type; + typedef typename iterator2_type::reference reference; + typedef typename iterator2_type::pointer pointer; typedef iterator1 dual_iterator_type; typedef reverse_iterator1 dual_reverse_iterator_type; diff --git a/doc/overview.htm b/doc/overview.htm index 65c16d6e..062db06c 100644 --- a/doc/overview.htm +++ b/doc/overview.htm @@ -436,9 +436,9 @@ how BLAS calls may be mapped onto our classes.

y = a * prod (A, x) + b * y or
y = a * prod (trans (A), x) + b * y
or
y = a * prod (herm (A), x) + b * y
- y <- A x + b y or
- y <- A
T x + b y
- y <- A
H x + b y + y <- a A x + b y or
+ y <- a A
T x + b y
+ y <- a A
H x + b y Adds the scaled product of a matrix with a vector. diff --git a/doc/vector_proxy.htm b/doc/vector_proxy.htm index 104e20ac..bb146b91 100644 --- a/doc/vector_proxy.htm +++ b/doc/vector_proxy.htm @@ -296,11 +296,11 @@ href="expression.htm#vector_expression">Vector Expression.

public container_const_reference<vector_range>, public random_access_iterator_base<const_iterator, value_type> { public: - typedef typename V::const_iterator::iterator_category iterator_category; - typedef typename V::const_iterator::difference_type difference_type; - typedef typename V::const_iterator::value_type value_type; - typedef typename V::const_iterator::reference reference; - typedef typename V::const_iterator::pointer pointer; + typedef typename const_iterator_type::iterator_category iterator_category; + typedef typename const_iterator_type::difference_type difference_type; + typedef typename const_iterator_type::value_type value_type; + typedef typename const_iterator_type::reference reference; + typedef typename const_iterator_type::pointer pointer; // Construction and destruction const_iterator (); @@ -335,11 +335,11 @@ href="expression.htm#vector_expression">Vector Expression.

public container_reference<vector_range>, public random_access_iterator_base<iterator, value_type> { public: - typedef typename V::iterator::iterator_category iterator_category; - typedef typename V::iterator::difference_type difference_type; - typedef typename V::iterator::value_type value_type; - typedef typename V::iterator::reference reference; - typedef typename V::iterator::pointer pointer; + typedef typename iterator_type::iterator_category iterator_category; + typedef typename iterator_type::difference_type difference_type; + typedef typename iterator_type::value_type value_type; + typedef typename iterator_type::reference reference; + typedef typename iterator_type::pointer pointer; // Construction and destruction iterator (); diff --git a/include/boost/numeric/ublas/banded.hpp b/include/boost/numeric/ublas/banded.hpp index 3f9d80f3..03244972 100644 --- a/include/boost/numeric/ublas/banded.hpp +++ b/include/boost/numeric/ublas/banded.hpp @@ -78,7 +78,7 @@ namespace boost { namespace numeric { namespace ublas { size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), lower_ (lower), upper_ (upper), data_ (std::max (ae ().size1 (), ae ().size2 ()) * (lower + 1 + upper)) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); } // Accessors @@ -204,7 +204,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE banded_matrix &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -221,7 +221,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE banded_matrix &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -238,19 +238,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE banded_matrix &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE banded_matrix& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE banded_matrix& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -286,27 +286,28 @@ namespace boost { namespace numeric { namespace ublas { void insert (size_type i, size_type j, const_reference t) { BOOST_UBLAS_CHECK (i < size1_, bad_index ()); BOOST_UBLAS_CHECK (j < size2_, bad_index ()); -#ifndef BOOST_UBLAS_USE_ET - if (t == value_type ()) - return; -#endif +// FIXME: is this ugly check still needed?! +// #ifndef BOOST_UBLAS_USE_ET +// if (t == value_type ()) +// return; +// #endif #ifdef BOOST_UBLAS_OWN_BANDED size_type k = std::max (i, j); size_type l = lower_ + j - i; - BOOST_UBLAS_CHECK (data () [functor_type::element (k, std::max (size1_, size2_), - l, lower_ + 1 + upper_)] == value_type (), bad_index ()); - // data ().insert (data ().begin () + functor_type::element (k, std::max (size1_, size2_), + BOOST_UBLAS_CHECK (type_traits::equals (data () [functor_type::element (k, std::max (size1_, size2_), + l, lower_ + 1 + upper_)], value_type ()), bad_index ()); + // data ().insert (data ().begin () + functor_type::element (k, std::max (size1_, size2_), // l, lower_ + 1 + upper_), t); - data () [functor_type::element (k, std::max (size1_, size2_), + data () [functor_type::element (k, std::max (size1_, size2_), l, lower_ + 1 + upper_)] = t; #else size_type k = j; size_type l = upper_ + i - j; - BOOST_UBLAS_CHECK (data () [functor_type::element (k, size2_, - l, lower_ + 1 + upper_)] == value_type (), bad_index ()); - // data ().insert (data ().begin () + functor_type::element (k, size2_, + BOOST_UBLAS_CHECK (type_traits::equals (data () [functor_type::element (k, size2_, + l, lower_ + 1 + upper_)], value_type ()), bad_index ()); + // data ().insert (data ().begin () + functor_type::element (k, size2_, // l, lower_ + 1 + upper_), t); - data () [functor_type::element (k, size2_, + data () [functor_type::element (k, size2_, l, lower_ + 1 + upper_)] = t; #endif } @@ -336,23 +337,6 @@ namespace boost { namespace numeric { namespace ublas { std::fill (data ().begin (), data ().end (), value_type ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -374,7 +358,6 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup @@ -386,11 +369,7 @@ namespace boost { namespace numeric { namespace ublas { size_type upper_i = std::min (j + 1 + lower_, size1_); i = std::min (i, upper_i); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find1 (int rank, size_type i, size_type j) { @@ -400,11 +379,7 @@ namespace boost { namespace numeric { namespace ublas { size_type upper_i = std::min (j + 1 + lower_, size1_); i = std::min (i, upper_i); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find2 (int rank, size_type i, size_type j) const { @@ -414,11 +389,7 @@ namespace boost { namespace numeric { namespace ublas { size_type upper_j = std::min (i + 1 + upper_, size2_); j = std::min (j, upper_j); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find2 (int rank, size_type i, size_type j) { @@ -428,11 +399,7 @@ namespace boost { namespace numeric { namespace ublas { size_type upper_j = std::min (i + 1 + upper_, size2_); j = std::min (j, upper_j); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { @@ -469,7 +436,7 @@ namespace boost { namespace numeric { namespace ublas { // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base typename banded_matrix::value_type banded_matrix::zero_ = 0; - // Banded matrix adaptor class + // Banded matrix adaptor class template class banded_adaptor: public matrix_expression > { @@ -1022,10 +989,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_reference const_reference; typedef typename M::reference reference; typedef typename M::const_pointer const_pointer; typedef typename M::pointer pointer; +#else + typedef typename M::const_reference const_reference; + typedef typename detail::ct_if::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif typedef const banded_adaptor const_self_type; typedef banded_adaptor self_type; typedef const matrix_const_reference const_closure_type; @@ -1130,7 +1108,7 @@ namespace boost { namespace numeric { namespace ublas { // Assignment BOOST_UBLAS_INLINE banded_adaptor &operator = (const banded_adaptor &m) { - matrix_assign > () (*this, m); + matrix_assign (scalar_assign (), *this, m); return *this; } BOOST_UBLAS_INLINE @@ -1141,49 +1119,49 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE banded_adaptor &operator = (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (ae)); + matrix_assign (scalar_assign (), *this, matrix (ae)); return *this; } template BOOST_UBLAS_INLINE banded_adaptor &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE banded_adaptor& operator += (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this + ae)); + matrix_assign (scalar_assign (), *this, matrix (*this + ae)); return *this; } template BOOST_UBLAS_INLINE banded_adaptor &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE banded_adaptor& operator -= (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this - ae)); + matrix_assign (scalar_assign (), *this, matrix (*this - ae)); return *this; } template BOOST_UBLAS_INLINE banded_adaptor &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE banded_adaptor& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE banded_adaptor& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -1195,7 +1173,7 @@ namespace boost { namespace numeric { namespace ublas { if (this != &m) { BOOST_UBLAS_CHECK (lower_ == m.lower_, bad_size ()); BOOST_UBLAS_CHECK (upper_ == m.upper_, bad_size ()); - matrix_swap > () (*this, m); + matrix_swap (scalar_swap (), *this, m); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -1205,23 +1183,6 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -1243,7 +1204,6 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup @@ -1255,11 +1215,7 @@ namespace boost { namespace numeric { namespace ublas { size_type upper_i = std::min (j + 1 + lower_, size1 ()); i = std::min (i, upper_i); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find1 (int rank, size_type i, size_type j) { @@ -1269,11 +1225,7 @@ namespace boost { namespace numeric { namespace ublas { size_type upper_i = std::min (j + 1 + lower_, size1 ()); i = std::min (i, upper_i); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find2 (int rank, size_type i, size_type j) const { @@ -1283,11 +1235,7 @@ namespace boost { namespace numeric { namespace ublas { size_type upper_j = std::min (i + 1 + upper_, size2 ()); j = std::min (j, upper_j); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find2 (int rank, size_type i, size_type j) { @@ -1297,11 +1245,7 @@ namespace boost { namespace numeric { namespace ublas { size_type upper_j = std::min (i + 1 + upper_, size2 ()); j = std::min (j, upper_j); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { @@ -1338,7 +1282,7 @@ namespace boost { namespace numeric { namespace ublas { // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base struct Indexed2DIteratorConcept { typedef I iterator_type; -#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR typedef typename I::dual_iterator_type dual_iterator_type; typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type; -#endif static void constraints () { iterator_type it = iterator_type (); // Function call it (); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - // Indices - it.index (); -#else // Indices it.index1 (); it.index2 (); @@ -289,7 +283,6 @@ namespace boost { namespace numeric { namespace ublas { ignore_unused_variable_warning (it_end); ignore_unused_variable_warning (it_rbegin); ignore_unused_variable_warning (it_rend); -#endif } }; diff --git a/include/boost/numeric/ublas/config.hpp b/include/boost/numeric/ublas/config.hpp index 03485bc5..fd0ddb4d 100644 --- a/include/boost/numeric/ublas/config.hpp +++ b/include/boost/numeric/ublas/config.hpp @@ -21,6 +21,7 @@ #include #include +#include #include #ifdef BOOST_MSVC @@ -56,6 +57,15 @@ +// Enable different sparse element proxies +// These fix a [1] = a [0] = 1, but probably won't work on broken compilers. +// Thanks to Marc Duflot for spotting this. +// #define BOOST_UBLAS_STRICT_STORAGE_SPARSE +#define BOOST_UBLAS_STRICT_VECTOR_SPARSE +#define BOOST_UBLAS_STRICT_MATRIX_SPARSE + + + // Enable performance options in release mode #ifdef NDEBUG @@ -95,7 +105,7 @@ // Bounds check #define BOOST_UBLAS_BOUNDS_CHECK // Type check for non dense matrices -// #define BOOST_UBLAS_TYPE_CHECK +#define BOOST_UBLAS_TYPE_CHECK #endif @@ -119,9 +129,6 @@ // #define BOOST_UBLAS_ET_CLOSURE_VALUE #define BOOST_UBLAS_ET_CLOSURE_REFERENCE -// Use canonical iterators. -// #define BOOST_UBLAS_USE_CANONICAL_ITERATOR - // Use indexed iterators. // #define BOOST_UBLAS_USE_INDEXED_ITERATOR @@ -161,8 +168,6 @@ #define BOOST_MSVC_STD_ITERATOR #endif -#define BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - #endif @@ -183,8 +188,6 @@ #define BOOST_UBLAS_USE_LONG_DOUBLE -#define BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - #endif @@ -225,8 +228,6 @@ // ICC sometimes needs qualified type names. #define BOOST_UBLAS_QUALIFIED_TYPENAME -#define BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - #endif @@ -242,8 +243,6 @@ #define BOOST_UBLAS_USE_LONG_DOUBLE -#define BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - #endif @@ -251,6 +250,21 @@ // Forward declarations namespace boost { namespace numeric { namespace ublas { +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + namespace detail { + + template + struct ct_if { + typedef T1 type; + }; + template + struct ct_if { + typedef T2 type; + }; + + } +#endif + template class unbounded_array; @@ -290,16 +304,8 @@ namespace boost { namespace numeric { namespace ublas { template class matrix_row; - template - class matrix_row_iterator; - template - class matrix_row_const_iterator; template class matrix_column; - template - class matrix_column_iterator; - template - class matrix_column_const_iterator; template class matrix_range; template @@ -307,11 +313,6 @@ namespace boost { namespace numeric { namespace ublas { template > class matrix_indirect; - template - struct vector_assign_scalar; - template - struct vector_assign; - template > class vector; @@ -324,9 +325,12 @@ namespace boost { namespace numeric { namespace ublas { template > class sparse_vector; - template, class TA = unbounded_array > + template, class TA = unbounded_array, std::size_t IB = 0> class compressed_vector; + template, class TA = unbounded_array, std::size_t IB = 0> + class coordinate_vector; + struct unknown_orientation_tag {}; struct row_major_tag {}; @@ -335,13 +339,6 @@ namespace boost { namespace numeric { namespace ublas { struct column_major_tag {}; struct column_major; - template - struct matrix_assign_scalar; - template - struct matrix_assign; - template - struct matrix_swap; - template > class matrix; @@ -393,9 +390,11 @@ namespace boost { namespace numeric { namespace ublas { template > > class sparse_vector_of_sparse_vector; - template, class TA = unbounded_array > + template, class TA = unbounded_array, std::size_t IB = 0> class compressed_matrix; + template, class TA = unbounded_array, std::size_t IB = 0> + class coordinate_matrix; template typename V::size_type num_elements (const V &v) { diff --git a/include/boost/numeric/ublas/exception.hpp b/include/boost/numeric/ublas/exception.hpp index 1d861cfe..0a572177 100644 --- a/include/boost/numeric/ublas/exception.hpp +++ b/include/boost/numeric/ublas/exception.hpp @@ -30,13 +30,13 @@ namespace boost { namespace numeric { namespace ublas { // public std::exception { public std::runtime_error { BOOST_UBLAS_EXPLICIT - divide_by_zero (const std::string &s = "exception: divide by zero"): + divide_by_zero (const std::string &s = "exception: divide by zero"): std::runtime_error (s) {} // virtual const char *what () const throw () { // return "exception: divide by zero"; // } virtual void raise () { -#ifndef BOOST_NO_EXCEPTIONS +#if ! defined (BOOST_NO_EXCEPTIONS) && defined (BOOST_UBLAS_USE_EXCEPTIONS) throw *this; #else abort (); @@ -48,13 +48,13 @@ namespace boost { namespace numeric { namespace ublas { // public std::exception { public std::logic_error { BOOST_UBLAS_EXPLICIT - internal_logic (const std::string &s = "exception: internal logic"): + internal_logic (const std::string &s = "exception: internal logic"): std::logic_error (s) {} // virtual const char *what () const throw () { // return "exception: internal logic"; // } virtual void raise () { -#ifndef BOOST_NO_EXCEPTIONS +#if ! defined (BOOST_NO_EXCEPTIONS) && defined (BOOST_UBLAS_USE_EXCEPTIONS) throw *this; #else abort (); @@ -66,13 +66,13 @@ namespace boost { namespace numeric { namespace ublas { // public std::exception { public std::logic_error { BOOST_UBLAS_EXPLICIT - external_logic (const std::string &s = "exception: external logic"): + external_logic (const std::string &s = "exception: external logic"): std::logic_error (s) {} // virtual const char *what () const throw () { // return "exception: external logic"; // } virtual void raise () { -#ifndef BOOST_NO_EXCEPTIONS +#if ! defined (BOOST_NO_EXCEPTIONS) && defined (BOOST_UBLAS_USE_EXCEPTIONS) throw *this; #else abort (); @@ -84,13 +84,13 @@ namespace boost { namespace numeric { namespace ublas { // public std::exception { public std::invalid_argument { BOOST_UBLAS_EXPLICIT - bad_argument (const std::string &s = "exception: bad argument"): + bad_argument (const std::string &s = "exception: bad argument"): std::invalid_argument (s) {} // virtual const char *what () const throw () { // return "exception: bad argument"; // } virtual void raise () { -#ifndef BOOST_NO_EXCEPTIONS +#if ! defined (BOOST_NO_EXCEPTIONS) && defined (BOOST_UBLAS_USE_EXCEPTIONS) throw *this; #else abort (); @@ -102,13 +102,13 @@ namespace boost { namespace numeric { namespace ublas { // public std::exception { public std::domain_error { BOOST_UBLAS_EXPLICIT - bad_size (const std::string &s = "exception: bad size"): + bad_size (const std::string &s = "exception: bad size"): std::domain_error (s) {} // virtual const char *what () const throw () { // return "exception: bad size"; // } virtual void raise () { -#ifndef BOOST_NO_EXCEPTIONS +#if ! defined (BOOST_NO_EXCEPTIONS) && defined (BOOST_UBLAS_USE_EXCEPTIONS) throw *this; #else abort (); @@ -120,13 +120,13 @@ namespace boost { namespace numeric { namespace ublas { // public std::exception { public std::out_of_range { BOOST_UBLAS_EXPLICIT - bad_index (const std::string &s = "exception: bad index"): + bad_index (const std::string &s = "exception: bad index"): std::out_of_range (s) {} // virtual const char *what () const throw () { // return "exception: bad index"; // } virtual void raise () { -#ifndef BOOST_NO_EXCEPTIONS +#if ! defined (BOOST_NO_EXCEPTIONS) && defined (BOOST_UBLAS_USE_EXCEPTIONS) throw *this; #else abort (); @@ -138,13 +138,13 @@ namespace boost { namespace numeric { namespace ublas { // public std::exception { public std::runtime_error { BOOST_UBLAS_EXPLICIT - singular (const std::string &s = "exception: singular"): + singular (const std::string &s = "exception: singular"): std::runtime_error (s) {} // virtual const char *what () const throw () { // return "exception: singular"; // } virtual void raise () { -#ifndef BOOST_NO_EXCEPTIONS +#if ! defined (BOOST_NO_EXCEPTIONS) && defined (BOOST_UBLAS_USE_EXCEPTIONS) throw *this; #else abort (); @@ -162,7 +162,7 @@ namespace boost { namespace numeric { namespace ublas { // return "exception: non real"; // } virtual void raise () { -#ifndef BOOST_NO_EXCEPTIONS +#if ! defined (BOOST_NO_EXCEPTIONS) && defined (BOOST_UBLAS_USE_EXCEPTIONS) throw *this; #else abort (); diff --git a/include/boost/numeric/ublas/functional.hpp b/include/boost/numeric/ublas/functional.hpp index fadd9a56..f37f5140 100644 --- a/include/boost/numeric/ublas/functional.hpp +++ b/include/boost/numeric/ublas/functional.hpp @@ -315,31 +315,31 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE - result_type operator () (const vector_expression &e) const { + result_type operator () (const vector_expression &e) const { real_type t (0); size_type size (e ().size ()); for (size_type i = 0; i < size; ++ i) { real_type u (type_traits::norm_1 (e () (i))); t += u; } - return t; + return t; } // Dense case template BOOST_UBLAS_INLINE - result_type operator () (difference_type size, I it) const { + result_type operator () (difference_type size, I it) const { real_type t (0); while (-- size >= 0) { real_type u (type_traits::norm_1 (*it)); t += u; ++ it; } - return t; + return t; } // Sparse case template BOOST_UBLAS_INLINE - result_type operator () (I it, const I &it_end) const { + result_type operator () (I it, const I &it_end) const { real_type t (0); while (it != it_end) { real_type u (type_traits::norm_1 (*it)); @@ -459,28 +459,28 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE - result_type operator () (const vector_expression &e) const { + result_type operator () (const vector_expression &e) const { real_type t (0); size_type size (e ().size ()); for (size_type i = 0; i < size; ++ i) { real_type u (type_traits::norm_inf (e () (i))); - if (u > t) + if (u > t) t = u; } - return t; + return t; } // Dense case template BOOST_UBLAS_INLINE - result_type operator () (difference_type size, I it) const { + result_type operator () (difference_type size, I it) const { real_type t (0); while (-- size >= 0) { real_type u (type_traits::norm_inf (*it)); - if (u > t) + if (u > t) t = u; ++ it; } - return t; + return t; } // Sparse case template @@ -519,8 +519,10 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE result_type operator () (const vector_expression &e) const { - result_type i_norm_inf (-1); - real_type t (-1); + // Here we'd better guarantee a valid return value to achieve BLAS compatibility + // result_type i_norm_inf (-1); + result_type i_norm_inf (e ().size () == 0 ? -1 : 0); + real_type t (0); size_type size (e ().size ()); for (size_type i = 0; i < size; ++ i) { real_type u (type_traits::norm_inf (e () (i))); @@ -535,8 +537,10 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE result_type operator () (difference_type size, I it) const { - result_type i_norm_inf (-1); - real_type t (-1); + // Here we'd better guarantee a valid return value to achieve BLAS compatibility + // result_type i_norm_inf (-1); + result_type i_norm_inf (size == 0 ? -1 : 0); + real_type t (0); while (-- size >= 0) { real_type u (type_traits::norm_inf (*it)); if (u > t) { @@ -551,8 +555,10 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE result_type operator () (I it, const I &it_end) const { - result_type i_norm_inf (-1); - real_type t (-1); + // Here we'd better guarantee a valid return value to achieve BLAS compatibility + // result_type i_norm_inf (-1); + result_type i_norm_inf (it ().size () == 0 ? -1 : 0); + real_type t (0); while (it != it_end) { real_type u (type_traits::norm_inf (*it)); if (u > t) { @@ -575,7 +581,7 @@ namespace boost { namespace numeric { namespace ublas { }; template - struct vector_inner_prod: + struct vector_inner_prod: public vector_scalar_binary_functor { typedef typename vector_scalar_binary_functor::size_type size_type ; typedef typename vector_scalar_binary_functor::difference_type difference_type; @@ -694,17 +700,6 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE result_type operator () (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - result_type t (0); - if (it1 != it1_end && it1.index () < it2.index ()) - it1 += std::min (it2.index () - it1.index (), size_type (it1_end - it1)); - if (it2 != it2_end && it2.index () < it1.index ()) - it2 += std::min (it1.index () - it2.index (), size_type (it2_end - it2)); - difference_type size (std::min (size_type (it1_end - it1), size_type (it2_end - it2))); - while (-- size >= 0) - t += *it1 * *it2, ++ it1, ++ it2; - return t; -#else result_type t (0); if (it1 != it1_end && it1.index2 () < it2.index ()) it1 += std::min (it2.index () - it1.index2 (), size_type (it1_end - it1)); @@ -714,16 +709,14 @@ namespace boost { namespace numeric { namespace ublas { while (-- size >= 0) t += *it1 * *it2, ++ it1, ++ it2; return t; -#endif } // Sparse case template BOOST_UBLAS_INLINE result_type operator () (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR result_type t (0); while (it1 != it1_end && it2 != it2_end) { - difference_type compare = it1.index () - it2.index (); + difference_type compare = it1.index2 () - it2.index (); if (compare < 0) ++ it1; else if (compare == 0) @@ -732,19 +725,6 @@ namespace boost { namespace numeric { namespace ublas { ++ it2; } return t; -#else - result_type t (0); - while (it1 != it1_end && it2 != it2_end) { - difference_type compare = it1.index2 () - it2.index (); - if (compare < 0) - ++ it1; - else if (compare == 0) - t += *it1 * *it2, ++ it1, ++ it2; - else if (compare > 0) - ++ it2; - } - return t; -#endif } }; @@ -789,17 +769,6 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE result_type operator () (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - result_type t (0); - if (it1 != it1_end && it1.index () < it2.index ()) - it1 += std::min (it2.index () - it1.index (), size_type (it1_end - it1)); - if (it2 != it2_end && it2.index () < it1.index ()) - it2 += std::min (it1.index () - it2.index (), size_type (it2_end - it2)); - difference_type size (std::min (size_type (it1_end - it1), size_type (it2_end - it2))); - while (-- size >= 0) - t += *it1 * *it2, ++ it1, ++ it2; - return t; -#else result_type t (0); if (it1 != it1_end && it1.index () < it2.index1 ()) it1 += std::min (it2.index1 () - it1.index (), size_type (it1_end - it1)); @@ -808,38 +777,23 @@ namespace boost { namespace numeric { namespace ublas { difference_type size (std::min (size_type (it1_end - it1), size_type (it2_end - it2))); while (-- size >= 0) t += *it1 * *it2, ++ it1, ++ it2; - return t; -#endif + return t; } // Sparse case template BOOST_UBLAS_INLINE result_type operator () (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - result_type t (0); - while (it1 != it1_end && it2 != it2_end) { - difference_type compare = it1.index () - it2.index (); - if (compare < 0) - ++ it1; - else if (compare == 0) - t += *it1 * *it2, ++ it1, ++ it2; - else if (compare > 0) - ++ it2; - } - return t; -#else result_type t (0); while (it1 != it1_end && it2 != it2_end) { difference_type compare = it1.index () - it2.index1 (); - if (compare < 0) + if (compare < 0) ++ it1; - else if (compare == 0) + else if (compare == 0) t += *it1 * *it2, ++ it1, ++ it2; else if (compare > 0) ++ it2; } - return t; -#endif + return t; } }; @@ -901,12 +855,12 @@ namespace boost { namespace numeric { namespace ublas { difference_type size (std::min (size_type (it1_end - it1), size_type (it2_end - it2))); while (-- size >= 0) t += *it1 * *it2, ++ it1, ++ it2; - return t; + return t; } // Sparse case template BOOST_UBLAS_INLINE - result_type operator () (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) const { + result_type operator () (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) const { result_type t (0); while (it1 != it1_end && it2 != it2_end) { difference_type compare = it1.index2 () - it2.index1 (); diff --git a/include/boost/numeric/ublas/hermitian.hpp b/include/boost/numeric/ublas/hermitian.hpp index 1492dd28..45fe6e2b 100644 --- a/include/boost/numeric/ublas/hermitian.hpp +++ b/include/boost/numeric/ublas/hermitian.hpp @@ -98,7 +98,7 @@ namespace boost { namespace numeric { namespace ublas { hermitian_matrix (const matrix_expression &ae): size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())), data_ (functor1_type::packed_size (ae ().size1 (), ae ().size2 ())) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); } // Accessors @@ -192,7 +192,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE hermitian_matrix &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -209,7 +209,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE hermitian_matrix &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -226,7 +226,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE hermitian_matrix &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template @@ -236,7 +236,7 @@ namespace boost { namespace numeric { namespace ublas { // otherwise the resulting matrix isn't hermitian. // Thanks to Peter Schmitteckert for spotting this. BOOST_UBLAS_CHECK (type_traits::imag (at) == 0, non_real ()); - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template @@ -246,7 +246,7 @@ namespace boost { namespace numeric { namespace ublas { // otherwise the resulting matrix isn't hermitian. // Thanks to Peter Schmitteckert for spotting this. BOOST_UBLAS_CHECK (type_traits::imag (at) == 0, non_real ()); - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -276,18 +276,21 @@ namespace boost { namespace numeric { namespace ublas { void insert (size_type i, size_type j, const_reference t) { BOOST_UBLAS_CHECK (i < size_, bad_index ()); BOOST_UBLAS_CHECK (j < size_, bad_index ()); -#ifndef BOOST_UBLAS_USE_ET - if (t == value_type ()) - return; -#endif +// FIXME: is this ugly check still needed?! +// #ifndef BOOST_UBLAS_USE_ET +// if (t == value_type ()) +// return; +// #endif if (functor1_type::other (i, j)) { size_type k = functor1_type::element (functor2_type (), i, size_, j, size_); - BOOST_UBLAS_CHECK (data () [k] == value_type () || data () [k] == t, bad_index ()); + BOOST_UBLAS_CHECK (type_traits::equals (data () [k], value_type ()) || + type_traits::equals (data () [k], t), bad_index ()); // data ().insert (data ().begin () + k, t); data () [k] = t; } else { size_type k = functor1_type::element (functor2_type (), j, size_, i, size_); - BOOST_UBLAS_CHECK (data () [k] == value_type () || data () [k] == type_traits::conj (t), bad_index ()); + BOOST_UBLAS_CHECK (type_traits::equals (data () [k], value_type ()) || + type_traits::equals (data () [k], type_traits::conj (t)), bad_index ()); // data ().insert (data ().begin () + k, type_traits::conj (t)); data () [k] = type_traits::conj (t); } @@ -312,23 +315,6 @@ namespace boost { namespace numeric { namespace ublas { std::fill (data ().begin (), data ().end (), value_type ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -350,86 +336,53 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_first1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor1_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_last1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor1_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_first2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor1_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_last2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor1_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base::value, + // typename M::const_reference, + // typename M::reference>::type reference; + typedef typename M::value_type const_reference; + typedef typename detail::ct_if::value, + typename M::value_type, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif typedef const hermitian_adaptor const_self_type; typedef hermitian_adaptor self_type; typedef const matrix_const_reference const_closure_type; @@ -1072,7 +1041,7 @@ namespace boost { namespace numeric { namespace ublas { // Assignment BOOST_UBLAS_INLINE hermitian_adaptor &operator = (const hermitian_adaptor &m) { - matrix_assign > () (*this, m); + matrix_assign (scalar_assign (), *this, m); return *this; } BOOST_UBLAS_INLINE @@ -1083,37 +1052,37 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE hermitian_adaptor &operator = (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (ae)); + matrix_assign (scalar_assign (), *this, matrix (ae)); return *this; } template BOOST_UBLAS_INLINE hermitian_adaptor &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE hermitian_adaptor& operator += (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this + ae)); + matrix_assign (scalar_assign (), *this, matrix (*this + ae)); return *this; } template BOOST_UBLAS_INLINE hermitian_adaptor &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE hermitian_adaptor& operator -= (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this - ae)); + matrix_assign (scalar_assign (), *this, matrix (*this - ae)); return *this; } template BOOST_UBLAS_INLINE hermitian_adaptor &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template @@ -1123,7 +1092,7 @@ namespace boost { namespace numeric { namespace ublas { // otherwise the resulting matrix isn't hermitian. // Thanks to Peter Schmitteckert for spotting this. BOOST_UBLAS_CHECK (type_traits::imag (at) == 0, non_real ()); - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template @@ -1133,7 +1102,7 @@ namespace boost { namespace numeric { namespace ublas { // otherwise the resulting matrix isn't hermitian. // Thanks to Peter Schmitteckert for spotting this. BOOST_UBLAS_CHECK (type_traits::imag (at) == 0, non_real ()); - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -1143,7 +1112,7 @@ namespace boost { namespace numeric { namespace ublas { // Too unusual semantic. // BOOST_UBLAS_CHECK (this != &m, external_logic ()); if (this != &m) - matrix_swap > () (*this, m); + matrix_swap (scalar_swap (), *this, m); } #ifdef BOOST_UBLAS_FRIEND_FUNCTION BOOST_UBLAS_INLINE @@ -1152,23 +1121,6 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -1190,86 +1142,53 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_first1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_last1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_first2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_last2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base BOOST_UBLAS_INLINE matrix (const matrix_expression &ae): size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (ae ().size1 () * ae ().size2 ()) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); } // Accessors @@ -151,7 +151,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE matrix &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -168,7 +168,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE matrix &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -185,19 +185,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE matrix &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE matrix& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -242,23 +242,6 @@ namespace boost { namespace numeric { namespace ublas { std::fill (data ().begin (), data ().end (), value_type ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -280,56 +263,39 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else return const_iterator1 (*this, data ().begin () + functor_type::element (i, size1_, j, size2_)); -#endif #endif } BOOST_UBLAS_INLINE iterator1 find1 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, i, j); #else return iterator1 (*this, data ().begin () + functor_type::element (i, size1_, j, size2_)); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else return const_iterator2 (*this, data ().begin () + functor_type::element (i, size1_, j, size2_)); -#endif #endif } BOOST_UBLAS_INLINE iterator2 find2 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, i, j); #else return iterator2 (*this, data ().begin () + functor_type::element (i, size1_, j, size2_)); -#endif #endif } BOOST_UBLAS_INLINE @@ -367,7 +333,7 @@ namespace boost { namespace numeric { namespace ublas { // Iterators simply are pointers. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base class vector_of_vector: public matrix_expression > { @@ -975,7 +941,7 @@ namespace boost { namespace numeric { namespace ublas { data_ (functor_type::size1 (ae ().size1 (), ae ().size2 ()) + 1) { for (size_type k = 0; k < functor_type::size1 (ae ().size1 (), ae ().size2 ()); ++ k) data_ [k].resize (functor_type::size2 (ae ().size1 (), ae ().size2 ())); - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); } // Accessors @@ -1052,7 +1018,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE vector_of_vector &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -1069,7 +1035,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE vector_of_vector &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -1086,19 +1052,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE vector_of_vector &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_of_vector& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE vector_of_vector& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -1142,23 +1108,6 @@ namespace boost { namespace numeric { namespace ublas { std::fill (data () [k].begin (), data () [k].end (), value_type ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -1180,56 +1129,39 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else return const_iterator1 (*this, i, j, data () [functor_type::element1 (i, size1_, j, size2_)].begin () + functor_type::element2 (i, size1_, j, size2_)); -#endif #endif } BOOST_UBLAS_INLINE iterator1 find1 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, i, j); #else return iterator1 (*this, i, j, data () [functor_type::element1 (i, size1_, j, size2_)].begin () + functor_type::element2 (i, size1_, j, size2_)); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else return const_iterator2 (*this, i, j, data () [functor_type::element1 (i, size1_, j, size2_)].begin () + functor_type::element2 (i, size1_, j, size2_)); -#endif #endif } BOOST_UBLAS_INLINE iterator2 find2 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, i, j); #else return iterator2 (*this, i, j, data () [functor_type::element1 (i, size1_, j, size2_)].begin () + functor_type::element2 (i, size1_, j, size2_)); -#endif #endif } BOOST_UBLAS_INLINE @@ -1267,7 +1199,7 @@ namespace boost { namespace numeric { namespace ublas { // Iterators simply are pointers. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base::assign (&it ()); @@ -1943,7 +1875,7 @@ namespace boost { namespace numeric { namespace ublas { // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { - return i == j ? one_ : zero_; + return i == j ? one_ : zero_; } // Assignment @@ -1981,19 +1913,6 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_const_iterator iterator1; - typedef matrix_column_const_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_const_iterator1 iterator1; typedef indexed_const_iterator2 iterator2; @@ -2009,7 +1928,6 @@ namespace boost { namespace numeric { namespace ublas { #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup @@ -2017,46 +1935,30 @@ namespace boost { namespace numeric { namespace ublas { const_iterator1 find_first1 (int rank, size_type i, size_type j) const { if (rank == 1) i = std::max (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { - if (rank == 1) + if (rank == 1) i = std::min (i, j + 1); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { if (rank == 1) j = std::max (j, i); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { if (rank == 1) j = std::min (j, i + 1); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base iterator1; - typedef matrix_column_const_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_const_iterator1 iterator1; typedef indexed_const_iterator2 iterator2; @@ -2470,7 +2359,6 @@ namespace boost { namespace numeric { namespace ublas { #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup @@ -2478,46 +2366,30 @@ namespace boost { namespace numeric { namespace ublas { const_iterator1 find_first1 (int rank, size_type i, size_type j) const { if (rank == 1) i = std::max (i, size_type (0)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { if (rank == 1) i = std::min (i, size_type (0)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { if (rank == 1) j = std::max (j, size_type (0)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { if (rank == 1) j = std::min (j, size_type (0)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public bidirectional_iterator_base, public bidirectional_iterator_base iterator1; - typedef matrix_column_const_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_const_iterator1 iterator1; typedef indexed_const_iterator2 iterator2; @@ -2912,25 +2771,16 @@ namespace boost { namespace numeric { namespace ublas { #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { @@ -2951,7 +2801,7 @@ namespace boost { namespace numeric { namespace ublas { // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base - class c_matrix: + class c_matrix: public matrix_expression > { public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS @@ -3289,7 +3139,7 @@ namespace boost { namespace numeric { namespace ublas { // Raising exceptions abstracted as requested during review. // throw std::bad_alloc (); bad_size ().raise (); - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); } // Accessors @@ -3365,7 +3215,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE c_matrix &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -3382,7 +3232,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE c_matrix &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -3399,19 +3249,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE c_matrix &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE c_matrix& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE c_matrix& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -3456,23 +3306,6 @@ namespace boost { namespace numeric { namespace ublas { std::fill (data_ [i], data_ [i] + size2_, value_type ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -3494,56 +3327,39 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else return const_iterator1 (*this, &data_ [i] [j]); -#endif #endif } BOOST_UBLAS_INLINE iterator1 find1 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, i, j); #else return iterator1 (*this, &data_ [i] [j]); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else return const_iterator2 (*this, &data_ [i] [j]); -#endif #endif } BOOST_UBLAS_INLINE iterator2 find2 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, i, j); #else return iterator2 (*this, &data_ [i] [j]); -#endif #endif } BOOST_UBLAS_INLINE @@ -3581,7 +3397,7 @@ namespace boost { namespace numeric { namespace ublas { // Iterators simply are pointers. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base + BOOST_UBLAS_INLINE + void restart (const matrix_expression &e, typename E::size_type index1, typename E::size_type index2, + typename E::const_iterator1 &it1e, typename E::const_iterator1 &it1e_end, + typename E::const_iterator2 &it2e, typename E::const_iterator2 &it2e_end, row_major_tag) { + it1e = e ().find_first1 (0, index1, 0); + it1e_end = e ().find_last1 (0, e ().size1 (), 0); + it2e = e ().find_first2 (1, index1, index2); + it2e_end = e ().find_last2 (1, index1, e ().size2 ()); + if (it2e != it2e_end && it2e.index2 () == index2) + ++ it2e; + } + template + BOOST_UBLAS_INLINE + void restart (const matrix_expression &e, typename E::size_type index1, typename E::size_type index2, + typename E::const_iterator2 &it2e, typename E::const_iterator2 &it2e_end, + typename E::const_iterator1 &it1e, typename E::const_iterator1 &it1e_end, column_major_tag) { + it2e = e ().find_first2 (0, 0, index2); + it2e_end = e ().find_last2 (0, 0, e ().size2 ()); + it1e = e ().find_first1 (1, index1, index2); + it1e_end = e ().find_last1 (1, e ().size1 (), index2); + if (it1e != it1e_end && it1e.index1 () == index1) + ++ it1e; + } + template + BOOST_UBLAS_INLINE + void restart (matrix_expression &e, typename E::size_type index1, typename E::size_type index2, + typename E::iterator1 &it1e, typename E::iterator1 &it1e_end, + typename E::iterator2 &it2e, typename E::iterator2 &it2e_end, row_major_tag) { + it1e = e ().find_first1 (0, index1, 0); + it1e_end = e ().find_last1 (0, e ().size1 (), 0); + it2e = e ().find_first2 (1, index1, index2); + it2e_end = e ().find_last2 (1, index1, e ().size2 ()); + if (it2e != it2e_end && it2e.index2 () == index2) + ++ it2e; + } + template + BOOST_UBLAS_INLINE + void restart (matrix_expression &e, typename E::size_type index1, typename E::size_type index2, + typename E::iterator2 &it2e, typename E::iterator2 &it2e_end, + typename E::iterator1 &it1e, typename E::iterator1 &it1e_end, column_major_tag) { + it2e = e ().find_first2 (0, 0, index2); + it2e_end = e ().find_last2 (0, 0, e ().size2 ()); + it1e = e ().find_first1 (1, index1, index2); + it1e_end = e ().find_last1 (1, e ().size1 (), index2); + if (it1e != it1e_end && it1e.index1 () == index1) + ++ it1e; + } + // Iterating row major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE void iterating_matrix_assign_scalar (const F &f, M &m, const T &t, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::difference_type difference_type; - difference_type size1 (m.size1 ()); - difference_type size2 (m.size2 ()); - typename M::iterator1 it1 (m.begin1 ()); - BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ()); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - BOOST_UBLAS_CHECK ((*it1).end () - it2 == size2, bad_size ()); - difference_type temp_size2 (size2); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size2 >= 0) - functor_type () (*it2, t), ++ it2; -#else - DD (temp_size2, 4, r, (functor_type () (*it2, t), ++ it2)); -#endif - ++ it1; - } -#else typedef F functor_type; typedef typename M::difference_type difference_type; difference_type size1 (m.size1 ()); @@ -89,33 +118,12 @@ namespace boost { namespace numeric { namespace ublas { #endif ++ it1; } -#endif } // Iterating column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE void iterating_matrix_assign_scalar (const F &f, M &m, const T &t, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::difference_type difference_type; - difference_type size2 (m.size2 ()); - difference_type size1 (m.size1 ()); - typename M::iterator2 it2 (m.begin2 ()); - BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ()); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - BOOST_UBLAS_CHECK ((*it2).end () - it1 == size1, bad_size ()); - difference_type temp_size1 (size1); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size1 >= 0) - functor_type () (*it1, t), ++ it1; -#else - DD (temp_size1, 4, r, (functor_type () (*it1, t), ++ it1)); -#endif - ++ it2; - } -#else typedef F functor_type; typedef typename M::difference_type difference_type; difference_type size2 (m.size2 ()); @@ -134,7 +142,6 @@ namespace boost { namespace numeric { namespace ublas { #endif ++ it2; } -#endif } // Indexing row major case template @@ -179,7 +186,7 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign_scalar (const F &f, M &m, const T &t, dense_proxy_tag, C c) { + void matrix_assign_scalar (const F &f, M &m, const T &t, dense_proxy_tag, C c) { typedef F functor_type; typedef C orientation_category; #ifdef BOOST_UBLAS_USE_INDEXING @@ -201,20 +208,7 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign_scalar (const F &f, M &m, const T &t, packed_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::difference_type difference_type; - typename M::iterator1 it1 (m.begin1 ()); - difference_type size1 (m.end1 () - it1); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - difference_type size2 ((*it1).end () - it2); - while (-- size2 >= 0) - functor_type () (*it2, t), ++ it2; - ++ it1; - } -#else + void matrix_assign_scalar (const F &f, M &m, const T &t, packed_proxy_tag, row_major_tag) { typedef F functor_type; typedef typename M::difference_type difference_type; typename M::iterator1 it1 (m.begin1 ()); @@ -226,26 +220,12 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it2, t), ++ it2; ++ it1; } -#endif } // Packed (proxy) column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign_scalar (const F &f, M &m, const T &t, packed_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::difference_type difference_type; - typename M::iterator2 it2 (m.begin2 ()); - difference_type size2 (m.end2 () - it2); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - difference_type size1 ((*it2).end () - it1); - while (-- size1 >= 0) - functor_type () (*it1, t), ++ it1; - ++ it2; - } -#else + void matrix_assign_scalar (const F &f, M &m, const T &t, packed_proxy_tag, column_major_tag) { typedef F functor_type; typedef typename M::difference_type difference_type; typename M::iterator2 it2 (m.begin2 ()); @@ -257,25 +237,12 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it1, t), ++ it1; ++ it2; } -#endif } // Sparse (proxy) row major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign_scalar (const F &f, M &m, const T &t, sparse_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - while (it1 != it1_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) - functor_type () (*it2, t), ++ it2; - ++ it1; - } -#else + void matrix_assign_scalar (const F &f, M &m, const T &t, sparse_proxy_tag, row_major_tag) { typedef F functor_type; typename M::iterator1 it1 (m.begin1 ()); typename M::iterator1 it1_end (m.end1 ()); @@ -286,25 +253,12 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it2, t), ++ it2; ++ it1; } -#endif } // Sparse (proxy) column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign_scalar (const F &f, M &m, const T &t, sparse_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - while (it2 != it2_end) { - typename matrix_column::iterator1 it1 ((*it2).begin ()); - typename matrix_column::iterator1 it1_end ((*it2).end ()); - while (it1 != it1_end) - functor_type () (*it1, t), ++ it1; - ++ it2; - } -#else + void matrix_assign_scalar (const F &f, M &m, const T &t, sparse_proxy_tag, column_major_tag) { typedef F functor_type; typename M::iterator2 it2 (m.begin2 ()); typename M::iterator2 it2_end (m.end2 ()); @@ -315,288 +269,17 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it1, t), ++ it1; ++ it2; } -#endif } -#endif - // matrix assignment_operation scalar - template - struct matrix_assign_scalar { + // Dispatcher + template + BOOST_UBLAS_INLINE + void matrix_assign_scalar (const F &f, M &m, const T &t) { typedef F functor_type; - typedef typename F::assign_category assign_category; - -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - // Iterating row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void iterating_assign (M &m, const T &t, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::difference_type difference_type; - difference_type size1 (m.size1 ()); - difference_type size2 (m.size2 ()); - typename M::iterator1 it1 (m.begin1 ()); - BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ()); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - BOOST_UBLAS_CHECK ((*it1).end () - it2 == size2, bad_size ()); - difference_type temp_size2 (size2); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size2 >= 0) - functor_type () (*it2, t), ++ it2; -#else - DD (temp_size2, 4, r, (functor_type () (*it2, t), ++ it2)); -#endif - ++ it1; - } -#else - typedef typename M::difference_type difference_type; - difference_type size1 (m.size1 ()); - difference_type size2 (m.size2 ()); - typename M::iterator1 it1 (m.begin1 ()); - BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ()); - while (-- size1 >= 0) { - typename M::iterator2 it2 (it1.begin ()); - BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ()); - difference_type temp_size2 (size2); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size2 >= 0) - functor_type () (*it2, t), ++ it2; -#else - DD (temp_size2, 4, r, (functor_type () (*it2, t), ++ it2)); -#endif - ++ it1; - } -#endif - } - // Iterating column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void iterating_assign (M &m, const T &t, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::difference_type difference_type; - difference_type size2 (m.size2 ()); - difference_type size1 (m.size1 ()); - typename M::iterator2 it2 (m.begin2 ()); - BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ()); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - BOOST_UBLAS_CHECK ((*it2).end () - it1 == size1, bad_size ()); - difference_type temp_size1 (size1); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size1 >= 0) - functor_type () (*it1, t), ++ it1; -#else - DD (temp_size1, 4, r, (functor_type () (*it1, t), ++ it1)); -#endif - ++ it2; - } -#else - typedef typename M::difference_type difference_type; - difference_type size2 (m.size2 ()); - difference_type size1 (m.size1 ()); - typename M::iterator2 it2 (m.begin2 ()); - BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ()); - while (-- size2 >= 0) { - typename M::iterator1 it1 (it2.begin ()); - BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ()); - difference_type temp_size1 (size1); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size1 >= 0) - functor_type () (*it1, t), ++ it1; -#else - DD (temp_size1, 4, r, (functor_type () (*it1, t), ++ it1)); -#endif - ++ it2; - } -#endif - } - // Indexing row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void indexing_assign (M &m, const T &t, row_major_tag) { - typedef typename M::difference_type difference_type; - difference_type size1 (m.size1 ()); - difference_type size2 (m.size2 ()); - for (difference_type i = 0; i < size1; ++ i) { -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - for (difference_type j = 0; j < size2; ++ j) - functor_type () (m (i, j), t); -#else - difference_type j (0); - DD (size2, 4, r, (functor_type () (m (i, j), t), ++ j)); -#endif - } - } - // Indexing column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void indexing_assign (M &m, const T &t, column_major_tag) { - typedef typename M::difference_type difference_type; - difference_type size2 (m.size2 ()); - difference_type size1 (m.size1 ()); - for (difference_type j = 0; j < size2; ++ j) -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - for (difference_type i = 0; i < size1; ++ i) { - functor_type () (m (i, j), t); -#else - difference_type i (0); - DD (size1, 4, r, (functor_type () (m (i, j), t), ++ i)); -#endif - } - } - - // Dense (proxy) case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const T &t, dense_proxy_tag, C c) { - typedef C orientation_category; -#ifdef BOOST_UBLAS_USE_INDEXING - indexing_assign (m, t, orientation_category ()); -#elif BOOST_UBLAS_USE_ITERATING - iterating_assign (m, t, orientation_category ()); -#else - typedef typename M::difference_type difference_type; - difference_type size1 (m.size1 ()); - difference_type size2 (m.size2 ()); - if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD && - size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD) - iterating_assign (m, t, orientation_category ()); - else - indexing_assign (m, t, orientation_category ()); -#endif - } - // Packed (proxy) row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const T &t, packed_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::difference_type difference_type; - typename M::iterator1 it1 (m.begin1 ()); - difference_type size1 (m.end1 () - it1); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - difference_type size2 ((*it1).end () - it2); - while (-- size2 >= 0) - functor_type () (*it2, t), ++ it2; - ++ it1; - } -#else - typedef typename M::difference_type difference_type; - typename M::iterator1 it1 (m.begin1 ()); - difference_type size1 (m.end1 () - it1); - while (-- size1 >= 0) { - typename M::iterator2 it2 (it1.begin ()); - difference_type size2 (it1.end () - it2); - while (-- size2 >= 0) - functor_type () (*it2, t), ++ it2; - ++ it1; - } -#endif - } - // Packed (proxy) column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const T &t, packed_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::difference_type difference_type; - typename M::iterator2 it2 (m.begin2 ()); - difference_type size2 (m.end2 () - it2); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - difference_type size1 ((*it2).end () - it1); - while (-- size1 >= 0) - functor_type () (*it1, t), ++ it1; - ++ it2; - } -#else - typedef typename M::difference_type difference_type; - typename M::iterator2 it2 (m.begin2 ()); - difference_type size2 (m.end2 () - it2); - while (-- size2 >= 0) { - typename M::iterator1 it1 (it2.begin ()); - difference_type size1 (it2.end () - it1); - while (-- size1 >= 0) - functor_type () (*it1, t), ++ it1; - ++ it2; - } -#endif - } - // Sparse (proxy) row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const T &t, sparse_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - while (it1 != it1_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) - functor_type () (*it2, t), ++ it2; - ++ it1; - } -#else - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - while (it1 != it1_end) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - while (it2 != it2_end) - functor_type () (*it2, t), ++ it2; - ++ it1; - } -#endif - } - // Sparse (proxy) column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const T &t, sparse_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - while (it2 != it2_end) { - typename matrix_column::iterator1 it1 ((*it2).begin ()); - typename matrix_column::iterator1 it1_end ((*it2).end ()); - while (it1 != it1_end) - functor_type () (*it1, t), ++ it1; - ++ it2; - } -#else - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - while (it2 != it2_end) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - while (it1 != it1_end) - functor_type () (*it1, t), ++ it1; - ++ it2; - } -#endif - } -#endif - - // Dispatcher - template - BOOST_UBLAS_INLINE - void operator () (M &m, const T &t) { - typedef typename M::storage_category storage_category; - typedef typename M::orientation_category orientation_category; -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - operator () (m, t, storage_category (), orientation_category ()); -#else - evaluate_matrix_assign_scalar (functor_type (), m, t, storage_category (), orientation_category ()); -#endif - } - }; + typedef typename M::storage_category storage_category; + typedef typename M::orientation_category orientation_category; + matrix_assign_scalar (functor_type (), m, t, storage_category (), orientation_category ()); + } template struct matrix_assign_traits { @@ -668,36 +351,11 @@ namespace boost { namespace numeric { namespace ublas { typedef sparse_proxy_tag storage_category; }; -#ifdef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN // Iterating row major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE void iterating_matrix_assign (const F &f, M &m, const matrix_expression &e, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::difference_type difference_type; - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); - typename M::iterator1 it1 (m.begin1 ()); - BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ()); - typename E::const_iterator1 it1e (e ().begin1 ()); - BOOST_UBLAS_CHECK (size2 == 0 || e ().end1 () - it1e == size1, bad_size ()); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - BOOST_UBLAS_CHECK ((*it1).end () - it2 == size2, bad_size ()); - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - BOOST_UBLAS_CHECK ((*it1e).end () - it2e == size2, bad_size ()); - difference_type temp_size2 (size2); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size2 >= 0) - functor_type () (*it2, *it2e), ++ it2, ++ it2e; -#else - DD (temp_size2, 2, r, (functor_type () (*it2, *it2e), ++ it2, ++ it2e)); -#endif - ++ it1, ++ it1e; - } -#else typedef F functor_type; typedef typename M::difference_type difference_type; difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); @@ -720,37 +378,12 @@ namespace boost { namespace numeric { namespace ublas { #endif ++ it1, ++ it1e; } -#endif } // Iterating column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE void iterating_matrix_assign (const F &f, M &m, const matrix_expression &e, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::difference_type difference_type; - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); - typename M::iterator2 it2 (m.begin2 ()); - BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ()); - typename E::const_iterator2 it2e (e ().begin2 ()); - BOOST_UBLAS_CHECK (size1 == 0 || e ().end2 () - it2e == size2, bad_size ()); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - BOOST_UBLAS_CHECK ((*it2).end () - it1 == size1, bad_size ()); - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - BOOST_UBLAS_CHECK ((*it2e).end () - it1e == size1, bad_size ()); - difference_type temp_size1 (size1); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size1 >= 0) - functor_type () (*it1, *it1e), ++ it1, ++ it1e; -#else - DD (temp_size1, 2, r, (functor_type () (*it1, *it1e), ++ it1, ++ it1e)); -#endif - ++ it2, ++ it2e; - } -#else typedef F functor_type; typedef typename M::difference_type difference_type; difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); @@ -773,7 +406,6 @@ namespace boost { namespace numeric { namespace ublas { #endif ++ it2, ++ it2e; } -#endif } // Indexing row major case template @@ -818,7 +450,7 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign (const F &f, M &m, const matrix_expression &e, dense_proxy_tag, C c) { + void matrix_assign (const F &f, M &m, const matrix_expression &e, dense_proxy_tag, C c) { typedef F functor_type; typedef C orientation_category; #ifdef BOOST_UBLAS_USE_INDEXING @@ -840,67 +472,7 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign (const F &f, M &m, const matrix_expression &e, packed_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - typedef F functor_type; - typedef typename M::size_type size_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, row_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, row_major_tag ()); -#endif - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - typename E::const_iterator1 it1e (e ().begin1 ()); - typename E::const_iterator1 it1e_end (e ().end1 ()); - if (it1e != it1e_end && it1e.index () < it1.index ()) - it1e += std::min (it1.index () - it1e.index (), size_type (it1e_end - it1e)); - while (it1 != it1_end && it1e != it1e_end && it1.index () < it1e.index ()) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } - while (it1 != it1_end && it1e != it1e_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - if (it2e != it2e_end && it2e.index2 () < it2.index2 ()) - it2e += std::min (it2.index2 () - it2e.index2 () <= size_type (it2e_end - it2e)); - while (it2 != it2_end && it2e != it2e_end && it2.index () < it2e.index ()) { - functor_type () (*it2, value_type ()); - ++ it2; - } - while (it2 != it2_end && it2e != it2e_end) { - functor_type () (*it2, *it2e); - ++ it2, ++ it2e; - } - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1, ++ it1e; - } - while (it1 != it1_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else + void matrix_assign (const F &f, M &m, const matrix_expression &e, packed_proxy_tag, row_major_tag) { BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); typedef F functor_type; @@ -958,74 +530,13 @@ namespace boost { namespace numeric { namespace ublas { } #ifdef BOOST_UBLAS_TYPE_CHECK BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif #endif } // Packed (proxy) column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign (const F &f, M &m, const matrix_expression &e, packed_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (m.size3 () == e ().size2 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - typedef F functor_type; - typedef typename M::size_type size_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, column_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, column_major_tag ()); -#endif - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - typename E::const_iterator2 it2e (e ().begin2 ()); - typename E::const_iterator2 it2e_end (e ().end2 ()); - if (it2e != it2e_end && it2e.index () < it2.index ()) - it2e += std::min (it2.index () - it2e.index (), size_type (it2e_end - it2e)); - while (it2 != it2_end && it2e != it2e_end && it2.index () < it2e.index ()) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } - while (it2 != it2_end && it2e != it2e_end) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - if (it1e != it1e_end && it1e.index1 () < it1.index1 ()) - it1e += std::min (it1.index1 () - it1e.index1 () <= size_type (it1e_end - it1e)); - while (it1 != it1_end && it1e != it1e_end && it1.index () < it1e.index ()) { - functor_type () (*it1, value_type ()); - ++ it1; - } - while (it1 != it1_end && it1e != it1e_end) { - functor_type () (*it1, *it1e); - ++ it1, ++ it1e; - } - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2, ++ it2e; - } - while (it2 != it2_end) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else + void matrix_assign (const F &f, M &m, const matrix_expression &e, packed_proxy_tag, column_major_tag) { BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); typedef F functor_type; @@ -1083,42 +594,13 @@ namespace boost { namespace numeric { namespace ublas { } #ifdef BOOST_UBLAS_TYPE_CHECK BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif #endif } // Sparse row major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign (const F &f, M &m, const matrix_expression &e, sparse_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - typedef F functor_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, row_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, row_major_tag ()); -#endif - m.clear (); - typename E::const_iterator1 it1e (e ().begin1 ()); - typename E::const_iterator1 it1e_end (e ().end1 ()); - while (it1e != it1e_end) { - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - while (it2e != it2e_end) { - value_type t (*it2e); - if (t != value_type ()) - m.insert (it1e.index (), it2e.index (), t); - ++ it2e; - } - ++ it1e; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else + void matrix_assign (const F &f, M &m, const matrix_expression &e, sparse_tag, row_major_tag) { BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); typedef F functor_type; @@ -1144,42 +626,13 @@ namespace boost { namespace numeric { namespace ublas { } #ifdef BOOST_UBLAS_TYPE_CHECK BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif #endif } // Sparse column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign (const F &f, M &m, const matrix_expression &e, sparse_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - typedef F functor_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, column_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, column_major_tag ()); -#endif - m.clear (); - typename E::const_iterator2 it2e (e ().begin2 ()); - typename E::const_iterator2 it2e_end (e ().end2 ()); - while (it2e != it2e_end) { - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - while (it1e != it1e_end) { - value_type t (*it1e); - if (t != value_type ()) - m.insert (it1e.index (), it2e.index (), t); - ++ it1e; - } - ++ it2e; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else + void matrix_assign (const F &f, M &m, const matrix_expression &e, sparse_tag, column_major_tag) { BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); typedef F functor_type; @@ -1205,80 +658,17 @@ namespace boost { namespace numeric { namespace ublas { } #ifdef BOOST_UBLAS_TYPE_CHECK BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif #endif } // Sparse proxy row major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign (const F &f, M &m, const matrix_expression &e, sparse_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - typedef F functor_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, row_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, row_major_tag ()); -#endif - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - typename E::const_iterator1 it1e (e ().begin1 ()); - typename E::const_iterator1 it1e_end (e ().end1 ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index () - it1e.index (); - if (compare == 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index () - it2e.index (); - if (compare == 0) { - functor_type () (*it2, *it2e); - ++ it2, ++ it2e; - } else if (compare < 0) { - functor_type () (*it2, value_type ()); - ++ it2; - } else if (compare > 0) { - ++ it2e; - } - } - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1, ++ it1e; - } else if (compare < 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } else if (compare > 0) { - ++ it1e; - } - } - while (it1 != it1_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else + void matrix_assign (const F &f, M &m, const matrix_expression &e, sparse_proxy_tag, row_major_tag) { BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); typedef F functor_type; + typedef typename M::size_type size_type; typedef typename M::value_type value_type; #ifdef BOOST_UBLAS_TYPE_CHECK matrix cm (m.size1 (), m.size2 ()); @@ -1305,9 +695,23 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it2, value_type ()); ++ it2; } else if (compare > 0) { - ++ it2e; + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2e.index1 ()), index2 (it2e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + restart (m, index1, index2, it1, it1_end, it2, it2_end, row_major_tag ()); + // The proxies could reference the same container. + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); } } + while (it2e != it2e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2e.index1 ()), index2 (it2e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); + } while (it2 != it2_end) { functor_type () (*it2, value_type ()); ++ it2; @@ -1322,9 +726,32 @@ namespace boost { namespace numeric { namespace ublas { } ++ it1; } else if (compare > 0) { + typename E::const_iterator2 it2e (it1e.begin ()); + typename E::const_iterator2 it2e_end (it1e.end ()); + while (it2e != it2e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2e.index1 ()), index2 (it2e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); + } ++ it1e; } } + while (it1e != it1e_end) { + typename E::const_iterator2 it2e (it1e.begin ()); + typename E::const_iterator2 it2e_end (it1e.end ()); + while (it2e != it2e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2e.index1 ()), index2 (it2e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); + } + ++ it1e; + } while (it1 != it1_end) { typename M::iterator2 it2 (it1.begin ()); typename M::iterator2 it2_end (it1.end ()); @@ -1336,83 +763,20 @@ namespace boost { namespace numeric { namespace ublas { } #ifdef BOOST_UBLAS_TYPE_CHECK BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif #endif } // Sparse proxy column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_assign (const F &f, M &m, const matrix_expression &e, sparse_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR + void matrix_assign (const F &f, M &m, const matrix_expression &e, sparse_proxy_tag, column_major_tag) { BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); typedef F functor_type; + typedef typename M::size_type size_type; typedef typename M::value_type value_type; #ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, column_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, column_major_tag ()); -#endif - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - typename E::const_iterator2 it2e (e ().begin2 ()); - typename E::const_iterator2 it2e_end (e ().end2 ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index () - it2e.index (); - if (compare == 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index () - it1e.index (); - if (compare == 0) { - functor_type () (*it1, *it1e); - ++ it1, ++ it1e; - } else if (compare < 0) { - functor_type () (*it1, value_type ()); - ++ it1; - } else if (compare > 0) { - ++ it1e; - } - } - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2, ++ it2e; - } else if (compare < 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } else if (compare > 0) { - ++ it2e; - } - } - while (it2 != it2_end) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - typedef F functor_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); + matrix cm (m.size1 (), m.size2 ()); indexing_matrix_assign (scalar_assign (), cm, m, column_major_tag ()); indexing_matrix_assign (functor_type (), cm, e, column_major_tag ()); #endif @@ -1436,9 +800,23 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it1, value_type ()); ++ it1; } else if (compare > 0) { - ++ it1e; + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1e.index1 ()), index2 (it1e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + restart (m, index1, index2, it2, it2_end, it1, it1_end, column_major_tag ()); + // The proxies could reference the same container. + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag ()); } } + while (it1e != it1e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1e.index1 ()), index2 (it1e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag ()); + } while (it1 != it1_end) { functor_type () (*it1, value_type ()); ++ it1; @@ -1453,9 +831,32 @@ namespace boost { namespace numeric { namespace ublas { } ++ it2; } else if (compare > 0) { + typename E::const_iterator1 it1e (it2e.begin ()); + typename E::const_iterator1 it1e_end (it2e.end ()); + while (it1e != it1e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1e.index1 ()), index2 (it1e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag ()); + } ++ it2e; } } + while (it2e != it2e_end) { + typename E::const_iterator1 it1e (it2e.begin ()); + typename E::const_iterator1 it1e_end (it2e.end ()); + while (it1e != it1e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1e.index1 ()), index2 (it1e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag ()); + } + ++ it2e; + } while (it2 != it2_end) { typename M::iterator1 it1 (it2.begin ()); typename M::iterator1 it1_end (it2.end ()); @@ -1467,820 +868,23 @@ namespace boost { namespace numeric { namespace ublas { } #ifdef BOOST_UBLAS_TYPE_CHECK BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif #endif } -#endif - // matrix assignment_operation matrix_expression - template - struct matrix_assign { + // Dispatcher + template + BOOST_UBLAS_INLINE + void matrix_assign (const F &f, M &m, const matrix_expression &e) { typedef F functor_type; - typedef typename F::assign_category assign_category; - -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - // Iterating row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void iterating_assign (M &m, const matrix_expression &e, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::difference_type difference_type; - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); - typename M::iterator1 it1 (m.begin1 ()); - BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ()); - typename E::const_iterator1 it1e (e ().begin1 ()); - BOOST_UBLAS_CHECK (size2 == 0 || e ().end1 () - it1e == size1, bad_size ()); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - BOOST_UBLAS_CHECK ((*it1).end () - it2 == size2, bad_size ()); - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - BOOST_UBLAS_CHECK ((*it1e).end () - it2e == size2, bad_size ()); - difference_type temp_size2 (size2); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size2 >= 0) - functor_type () (*it2, *it2e), ++ it2, ++ it2e; -#else - DD (temp_size2, 2, r, (functor_type () (*it2, *it2e), ++ it2, ++ it2e)); -#endif - ++ it1, ++ it1e; - } -#else - typedef typename M::difference_type difference_type; - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); - typename M::iterator1 it1 (m.begin1 ()); - BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ()); - typename E::const_iterator1 it1e (e ().begin1 ()); - BOOST_UBLAS_CHECK (size2 == 0 || e ().end1 () - it1e == size1, bad_size ()); - while (-- size1 >= 0) { - typename M::iterator2 it2 (it1.begin ()); - BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ()); - typename E::const_iterator2 it2e (it1e.begin ()); - BOOST_UBLAS_CHECK (it1e.end () - it2e == size2, bad_size ()); - difference_type temp_size2 (size2); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size2 >= 0) - functor_type () (*it2, *it2e), ++ it2, ++ it2e; -#else - DD (temp_size2, 2, r, (functor_type () (*it2, *it2e), ++ it2, ++ it2e)); -#endif - ++ it1, ++ it1e; - } -#endif - } - // Iterating column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void iterating_assign (M &m, const matrix_expression &e, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::difference_type difference_type; - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); - typename M::iterator2 it2 (m.begin2 ()); - BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ()); - typename E::const_iterator2 it2e (e ().begin2 ()); - BOOST_UBLAS_CHECK (size1 == 0 || e ().end2 () - it2e == size2, bad_size ()); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - BOOST_UBLAS_CHECK ((*it2).end () - it1 == size1, bad_size ()); - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - BOOST_UBLAS_CHECK ((*it2e).end () - it1e == size1, bad_size ()); - difference_type temp_size1 (size1); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size1 >= 0) - functor_type () (*it1, *it1e), ++ it1, ++ it1e; -#else - DD (temp_size1, 2, r, (functor_type () (*it1, *it1e), ++ it1, ++ it1e)); -#endif - ++ it2, ++ it2e; - } -#else - typedef typename M::difference_type difference_type; - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); - typename M::iterator2 it2 (m.begin2 ()); - BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ()); - typename E::const_iterator2 it2e (e ().begin2 ()); - BOOST_UBLAS_CHECK (size1 == 0 || e ().end2 () - it2e == size2, bad_size ()); - while (-- size2 >= 0) { - typename M::iterator1 it1 (it2.begin ()); - BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ()); - typename E::const_iterator1 it1e (it2e.begin ()); - BOOST_UBLAS_CHECK (it2e.end () - it1e == size1, bad_size ()); - difference_type temp_size1 (size1); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- temp_size1 >= 0) - functor_type () (*it1, *it1e), ++ it1, ++ it1e; -#else - DD (temp_size1, 2, r, (functor_type () (*it1, *it1e), ++ it1, ++ it1e)); -#endif - ++ it2, ++ it2e; - } -#endif - } - // Indexing row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void indexing_assign (M &m, const matrix_expression &e, row_major_tag) { - typedef typename M::difference_type difference_type; - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); - for (difference_type i = 0; i < size1; ++ i) { -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - for (difference_type j = 0; j < size2; ++ j) - functor_type () (m (i, j), e () (i, j)); -#else - difference_type j (0); - DD (size2, 2, r, (functor_type () (m (i, j), e () (i, j)), ++ j)); -#endif - } - } - // Indexing column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void indexing_assign (M &m, const matrix_expression &e, column_major_tag) { - typedef typename M::difference_type difference_type; - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); - for (difference_type j = 0; j < size2; ++ j) -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - for (difference_type i = 0; i < size1; ++ i) { - functor_type () (m (i, j), e () (i, j)); -#else - difference_type i (0); - DD (size1, 2, r, (functor_type () (m (i, j), e () (i, j)), ++ i)); -#endif - } - } - - // Dense (proxy) case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const matrix_expression &e, dense_proxy_tag, C c) { - typedef C orientation_category; -#ifdef BOOST_UBLAS_USE_INDEXING - indexing_assign (m, e, orientation_category ()); -#elif BOOST_UBLAS_USE_ITERATING - iterating_assign (m, e, orientation_category ()); -#else - typedef typename M::difference_type difference_type; - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ())); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ())); - if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD && - size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD) - iterating_assign (m, e, orientation_category ()); - else - indexing_assign (m, e, orientation_category ()); -#endif - } - // Packed (proxy) row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const matrix_expression &e, packed_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - typedef typename M::size_type size_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - matrix_assign > ().indexing_assign (cm, m, row_major_tag ()); - matrix_assign ().indexing_assign (cm, e, row_major_tag ()); -#endif - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - typename E::const_iterator1 it1e (e ().begin1 ()); - typename E::const_iterator1 it1e_end (e ().end1 ()); - if (it1e != it1e_end && it1e.index () < it1.index ()) - it1e += std::min (it1.index () - it1e.index (), size_type (it1e_end - it1e)); - while (it1 != it1_end && it1e != it1e_end && it1.index () < it1e.index ()) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } - while (it1 != it1_end && it1e != it1e_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - if (it2e != it2e_end && it2e.index2 () < it2.index2 ()) - it2e += std::min (it2.index2 () - it2e.index2 () <= size_type (it2e_end - it2e)); - while (it2 != it2_end && it2e != it2e_end && it2.index () < it2e.index ()) { - functor_type () (*it2, value_type ()); - ++ it2; - } - while (it2 != it2_end && it2e != it2e_end) { - functor_type () (*it2, *it2e); - ++ it2, ++ it2e; - } - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1, ++ it1e; - } - while (it1 != it1_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - typedef typename M::size_type size_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - matrix_assign > ().indexing_assign (cm, m, row_major_tag ()); - matrix_assign ().indexing_assign (cm, e, row_major_tag ()); -#endif - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - typename E::const_iterator1 it1e (e ().begin1 ()); - typename E::const_iterator1 it1e_end (e ().end1 ()); - if (it1e != it1e_end && it1e.index1 () < it1.index1 ()) - it1e += std::min (it1.index1 () - it1e.index1 (), size_type (it1e_end - it1e)); - while (it1 != it1_end && it1e != it1e_end && it1.index1 () < it1e.index1 ()) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } - while (it1 != it1_end && it1e != it1e_end) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - typename E::const_iterator2 it2e (it1e.begin ()); - typename E::const_iterator2 it2e_end (it1e.end ()); - if (it2e != it2e_end && it2e.index2 () < it2.index2 ()) - it2e += std::min (it2.index2 () - it2e.index2 (), size_type (it2e_end - it2e)); - while (it2 != it2_end && it2e != it2e_end && it2.index2 () < it2e.index2 ()) { - functor_type () (*it2, value_type ()); - ++ it2; - } - while (it2 != it2_end && it2e != it2e_end) { - functor_type () (*it2, *it2e); - ++ it2, ++ it2e; - } - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1, ++ it1e; - } - while (it1 != it1_end) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#endif - } - // Packed (proxy) column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const matrix_expression &e, packed_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (m.size3 () == e ().size2 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - typedef typename M::size_type size_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - matrix_assign > ().indexing_assign (cm, m, column_major_tag ()); - matrix_assign ().indexing_assign (cm, e, column_major_tag ()); -#endif - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - typename E::const_iterator2 it2e (e ().begin2 ()); - typename E::const_iterator2 it2e_end (e ().end2 ()); - if (it2e != it2e_end && it2e.index () < it2.index ()) - it2e += std::min (it2.index () - it2e.index (), size_type (it2e_end - it2e)); - while (it2 != it2_end && it2e != it2e_end && it2.index () < it2e.index ()) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } - while (it2 != it2_end && it2e != it2e_end) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - if (it1e != it1e_end && it1e.index1 () < it1.index1 ()) - it1e += std::min (it1.index1 () - it1e.index1 () <= size_type (it1e_end - it1e)); - while (it1 != it1_end && it1e != it1e_end && it1.index () < it1e.index ()) { - functor_type () (*it1, value_type ()); - ++ it1; - } - while (it1 != it1_end && it1e != it1e_end) { - functor_type () (*it1, *it1e); - ++ it1, ++ it1e; - } - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2, ++ it2e; - } - while (it2 != it2_end) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - typedef typename M::size_type size_type; - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - matrix_assign > ().indexing_assign (cm, m, column_major_tag ()); - matrix_assign ().indexing_assign (cm, e, column_major_tag ()); -#endif - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - typename E::const_iterator2 it2e (e ().begin2 ()); - typename E::const_iterator2 it2e_end (e ().end2 ()); - if (it2e != it2e_end && it2e.index2 () < it2.index2 ()) - it2e += std::min (it2.index2 () - it2e.index2 (), size_type (it2e_end - it2e)); - while (it2 != it2_end && it2e != it2e_end && it2.index2 () < it2e.index2 ()) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } - while (it2 != it2_end && it2e != it2e_end) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - typename E::const_iterator1 it1e (it2e.begin ()); - typename E::const_iterator1 it1e_end (it2e.end ()); - if (it1e != it1e_end && it1e.index1 () < it1.index1 ()) - it1e += std::min (it1.index1 () - it1e.index1 (), size_type (it1e_end - it1e)); - while (it1 != it1_end && it1e != it1e_end && it1.index1 () < it1e.index1 ()) { - functor_type () (*it1, value_type ()); - ++ it1; - } - while (it1 != it1_end && it1e != it1e_end) { - functor_type () (*it1, *it1e); - ++ it1, ++ it1e; - } - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2, ++ it2e; - } - while (it2 != it2_end) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#endif - } - // Sparse row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const matrix_expression &e, sparse_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, row_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, row_major_tag ()); -#endif - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - m.clear (); - typename E::const_iterator1 it1e (e ().begin1 ()); - typename E::const_iterator1 it1e_end (e ().end1 ()); - while (it1e != it1e_end) { - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - while (it2e != it2e_end) { - value_type t (*it2e); - if (t != value_type ()) - m.insert (it1e.index (), it2e.index (), t); - ++ it2e; - } - ++ it1e; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, row_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, row_major_tag ()); -#endif - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - m.clear (); - typename E::const_iterator1 it1e (e ().begin1 ()); - typename E::const_iterator1 it1e_end (e ().end1 ()); - while (it1e != it1e_end) { - typename E::const_iterator2 it2e (it1e.begin ()); - typename E::const_iterator2 it2e_end (it1e.end ()); - while (it2e != it2e_end) { - value_type t (*it2e); - if (t != value_type ()) - m.insert (it2e.index1 (), it2e.index2 (), t); - ++ it2e; - } - ++ it1e; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#endif - } - // Sparse column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const matrix_expression &e, sparse_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, column_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, column_major_tag ()); -#endif - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - m.clear (); - typename E::const_iterator2 it2e (e ().begin2 ()); - typename E::const_iterator2 it2e_end (e ().end2 ()); - while (it2e != it2e_end) { - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - while (it1e != it1e_end) { - value_type t (*it1e); - if (t != value_type ()) - m.insert (it1e.index (), it2e.index (), t); - ++ it1e; - } - ++ it2e; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else - typedef typename M::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - indexing_matrix_assign (scalar_assign (), cm, m, column_major_tag ()); - indexing_matrix_assign (functor_type (), cm, e, column_major_tag ()); -#endif - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - m.clear (); - typename E::const_iterator2 it2e (e ().begin2 ()); - typename E::const_iterator2 it2e_end (e ().end2 ()); - while (it2e != it2e_end) { - typename E::const_iterator1 it1e (it2e.begin ()); - typename E::const_iterator1 it1e_end (it2e.end ()); - while (it1e != it1e_end) { - value_type t (*it1e); - if (t != value_type ()) - m.insert (it1e.index1 (), it1e.index2 (), t); - ++ it1e; - } - ++ it2e; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#endif - } - // Sparse proxy row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const matrix_expression &e, sparse_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - 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; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - matrix_assign > ().indexing_assign (cm, m, row_major_tag ()); - matrix_assign ().indexing_assign (cm, e, row_major_tag ()); -#endif - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - typename E::const_iterator1 it1e (e ().begin1 ()); - typename E::const_iterator1 it1e_end (e ().end1 ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index () - it1e.index (); - if (compare == 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index () - it2e.index (); - if (compare == 0) { - functor_type () (*it2, *it2e); - ++ it2, ++ it2e; - } else if (compare < 0) { - functor_type () (*it2, value_type ()); - ++ it2; - } else if (compare > 0) { - ++ it2e; - } - } - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1, ++ it1e; - } else if (compare < 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } else if (compare > 0) { - ++ it1e; - } - } - while (it1 != it1_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else - 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; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - matrix_assign > ().indexing_assign (cm, m, row_major_tag ()); - matrix_assign ().indexing_assign (cm, e, row_major_tag ()); -#endif - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - typename E::const_iterator1 it1e (e ().begin1 ()); - typename E::const_iterator1 it1e_end (e ().end1 ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index1 () - it1e.index1 (); - if (compare == 0) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - typename E::const_iterator2 it2e (it1e.begin ()); - typename E::const_iterator2 it2e_end (it1e.end ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index2 () - it2e.index2 (); - if (compare == 0) { - functor_type () (*it2, *it2e); - ++ it2, ++ it2e; - } else if (compare < 0) { - functor_type () (*it2, value_type ()); - ++ it2; - } else if (compare > 0) { - ++ it2e; - } - } - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1, ++ it1e; - } else if (compare < 0) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } else if (compare > 0) { - ++ it1e; - } - } - while (it1 != it1_end) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - while (it2 != it2_end) { - functor_type () (*it2, value_type ()); - ++ it2; - } - ++ it1; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#endif - } - // Sparse proxy column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, const matrix_expression &e, sparse_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - 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; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - matrix_assign > ().indexing_assign (cm, m, column_major_tag ()); - matrix_assign ().indexing_assign (cm, e, column_major_tag ()); -#endif - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - typename E::const_iterator2 it2e (e ().begin2 ()); - typename E::const_iterator2 it2e_end (e ().end2 ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index () - it2e.index (); - if (compare == 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index () - it1e.index (); - if (compare == 0) { - functor_type () (*it1, *it1e); - ++ it1, ++ it1e; - } else if (compare < 0) { - functor_type () (*it1, value_type ()); - ++ it1; - } else if (compare > 0) { - ++ it1e; - } - } - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2, ++ it2e; - } else if (compare < 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } else if (compare > 0) { - ++ it2e; - } - } - while (it2 != it2_end) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#else - 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; -#ifdef BOOST_UBLAS_TYPE_CHECK - matrix cm (m.size1 (), m.size2 ()); - matrix_assign > ().indexing_assign (cm, m, column_major_tag ()); - matrix_assign ().indexing_assign (cm, e, column_major_tag ()); -#endif - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - typename E::const_iterator2 it2e (e ().begin2 ()); - typename E::const_iterator2 it2e_end (e ().end2 ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index2 () - it2e.index2 (); - if (compare == 0) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - typename E::const_iterator1 it1e (it2e.begin ()); - typename E::const_iterator1 it1e_end (it2e.end ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index1 () - it1e.index1 (); - if (compare == 0) { - functor_type () (*it1, *it1e); - ++ it1, ++ it1e; - } else if (compare < 0) { - functor_type () (*it1, value_type ()); - ++ it1; - } else if (compare > 0) { - ++ it1e; - } - } - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2, ++ it2e; - } else if (compare < 0) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } else if (compare > 0) { - ++ it2e; - } - } - while (it2 != it2_end) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - while (it1 != it1_end) { - functor_type () (*it1, value_type ()); - ++ it1; - } - ++ it2; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (m, cm), external_logic ()); -#endif -#endif - } -#endif - - // Dispatcher - template - BOOST_UBLAS_INLINE - void operator () (M &m, const matrix_expression &e) { - typedef typename matrix_assign_traits::storage_category storage_category; - // FIXME: can't we improve the dispatch here? - // typedef typename E::orientation_category orientation_category; - typedef typename M::orientation_category orientation_category; -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - operator () (m, e, storage_category (), orientation_category ()); -#else - evaluate_matrix_assign (functor_type (), m, e, storage_category (), orientation_category ()); -#endif - } - }; + typedef typename matrix_assign_traits::storage_category storage_category; + // FIXME: can't we improve the dispatch here? + // typedef typename E::orientation_category orientation_category; + typedef typename M::orientation_category orientation_category; + matrix_assign (functor_type (), m, e, storage_category (), orientation_category ()); + } template struct matrix_swap_traits { @@ -2297,28 +901,11 @@ namespace boost { namespace numeric { namespace ublas { typedef sparse_proxy_tag storage_category; }; -#ifdef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN // Dense (proxy) row major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_swap (const F &f, M &m, matrix_expression &e, dense_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator1 it1 (m.begin1 ()); - typename E::iterator1 it1e (e ().begin1 ()); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (e ().end1 () - it1e))); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2e ((*it1e).begin ()); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type ((*it1e).end () - it2e))); - while (-- size2 >= 0) - functor_type () (*it2, *it2e), ++ it2, ++ it2e; - ++ it1, ++ it1e; - } -#else + void matrix_swap (const F &f, M &m, matrix_expression &e, dense_proxy_tag, row_major_tag) { typedef F functor_type; typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; @@ -2333,29 +920,12 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it2, *it2e), ++ it2, ++ it2e; ++ it1, ++ it1e; } -#endif } // Dense (proxy) column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_swap (const F &f, M &m, matrix_expression &e, dense_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator2 it2 (m.begin2 ()); - typename E::iterator2 it2e (e ().begin2 ()); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (e ().end2 () - it2e))); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1e ((*it2e).begin ()); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type ((*it2e).end () - it1e))); - while (-- size1 >= 0) - functor_type () (*it1, *it1e), ++ it1, ++ it1e; - ++ it2, ++ it2e; - } -#else + void matrix_swap (const F &f, M &m, matrix_expression &e, dense_proxy_tag, column_major_tag) { typedef F functor_type; typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; @@ -2370,29 +940,12 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it1, *it1e), ++ it1, ++ it1e; ++ it2, ++ it2e; } -#endif } // Packed (proxy) row major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_swap (const F &f, M &m, matrix_expression &e, packed_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator1 it1 (m.begin1 ()); - typename E::iterator1 it1e (e ().begin1 ()); - difference_type size1 (BOOST_UBLAS_SAME (m.end1 () - it1, e ().end1 () - it1e)); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2e ((*it1e).begin ()); - difference_type size2 (BOOST_UBLAS_SAME ((*it1).end () - it2, (*it1e).end () - it2e)); - while (-- size2 >= 0) - functor_type () (*it2, *it2e), ++ it2, ++ it2e; - ++ it1, ++ it1e; - } -#else + void matrix_swap (const F &f, M &m, matrix_expression &e, packed_proxy_tag, row_major_tag) { typedef F functor_type; typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; @@ -2407,29 +960,12 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it2, *it2e), ++ it2, ++ it2e; ++ it1, ++ it1e; } -#endif } // Packed (proxy) column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_swap (const F &f, M &m, matrix_expression &e, packed_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef F functor_type; - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator2 it2 (m.begin2 ()); - typename E::iterator2 it2e (e ().begin2 ()); - difference_type size2 (BOOST_UBLAS_SAME (m.end2 () - it2, e ().end2 () - it2e)); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1e ((*it2e).begin ()); - difference_type size1 (BOOST_UBLAS_SAME ((*it2).end () - it1, (*it2e).end () - it1e)); - while (-- size1 >= 0) - functor_type () (*it1, *it1e), ++ it1, ++ it1e; - ++ it2, ++ it2e; - } -#else + void matrix_swap (const F &f, M &m, matrix_expression &e, packed_proxy_tag, column_major_tag) { typedef F functor_type; typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; @@ -2444,90 +980,16 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it1, *it1e), ++ it1, ++ it1e; ++ it2, ++ it2e; } -#endif } // Sparse (proxy) row major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_swap (const F &f, M &m, matrix_expression &e, sparse_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - typedef F functor_type; - typedef typename M::value_type value_type; - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - typename E::iterator1 it1e (e ().begin1 ()); - typename E::iterator1 it1e_end (e ().end1 ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index () - it1e.index (); - if (compare == 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - typename matrix_row::iterator it2e ((*it1e).begin ()); - typename matrix_row::iterator it2e_end ((*it1e).end ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index () - it2e.index (); - if (compare == 0) { - functor_type () (*it2, *it2e); - ++ it2, ++ it2e; - } else { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - } - if (it2 != it2_end || it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1, ++ it1e; - } else if (compare < 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - if (it2 != it2_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1; - } else if (compare > 0) { - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - if (it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1e; - } - } - while (it1 != it1_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - if (it2 != it2_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1; - } - while (it1e != it1e_end) { - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - if (it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1e; - } -#else + void matrix_swap (const F &f, M &m, matrix_expression &e, sparse_proxy_tag, row_major_tag) { BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); typedef F functor_type; + typedef typename M::size_type size_type; typedef typename M::value_type value_type; typename M::iterator1 it1 (m.begin1 ()); typename M::iterator1 it1_end (m.end1 ()); @@ -2545,142 +1007,105 @@ namespace boost { namespace numeric { namespace ublas { if (compare == 0) { functor_type () (*it2, *it2e); ++ it2, ++ it2e; - } else { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + } else if (compare < 0) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2.index1 ()), index2 (it2.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); + // The proxies could reference the same container. + restart (m, index1, index2, it1, it1_end, it2, it2_end, row_major_tag ()); + } else if (compare > 0) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2e.index1 ()), index2 (it2e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + restart (m, index1, index2, it1, it1_end, it2, it2_end, row_major_tag ()); + // The proxies could reference the same container. + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); } } - if (it2 != it2_end || it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + while (it2e != it2e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2e.index1 ()), index2 (it2e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); + restart (m, index1, index2, it1, it1_end, it2, it2_end, row_major_tag ()); + } + while (it2 != it2_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2.index1 ()), index2 (it2.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (m, index1, index2, it1, it1_end, it2, it2_end, row_major_tag ()); + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); } ++ it1, ++ it1e; } else if (compare < 0) { typename M::iterator2 it2 (it1.begin ()); typename M::iterator2 it2_end (it1.end ()); - if (it2 != it2_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + while (it2 != it2_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2.index1 ()), index2 (it2.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (m, index1, index2, it1, it1_end, it2, it2_end, row_major_tag ()); } ++ it1; } else if (compare > 0) { - typename E::const_iterator2 it2e (it1e.begin ()); - typename E::const_iterator2 it2e_end (it1e.end ()); - if (it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + typename E::iterator2 it2e (it1e.begin ()); + typename E::iterator2 it2e_end (it1e.end ()); + while (it2e != it2e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2e.index1 ()), index2 (it2e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); } ++ it1e; } } - while (it1 != it1_end) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - if (it2 != it2_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1; - } while (it1e != it1e_end) { - typename E::const_iterator2 it2e (it1e.begin ()); - typename E::const_iterator2 it2e_end (it1e.end ()); - if (it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + typename E::iterator2 it2e (it1e.begin ()); + typename E::iterator2 it2e_end (it1e.end ()); + while (it2e != it2e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2e.index1 ()), index2 (it2e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it1e, it1e_end, it2e, it2e_end, row_major_tag ()); } ++ it1e; } -#endif + while (it1 != it1_end) { + typename M::iterator2 it2 (it1.begin ()); + typename M::iterator2 it2_end (it1.end ()); + while (it2 != it2_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it2.index1 ()), index2 (it2.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (m, index1, index2, it1, it1_end, it2, it2_end, row_major_tag ()); + } + ++ it1; + } } // Sparse (proxy) column major case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_matrix_swap (const F &f, M &m, matrix_expression &e, sparse_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); - BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); - typedef F functor_type; - typedef typename M::value_type value_type; - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - typename E::iterator2 it2e (e ().begin2 ()); - typename E::iterator2 it2e_end (e ().end2 ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index () - it2e.index (); - if (compare == 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - typename matrix_column::iterator it1e ((*it2e).begin ()); - typename matrix_column::iterator it1e_end ((*it2e).end ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index () - it1e.index (); - if (compare == 0) { - functor_type () (*it1, *it1e); - ++ it1, ++ it1e; - } else { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - } - if (it1 != it1_end || it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2, ++ it2e; - } else if (compare < 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - if (it1 != it1_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2; - } else if (compare > 0) { - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - if (it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2e; - } - } - while (it2 != it2_end) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - if (it1 != it1_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2; - } - while (it2e != it2e_end) { - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - if (it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2e; - } -#else + void matrix_swap (const F &f, M &m, matrix_expression &e, sparse_proxy_tag, column_major_tag) { BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); typedef F functor_type; + typedef typename M::size_type size_type; typedef typename M::value_type value_type; typename M::iterator2 it2 (m.begin2 ()); typename M::iterator2 it2_end (m.end2 ()); @@ -2698,529 +1123,110 @@ namespace boost { namespace numeric { namespace ublas { if (compare == 0) { functor_type () (*it1, *it1e); ++ it1, ++ it1e; - } else { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + } else if (compare < 0) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1.index1 ()), index2 (it1.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag () ()); + // The proxies could reference the same container. + restart (m, index1, index2, it2, it2_end, it1, it1_end, column_major_tag () ()); + } else if (compare > 0) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1e.index1 ()), index2 (it1e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + restart (m, index1, index2, it2, it2_end, it1, it1_end, column_major_tag () ()); + // The proxies could reference the same container. + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag () ()); } } - if (it1 != it1_end || it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + while (it1e != it1e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1e.index1 ()), index2 (it1e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag () ()); + restart (m, index1, index2, it2, it2_end, it1, it1_end, column_major_tag () ()); + } + while (it1 != it1_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1.index1 ()), index2 (it1.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (m, index1, index2, it2, it2_end, it1, it1_end, column_major_tag () ()); + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag () ()); } ++ it2, ++ it2e; } else if (compare < 0) { typename M::iterator1 it1 (it2.begin ()); typename M::iterator1 it1_end (it2.end ()); - if (it1 != it1_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + while (it1 != it1_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1.index1 ()), index2 (it1.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (m, index1, index2, it2, it2_end, it1, it1_end, column_major_tag () ()); } ++ it2; } else if (compare > 0) { - typename E::const_iterator1 it1e (it2e.begin ()); - typename E::const_iterator1 it1e_end (it2e.end ()); - if (it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + typename E::iterator1 it1e (it2e.begin ()); + typename E::iterator1 it1e_end (it2e.end ()); + while (it1e != it1e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1e.index1 ()), index2 (it1e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag () ()); } ++ it2e; } } + while (it2e != it2e_end) { + typename E::iterator1 it1e (it2e.begin ()); + typename E::iterator1 it1e_end (it2e.end ()); + while (it1e != it1e_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1e.index1 ()), index2 (it1e.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (e, index1, index2, it2e, it2e_end, it1e, it1e_end, column_major_tag () ()); + } + ++ it2e; + } while (it2 != it2_end) { typename M::iterator1 it1 (it2.begin ()); typename M::iterator1 it1_end (it2.end ()); - if (it1 != it1_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); + while (it1 != it1_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index1 (it1.index1 ()), index2 (it1.index2 ()); + functor_type () (m (index1, index2), e () (index1, index2)); + // The proxies could reference the same container. + restart (m, index1, index2, it2, it2_end, it1, it1_end, column_major_tag () ()); } ++ it2; } - while (it2e != it2e_end) { - typename E::const_iterator1 it1e (it2e.begin ()); - typename E::const_iterator1 it1e_end (it2e.end ()); - if (it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2e; - } -#endif } -#endif - // matrix swap_operation matrix_expression - template - struct matrix_swap { + // Dispatcher + template + BOOST_UBLAS_INLINE + void matrix_swap (const F &f, M &m, matrix_expression &e) { typedef F functor_type; - -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - // Dense (proxy) row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, matrix_expression &e, dense_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator1 it1 (m.begin1 ()); - typename E::iterator1 it1e (e ().begin1 ()); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (e ().end1 () - it1e))); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2e ((*it1e).begin ()); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type ((*it1e).end () - it2e))); - while (-- size2 >= 0) - functor_type () (*it2, *it2e), ++ it2, ++ it2e; - ++ it1, ++ it1e; - } -#else - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator1 it1 (m.begin1 ()); - typename E::iterator1 it1e (e ().begin1 ()); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (e ().end1 () - it1e))); - while (-- size1 >= 0) { - typename M::iterator2 it2 (it1.begin ()); - typename E::iterator2 it2e (it1e.begin ()); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (it1e.end () - it2e))); - while (-- size2 >= 0) - functor_type () (*it2, *it2e), ++ it2, ++ it2e; - ++ it1, ++ it1e; - } -#endif - } - // Dense (proxy) column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, matrix_expression &e, dense_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator2 it2 (m.begin2 ()); - typename E::iterator2 it2e (e ().begin2 ()); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (e ().end2 () - it2e))); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1e ((*it2e).begin ()); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type ((*it2e).end () - it1e))); - while (-- size1 >= 0) - functor_type () (*it1, *it1e), ++ it1, ++ it1e; - ++ it2, ++ it2e; - } -#else - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator2 it2 (m.begin2 ()); - typename E::iterator2 it2e (e ().begin2 ()); - difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (e ().end2 () - it2e))); - while (-- size2 >= 0) { - typename M::iterator1 it1 (it2.begin ()); - typename E::iterator1 it1e (it2e.begin ()); - difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (it2e.end () - it1e))); - while (-- size1 >= 0) - functor_type () (*it1, *it1e), ++ it1, ++ it1e; - ++ it2, ++ it2e; - } -#endif - } - // Packed (proxy) row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, matrix_expression &e, packed_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator1 it1 (m.begin1 ()); - typename E::iterator1 it1e (e ().begin1 ()); - difference_type size1 (BOOST_UBLAS_SAME (m.end1 () - it1, e ().end1 () - it1e)); - while (-- size1 >= 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2e ((*it1e).begin ()); - difference_type size2 (BOOST_UBLAS_SAME ((*it1).end () - it2, (*it1e).end () - it2e)); - while (-- size2 >= 0) - functor_type () (*it2, *it2e), ++ it2, ++ it2e; - ++ it1, ++ it1e; - } -#else - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator1 it1 (m.begin1 ()); - typename E::iterator1 it1e (e ().begin1 ()); - difference_type size1 (BOOST_UBLAS_SAME (m.end1 () - it1, e ().end1 () - it1e)); - while (-- size1 >= 0) { - typename M::iterator2 it2 (it1.begin ()); - typename E::iterator2 it2e (it1e.begin ()); - difference_type size2 (BOOST_UBLAS_SAME (it1.end () - it2, it1e.end () - it2e)); - while (-- size2 >= 0) - functor_type () (*it2, *it2e), ++ it2, ++ it2e; - ++ it1, ++ it1e; - } -#endif - } - // Packed (proxy) column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, matrix_expression &e, packed_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator2 it2 (m.begin2 ()); - typename E::iterator2 it2e (e ().begin2 ()); - difference_type size2 (BOOST_UBLAS_SAME (m.end2 () - it2, e ().end2 () - it2e)); - while (-- size2 >= 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1e ((*it2e).begin ()); - difference_type size1 (BOOST_UBLAS_SAME ((*it2).end () - it1, (*it2e).end () - it1e)); - while (-- size1 >= 0) - functor_type () (*it1, *it1e), ++ it1, ++ it1e; - ++ it2, ++ it2e; - } -#else - typedef typename M::size_type size_type; - typedef typename M::difference_type difference_type; - typename M::iterator2 it2 (m.begin2 ()); - typename E::iterator2 it2e (e ().begin2 ()); - difference_type size2 (BOOST_UBLAS_SAME (m.end2 () - it2, e ().end2 () - it2e)); - while (-- size2 >= 0) { - typename M::iterator1 it1 (it2.begin ()); - typename E::iterator1 it1e (it2e.begin ()); - difference_type size1 (BOOST_UBLAS_SAME (it2.end () - it1, it2e.end () - it1e)); - while (-- size1 >= 0) - functor_type () (*it1, *it1e), ++ it1, ++ it1e; - ++ it2, ++ it2e; - } -#endif - } - // Sparse (proxy) row major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, matrix_expression &e, sparse_proxy_tag, row_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - 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; - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - typename E::iterator1 it1e (e ().begin1 ()); - typename E::iterator1 it1e_end (e ().end1 ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index () - it1e.index (); - if (compare == 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - typename matrix_row::iterator it2e ((*it1e).begin ()); - typename matrix_row::iterator it2e_end ((*it1e).end ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index () - it2e.index (); - if (compare == 0) { - functor_type () (*it2, *it2e); - ++ it2, ++ it2e; - } else { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - } - if (it2 != it2_end || it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1, ++ it1e; - } else if (compare < 0) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - if (it2 != it2_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1; - } else if (compare > 0) { - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - if (it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1e; - } - } - while (it1 != it1_end) { - typename matrix_row::iterator it2 ((*it1).begin ()); - typename matrix_row::iterator it2_end ((*it1).end ()); - if (it2 != it2_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1; - } - while (it1e != it1e_end) { - typename matrix_row::const_iterator it2e ((*it1e).begin ()); - typename matrix_row::const_iterator it2e_end ((*it1e).end ()); - if (it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1e; - } -#else - 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; - typename M::iterator1 it1 (m.begin1 ()); - typename M::iterator1 it1_end (m.end1 ()); - typename E::iterator1 it1e (e ().begin1 ()); - typename E::iterator1 it1e_end (e ().end1 ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index1 () - it1e.index1 (); - if (compare == 0) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - typename E::iterator2 it2e (it1e.begin ()); - typename E::iterator2 it2e_end (it1e.end ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index2 () - it2e.index2 (); - if (compare == 0) { - functor_type () (*it2, *it2e); - ++ it2, ++ it2e; - } else { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - } - if (it2 != it2_end || it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1, ++ it1e; - } else if (compare < 0) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - if (it2 != it2_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1; - } else if (compare > 0) { - typename E::const_iterator2 it2e (it1e.begin ()); - typename E::const_iterator2 it2e_end (it1e.end ()); - if (it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1e; - } - } - while (it1 != it1_end) { - typename M::iterator2 it2 (it1.begin ()); - typename M::iterator2 it2_end (it1.end ()); - if (it2 != it2_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1; - } - while (it1e != it1e_end) { - typename E::const_iterator2 it2e (it1e.begin ()); - typename E::const_iterator2 it2e_end (it1e.end ()); - if (it2e != it2e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it1e; - } -#endif - } - // Sparse (proxy) column major case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (M &m, matrix_expression &e, sparse_proxy_tag, column_major_tag) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - 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; - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - typename E::iterator2 it2e (e ().begin2 ()); - typename E::iterator2 it2e_end (e ().end2 ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index () - it2e.index (); - if (compare == 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - typename matrix_column::iterator it1e ((*it2e).begin ()); - typename matrix_column::iterator it1e_end ((*it2e).end ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index () - it1e.index (); - if (compare == 0) { - functor_type () (*it1, *it1e); - ++ it1, ++ it1e; - } else { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - } - if (it1 != it1_end || it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2, ++ it2e; - } else if (compare < 0) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - if (it1 != it1_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2; - } else if (compare > 0) { - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - if (it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2e; - } - } - while (it2 != it2_end) { - typename matrix_column::iterator it1 ((*it2).begin ()); - typename matrix_column::iterator it1_end ((*it2).end ()); - if (it1 != it1_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2; - } - while (it2e != it2e_end) { - typename matrix_column::const_iterator it1e ((*it2e).begin ()); - typename matrix_column::const_iterator it1e_end ((*it2e).end ()); - if (it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2e; - } -#else - 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; - typename M::iterator2 it2 (m.begin2 ()); - typename M::iterator2 it2_end (m.end2 ()); - typename E::iterator2 it2e (e ().begin2 ()); - typename E::iterator2 it2e_end (e ().end2 ()); - while (it2 != it2_end && it2e != it2e_end) { - int compare = it2.index2 () - it2e.index2 (); - if (compare == 0) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - typename E::iterator1 it1e (it2e.begin ()); - typename E::iterator1 it1e_end (it2e.end ()); - while (it1 != it1_end && it1e != it1e_end) { - int compare = it1.index1 () - it1e.index1 (); - if (compare == 0) { - functor_type () (*it1, *it1e); - ++ it1, ++ it1e; - } else { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - } - if (it1 != it1_end || it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2, ++ it2e; - } else if (compare < 0) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - if (it1 != it1_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2; - } else if (compare > 0) { - typename E::const_iterator1 it1e (it2e.begin ()); - typename E::const_iterator1 it1e_end (it2e.end ()); - if (it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2e; - } - } - while (it2 != it2_end) { - typename M::iterator1 it1 (it2.begin ()); - typename M::iterator1 it1_end (it2.end ()); - if (it1 != it1_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2; - } - while (it2e != it2e_end) { - typename E::const_iterator1 it1e (it2e.begin ()); - typename E::const_iterator1 it1e_end (it2e.end ()); - if (it1e != it1e_end) { - // Raising exceptions abstracted as requested during review. - // throw external_logic (); - external_logic ().raise (); - } - ++ it2e; - } -#endif - } -#endif - - // Dispatcher - template - BOOST_UBLAS_INLINE - void operator () (M &m, matrix_expression &e) { - typedef typename matrix_swap_traits::storage_category storage_category; - // FIXME: can't we improve the dispatch here? - // typedef typename E::orientation_category orientation_category; - typedef typename M::orientation_category orientation_category; -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - operator () (m, e, storage_category (), orientation_category ()); -#else - evaluate_matrix_swap (functor_type (), m, e, storage_category (), orientation_category ()); -#endif - } - }; + typedef typename matrix_swap_traits::storage_category storage_category; + // FIXME: can't we improve the dispatch here? + // typedef typename E::orientation_category orientation_category; + typedef typename M::orientation_category orientation_category; + matrix_swap (functor_type (), m, e, storage_category (), orientation_category ()); + } }}} diff --git a/include/boost/numeric/ublas/matrix_expression.hpp b/include/boost/numeric/ublas/matrix_expression.hpp index f0e057a8..0bc82f50 100644 --- a/include/boost/numeric/ublas/matrix_expression.hpp +++ b/include/boost/numeric/ublas/matrix_expression.hpp @@ -291,18 +291,10 @@ namespace boost { namespace numeric { namespace ublas { // Reverse iterators -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, matrix_row > > const_reverse_iterator1; -#else - typedef reverse_iterator_base const_reverse_iterator1; -#endif -#else #ifdef BOOST_MSVC_STD_ITERATOR typedef reverse_iterator_base1 const_reverse_iterator1; #else typedef reverse_iterator_base1 const_reverse_iterator1; -#endif #endif BOOST_UBLAS_INLINE @@ -314,18 +306,10 @@ namespace boost { namespace numeric { namespace ublas { return const_reverse_iterator1 (begin1 ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, matrix_column > > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_MSVC_STD_ITERATOR typedef reverse_iterator_base2 const_reverse_iterator2; #else typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif BOOST_UBLAS_INLINE @@ -488,18 +472,10 @@ namespace boost { namespace numeric { namespace ublas { // Reverse iterators -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, matrix_row > > const_reverse_iterator1; -#else - typedef reverse_iterator_base const_reverse_iterator1; -#endif -#else #ifdef BOOST_MSVC_STD_ITERATOR typedef reverse_iterator_base1 const_reverse_iterator1; #else typedef reverse_iterator_base1 const_reverse_iterator1; -#endif #endif BOOST_UBLAS_INLINE @@ -511,18 +487,10 @@ namespace boost { namespace numeric { namespace ublas { return const_reverse_iterator1 (begin1 ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, matrix_row > > reverse_iterator1; -#else - typedef reverse_iterator_base reverse_iterator1; -#endif -#else #ifdef BOOST_MSVC_STD_ITERATOR typedef reverse_iterator_base1 reverse_iterator1; #else typedef reverse_iterator_base1 reverse_iterator1; -#endif #endif BOOST_UBLAS_INLINE @@ -534,18 +502,10 @@ namespace boost { namespace numeric { namespace ublas { return reverse_iterator1 (begin1 ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, matrix_column > > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_MSVC_STD_ITERATOR typedef reverse_iterator_base2 const_reverse_iterator2; #else typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif BOOST_UBLAS_INLINE @@ -557,18 +517,10 @@ namespace boost { namespace numeric { namespace ublas { return const_reverse_iterator2 (begin2 ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, matrix_column > > reverse_iterator2; -#else - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_MSVC_STD_ITERATOR typedef reverse_iterator_base2 reverse_iterator2; #else typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif BOOST_UBLAS_INLINE @@ -613,7 +565,7 @@ namespace boost { namespace numeric { namespace ublas { // Construction and destruction BOOST_UBLAS_INLINE - vector_matrix_binary (): + vector_matrix_binary (): e1_ (), e2_ () {} BOOST_UBLAS_INLINE vector_matrix_binary (const expression1_type &e1, const expression2_type &e2): @@ -622,11 +574,11 @@ namespace boost { namespace numeric { namespace ublas { // Accessors BOOST_UBLAS_INLINE size_type size1 () const { - return e1_.size (); + return e1_.size (); } BOOST_UBLAS_INLINE size_type size2 () const { - return e2_.size (); + return e2_.size (); } BOOST_UBLAS_INLINE const expression1_type &expression1 () const { @@ -643,21 +595,6 @@ namespace boost { namespace numeric { namespace ublas { return functor_type () (e1_ (i), e2_ (j)); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef matrix_row_const_iterator, iterator_category> const_iterator1; - typedef const_iterator1 iterator1; - typedef matrix_column_const_iterator, iterator_category> const_iterator2; - typedef const_iterator2 iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, matrix_row > >const_reverse_iterator1; - typedef reverse_iterator_base >, matrix_column > > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef typename iterator_restrict_traits::iterator_category iterator_category; @@ -677,20 +614,19 @@ namespace boost { namespace numeric { namespace ublas { #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { const_iterator1_type it1 (e1_.find_first (i)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it1.index ()); -#else + const_iterator1_type it1_end (e1_.find_last (size1 ())); const_iterator2_type it2 (e2_.find_first (j)); const_iterator2_type it2_end (e2_.find_last (size2 ())); - if (it2 != it2_end && it2.index () != j) + if (it2 == it2_end || (rank == 1 && it2.index () != j)) { + it1 = it1_end; it2 = it2_end; + } #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it1.index (), it2.index ()); #else @@ -699,19 +635,18 @@ namespace boost { namespace numeric { namespace ublas { #else return const_iterator1 (*this, it1, it2); #endif -#endif #endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { const_iterator1_type it1 (e1_.find_last (i)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it1.index ()); -#else + const_iterator1_type it1_end (e1_.find_last (size1 ())); const_iterator2_type it2 (e2_.find_first (j)); const_iterator2_type it2_end (e2_.find_last (size2 ())); - if (it2 != it2_end && it2.index () != j) + if (it2 == it2_end || (rank == 1 && it2.index () != j)) { + it1 = it1_end; it2 = it2_end; + } #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it1.index (), it2.index ()); #else @@ -720,19 +655,18 @@ namespace boost { namespace numeric { namespace ublas { #else return const_iterator1 (*this, it1, it2); #endif -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { const_iterator2_type it2 (e2_.find_first (j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it2.index ()); -#else + const_iterator2_type it2_end (e2_.find_last (size2 ())); const_iterator1_type it1 (e1_.find_first (i)); const_iterator1_type it1_end (e1_.find_last (size1 ())); - if (it1 != it1_end && it1.index () != i) + if (it1 == it1_end || (rank == 1 && it1.index () != i)) { + it2 = it2_end; it1 = it1_end; + } #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it1.index (), it2.index ()); #else @@ -741,19 +675,18 @@ namespace boost { namespace numeric { namespace ublas { #else return const_iterator2 (*this, it1, it2); #endif -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { const_iterator2_type it2 (e2_.find_last (j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it2.index ()); -#else + const_iterator2_type it2_end (e2_.find_last (size2 ())); const_iterator1_type it1 (e1_.find_first (i)); const_iterator1_type it1_end (e1_.find_last (size1 ())); - if (it1 != it1_end && it1.index () != i) + if (it1 == it1_end || (rank == 1 && it1.index () != i)) { + it2 = it2_end; it1 = it1_end; + } #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it1.index (), it2.index ()); #else @@ -762,14 +695,13 @@ namespace boost { namespace numeric { namespace ublas { #else return const_iterator2 (*this, it1, it2); #endif -#endif #endif } // Iterators enhance the iterators of the referenced expressions // with the binary functor. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -921,7 +853,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -932,7 +864,7 @@ namespace boost { namespace numeric { namespace ublas { public random_access_iterator_base::iterator_category, const_iterator2, value_type> { -#endif +#endif public: typedef typename iterator_restrict_traits::iterator_category iterator_category; @@ -1175,19 +1107,6 @@ namespace boost { namespace numeric { namespace ublas { return functor_type () (e_ (i, j)); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_const_iterator, typename const_iterator1_type::iterator_category> const_iterator1; - typedef const_iterator1 iterator1; - typedef matrix_column_const_iterator, typename const_iterator2_type::iterator_category> const_iterator2; - typedef const_iterator2 iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, matrix_row > > const_reverse_iterator1; - typedef reverse_iterator_base >, matrix_column > > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_const_iterator1 const_iterator1; typedef const_iterator1 iterator1; @@ -1205,67 +1124,50 @@ namespace boost { namespace numeric { namespace ublas { #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { const_iterator1_type it1 (e_.find_first1 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it1.index1 (), it1.index2 ()); #else return const_iterator1 (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { const_iterator1_type it1 (e_.find_last1 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it1.index1 (), it1.index2 ()); #else return const_iterator1 (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { const_iterator2_type it2 (e_.find_first2 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it2.index1 (), it2.index2 ()); #else return const_iterator2 (*this, it2); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { const_iterator2_type it2 (e_.find_last2 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it2.index1 (), it2.index2 ()); #else return const_iterator2 (*this, it2); -#endif #endif } // Iterators enhance the iterators of the referenced expression // with the unary functor. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -1389,7 +1291,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -1638,19 +1540,6 @@ namespace boost { namespace numeric { namespace ublas { return functor_type () (e_ (j, i)); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_const_iterator, typename const_iterator1_type::iterator_category> const_iterator1; - typedef const_iterator1 iterator1; - typedef matrix_column_const_iterator, typename const_iterator2_type::iterator_category> const_iterator2; - typedef const_iterator2 iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, matrix_row > > const_reverse_iterator1; - typedef reverse_iterator_base >, matrix_column > > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_const_iterator1 const_iterator1; typedef const_iterator1 iterator1; @@ -1668,67 +1557,50 @@ namespace boost { namespace numeric { namespace ublas { #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { const_iterator1_type it1 (e_.find_first2 (rank, j, i)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it1.index2 (), it1.index1 ()); #else return const_iterator1 (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { const_iterator1_type it1 (e_.find_last2 (rank, j, i)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it1.index2 (), it1.index1 ()); #else return const_iterator1 (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { const_iterator2_type it2 (e_.find_first1 (rank, j, i)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it2.index2 (), it2.index1 ()); #else return const_iterator2 (*this, it2); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { const_iterator2_type it2 (e_.find_last1 (rank, j, i)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it2.index2 (), it2.index1 ()); #else return const_iterator2 (*this, it2); -#endif #endif } // Iterators enhance the iterators of the referenced expression // with the unary functor. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -1852,7 +1724,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -2090,29 +1962,12 @@ namespace boost { namespace numeric { namespace ublas { return functor_type () (e1_ (i, j), e2_ (i, j)); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename iterator_restrict_traits::iterator_category iterator_category1; - typedef matrix_row_const_iterator, iterator_category1> const_iterator1; - typedef const_iterator1 iterator1; - typedef typename iterator_restrict_traits::iterator_category iterator_category2; - typedef matrix_column_const_iterator, iterator_category2> const_iterator2; - typedef const_iterator2 iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, matrix_binary > const_reverse_iterator1; - typedef reverse_iterator_base, matrix_binary > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #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; @@ -2128,7 +1983,6 @@ namespace boost { namespace numeric { namespace ublas { #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup @@ -2138,16 +1992,14 @@ namespace boost { namespace numeric { namespace ublas { const_iterator11_type it11_end (e1_.find_first1 (rank, size1 (), j)); const_iterator21_type it21 (e2_.find_first1 (rank, i, j)); const_iterator21_type it21_end (e2_.find_first1 (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_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end); -#endif #endif } BOOST_UBLAS_INLINE @@ -2156,16 +2008,14 @@ namespace boost { namespace numeric { namespace ublas { const_iterator11_type it11_end (e1_.find_last1 (rank, size1 (), j)); const_iterator21_type it21 (e2_.find_last1 (rank, i, j)); const_iterator21_type it21_end (e2_.find_last1 (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::max (it11 != it11_end ? it11.index1 () : size1 (), it21 != it21_end ? it21.index1 () : size1 ()); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end); -#endif #endif } BOOST_UBLAS_INLINE @@ -2174,16 +2024,14 @@ namespace boost { namespace numeric { namespace ublas { const_iterator12_type it12_end (e1_.find_first2 (rank, i, size2 ())); const_iterator22_type it22 (e2_.find_first2 (rank, i, j)); const_iterator22_type it22_end (e2_.find_first2 (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_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end); -#endif #endif } BOOST_UBLAS_INLINE @@ -2192,23 +2040,21 @@ namespace boost { namespace numeric { namespace ublas { const_iterator12_type it12_end (e1_.find_last2 (rank, i, size2 ())); const_iterator22_type it22 (e2_.find_last2 (rank, i, j)); const_iterator22_type it22_end (e2_.find_last2 (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::max (it12 != it12_end ? it12.index2 () : size2 (), it22 != it22_end ? it22.index2 () : size2 ()); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end); -#endif #endif } // Iterators enhance the iterators of the referenced expression // with the binary functor. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -2456,7 +2302,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -2826,19 +2672,6 @@ namespace boost { namespace numeric { namespace ublas { return functor_type () (e1_, e2_ (i, j)); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_const_iterator, typename const_iterator21_type::iterator_category> const_iterator1; - typedef const_iterator1 iterator1; - typedef matrix_column_const_iterator, typename const_iterator22_type::iterator_category> const_iterator2; - typedef const_iterator2 iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, matrix_binary_scalar1 > const_reverse_iterator1; - typedef reverse_iterator_base, matrix_binary_scalar1 > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_const_iterator1 const_iterator1; typedef const_iterator1 iterator1; @@ -2856,67 +2689,50 @@ namespace boost { namespace numeric { namespace ublas { #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { const_iterator21_type it21 (e2_.find_first1 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it21.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it21.index1 (), it21.index2 ()); #else return const_iterator1 (*this, e1_, it21); -#endif #endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { const_iterator21_type it21 (e2_.find_last1 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it21.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it21.index1 (), it21.index2 ()); #else return const_iterator1 (*this, e1_, it21); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { const_iterator22_type it22 (e2_.find_first2 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it22.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it22.index1 (), it22.index2 ()); #else return const_iterator2 (*this, e1_, it22); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { const_iterator22_type it22 (e2_.find_last2 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it22.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it22.index1 (), it22.index2 ()); #else return const_iterator2 (*this, e1_, it22); -#endif #endif } // Iterators enhance the iterators of the referenced expression // with the binary functor. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -3046,7 +2862,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -3284,19 +3100,6 @@ namespace boost { namespace numeric { namespace ublas { return functor_type () (e1_ (i, j), e2_); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_const_iterator, typename const_iterator11_type::iterator_category> const_iterator1; - typedef const_iterator1 iterator1; - typedef matrix_column_const_iterator, typename const_iterator12_type::iterator_category> const_iterator2; - typedef const_iterator2 iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, matrix_binary_scalar2 > const_reverse_iterator1; - typedef reverse_iterator_base, matrix_binary_scalar2 > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_const_iterator1 const_iterator1; typedef const_iterator1 iterator1; @@ -3314,67 +3117,50 @@ namespace boost { namespace numeric { namespace ublas { #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { const_iterator11_type it11 (e1_.find_first1 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it11.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it11.index1 (), it11.index2 ()); #else return const_iterator1 (*this, it11, e2_); -#endif #endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { const_iterator11_type it11 (e1_.find_last1 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it11.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it11.index1 (), it11.index2 ()); #else return const_iterator1 (*this, it11, e2_); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { const_iterator12_type it12 (e1_.find_first2 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it12.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it12.index1 (), it12.index2 ()); #else return const_iterator2 (*this, it12, e2_); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { const_iterator12_type it12 (e1_.find_last2 (rank, i, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it12.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it12.index1 (), it12.index2 ()); #else return const_iterator2 (*this, it12, e2_); -#endif #endif } // Iterators enhance the iterators of the referenced expression // with the binary functor. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -3504,7 +3290,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -3830,34 +3616,18 @@ namespace boost { namespace numeric { namespace ublas { return mvb (index ()); #elif BOOST_UBLAS_USE_ITERATING difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ()); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type () (size, (*it1_).begin (), e2_begin_); -#else - return functor_type () (size, (*it1_).begin (), mvb.expression2 ().begin ()); -#endif -#else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING return functor_type () (size, it1_.begin (), e2_begin_); #else return functor_type () (size, it1_.begin (), mvb.expression2 ().begin ()); #endif -#endif #else difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ()); if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type () (size, (*it1_).begin (), e2_begin_); -#else - return functor_type () (size, (*it1_).begin (), mvb.expression2 ().begin ()); -#endif -#else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING return functor_type () (size, it1_.begin (), e2_begin_); #else return functor_type () (size, it1_.begin (), mvb.expression2 ().begin ()); -#endif #endif else return mvb (index ()); @@ -3867,42 +3637,22 @@ namespace boost { namespace numeric { namespace ublas { // Packed bidirectional specialization BOOST_UBLAS_INLINE value_type dereference (packed_random_access_iterator_tag) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type () ((*it1_).begin (), (*it1_).end (), e2_begin_, e2_end_); -#else - const matrix_vector_binary1 &mvb = (*this) (); - return functor_type () ((*it1_).begin (), (*it1_).end (), mvb.expression2 ().begin (), mvb.expression2 ().end ()); -#endif -#else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING return functor_type () (it1_.begin (), it1_.end (), e2_begin_, e2_end_); #else const matrix_vector_binary1 &mvb = (*this) (); return functor_type () (it1_.begin (), it1_.end (), mvb.expression2 ().begin (), mvb.expression2 ().end ()); -#endif #endif } // Sparse bidirectional specialization BOOST_UBLAS_INLINE value_type dereference (sparse_bidirectional_iterator_tag) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type () ((*it1_).begin (), (*it1_).end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ()); -#else - const matrix_vector_binary1 &mvb = (*this) (); - return functor_type () ((*it1_).begin (), (*it1_).end (), mvb.expression2 ().begin (), mvb.expression2 ().end (), -sparse_bidirectional_iterator_tag ()); -#endif -#else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING return functor_type () (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ()); #else const matrix_vector_binary1 &mvb = (*this) (); - return functor_type () (it1_.begin (), it1_.end (), mvb.expression2 ().begin (), mvb.expression2 ().end (), -sparse_bidirectional_iterator_tag ()); -#endif + return functor_type () (it1_.begin (), it1_.end (), mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ()); #endif } @@ -3941,11 +3691,7 @@ sparse_bidirectional_iterator_tag ()); // Index BOOST_UBLAS_INLINE size_type index () const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return it1_.index (); -#else return it1_.index1 (); -#endif } // Assignment @@ -4101,7 +3847,7 @@ sparse_bidirectional_iterator_tag ()); V prec_prod (const matrix_expression &e1, const vector_expression &e2) { - return V (prod (e1, e2)); + return V (prec_prod (e1, e2)); } template @@ -4239,34 +3985,18 @@ sparse_bidirectional_iterator_tag ()); return mvb (index ()); #elif BOOST_UBLAS_USE_ITERATING difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ()); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type () (size, e1_begin_, (*it2_).begin ()); -#else - return functor_type () (size, mvb.expression1 ().begin (), (*it2_).begin ()); -#endif -#else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING return functor_type () (size, e1_begin_, it2_.begin ()); #else return functor_type () (size, mvb.expression1 ().begin (), it2_.begin ()); #endif -#endif #else difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ()); if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type () (size, e1_begin_, (*it2_).begin ()); -#else - return functor_type () (size, mvb.expression1 ().begin (), (*it2_).begin ()); -#endif -#else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING return functor_type () (size, e1_begin_, it2_.begin ()); #else return functor_type () (size, mvb.expression1 ().begin (), it2_.begin ()); -#endif #endif else return mvb (index ()); @@ -4276,42 +4006,22 @@ sparse_bidirectional_iterator_tag ()); // Packed bidirectional specialization BOOST_UBLAS_INLINE value_type dereference (packed_random_access_iterator_tag) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type () (e1_begin_, e1_end_, (*it2_).begin (), (*it2_).end ()); -#else - const matrix_vector_binary2 &mvb = (*this) (); - return functor_type () (mvb.expression1 ().begin (), mvb.expression1 ().end (), (*it2_).begin (), (*it2_).end ()); -#endif -#else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING return functor_type () (e1_begin_, e1_end_, it2_.begin (), it2_.end ()); #else const matrix_vector_binary2 &mvb = (*this) (); return functor_type () (mvb.expression1 ().begin (), mvb.expression1 ().end (), it2_.begin (), it2_.end ()); -#endif #endif } // Sparse bidirectional specialization BOOST_UBLAS_INLINE value_type dereference (sparse_bidirectional_iterator_tag) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR -#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type () (e1_begin_, e1_end_, (*it2_).begin (), (*it2_).end (), sparse_bidirectional_iterator_tag ()); -#else - const matrix_vector_binary2 &mvb = (*this) (); - return functor_type () (mvb.expression1 ().begin (), mvb.expression1 ().end (), (*it2_).begin (), (*it2_).end (), -sparse_bidirectional_iterator_tag ()); -#endif -#else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING return functor_type () (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); #else const matrix_vector_binary2 &mvb = (*this) (); - return functor_type () (mvb.expression1 ().begin (), mvb.expression1 ().end (), it2_.begin (), it2_.end (), -sparse_bidirectional_iterator_tag ()); -#endif + return functor_type () (mvb.expression1 ().begin (), mvb.expression1 ().end (), it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); #endif } @@ -4350,11 +4060,7 @@ sparse_bidirectional_iterator_tag ()); // Index BOOST_UBLAS_INLINE size_type index () const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return it2_.index (); -#else return it2_.index2 (); -#endif } // Assignment @@ -4510,7 +4216,7 @@ sparse_bidirectional_iterator_tag ()); V prec_prod (const vector_expression &e1, const matrix_expression &e2) { - return V (prod (e1, e2)); + return V (prec_prod (e1, e2)); } template @@ -4571,23 +4277,8 @@ sparse_bidirectional_iterator_tag ()); return functor_type () (e1_, e2_, i, j); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef matrix_row_const_iterator, iterator_category> const_iterator1; - typedef const_iterator1 iterator1; - typedef matrix_column_const_iterator, iterator_category> const_iterator2; - typedef const_iterator2 iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, matrix_matrix_binary > const_reverse_iterator1; - typedef reverse_iterator_base, matrix_matrix_binary > const_reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; -#endif -#else #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; @@ -4605,7 +4296,6 @@ sparse_bidirectional_iterator_tag ()); #else typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; -#endif #endif // Element lookup @@ -4614,9 +4304,6 @@ sparse_bidirectional_iterator_tag ()); // FIXME: sparse matrix tests fail! // const_iterator11_type it11 (e1_.find_first1 (rank, i, 0)); const_iterator11_type it11 (e1_.find_first1 (0, i, 0)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it11.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it11.index1 (), j); #else @@ -4624,7 +4311,6 @@ sparse_bidirectional_iterator_tag ()); // const_iterator22_type it22 (e2_.find_first2 (rank, 0, j)); const_iterator22_type it22 (e2_.find_first2 (0, 0, j)); return const_iterator1 (*this, it11, it22); -#endif #endif } BOOST_UBLAS_INLINE @@ -4632,9 +4318,6 @@ sparse_bidirectional_iterator_tag ()); // FIXME: sparse matrix tests fail! // const_iterator11_type it11 (e1_.find_last1 (rank, i, 0)); const_iterator11_type it11 (e1_.find_last1 (0, i, 0)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it11.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it11.index1 (), j); #else @@ -4642,7 +4325,6 @@ sparse_bidirectional_iterator_tag ()); // const_iterator22_type it22 (e2_.find_last2 (rank, 0, j)); const_iterator22_type it22 (e2_.find_last2 (0, 0, j)); return const_iterator1 (*this, it11, it22); -#endif #endif } BOOST_UBLAS_INLINE @@ -4650,9 +4332,6 @@ sparse_bidirectional_iterator_tag ()); // FIXME: sparse matrix tests fail! // const_iterator22_type it22 (e2_.find_first2 (rank, 0, j)); const_iterator22_type it22 (e2_.find_first2 (0, 0, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it22.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, it22.index2 ()); #else @@ -4660,7 +4339,6 @@ sparse_bidirectional_iterator_tag ()); // const_iterator11_type it11 (e1_.find_first1 (rank, i, 0)); const_iterator11_type it11 (e1_.find_first1 (0, i, 0)); return const_iterator2 (*this, it11, it22); -#endif #endif } BOOST_UBLAS_INLINE @@ -4668,9 +4346,6 @@ sparse_bidirectional_iterator_tag ()); // FIXME: sparse matrix tests fail! // const_iterator22_type it22 (e2_.find_last2 (rank, 0, j)); const_iterator22_type it22 (e2_.find_last2 (0, 0, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it22.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, it22.index2 ()); #else @@ -4678,13 +4353,12 @@ sparse_bidirectional_iterator_tag ()); // const_iterator11_type it11 (e1_.find_last1 (rank, i, 0)); const_iterator11_type it11 (e1_.find_last1 (0, i, 0)); return const_iterator2 (*this, it11, it22); -#endif #endif } // Iterators simply are pointers. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -4878,7 +4552,7 @@ sparse_bidirectional_iterator_tag ()); return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -4964,7 +4638,7 @@ sparse_bidirectional_iterator_tag ()); #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING return functor_type () (it1_begin_, it1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); #else - return functor_type () (it1_.begin (), it1_.end (), it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); + return functor_type () (it1_.begin (), it1_.end (), it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); #endif } @@ -5185,7 +4859,7 @@ sparse_bidirectional_iterator_tag ()); M prec_prod (const matrix_expression &e1, const matrix_expression &e2) { - return M (prod (e1, e2)); + return M (prec_prod (e1, e2)); } template diff --git a/include/boost/numeric/ublas/matrix_proxy.hpp b/include/boost/numeric/ublas/matrix_proxy.hpp index a0cbd02c..5b9609a9 100644 --- a/include/boost/numeric/ublas/matrix_proxy.hpp +++ b/include/boost/numeric/ublas/matrix_proxy.hpp @@ -38,10 +38,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_reference const_reference; typedef typename M::reference reference; typedef typename M::const_pointer const_pointer; typedef typename M::pointer pointer; +#else + typedef typename M::const_reference const_reference; + typedef typename detail::ct_if::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const vector_const_reference > const_closure_type; typedef vector_reference > closure_type; @@ -50,8 +61,15 @@ namespace boost { namespace numeric { namespace ublas { typedef const matrix_row const_closure_type; typedef matrix_row closure_type; #endif +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_iterator2 const_iterator_type; typedef typename M::iterator2 iterator_type; +#else + typedef typename M::const_iterator2 const_iterator_type; + typedef typename detail::ct_if::value, + typename M::const_iterator2, + typename M::iterator2>::type iterator_type; +#endif typedef typename storage_restrict_traits::storage_category storage_category; @@ -61,7 +79,10 @@ namespace boost { namespace numeric { namespace ublas { data_ (nil_), i_ () {} BOOST_UBLAS_INLINE matrix_row (matrix_type &data, size_type i): - data_ (data), i_ (i) {} + data_ (data), i_ (i) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (i_ < data_.size1 (), bad_index ()); + } // Accessors BOOST_UBLAS_INLINE @@ -69,6 +90,10 @@ namespace boost { namespace numeric { namespace ublas { return data_.size2 (); } BOOST_UBLAS_INLINE + size_type index () const { + return i_; + } + BOOST_UBLAS_INLINE const_matrix_type &data () const { return data_; } @@ -116,62 +141,62 @@ namespace boost { namespace numeric { namespace ublas { matrix_row &operator = (const matrix_row &mr) { // FIXME: the rows could be differently sized. // std::copy (mr.begin (), mr.end (), begin ()); - vector_assign > () (*this, vector (mr)); + vector_assign (scalar_assign (), *this, vector (mr)); return *this; } BOOST_UBLAS_INLINE matrix_row &assign_temporary (matrix_row &mr) { // FIXME: this is suboptimal. // return *this = mr; - vector_assign > () (*this, mr); + vector_assign (scalar_assign (), *this, mr); return *this; } template BOOST_UBLAS_INLINE matrix_row &operator = (const vector_expression &ae) { - vector_assign > () (*this, vector (ae)); + vector_assign (scalar_assign (), *this, vector (ae)); return *this; } template BOOST_UBLAS_INLINE matrix_row &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_row &operator += (const vector_expression &ae) { - vector_assign > () (*this, vector (*this + ae)); + vector_assign (scalar_assign (), *this, vector (*this + ae)); return *this; } template BOOST_UBLAS_INLINE matrix_row &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_row &operator -= (const vector_expression &ae) { - vector_assign > () (*this, vector (*this - ae)); + vector_assign (scalar_assign (), *this, vector (*this - ae)); return *this; } template BOOST_UBLAS_INLINE matrix_row &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_row &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE matrix_row &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -182,7 +207,9 @@ namespace boost { namespace numeric { namespace ublas { // BOOST_UBLAS_CHECK (this != &mr, external_logic ()); if (this != &mr) { BOOST_UBLAS_CHECK (size () == mr.size (), bad_size ()); - std::swap_ranges (begin (), end (), mr.begin ()); + // Sparse ranges may be nonconformant now. + // std::swap_ranges (begin (), end (), mr.begin ()); + vector_swap (scalar_swap (), *this, mr); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -192,11 +219,11 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#if defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) || defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator, - BOOST_UBLAS_TYPENAME matrix_type::iterator2::iterator_category> iterator; + BOOST_UBLAS_TYPENAME iterator_type::iterator_category> iterator; typedef indexed_const_iterator, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator2::iterator_category> const_iterator; + BOOST_UBLAS_TYPENAME const_iterator_type::iterator_category> const_iterator; #else class const_iterator; class iterator; @@ -206,74 +233,58 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE const_iterator find_first (size_type j) const { const_iterator_type it2 (data ().find_first2 (1, i_, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator (*this, it2.index2 ()); #else return const_iterator (*this, it2); -#endif #endif } BOOST_UBLAS_INLINE iterator find_first (size_type j) { iterator_type it2 (data ().find_first2 (1, i_, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator (*this, it2.index2 ()); #else return iterator (*this, it2); -#endif #endif } BOOST_UBLAS_INLINE const_iterator find_last (size_type j) const { const_iterator_type it2 (data ().find_last2 (1, i_, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator (*this, it2.index2 ()); #else return const_iterator (*this, it2); -#endif #endif } BOOST_UBLAS_INLINE iterator find_last (size_type j) { iterator_type it2 (data ().find_last2 (1, i_, j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator (*this, it2.index2 ()); #else return iterator (*this, it2); -#endif #endif } // Iterators simply are pointers. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { #endif public: - typedef typename M::const_iterator2::iterator_category iterator_category; - typedef typename M::const_iterator2::difference_type difference_type; - typedef typename M::const_iterator2::value_type value_type; - typedef typename M::const_iterator2::reference reference; - typedef typename M::const_iterator2::pointer pointer; + typedef typename const_iterator_type::iterator_category iterator_category; + typedef typename const_iterator_type::difference_type difference_type; + typedef typename const_iterator_type::value_type value_type; + typedef typename const_iterator_type::reference reference; + typedef typename const_iterator_type::pointer pointer; // Construction and destruction BOOST_UBLAS_INLINE @@ -365,22 +376,22 @@ namespace boost { namespace numeric { namespace ublas { return find_last (size ()); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator: public container_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { -#endif +#endif public: - typedef typename M::iterator2::iterator_category iterator_category; - typedef typename M::iterator2::difference_type difference_type; - typedef typename M::iterator2::value_type value_type; - typedef typename M::iterator2::reference reference; - typedef typename M::iterator2::pointer pointer; + typedef typename iterator_type::iterator_category iterator_category; + typedef typename iterator_type::difference_type difference_type; + typedef typename iterator_type::value_type value_type; + typedef typename iterator_type::reference reference; + typedef typename iterator_type::pointer pointer; // Construction and destruction BOOST_UBLAS_INLINE @@ -520,246 +531,6 @@ namespace boost { namespace numeric { namespace ublas { } #endif - // Matrix row iterator - template - class matrix_row_iterator: - public container_reference, - public random_access_iterator_base, - matrix_row, - typename M::difference_type> { - public: - typedef M matrix_type; - typedef I iterator_category; - typedef typename matrix_type::size_type size_type; - typedef typename matrix_type::difference_type difference_type; - typedef matrix_row value_type; - typedef matrix_row reference; - typedef value_type *pointer; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_row_iterator (): - container_reference (), it_ () {} - BOOST_UBLAS_INLINE - matrix_row_iterator (matrix_type &m, size_type it): - container_reference (m), it_ (it) {} - - // Arithmetic - BOOST_UBLAS_INLINE - matrix_row_iterator &operator ++ () { - ++ it_; - return *this; - } - BOOST_UBLAS_INLINE - matrix_row_iterator &operator -- () { - -- it_; - return *this; - } - BOOST_UBLAS_INLINE - matrix_row_iterator &operator += (difference_type n) { - it_ += n; - return *this; - } - BOOST_UBLAS_INLINE - matrix_row_iterator &operator -= (difference_type n) { - it_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const matrix_row_iterator &it) const { - return it_ - it.it_; - } - - // Dereference - BOOST_UBLAS_INLINE - reference operator * () const { - BOOST_UBLAS_CHECK (index () < (*this) ().size1 (), bad_index ()); - return row ((*this) (), it_); - } - - // Index - BOOST_UBLAS_INLINE - size_type index () const { - return it_; - } - - // Assignment - BOOST_UBLAS_INLINE - matrix_row_iterator &operator = (const matrix_row_iterator &it) { - assign (&it ()); - it_ = it.it_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const matrix_row_iterator &it) const { - BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); - return it_ == it.it_; - } - BOOST_UBLAS_INLINE - bool operator < (const matrix_row_iterator &it) const { - BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); - return it_ < it.it_; - } - - private: - size_type it_; - }; - -#ifdef BOOST_MSVC_STD_ITERATOR - template - BOOST_UBLAS_INLINE - matrix_row_iterator operator ++ (const matrix_row_iterator &it, int) { - matrix_row_iterator tmp (it); - ++ tmp; - return tmp; - } - template - BOOST_UBLAS_INLINE - matrix_row_iterator operator -- (const matrix_row_iterator &it, int) { - matrix_row_iterator tmp (it); - -- tmp; - return tmp; - } - template - BOOST_UBLAS_INLINE - matrix_row_iterator operator + (const matrix_row_iterator &it, std::ptrdiff_t n) { - matrix_row_iterator tmp (it); - return tmp += n; - } - template - BOOST_UBLAS_INLINE - matrix_row_iterator operator - (const matrix_row_iterator &it, std::ptrdiff_t n) { - matrix_row_iterator tmp (it); - return tmp -= n; - } -#endif - - template - class matrix_row_const_iterator: - public container_const_reference, - public random_access_iterator_base, - matrix_row, - typename M::difference_type> { - public: - typedef M matrix_type; - typedef I iterator_category; - typedef typename matrix_type::size_type size_type; - typedef typename matrix_type::difference_type difference_type; - typedef matrix_row value_type; - typedef const matrix_row const_reference; - typedef matrix_row reference; - typedef value_type *pointer; - typedef matrix_row_iterator iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_row_const_iterator (): - container_const_reference (), it_ () {} - BOOST_UBLAS_INLINE - matrix_row_const_iterator (const matrix_type &c, size_type it): - container_const_reference (c), it_ (it) {} - BOOST_UBLAS_INLINE - matrix_row_const_iterator (const iterator_type &it): - container_const_reference (it ()), it_ (it.index ()) {} - - // Arithmetic - BOOST_UBLAS_INLINE - matrix_row_const_iterator &operator ++ () { - ++ it_; - return *this; - } - BOOST_UBLAS_INLINE - matrix_row_const_iterator &operator -- () { - -- it_; - return *this; - } - BOOST_UBLAS_INLINE - matrix_row_const_iterator &operator += (difference_type n) { - it_ += n; - return *this; - } - BOOST_UBLAS_INLINE - matrix_row_const_iterator &operator -= (difference_type n) { - it_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const matrix_row_const_iterator &it) const { - return it_ - it.it_; - } - - // Dereference - BOOST_UBLAS_INLINE - reference operator * () const { - BOOST_UBLAS_CHECK (index () < (*this) ().size1 (), bad_index ()); - return row ((*this) (), it_); - } - - // Index - BOOST_UBLAS_INLINE - size_type index () const { - return it_; - } - - // Assignment - BOOST_UBLAS_INLINE - matrix_row_const_iterator &operator = (const matrix_row_const_iterator &it) { - assign (&it ()); - it_ = it.it_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const matrix_row_const_iterator &it) const { - BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); - return it_ == it.it_; - } - BOOST_UBLAS_INLINE - bool operator < (const matrix_row_const_iterator &it) const { - BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); - return it_ < it.it_; - } - - private: - size_type it_; - - friend class matrix_row_iterator; - }; - -#ifdef BOOST_MSVC_STD_ITERATOR - template - BOOST_UBLAS_INLINE - matrix_row_const_iterator operator ++ (const matrix_row_const_iterator &it, int) { - matrix_row_const_iterator tmp (it); - ++ tmp; - return tmp; - } - template - BOOST_UBLAS_INLINE - matrix_row_const_iterator operator -- (const matrix_row_const_iterator &it, int) { - matrix_row_const_iterator tmp (it); - -- tmp; - return tmp; - } - template - BOOST_UBLAS_INLINE - matrix_row_const_iterator operator + (const matrix_row_const_iterator &it, std::ptrdiff_t n) { - matrix_row_const_iterator tmp (it); - return tmp += n; - } - template - BOOST_UBLAS_INLINE - matrix_row_const_iterator operator - (const matrix_row_const_iterator &it, std::ptrdiff_t n) { - matrix_row_const_iterator tmp (it); - return tmp -= n; - } -#endif - // Matrix based column vector class template class matrix_column: @@ -773,10 +544,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_reference const_reference; typedef typename M::reference reference; typedef typename M::const_pointer const_pointer; typedef typename M::pointer pointer; +#else + typedef typename M::const_reference const_reference; + typedef typename detail::ct_if::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const vector_const_reference > const_closure_type; typedef vector_reference > closure_type; @@ -785,23 +567,37 @@ namespace boost { namespace numeric { namespace ublas { typedef const matrix_column const_closure_type; typedef matrix_column closure_type; #endif +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_iterator1 const_iterator_type; typedef typename M::iterator1 iterator_type; +#else + typedef typename M::const_iterator1 const_iterator_type; + typedef typename detail::ct_if::value, + typename M::const_iterator1, + typename M::iterator1>::type iterator_type; +#endif typedef typename storage_restrict_traits::storage_category storage_category; // Construction and destruction BOOST_UBLAS_INLINE - matrix_column (): + matrix_column (): data_ (nil_), j_ () {} BOOST_UBLAS_INLINE - matrix_column (matrix_type &data, size_type j): - data_ (data), j_ (j) {} + matrix_column (matrix_type &data, size_type j): + data_ (data), j_ (j) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (j_ < data_.size2 (), bad_index ()); + } // Accessors BOOST_UBLAS_INLINE - size_type size () const { - return data_.size1 (); + size_type size () const { + return data_.size1 (); + } + BOOST_UBLAS_INLINE + size_type index () const { + return j_; } BOOST_UBLAS_INLINE const_matrix_type &data () const { @@ -851,62 +647,62 @@ namespace boost { namespace numeric { namespace ublas { matrix_column &operator = (const matrix_column &mc) { // FIXME: the columns could be differently sized. // std::copy (mc.begin (), mc.end (), begin ()); - vector_assign > () (*this, vector (mc)); + vector_assign (scalar_assign (), *this, vector (mc)); return *this; } BOOST_UBLAS_INLINE matrix_column &assign_temporary (matrix_column &mc) { // FIXME: this is suboptimal. // return *this = mc; - vector_assign > () (*this, mc); + vector_assign (scalar_assign (), *this, mc); return *this; } template BOOST_UBLAS_INLINE matrix_column &operator = (const vector_expression &ae) { - vector_assign > () (*this, vector (ae)); + vector_assign (scalar_assign (), *this, vector (ae)); return *this; } template BOOST_UBLAS_INLINE matrix_column &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_column &operator += (const vector_expression &ae) { - vector_assign > () (*this, vector (*this + ae)); + vector_assign (scalar_assign (), *this, vector (*this + ae)); return *this; } template BOOST_UBLAS_INLINE matrix_column &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_column &operator -= (const vector_expression &ae) { - vector_assign > () (*this, vector (*this - ae)); + vector_assign (scalar_assign (), *this, vector (*this - ae)); return *this; } template BOOST_UBLAS_INLINE matrix_column &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_column &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE matrix_column &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -917,7 +713,9 @@ namespace boost { namespace numeric { namespace ublas { // BOOST_UBLAS_CHECK (this != &mc, external_logic ()); if (this != &mc) { BOOST_UBLAS_CHECK (size () == mc.size (), bad_size ()); - std::swap_ranges (begin (), end (), mc.begin ()); + // Sparse ranges may be nonconformant now. + // std::swap_ranges (begin (), end (), mc.begin ()); + vector_swap (scalar_swap (), *this, mc); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -927,11 +725,11 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#if defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) || defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator, - BOOST_UBLAS_TYPENAME matrix_type::iterator1::iterator_category> iterator; + BOOST_UBLAS_TYPENAME iterator_type::iterator_category> iterator; typedef indexed_const_iterator, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator1::iterator_category> const_iterator; + BOOST_UBLAS_TYPENAME const_iterator_type::iterator_category> const_iterator; #else class const_iterator; class iterator; @@ -941,74 +739,58 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE const_iterator find_first (size_type i) const { const_iterator_type it1 (data ().find_first1 (1, i, j_)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator (*this, it1.index1 ()); #else return const_iterator (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE iterator find_first (size_type i) { iterator_type it1 (data ().find_first1 (1, i, j_)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator (*this, it1.index1 ()); #else return iterator (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE const_iterator find_last (size_type i) const { const_iterator_type it1 (data ().find_last1 (1, i, j_)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator (*this, it1.index1 ()); #else return const_iterator (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE iterator find_last (size_type i) { iterator_type it1 (data ().find_last1 (1, i, j_)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator (*this, it1.index1 ()); #else return iterator (*this, it1); -#endif #endif } // Iterators simply are pointers. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { #endif public: - typedef typename M::const_iterator1::iterator_category iterator_category; - typedef typename M::const_iterator1::difference_type difference_type; - typedef typename M::const_iterator1::value_type value_type; - typedef typename M::const_iterator1::reference reference; - typedef typename M::const_iterator1::pointer pointer; + typedef typename const_iterator_type::iterator_category iterator_category; + typedef typename const_iterator_type::difference_type difference_type; + typedef typename const_iterator_type::value_type value_type; + typedef typename const_iterator_type::reference reference; + typedef typename const_iterator_type::pointer pointer; // Construction and destruction BOOST_UBLAS_INLINE @@ -1100,22 +882,22 @@ namespace boost { namespace numeric { namespace ublas { return find_last (size ()); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator: public container_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { #endif public: - typedef typename M::iterator1::iterator_category iterator_category; - typedef typename M::iterator1::difference_type difference_type; - typedef typename M::iterator1::value_type value_type; - typedef typename M::iterator1::reference reference; - typedef typename M::iterator1::pointer pointer; + typedef typename iterator_type::iterator_category iterator_category; + typedef typename iterator_type::difference_type difference_type; + typedef typename iterator_type::value_type value_type; + typedef typename iterator_type::reference reference; + typedef typename iterator_type::pointer pointer; // Construction and destruction BOOST_UBLAS_INLINE @@ -1255,246 +1037,6 @@ namespace boost { namespace numeric { namespace ublas { } #endif - // Matrix column iterator - template - class matrix_column_iterator: - public container_reference, - public random_access_iterator_base, - matrix_column, - typename M::difference_type> { - public: - typedef M matrix_type; - typedef I iterator_category; - typedef typename matrix_type::size_type size_type; - typedef typename matrix_type::difference_type difference_type; - typedef matrix_column value_type; - typedef matrix_column reference; - typedef value_type *pointer; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_column_iterator (): - container_reference (), it_ () {} - BOOST_UBLAS_INLINE - matrix_column_iterator (matrix_type &m, size_type it): - container_reference (m), it_ (it) {} - - // Arithmetic - BOOST_UBLAS_INLINE - matrix_column_iterator &operator ++ () { - ++ it_; - return *this; - } - BOOST_UBLAS_INLINE - matrix_column_iterator &operator -- () { - -- it_; - return *this; - } - BOOST_UBLAS_INLINE - matrix_column_iterator &operator += (difference_type n) { - it_ += n; - return *this; - } - BOOST_UBLAS_INLINE - matrix_column_iterator &operator -= (difference_type n) { - it_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const matrix_column_iterator &it) const { - return it_ - it.it_; - } - - // Dereference - BOOST_UBLAS_INLINE - reference operator * () const { - BOOST_UBLAS_CHECK (index () < (*this) ().size2 (), bad_index ()); - return column ((*this) (), it_); - } - - // Index - BOOST_UBLAS_INLINE - size_type index () const { - return it_; - } - - // Assignment - BOOST_UBLAS_INLINE - matrix_column_iterator &operator = (const matrix_column_iterator &it) { - assign (&it ()); - it_ = it.it_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const matrix_column_iterator &it) const { - BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); - return it_ == it.it_; - } - BOOST_UBLAS_INLINE - bool operator < (const matrix_column_iterator &it) const { - BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); - return it_ < it.it_; - } - - private: - size_type it_; - }; - -#ifdef BOOST_MSVC_STD_ITERATOR - template - BOOST_UBLAS_INLINE - matrix_column_iterator operator ++ (const matrix_column_iterator &it, int) { - matrix_column_iterator tmp (it); - ++ tmp; - return tmp; - } - template - BOOST_UBLAS_INLINE - matrix_column_iterator operator -- (const matrix_column_iterator &it, int) { - matrix_column_iterator tmp (it); - -- tmp; - return tmp; - } - template - BOOST_UBLAS_INLINE - matrix_column_iterator operator + (const matrix_column_iterator &it, std::ptrdiff_t n) { - matrix_column_iterator tmp (it); - return tmp += n; - } - template - BOOST_UBLAS_INLINE - matrix_column_iterator operator - (const matrix_column_iterator &it, std::ptrdiff_t n) { - matrix_column_iterator tmp (it); - return tmp -= n; - } -#endif - - template - class matrix_column_const_iterator: - public container_const_reference, - public random_access_iterator_base, - matrix_column, - typename M::difference_type> { - public: - typedef M matrix_type; - typedef I iterator_category; - typedef typename matrix_type::size_type size_type; - typedef typename matrix_type::difference_type difference_type; - typedef matrix_column value_type; - typedef const matrix_column const_reference; - typedef matrix_column reference; - typedef value_type *pointer; - typedef matrix_column_iterator iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_column_const_iterator (): - container_const_reference (), it_ () {} - BOOST_UBLAS_INLINE - matrix_column_const_iterator (const matrix_type &c, size_type it): - container_const_reference (c), it_ (it) {} - BOOST_UBLAS_INLINE - matrix_column_const_iterator (const iterator_type &it): - container_const_reference (it ()), it_ (it.index ()) {} - - // Arithmetic - BOOST_UBLAS_INLINE - matrix_column_const_iterator &operator ++ () { - ++ it_; - return *this; - } - BOOST_UBLAS_INLINE - matrix_column_const_iterator &operator -- () { - -- it_; - return *this; - } - BOOST_UBLAS_INLINE - matrix_column_const_iterator &operator += (difference_type n) { - it_ += n; - return *this; - } - BOOST_UBLAS_INLINE - matrix_column_const_iterator &operator -= (difference_type n) { - it_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const matrix_column_const_iterator &it) const { - return it_ - it.it_; - } - - // Dereference - BOOST_UBLAS_INLINE - reference operator * () const { - BOOST_UBLAS_CHECK (index () < (*this) ().size2 (), bad_index ()); - return column ((*this) (), it_); - } - - // Index - BOOST_UBLAS_INLINE - size_type index () const { - return it_; - } - - // Assignment - BOOST_UBLAS_INLINE - matrix_column_const_iterator &operator = (const matrix_column_const_iterator &it) { - assign (&it ()); - it_ = it.it_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const matrix_column_const_iterator &it) const { - BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); - return it_ == it.it_; - } - BOOST_UBLAS_INLINE - bool operator < (const matrix_column_const_iterator &it) const { - BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); - return it_ < it.it_; - } - - private: - size_type it_; - - friend class matrix_column_iterator; - }; - -#ifdef BOOST_MSVC_STD_ITERATOR - template - BOOST_UBLAS_INLINE - matrix_column_const_iterator operator ++ (const matrix_column_const_iterator &it, int) { - matrix_column_const_iterator tmp (it); - ++ tmp; - return tmp; - } - template - BOOST_UBLAS_INLINE - matrix_column_const_iterator operator -- (const matrix_column_const_iterator &it, int) { - matrix_column_const_iterator tmp (it); - -- tmp; - return tmp; - } - template - BOOST_UBLAS_INLINE - matrix_column_const_iterator operator + (const matrix_column_const_iterator &it, std::ptrdiff_t n) { - matrix_column_const_iterator tmp (it); - return tmp += n; - } - template - BOOST_UBLAS_INLINE - matrix_column_const_iterator operator - (const matrix_column_const_iterator &it, std::ptrdiff_t n) { - matrix_column_const_iterator tmp (it); - return tmp -= n; - } -#endif - // Matrix based vector range class template class matrix_vector_range: @@ -1508,10 +1050,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_reference const_reference; typedef typename M::reference reference; typedef typename M::const_pointer const_pointer; typedef typename M::pointer pointer; +#else + typedef typename M::const_reference const_reference; + typedef typename detail::ct_if::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const vector_const_reference > const_closure_type; typedef vector_reference > closure_type; @@ -1541,17 +1094,31 @@ namespace boost { namespace numeric { namespace ublas { #ifdef BOOST_UBLAS_ENABLE_INDEX_SET_ALL BOOST_UBLAS_INLINE matrix_vector_range (matrix_type &data, const range<> &r1, const range<> &r2): - data_ (data), r1_ (r1), r2_ (r2) {} + data_ (data), r1_ (r1), r2_ (r2) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () && + r1_.start () + r1_.size () <= data_.size1 (), bad_index ()); + BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () && + r2_.start () + r2_.size () <= data_.size2 (), bad_index ()); + BOOST_UBLAS_CHECK (r1_.size () == r2_.size (), bad_size ()); + } #else BOOST_UBLAS_INLINE matrix_vector_range (matrix_type &data, const range &r1, const range &r2): - data_ (data), r1_ (r1), r2_ (r2) {} + data_ (data), r1_ (r1), r2_ (r2) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () && + r1_.start () + r1_.size () <= data_.size1 (), bad_index ()); + BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () && + r2_.start () + r2_.size () <= data_.size2 (), bad_index ()); + BOOST_UBLAS_CHECK (r1_.size () == r2_.size (), bad_size ()); + } #endif // Accessors BOOST_UBLAS_INLINE - size_type size () const { - return BOOST_UBLAS_SAME (r1_.size (), r2_.size ()); + size_type size () const { + return BOOST_UBLAS_SAME (r1_.size (), r2_.size ()); } BOOST_UBLAS_INLINE const_matrix_type &data () const { @@ -1581,7 +1148,7 @@ namespace boost { namespace numeric { namespace ublas { // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i) const { - return data () (r1_ (i), r2_ (i)); + return data () (r1_ (i), r2_ (i)); } BOOST_UBLAS_INLINE reference operator () (size_type i) { @@ -1602,62 +1169,62 @@ namespace boost { namespace numeric { namespace ublas { matrix_vector_range &operator = (const matrix_vector_range &mvr) { // FIXME: the ranges could be differently sized. // std::copy (mvr.begin (), mvr.end (), begin ()); - vector_assign > () (*this, vector (mvr)); + vector_assign (scalar_assign (), *this, vector (mvr)); return *this; } BOOST_UBLAS_INLINE matrix_vector_range &assign_temporary (matrix_vector_range &mvr) { // FIXME: this is suboptimal. // return *this = mvr; - vector_assign > () (*this, mvr); + vector_assign (scalar_assign (), *this, mvr); return *this; } template BOOST_UBLAS_INLINE matrix_vector_range &operator = (const vector_expression &ae) { - vector_assign > () (*this, vector (ae)); + vector_assign (scalar_assign (), *this, vector (ae)); return *this; } template BOOST_UBLAS_INLINE matrix_vector_range &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_vector_range &operator += (const vector_expression &ae) { - vector_assign > () (*this, vector (*this + ae)); + vector_assign (scalar_assign (), *this, vector (*this + ae)); return *this; } template BOOST_UBLAS_INLINE matrix_vector_range &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_vector_range &operator -= (const vector_expression &ae) { - vector_assign > () (*this, vector (*this - ae)); + vector_assign (scalar_assign (), *this, vector (*this - ae)); return *this; } template BOOST_UBLAS_INLINE matrix_vector_range &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_vector_range &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE matrix_vector_range &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -1668,7 +1235,9 @@ namespace boost { namespace numeric { namespace ublas { // BOOST_UBLAS_CHECK (this != &mvr, external_logic ()); if (this != &mvr) { BOOST_UBLAS_CHECK (size () == mvr.size (), bad_size ()); - std::swap_ranges (begin (), end (), mvr.begin ()); + // Sparse ranges may be nonconformant now. + // std::swap_ranges (begin (), end (), mvr.begin ()); + vector_swap (scalar_swap (), *this, mvr); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -1986,10 +1555,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_reference const_reference; typedef typename M::reference reference; typedef typename M::const_pointer const_pointer; typedef typename M::pointer pointer; +#else + typedef typename M::const_reference const_reference; + typedef typename detail::ct_if::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const vector_const_reference > const_closure_type; typedef vector_reference > closure_type; @@ -2019,11 +1599,31 @@ namespace boost { namespace numeric { namespace ublas { #ifdef BOOST_UBLAS_ENABLE_INDEX_SET_ALL BOOST_UBLAS_INLINE matrix_vector_slice (matrix_type &data, const slice<> &s1, const slice<> &s2): - data_ (data), s1_ (s1), s2_ (s2) {} + data_ (data), s1_ (s1), s2_ (s2) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () && + s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ()); + BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () && + s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ()); + // One of the slices may be stationary. + // Thanks to Michael Stevens for this extension. + BOOST_UBLAS_CHECK ((s1_.stride () != 0 || s2_.stride () != 0) && + s1_.size () == s2_.size (), bad_size ()); + } #else BOOST_UBLAS_INLINE matrix_vector_slice (matrix_type &data, const slice &s1, const slice &s2): - data_ (data), s1_ (s1), s2_ (s2) {} + data_ (data), s1_ (s1), s2_ (s2) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () && + s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ()); + BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () && + s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ()); + // One of the slices may be stationary. + // Thanks to Michael Stevens for this extension. + BOOST_UBLAS_CHECK ((s1_.stride () != 0 || s2_.stride () != 0) && + s1_.size () == s2_.size (), bad_size ()); + } #endif // Accessors @@ -2080,62 +1680,62 @@ namespace boost { namespace numeric { namespace ublas { matrix_vector_slice &operator = (const matrix_vector_slice &mvs) { // FIXME: the slices could be differently sized. // std::copy (mvs.begin (), mvs.end (), begin ()); - vector_assign > () (*this, vector (mvs)); + vector_assign (scalar_assign (), *this, vector (mvs)); return *this; } BOOST_UBLAS_INLINE matrix_vector_slice &assign_temporary (matrix_vector_slice &mvs) { // FIXME: this is suboptimal. // return *this = mvs; - vector_assign > () (*this, mvs); + vector_assign (scalar_assign (), *this, mvs); return *this; } template BOOST_UBLAS_INLINE matrix_vector_slice &operator = (const vector_expression &ae) { - vector_assign > () (*this, vector (ae)); + vector_assign (scalar_assign (), *this, vector (ae)); return *this; } template BOOST_UBLAS_INLINE matrix_vector_slice &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_vector_slice &operator += (const vector_expression &ae) { - vector_assign > () (*this, vector (*this + ae)); + vector_assign (scalar_assign (), *this, vector (*this + ae)); return *this; } template BOOST_UBLAS_INLINE matrix_vector_slice &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_vector_slice &operator -= (const vector_expression &ae) { - vector_assign > () (*this, vector (*this - ae)); + vector_assign (scalar_assign (), *this, vector (*this - ae)); return *this; } template BOOST_UBLAS_INLINE matrix_vector_slice &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_vector_slice &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE matrix_vector_slice &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -2146,7 +1746,9 @@ namespace boost { namespace numeric { namespace ublas { // BOOST_UBLAS_CHECK (this != &mvs, external_logic ()); if (this != &mvs) { BOOST_UBLAS_CHECK (size () == mvs.size (), bad_size ()); - std::swap_ranges (begin (), end (), mvs.begin ()); + // Sparse ranges may be nonconformant now. + // std::swap_ranges (begin (), end (), mvs.begin ()); + vector_swap (scalar_swap (), *this, mvs); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -2246,19 +1848,25 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE difference_type operator - (const const_iterator &it) const { - return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); + // One of the slices may be stationary. + // Thanks to Michael Stevens for this extension. + // return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); + return std::max (it1_ - it.it1_, it2_ - it.it2_); } // Dereference BOOST_UBLAS_INLINE reference operator * () const { - return (*this) ().data () (*it1_, *it2_); + return (*this) ().data () (*it1_, *it2_); } // Index BOOST_UBLAS_INLINE size_type index () const { - return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); + // One of the slices may be stationary. + // Thanks to Michael Stevens for this extension. + // return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); + return std::max (it1_.index (), it2_.index ()); } // Assignment @@ -2352,7 +1960,10 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE difference_type operator - (const iterator &it) const { - return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); + // One of the slices may be stationary. + // Thanks to Michael Stevens for this extension. + // return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); + return std::max (it1_ - it.it1_, it2_ - it.it2_); } // Dereference @@ -2364,10 +1975,13 @@ namespace boost { namespace numeric { namespace ublas { // Index BOOST_UBLAS_INLINE size_type index () const { - return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); + // One of the slices may be stationary. + // Thanks to Michael Stevens for this extension. + // return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); + return std::max (it1_.index (), it2_.index ()); } - // Assignment + // Assignment BOOST_UBLAS_INLINE iterator &operator = (const iterator &it) { container_reference::assign (&it ()); @@ -2466,10 +2080,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_reference const_reference; typedef typename M::reference reference; typedef typename M::const_pointer const_pointer; typedef typename M::pointer pointer; +#else + typedef typename M::const_reference const_reference; + typedef typename detail::ct_if::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const vector_const_reference > const_closure_type; typedef vector_reference > closure_type; @@ -2494,7 +2119,10 @@ namespace boost { namespace numeric { namespace ublas { data_ (data), ia1_ (size), ia2_ (size) {} BOOST_UBLAS_INLINE matrix_vector_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2): - data_ (data), ia1_ (ia1), ia2_ (ia2) {} + data_ (data), ia1_ (ia1), ia2_ (ia2) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (ia1_.size () == ia2_.size (), bad_size ()); + } // Accessors BOOST_UBLAS_INLINE @@ -2566,62 +2194,62 @@ namespace boost { namespace numeric { namespace ublas { matrix_vector_indirect &operator = (const matrix_vector_indirect &mvi) { // FIXME: the indirects could be differently sized. // std::copy (mvi.begin (), mvi.end (), begin ()); - vector_assign > () (*this, vector (mvi)); + vector_assign (scalar_assign (), *this, vector (mvi)); return *this; } BOOST_UBLAS_INLINE matrix_vector_indirect &assign_temporary (matrix_vector_indirect &mvi) { // FIXME: this is suboptimal. // return *this = mvi; - vector_assign > () (*this, mvi); + vector_assign (scalar_assign (), *this, mvi); return *this; } template BOOST_UBLAS_INLINE matrix_vector_indirect &operator = (const vector_expression &ae) { - vector_assign > () (*this, vector (ae)); + vector_assign (scalar_assign (), *this, vector (ae)); return *this; } template BOOST_UBLAS_INLINE matrix_vector_indirect &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_vector_indirect &operator += (const vector_expression &ae) { - vector_assign > () (*this, vector (*this + ae)); + vector_assign (scalar_assign (), *this, vector (*this + ae)); return *this; } template BOOST_UBLAS_INLINE matrix_vector_indirect &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_vector_indirect &operator -= (const vector_expression &ae) { - vector_assign > () (*this, vector (*this - ae)); + vector_assign (scalar_assign (), *this, vector (*this - ae)); return *this; } template BOOST_UBLAS_INLINE matrix_vector_indirect &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_vector_indirect &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE matrix_vector_indirect &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -2632,7 +2260,9 @@ namespace boost { namespace numeric { namespace ublas { // BOOST_UBLAS_CHECK (this != &mvi, external_logic ()); if (this != &mvi) { BOOST_UBLAS_CHECK (size () == mvi.size (), bad_size ()); - std::swap_ranges (begin (), end (), mvi.begin ()); + // Sparse ranges may be nonconformant now. + // std::swap_ranges (begin (), end (), mvi.begin ()); + vector_swap (scalar_swap (), *this, mvi); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -2945,10 +2575,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_reference const_reference; typedef typename M::reference reference; typedef typename M::const_pointer const_pointer; typedef typename M::pointer pointer; +#else + typedef typename M::const_reference const_reference; + typedef typename detail::ct_if::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const matrix_const_reference > const_closure_type; typedef matrix_reference > closure_type; @@ -2957,10 +2598,21 @@ namespace boost { namespace numeric { namespace ublas { typedef const matrix_range const_closure_type; typedef matrix_range closure_type; #endif +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_iterator1 const_iterator1_type; typedef typename M::iterator1 iterator1_type; typedef typename M::const_iterator2 const_iterator2_type; typedef typename M::iterator2 iterator2_type; +#else + typedef typename M::const_iterator1 const_iterator1_type; + typedef typename detail::ct_if::value, + typename M::const_iterator1, + typename M::iterator1>::type iterator1_type; + typedef typename M::const_iterator2 const_iterator2_type; + typedef typename detail::ct_if::value, + typename M::const_iterator2, + typename M::iterator2>::type iterator2_type; +#endif typedef typename storage_restrict_traits::storage_category storage_category; typedef typename M::orientation_category orientation_category; @@ -2972,11 +2624,23 @@ namespace boost { namespace numeric { namespace ublas { #ifdef BOOST_UBLAS_ENABLE_INDEX_SET_ALL BOOST_UBLAS_INLINE matrix_range (matrix_type &data, const range<> &r1, const range<> &r2): - data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {} + data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () && + r1_.start () + r1_.size () <= data_.size1 (), bad_index ()); + BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () && + r2_.start () + r2_.size () <= data_.size2 (), bad_index ()); + } #else BOOST_UBLAS_INLINE matrix_range (matrix_type &data, const range &r1, const range &r2): - data_ (data), r1_ (r1), r2_ (r2) {} + data_ (data), r1_ (r1), r2_ (r2) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () && + r1_.start () + r1_.size () <= data_.size1 (), bad_index ()); + BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () && + r2_.start () + r2_.size () <= data_.size2 (), bad_index ()); + } #endif // Accessors @@ -3046,7 +2710,7 @@ namespace boost { namespace numeric { namespace ublas { // Assignment BOOST_UBLAS_INLINE matrix_range &operator = (const matrix_range &mr) { - matrix_assign > () (*this, mr); + matrix_assign (scalar_assign (), *this, mr); return *this; } BOOST_UBLAS_INLINE @@ -3056,49 +2720,49 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE matrix_range &operator = (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (ae)); + matrix_assign (scalar_assign (), *this, matrix (ae)); return *this; } template BOOST_UBLAS_INLINE matrix_range &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_range& operator += (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this + ae)); + matrix_assign (scalar_assign (), *this, matrix (*this + ae)); return *this; } template BOOST_UBLAS_INLINE matrix_range &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_range& operator -= (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this - ae)); + matrix_assign (scalar_assign (), *this, matrix (*this - ae)); return *this; } template BOOST_UBLAS_INLINE matrix_range &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_range& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE matrix_range& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -3110,7 +2774,7 @@ namespace boost { namespace numeric { namespace ublas { if (this != &mr) { BOOST_UBLAS_CHECK (size1 () == mr.size1 (), bad_size ()); BOOST_UBLAS_CHECK (size2 () == mr.size2 (), bad_size ()); - matrix_swap > () (*this, mr); + matrix_swap (scalar_swap (), *this, mr); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -3120,36 +2784,15 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator, - BOOST_UBLAS_TYPENAME matrix_type::iterator1::iterator_category> iterator1; - typedef matrix_column_iterator, - BOOST_UBLAS_TYPENAME matrix_type::iterator2::iterator_category> iterator2; - typedef matrix_row_const_iterator, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator1::iterator_category> const_iterator1; - typedef matrix_column_const_iterator, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator2::iterator_category> const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, typename matrix_row > > const_reverse_iterator1; - typedef reverse_iterator_base >, typename matrix_row > > reverse_iterator1; - typedef reverse_iterator_base >, typename matrix_column > > const_reverse_iterator2; - typedef reverse_iterator_base >, typename matrix_column > > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1, - BOOST_UBLAS_TYPENAME matrix_type::iterator1::iterator_category> iterator1; + BOOST_UBLAS_TYPENAME iterator1_type::iterator_category> iterator1; typedef indexed_iterator2, - BOOST_UBLAS_TYPENAME matrix_type::iterator2::iterator_category> iterator2; + BOOST_UBLAS_TYPENAME iterator2_type::iterator_category> iterator2; typedef indexed_const_iterator1, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator1::iterator_category> const_iterator1; + BOOST_UBLAS_TYPENAME const_iterator1_type::iterator_category> const_iterator1; typedef indexed_const_iterator2, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator2::iterator_category> const_iterator2; + BOOST_UBLAS_TYPENAME const_iterator2_type::iterator_category> const_iterator2; #else class const_iterator1; class iterator1; @@ -3166,133 +2809,100 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { const_iterator1_type it1 (data ().find_first1 (rank, start1 () + i, start2 () + j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it1.index1 (), it1.index2 ()); #else return const_iterator1 (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE iterator1 find_first1 (int rank, size_type i, size_type j) { iterator1_type it1 (data ().find_first1 (rank, start1 () + i, start2 () + j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, it1.index1 (), it1.index2 ()); #else return iterator1 (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { const_iterator1_type it1 (data ().find_last1 (rank, start1 () + i, start2 () + j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it1.index1 (), it1.index2 ()); #else return const_iterator1 (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE iterator1 find_last1 (int rank, size_type i, size_type j) { iterator1_type it1 (data ().find_last1 (rank, start1 () + i, start2 () + j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, it1.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, it1.index1 (), it1.index2 ()); #else return iterator1 (*this, it1); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { const_iterator2_type it2 (data ().find_first2 (rank, start1 () + i, start2 () + j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it2.index1 (), it2.index2 ()); #else return const_iterator2 (*this, it2); -#endif #endif } BOOST_UBLAS_INLINE iterator2 find_first2 (int rank, size_type i, size_type j) { iterator2_type it2 (data ().find_first2 (rank, start1 () + i, start2 () + j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, it2.index1 (), it2.index2 ()); #else return iterator2 (*this, it2); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { const_iterator2_type it2 (data ().find_last2 (rank, start1 () + i, start2 () + j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it2.index1 (), it2.index2 ()); #else return const_iterator2 (*this, it2); -#endif #endif } BOOST_UBLAS_INLINE iterator2 find_last2 (int rank, size_type i, size_type j) { iterator2_type it2 (data ().find_last2 (rank, start1 () + i, start2 () + j)); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, it2.index ()); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, it2.index1 (), it2.index2 ()); #else return iterator2 (*this, it2); -#endif #endif } // Iterators simply are pointers. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { #endif public: - typedef typename M::const_iterator1::iterator_category iterator_category; - typedef typename M::const_iterator1::difference_type difference_type; - typedef typename M::const_iterator1::value_type value_type; - typedef typename M::const_iterator1::reference reference; - typedef typename M::const_iterator1::pointer pointer; + typedef typename const_iterator1_type::iterator_category iterator_category; + typedef typename const_iterator1_type::difference_type difference_type; + typedef typename const_iterator1_type::value_type value_type; + typedef typename const_iterator1_type::reference reference; + typedef typename const_iterator1_type::pointer pointer; typedef const_iterator2 dual_iterator_type; typedef const_reverse_iterator2 dual_reverse_iterator_type; @@ -3402,22 +3012,22 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator1: public container_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { #endif public: - typedef typename M::iterator1::iterator_category iterator_category; - typedef typename M::iterator1::difference_type difference_type; - typedef typename M::iterator1::value_type value_type; - typedef typename M::iterator1::reference reference; - typedef typename M::iterator1::pointer pointer; + typedef typename iterator1_type::iterator_category iterator_category; + typedef typename iterator1_type::difference_type difference_type; + typedef typename iterator1_type::value_type value_type; + typedef typename iterator1_type::reference reference; + typedef typename iterator1_type::pointer pointer; typedef iterator2 dual_iterator_type; typedef reverse_iterator2 dual_reverse_iterator_type; @@ -3526,22 +3136,22 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { #endif public: - typedef typename M::const_iterator2::iterator_category iterator_category; - typedef typename M::const_iterator2::difference_type difference_type; - typedef typename M::const_iterator2::value_type value_type; - typedef typename M::const_iterator2::reference reference; - typedef typename M::const_iterator2::pointer pointer; + typedef typename const_iterator2_type::iterator_category iterator_category; + typedef typename const_iterator2_type::difference_type difference_type; + typedef typename const_iterator2_type::value_type value_type; + typedef typename const_iterator2_type::reference reference; + typedef typename const_iterator2_type::pointer pointer; typedef const_iterator1 dual_iterator_type; typedef const_reverse_iterator1 dual_reverse_iterator_type; @@ -3651,22 +3261,22 @@ namespace boost { namespace numeric { namespace ublas { return find_last2 (0, 0, size2 ()); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator2: public container_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { -#endif +#endif public: - typedef typename M::iterator2::iterator_category iterator_category; - typedef typename M::iterator2::difference_type difference_type; - typedef typename M::iterator2::value_type value_type; - typedef typename M::iterator2::reference reference; - typedef typename M::iterator2::pointer pointer; + typedef typename iterator2_type::iterator_category iterator_category; + typedef typename iterator2_type::difference_type difference_type; + typedef typename iterator2_type::value_type value_type; + typedef typename iterator2_type::reference reference; + typedef typename iterator2_type::pointer pointer; typedef iterator1 dual_iterator_type; typedef reverse_iterator1 dual_reverse_iterator_type; @@ -3880,10 +3490,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_reference const_reference; typedef typename M::reference reference; typedef typename M::const_pointer const_pointer; typedef typename M::pointer pointer; +#else + typedef typename M::const_reference const_reference; + typedef typename detail::ct_if::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const matrix_const_reference > const_closure_type; typedef matrix_reference > closure_type; @@ -3914,20 +3535,48 @@ namespace boost { namespace numeric { namespace ublas { #ifdef BOOST_UBLAS_ENABLE_INDEX_SET_ALL BOOST_UBLAS_INLINE matrix_slice (matrix_type &data, const slice<> &s1, const slice<> &s2): - data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {} + data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () && + s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ()); + BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () && + s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ()); + } #else BOOST_UBLAS_INLINE matrix_slice (matrix_type &data, const slice &s1, const slice &s2): - data_ (data), s1_ (s1), s2_ (s2) {} + data_ (data), s1_ (s1), s2_ (s2) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () && + s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ()); + BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () && + s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ()); + } #endif // Accessors BOOST_UBLAS_INLINE + size_type start1 () const { + return s1_.start (); + } + BOOST_UBLAS_INLINE + size_type start2 () const { + return s2_.start (); + } + BOOST_UBLAS_INLINE + difference_type stride1 () const { + return s1_.stride (); + } + BOOST_UBLAS_INLINE + difference_type stride2 () const { + return s2_.stride (); + } + BOOST_UBLAS_INLINE size_type size1 () const { return s1_.size (); } BOOST_UBLAS_INLINE - size_type size2 () const { + size_type size2 () const { return s2_.size (); } BOOST_UBLAS_INLINE @@ -3988,7 +3637,7 @@ namespace boost { namespace numeric { namespace ublas { // Assignment BOOST_UBLAS_INLINE matrix_slice &operator = (const matrix_slice &ms) { - matrix_assign > () (*this, ms); + matrix_assign (scalar_assign (), *this, ms); return *this; } BOOST_UBLAS_INLINE @@ -3998,49 +3647,49 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE matrix_slice &operator = (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (ae)); + matrix_assign (scalar_assign (), *this, matrix (ae)); return *this; } template BOOST_UBLAS_INLINE matrix_slice &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_slice& operator += (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this + ae)); + matrix_assign (scalar_assign (), *this, matrix (*this + ae)); return *this; } template BOOST_UBLAS_INLINE matrix_slice &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_slice& operator -= (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this - ae)); + matrix_assign (scalar_assign (), *this, matrix (*this - ae)); return *this; } template BOOST_UBLAS_INLINE matrix_slice &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_slice& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE matrix_slice& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -4052,7 +3701,7 @@ namespace boost { namespace numeric { namespace ublas { if (this != &ms) { BOOST_UBLAS_CHECK (size1 () == ms.size1 (), bad_size ()); BOOST_UBLAS_CHECK (size2 () == ms.size2 (), bad_size ()); - matrix_swap > () (*this, ms); + matrix_swap (scalar_swap (), *this, ms); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -4062,27 +3711,6 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator, - BOOST_UBLAS_TYPENAME matrix_type::iterator1::iterator_category> iterator1; - typedef matrix_column_iterator, - BOOST_UBLAS_TYPENAME matrix_type::iterator2::iterator_category> iterator2; - typedef matrix_row_const_iterator, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator1::iterator_category> const_iterator1; - typedef matrix_column_const_iterator, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator2::iterator_category> const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, typename matrix_row > > const_reverse_iterator1; - typedef reverse_iterator_base >, typename matrix_row > > reverse_iterator1; - typedef reverse_iterator_base >, typename matrix_column > > const_reverse_iterator2; - typedef reverse_iterator_base >, typename matrix_column > > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1, BOOST_UBLAS_TYPENAME matrix_type::iterator1::iterator_category> iterator1; @@ -4108,110 +3736,77 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else return const_iterator1 (*this, s1_.begin () + i, s2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE iterator1 find_first1 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, i, j); #else return iterator1 (*this, s1_.begin () + i, s2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else return const_iterator1 (*this, s1_.begin () + i, s2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE iterator1 find_last1 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, i, j); #else return iterator1 (*this, s1_.begin () + i, s2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else return const_iterator2 (*this, s1_.begin () + i, s2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE iterator2 find_first2 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, i, j); #else return iterator2 (*this, s1_.begin () + i, s2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else return const_iterator2 (*this, s1_.begin () + i, s2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE iterator2 find_last2 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, i, j); #else return iterator2 (*this, s1_.begin () + i, s2_.begin () + j); -#endif #endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -4336,7 +3931,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator1: public container_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -4460,7 +4055,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -4585,7 +4180,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last2 (0, 0, size2 ()); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator2: public container_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -4832,10 +4427,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename M::const_reference const_reference; typedef typename M::reference reference; typedef typename M::const_pointer const_pointer; typedef typename M::pointer pointer; +#else + typedef typename M::const_reference const_reference; + typedef typename detail::ct_if::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const matrix_const_reference > const_closure_type; typedef matrix_reference > closure_type; @@ -4956,7 +4562,7 @@ namespace boost { namespace numeric { namespace ublas { // Assignment BOOST_UBLAS_INLINE matrix_indirect &operator = (const matrix_indirect &mi) { - matrix_assign > () (*this, mi); + matrix_assign (scalar_assign (), *this, mi); return *this; } BOOST_UBLAS_INLINE @@ -4966,49 +4572,49 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE matrix_indirect &operator = (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (ae)); + matrix_assign (scalar_assign (), *this, matrix (ae)); return *this; } template BOOST_UBLAS_INLINE matrix_indirect &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_indirect& operator += (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this + ae)); + matrix_assign (scalar_assign (), *this, matrix (*this + ae)); return *this; } template BOOST_UBLAS_INLINE matrix_indirect &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_indirect& operator -= (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this - ae)); + matrix_assign (scalar_assign (), *this, matrix (*this - ae)); return *this; } template BOOST_UBLAS_INLINE matrix_indirect &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_indirect& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE matrix_indirect& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -5020,7 +4626,7 @@ namespace boost { namespace numeric { namespace ublas { if (this != &mi) { BOOST_UBLAS_CHECK (size1 () == mi.size1 (), bad_size ()); BOOST_UBLAS_CHECK (size2 () == mi.size2 (), bad_size ()); - matrix_swap > () (*this, mi); + matrix_swap (scalar_swap (), *this, mi); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -5030,27 +4636,6 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator, - BOOST_UBLAS_TYPENAME matrix_type::iterator1::iterator_category> iterator1; - typedef matrix_column_iterator, - BOOST_UBLAS_TYPENAME matrix_type::iterator2::iterator_category> iterator2; - typedef matrix_row_const_iterator, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator1::iterator_category> const_iterator1; - typedef matrix_column_const_iterator, - BOOST_UBLAS_TYPENAME matrix_type::const_iterator2::iterator_category> const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base >, typename matrix_row > > const_reverse_iterator1; - typedef reverse_iterator_base >, typename matrix_row > > reverse_iterator1; - typedef reverse_iterator_base >, typename matrix_column > > const_reverse_iterator2; - typedef reverse_iterator_base >, typename matrix_column > > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1, BOOST_UBLAS_TYPENAME matrix_type::iterator1::iterator_category> iterator1; @@ -5076,110 +4661,77 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else return const_iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE iterator1 find_first1 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, i, j); #else return iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else return const_iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE iterator1 find_last1 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, i, j); #else return iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else return const_iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE iterator2 find_first2 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, i, j); #else return iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else return const_iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j); -#endif #endif } BOOST_UBLAS_INLINE iterator2 find_last2 (int rank, size_type i, size_type j) { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, i, j); #else return iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j); -#endif #endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -5304,7 +4856,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator1: public container_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -5428,7 +4980,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1 (), 0); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -5553,7 +5105,7 @@ namespace boost { namespace numeric { namespace ublas { return find_last2 (0, 0, size2 ()); } -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator2: public container_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS @@ -5753,7 +5305,7 @@ namespace boost { namespace numeric { namespace ublas { } #endif #endif - // These signatures are to general for MSVC + // These signatures are too general for MSVC // template // BOOST_UBLAS_INLINE // matrix_indirect project (M &data, const IA &ia1, const IA &ia2) { diff --git a/include/boost/numeric/ublas/matrix_sparse.hpp b/include/boost/numeric/ublas/matrix_sparse.hpp index 9e3d6c9f..8b1cf177 100644 --- a/include/boost/numeric/ublas/matrix_sparse.hpp +++ b/include/boost/numeric/ublas/matrix_sparse.hpp @@ -25,6 +25,148 @@ namespace boost { namespace numeric { namespace ublas { +#ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE + + template + class sparse_matrix_element: + public container_reference { + public: + typedef M matrix_type; + typedef typename M::size_type size_type; + typedef typename M::value_type value_type; + // typedef const value_type &const_reference; + typedef typename type_traits::const_reference const_reference; + typedef value_type &reference; + typedef value_type *pointer; + + // Construction and destruction + BOOST_UBLAS_INLINE + sparse_matrix_element (matrix_type &m, pointer it, size_type i, size_type j): + container_reference (m), it_ (it), i_ (i), j_ (j), d_ (*it) {} + BOOST_UBLAS_INLINE + sparse_matrix_element (matrix_type &v, size_type i, size_type j): + container_reference (v), it_ (), i_ (i), j_ (j), d_ () { + pointer it = (*this) ().find_element (i_, j_); + if (! it) + (*this) ().insert (i_, j_, d_); + else + d_ = *it; + } + BOOST_UBLAS_INLINE + ~sparse_matrix_element () { + if (! it_) + it_ = (*this) ().find_element (i_, j_); + BOOST_UBLAS_CHECK (it_, internal_logic ()); + *it_ = d_; + } + + // Assignment + template + BOOST_UBLAS_INLINE + sparse_matrix_element &operator = (const D &d) { + d_ = d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_matrix_element &operator = (const sparse_matrix_element &p) { + d_ = p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_matrix_element &operator = (const sparse_matrix_element &p) { + // d_ = value_type (p); + // return *this; + // } + template + BOOST_UBLAS_INLINE + sparse_matrix_element &operator += (const D &d) { + d_ += d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_matrix_element &operator += (const sparse_matrix_element &p) { + d_ += p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_matrix_element &operator += (const sparse_matrix_element &p) { + // d_ += value_type (p); + // return *this; + // } + template + BOOST_UBLAS_INLINE + sparse_matrix_element &operator -= (const D &d) { + d_ -= d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_matrix_element &operator -= (const sparse_matrix_element &p) { + d_ -= p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_matrix_element &operator -= (const sparse_matrix_element &p) { + // d_ -= value_type (p); + // return *this; + // } + template + BOOST_UBLAS_INLINE + sparse_matrix_element &operator *= (const D &d) { + d_ *= d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_matrix_element &operator *= (const sparse_matrix_element &p) { + d_ *= p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_matrix_element &operator *= (const sparse_matrix_element &p) { + // d_ *= value_type (p); + // return *this; + // } + template + BOOST_UBLAS_INLINE + sparse_matrix_element &operator /= (const D &d) { + d_ /= d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_matrix_element &operator /= (const sparse_matrix_element &p) { + d_ /= p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_matrix_element &operator /= (const sparse_matrix_element &p) { + // d_ /= value_type (p); + // return *this; + // } + + // Conversion + // FIXME: GCC 3.1 warn's, if enabled + // BOOST_UBLAS_INLINE + // operator const_reference () const { + // return d_; + // } + BOOST_UBLAS_INLINE + operator reference () { + return d_; + } + + private: + pointer it_; + size_type i_; + size_type j_; + value_type d_; + }; + +#endif + // Array based sparse matrix class template class sparse_matrix: @@ -38,9 +180,11 @@ namespace boost { namespace numeric { namespace ublas { typedef T value_type; // typedef const T &const_reference; typedef typename type_traits::const_reference const_reference; -#ifndef BOOST_UBLAS_STRICT_SPARSE_ELEMENT_ASSIGN +#if ! defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) && ! defined (BOOST_UBLAS_STRICT_MATRIX_SPARSE) typedef T &reference; -#else +#elif defined (BOOST_UBLAS_STRICT_MATRIX_SPARSE) + typedef sparse_matrix_element reference; +#elif defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) typedef typename map_traits::reference reference; #endif typedef const T *const_pointer; @@ -64,10 +208,7 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE sparse_matrix (size_type size1, size_type size2, size_type non_zeros = 0): size1_ (size1), size2_ (size2), non_zeros_ (non_zeros), data_ () { -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - non_zeros_ = std::max (non_zeros_, std::min (size1_, size2_)); - map_traits::reserve (data_, non_zeros_); -#endif + reserve (non_zeros_); } BOOST_UBLAS_INLINE sparse_matrix (const sparse_matrix &m): @@ -76,11 +217,8 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE sparse_matrix (const matrix_expression &ae, size_type non_zeros = 0): size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), non_zeros_ (non_zeros), data_ () { -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - non_zeros_ = std::max (non_zeros_, std::min (size1_, size2_)); - map_traits::reserve (data_, non_zeros_); -#endif - matrix_assign > () (*this, ae); + reserve (non_zeros_); + matrix_assign (scalar_assign (), *this, ae); } // Accessors @@ -110,14 +248,32 @@ namespace boost { namespace numeric { namespace ublas { void resize (size_type size1, size_type size2, size_type non_zeros = 0) { size1_ = size1; size2_ = size2; - non_zeros_ = non_zeros; + non_zeros_ = std::max (non_zeros, std::min (size1_, size2_)); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - non_zeros_ = std::max (non_zeros_, std::min (size1_, size2_)); map_traits::reserve (data (), non_zeros_); #endif data ().clear (); } + // Reserving + BOOST_UBLAS_INLINE + void reserve (size_type non_zeros = 0) { + non_zeros_ = std::max (non_zeros, std::min (size1_, size2_)); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + map_traits::reserve (data (), non_zeros_); +#endif + } + + // Proxy support +#ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE + pointer find_element (size_type i, size_type j) { + iterator_type it (data ().find (functor_type::element (i, size1_, j, size2_))); + if (it == data ().end () || (*it).first != functor_type::element (i, size1_, j, size2_)) + return 0; + return &(*it).second; + } +#endif + // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { @@ -128,7 +284,11 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { +#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE return data () [functor_type::element (i, size1_, j, size2_)]; +#else + return reference (*this, i, j); +#endif } // Assignment @@ -147,7 +307,7 @@ namespace boost { namespace numeric { namespace ublas { return *this; } BOOST_UBLAS_INLINE - sparse_matrix &assign_temporary (sparse_matrix &m) { + sparse_matrix &assign_temporary (sparse_matrix &m) { swap (m); return *this; } @@ -172,7 +332,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE sparse_matrix &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -189,7 +349,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE sparse_matrix &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -206,19 +366,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE sparse_matrix &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE sparse_matrix& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE sparse_matrix& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -248,10 +408,6 @@ namespace boost { namespace numeric { namespace ublas { // Element insertion and erasure BOOST_UBLAS_INLINE void insert (size_type i, size_type j, const_reference t) { -#ifdef BOOST_UBLAS_CHECK_FOR_ZERO - if (t == value_type ()) - return; -#endif BOOST_UBLAS_CHECK (data ().find (functor_type::element (i, size1_, j, size2_)) == data ().end (), bad_index ()); data ().insert (data ().end (), std::pair (functor_type::element (i, size1_, j, size2_), t)); } @@ -268,17 +424,10 @@ namespace boost { namespace numeric { namespace ublas { data ().clear (); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#else class const_iterator1; class iterator1; class const_iterator2; class iterator2; -#endif #ifdef BOOST_MSVC_STD_ITERATOR typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base1 reverse_iterator1; @@ -318,11 +467,7 @@ namespace boost { namespace numeric { namespace ublas { i = size1_; rank = 0; } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, rank, i, j, it); -#endif } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE @@ -350,11 +495,7 @@ namespace boost { namespace numeric { namespace ublas { i = size1_; rank = 0; } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, rank, i, j, it); -#endif } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE @@ -383,11 +524,7 @@ namespace boost { namespace numeric { namespace ublas { j = size2_; rank = 0; } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, rank, i, j, it); -#endif } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE @@ -416,11 +553,7 @@ namespace boost { namespace numeric { namespace ublas { j = size2_; rank = 0; } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, rank, i, j, it); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { @@ -457,10 +590,9 @@ namespace boost { namespace numeric { namespace ublas { // Iterators simply are pointers. -#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR class const_iterator1: public container_const_reference, - public bidirectional_iterator_base { public: typedef sparse_bidirectional_iterator_tag iterator_category; @@ -586,7 +718,6 @@ namespace boost { namespace numeric { namespace ublas { size_type j_; const_iterator_type it_; }; -#endif BOOST_UBLAS_INLINE const_iterator1 begin1 () const { @@ -597,7 +728,6 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1_, 0); } -#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR class iterator1: public container_reference, public bidirectional_iterator_base::make_reference ((*this) ().data (), it_); #endif } else { @@ -727,7 +859,6 @@ namespace boost { namespace numeric { namespace ublas { friend class const_iterator1; }; -#endif BOOST_UBLAS_INLINE iterator1 begin1 () { @@ -738,7 +869,6 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1_, 0); } -#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR class const_iterator2: public container_const_reference, public bidirectional_iterator_base, public bidirectional_iterator_base::make_reference ((*this) ().data (), it_); #endif } else { @@ -941,12 +1071,12 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE iterator1 begin () const { sparse_matrix &m = (*this) (); - return m.find_first1 (1, 0, index2 ()); + return m.find_first1 (1, 0, index2 ()); } BOOST_UBLAS_INLINE iterator1 end () const { sparse_matrix &m = (*this) (); - return m.find_last1 (1, m.size1 (), index2 ()); + return m.find_last1 (1, m.size1 (), index2 ()); } BOOST_UBLAS_INLINE reverse_iterator1 rbegin () const { @@ -1008,7 +1138,6 @@ namespace boost { namespace numeric { namespace ublas { friend class const_iterator2; }; -#endif BOOST_UBLAS_INLINE iterator2 begin2 () { @@ -1081,9 +1210,11 @@ namespace boost { namespace numeric { namespace ublas { typedef T value_type; // typedef const T &const_reference; typedef typename type_traits::const_reference const_reference; -#ifndef BOOST_UBLAS_STRICT_SPARSE_ELEMENT_ASSIGN +#if ! defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) && ! defined (BOOST_UBLAS_STRICT_MATRIX_SPARSE) typedef T &reference; -#else +#elif defined (BOOST_UBLAS_STRICT_MATRIX_SPARSE) + typedef sparse_matrix_element reference; +#elif defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) typedef typename map_traits::reference reference; #endif typedef const T *const_pointer; @@ -1121,7 +1252,7 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE sparse_vector_of_sparse_vector (const matrix_expression &ae, size_type non_zeros = 0): size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), non_zeros_ (non_zeros), data_ () { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); } // Accessors @@ -1159,6 +1290,19 @@ namespace boost { namespace numeric { namespace ublas { data () [functor_type::size1 (size1_, size2_)] = vector_data_value_type (); } + // Proxy support +#ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE + pointer find_element (size_type i, size_type j) { + vector_iterator_type itv (data ().find (functor_type::element1 (i, size1_, j, size2_))); + if (itv == data ().end () || (*itv).first != functor_type::element1 (i, size1_, j, size2_)) + return 0; + iterator_type it ((*itv).second.find (functor_type::element2 (i, size1_, j, size2_))); + if (it == (*itv).second.end () || (*it).first != functor_type::element2 (i, size1_, j, size2_)) + return 0; + return &(*it).second; + } +#endif + // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { @@ -1172,7 +1316,11 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { +#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE return data () [functor_type::element1 (i, size1_, j, size2_)] [functor_type::element2 (i, size1_, j, size2_)]; +#else + return reference (*this, i, j); +#endif } // Assignment @@ -1216,7 +1364,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE sparse_vector_of_sparse_vector &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -1233,7 +1381,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE sparse_vector_of_sparse_vector &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -1250,19 +1398,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE sparse_vector_of_sparse_vector &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE sparse_vector_of_sparse_vector& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE sparse_vector_of_sparse_vector& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -1292,12 +1440,8 @@ namespace boost { namespace numeric { namespace ublas { // Element insertion and erasure BOOST_UBLAS_INLINE void insert (size_type i, size_type j, const_reference t) { -#ifdef BOOST_UBLAS_CHECK_FOR_ZERO - if (t == value_type ()) - return; -#endif vector_iterator_type itv (data ().find (functor_type::element1 (i, size1_, j, size2_))); - if (itv == data ().end ()) + if (itv == data ().end ()) itv = data ().insert (data ().end (), std::pair (functor_type::element1 (i, size1_, j, size2_), vector_data_value_type ())); BOOST_UBLAS_CHECK ((*itv).second.find (functor_type::element2 (i, size1_, j, size2_)) == (*itv).second.end (), bad_index ()); (*itv).second.insert ((*itv).second.end (), std::pair (functor_type::element2 (i, size1_, j, size2_), t)); @@ -1305,7 +1449,7 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE void erase (size_type i, size_type j) { vector_iterator_type itv (data ().find (functor_type::element1 (i, size1_, j, size2_))); - if (itv == data ().end ()) + if (itv == data ().end ()) return; iterator_type it ((*itv).second.find (functor_type::element2 (i, size1_, j, size2_))); if (it == (*itv).second.end ()) @@ -1317,17 +1461,10 @@ namespace boost { namespace numeric { namespace ublas { data ().clear (); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#else class const_iterator1; class iterator1; class const_iterator2; class iterator2; -#endif #ifdef BOOST_MSVC_STD_ITERATOR typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base1 reverse_iterator1; @@ -1349,11 +1486,7 @@ namespace boost { namespace numeric { namespace ublas { vector_const_iterator_type itv (data ().lower_bound (functor_type::element1 (i, size1_, j, size2_))); vector_const_iterator_type itv_end (data ().end ()); if (itv == itv_end) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); -#endif const_iterator_type it ((*itv).second.lower_bound (functor_type::element2 (i, size1_, j, size2_))); const_iterator_type it_end ((*itv).second.end ()); @@ -1366,22 +1499,11 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); if ((rank == 0 && index2 >= j) || (rank == 1 && index2 == j)) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, rank, i, j, itv, it); -#endif } - if (rank == 0 || i >= size1_) { - if (rank == 1) - rank = 0; -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else - return const_iterator1 (*this, rank, i, j, itv, it_end); -#endif - } + if (rank == 0 || i >= size1_) + return const_iterator1 (*this, 0, i, j, itv, it_end); ++ i; } } @@ -1393,11 +1515,7 @@ namespace boost { namespace numeric { namespace ublas { vector_iterator_type itv (data ().lower_bound (functor_type::element1 (i, size1_, j, size2_))); vector_iterator_type itv_end (data ().end ()); if (itv == itv_end) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); -#endif iterator_type it ((*itv).second.lower_bound (functor_type::element2 (i, size1_, j, size2_))); iterator_type it_end ((*itv).second.end ()); @@ -1410,22 +1528,11 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); if ((rank == 0 && index2 >= j) || (rank == 1 && index2 == j)) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, rank, i, j, itv, it); -#endif } - if (rank == 0 || i >= size1_) { - if (rank == 1) - rank = 0; -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else - return iterator1 (*this, rank, i, j, itv, it_end); -#endif - } + if (rank == 0 || i >= size1_) + return iterator1 (*this, 0, i, j, itv, it_end); ++ i; } } @@ -1437,11 +1544,7 @@ namespace boost { namespace numeric { namespace ublas { vector_const_iterator_type itv (data ().lower_bound (functor_type::element1 (i, size1_, j, size2_))); vector_const_iterator_type itv_end (data ().end ()); if (itv == itv_end) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); -#endif const_iterator_type it ((*itv).second.lower_bound (functor_type::element2 (i, size1_, j, size2_))); const_iterator_type it_end ((*itv).second.end ()); @@ -1454,22 +1557,11 @@ namespace boost { namespace numeric { namespace ublas { #endif if ((rank == 0 && index1 >= i) || (rank == 1 && index1 == i)) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, rank, i, j, itv, it); -#endif } - if (rank == 0 || j >= size2_) { - if (rank == 1) - rank = 0; -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else - return const_iterator2 (*this, rank, i, j, itv, it_end); -#endif - } + if (rank == 0 || j >= size2_) + return const_iterator2 (*this, 0, i, j, itv, it_end); ++ j; } } @@ -1481,11 +1573,7 @@ namespace boost { namespace numeric { namespace ublas { vector_iterator_type itv (data ().lower_bound (functor_type::element1 (i, size1_, j, size2_))); vector_iterator_type itv_end (data ().end ()); if (itv == itv_end) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); -#endif iterator_type it ((*itv).second.lower_bound (functor_type::element2 (i, size1_, j, size2_))); iterator_type it_end ((*itv).second.end ()); @@ -1498,22 +1586,11 @@ namespace boost { namespace numeric { namespace ublas { #endif if ((rank == 0 && index1 >= i) || (rank == 1 && index1 == i)) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, rank, i, j, itv, it); -#endif } - if (rank == 0 || j >= size2_) { - if (rank == 1) - rank = 0; -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else - return iterator2 (*this, rank, i, j, itv, it_end); -#endif - } + if (rank == 0 || j >= size2_) + return iterator2 (*this, 0, i, j, itv, it_end); ++ j; } } @@ -1552,7 +1629,6 @@ namespace boost { namespace numeric { namespace ublas { // Iterators simply are pointers. -#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR class const_iterator1: public container_const_reference, public bidirectional_iterator_base, public bidirectional_iterator_base::make_reference ((*itv_).second, it_); +#endif } else { return (*this) () (i_, j_); } @@ -1783,12 +1863,12 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE iterator2 begin () const { sparse_vector_of_sparse_vector &m = (*this) (); - return m.find_first2 (1, index1 (), 0); + return m.find_first2 (1, index1 (), 0); } BOOST_UBLAS_INLINE iterator2 end () const { sparse_vector_of_sparse_vector &m = (*this) (); - return m.find_last2 (1, index1 (), m.size2 ()); + return m.find_last2 (1, index1 (), m.size2 ()); } BOOST_UBLAS_INLINE reverse_iterator2 rbegin () const { @@ -1850,7 +1930,6 @@ namespace boost { namespace numeric { namespace ublas { friend class const_iterator1; }; -#endif BOOST_UBLAS_INLINE iterator1 begin1 () { @@ -1861,7 +1940,6 @@ namespace boost { namespace numeric { namespace ublas { return find_last1 (0, size1_, 0); } -#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR class const_iterator2: public container_const_reference, public bidirectional_iterator_base, public bidirectional_iterator_base::make_reference ((*itv_).second, it_); +#endif } else { return (*this) () (i_, j_); } @@ -2159,7 +2241,6 @@ namespace boost { namespace numeric { namespace ublas { friend class const_iterator2; }; -#endif BOOST_UBLAS_INLINE iterator2 begin2 () { @@ -2220,26 +2301,31 @@ namespace boost { namespace numeric { namespace ublas { typename sparse_vector_of_sparse_vector::value_type sparse_vector_of_sparse_vector::zero_ = 0; // Array based sparse matrix class - template + // Thanks to Kresimir Fresl for extending this to cover different index bases. + template class compressed_matrix: - public matrix_expression > { + public matrix_expression > { public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - BOOST_UBLAS_USING matrix_expression >::operator (); + BOOST_UBLAS_USING matrix_expression >::operator (); #endif typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef T value_type; // typedef const T &const_reference; typedef typename type_traits::const_reference const_reference; +#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE typedef T &reference; +#else + typedef sparse_matrix_element reference; +#endif typedef const T *const_pointer; typedef T *pointer; typedef IA index_array_type; typedef TA value_array_type; typedef F functor_type; - typedef const compressed_matrix const_self_type; - typedef compressed_matrix self_type; + typedef const compressed_matrix const_self_type; + typedef compressed_matrix self_type; typedef const matrix_const_reference const_closure_type; typedef matrix_reference closure_type; typedef typename IA::const_iterator vector_const_iterator_type; @@ -2251,51 +2337,53 @@ namespace boost { namespace numeric { namespace ublas { // Construction and destruction BOOST_UBLAS_INLINE - compressed_matrix (): - size1_ (0), size2_ (0), non_zeros_ (0), - filled1_ (0), filled2_ (0), - index1_data_ (), + compressed_matrix (): + size1_ (0), size2_ (0), non_zeros_ (0), + filled1_ (1), filled2_ (0), + index1_data_ (1), index2_data_ (), value_data_ () { - index1_data_.clear (); + index1_data_ [filled1_ - 1] = k_based (filled2_); } BOOST_UBLAS_INLINE - compressed_matrix (size_type size1, size_type size2, size_type non_zeros = 0): + compressed_matrix (size_type size1, size_type size2, size_type non_zeros = 0): size1_ (size1), size2_ (size2), non_zeros_ (non_zeros), - filled1_ (0), filled2_ (0), - index1_data_ (functor_type::size1 (size1_, size2_)), + filled1_ (1), filled2_ (0), + index1_data_ (functor_type::size1 (size1_, size2_) + 1), index2_data_ (non_zeros), value_data_ (non_zeros) { - index1_data_.clear (); + index1_data_ [filled1_ - 1] = k_based (filled2_); + reserve (non_zeros_); } BOOST_UBLAS_INLINE compressed_matrix (const compressed_matrix &m): - size1_ (m.size1_), size2_ (m.size2_), non_zeros_ (m.non_zeros_), + size1_ (m.size1_), size2_ (m.size2_), non_zeros_ (m.non_zeros_), filled1_ (m.filled1_), filled2_ (m.filled2_), - index1_data_ (m.index1_data_), + index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) { - index1_data_.clear (); + BOOST_UBLAS_CHECK (index1_data_ [filled1_ - 1] == k_based (filled2_), internal_logic ()); } template BOOST_UBLAS_INLINE - compressed_matrix (const matrix_expression &ae, size_type non_zeros = 0): - size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), non_zeros_ (non_zeros), - filled1_ (0), filled2_ (0), - index1_data_ (functor_type::size1 (ae ().size1 (), ae ().size2 ())), + compressed_matrix (const matrix_expression &ae, size_type non_zeros = 0): + size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), non_zeros_ (non_zeros), + filled1_ (1), filled2_ (0), + index1_data_ (functor_type::size1 (ae ().size1 (), ae ().size2 ()) + 1), index2_data_ (non_zeros), value_data_ (non_zeros) { - index1_data_.clear (); - matrix_assign > () (*this, ae); + index1_data_ [filled1_ - 1] = k_based (filled2_); + reserve (non_zeros_); + matrix_assign (scalar_assign (), *this, ae); } // Accessors BOOST_UBLAS_INLINE - size_type size1 () const { + size_type size1 () const { return size1_; } BOOST_UBLAS_INLINE - size_type size2 () const { + size_type size2 () const { return size2_; } BOOST_UBLAS_INLINE - size_type non_zeros () const { + size_type non_zeros () const { return non_zeros_; } BOOST_UBLAS_INLINE @@ -2322,58 +2410,91 @@ namespace boost { namespace numeric { namespace ublas { value_array_type &value_data () { return value_data_; } + BOOST_UBLAS_INLINE + size_type index_base () { + return index_base_; + } // Resizing BOOST_UBLAS_INLINE void resize (size_type size1, size_type size2, size_type non_zeros = 0) { size1_ = size1; size2_ = size2; - non_zeros_ = non_zeros; - filled1_ = 0; + non_zeros_ = std::max (non_zeros, std::min (size1_, size2_)); + filled1_ = 1; filled2_ = 0; - index1_data ().resize (functor_type::size1 (size1, size2)); - index2_data ().resize (non_zeros); - value_data ().resize (non_zeros); - index1_data ().clear (); + index1_data ().resize (functor_type::size1 (size1, size2) + 1); + index2_data ().resize (non_zeros_); + value_data ().resize (non_zeros_); + index1_data_ [filled1_ - 1] = k_based (filled2_); } + // Reserving + BOOST_UBLAS_INLINE + void reserve (size_type non_zeros = 0, bool preserve = false) { + non_zeros_ = std::max (non_zeros, std::min (size1_, size2_)); + index2_data ().resize (non_zeros_, preserve); + value_data ().resize (non_zeros_, preserve); + } + + // Proxy support +#ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE + pointer find_element (size_type i, size_type j) { + size_type element1 (functor_type::element1 (i, size1_, j, size2_)); + size_type element2 (functor_type::element2 (i, size1_, j, size2_)); + if (filled1_ <= element1 + 1) + return 0; + vector_const_iterator_type itv (index1_data ().begin () + element1); + const_iterator_type it_begin (index2_data ().begin () + zero_based (*itv)); + const_iterator_type it_end (index2_data ().begin () + zero_based (*(itv + 1))); + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + if (it == it_end || *it != k_based (element2)) + return 0; + return &value_data () [it - index2_data ().begin ()]; + } +#endif + // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { size_type element1 (functor_type::element1 (i, size1_, j, size2_)); size_type element2 (functor_type::element2 (i, size1_, j, size2_)); - vector_const_iterator_type itv (index1_data ().begin () + element1); - if (filled1_ <= element1) + if (filled1_ <= element1 + 1) return zero_; - const_iterator_type it_begin (index2_data ().begin () + *itv - 1); - const_iterator_type it_end (index2_data ().begin () + filled2_); - if (filled1_ > element1 + 1) - it_end = index2_data ().begin () + *(itv + 1) - 1; - const_iterator_type it (std::lower_bound (it_begin, it_end, element2 + 1, std::less ())); - if (it == it_end || *it != element2 + 1) + vector_const_iterator_type itv (index1_data ().begin () + element1); + const_iterator_type it_begin (index2_data ().begin () + zero_based (*itv)); + const_iterator_type it_end (index2_data ().begin () + zero_based (*(itv + 1))); + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + if (it == it_end || *it != k_based (element2)) return zero_; return value_data () [it - index2_data ().begin ()]; } BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { +#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE size_type element1 (functor_type::element1 (i, size1_, j, size2_)); size_type element2 (functor_type::element2 (i, size1_, j, size2_)); + if (filled1_ <= element1 + 1) + insert (i, j, value_type ()); vector_const_iterator_type itv (index1_data ().begin () + element1); - if (filled1_ <= element1) - insert (i, j, value_type ()); - const_iterator_type it_begin (index2_data ().begin () + *itv - 1); - const_iterator_type it_end (index2_data ().begin () + filled2_); - if (filled1_ > element1 + 1) - it_end = index2_data ().begin () + *(itv + 1) - 1; - const_iterator_type it (std::lower_bound (it_begin, it_end, element2 + 1, std::less ())); - if (it == it_end || *it != element2 + 1) + const_iterator_type it_begin (index2_data ().begin () + zero_based (*itv)); + const_iterator_type it_end (index2_data ().begin () + zero_based (*(itv + 1)); + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + if (it == it_end || *it != k_based (element2)) { insert (i, j, value_type ()); + it_begin = index2_data ().begin () + zero_based (*itv); + it_end = index2_data ().begin () + zero_based (*(itv + 1)); + it = detail::lower_bound (it_begin, it_end, k_based (element2), std::less ()); + } return value_data () [it - index2_data ().begin ()]; +#else + return reference (*this, i, j); +#endif } // Assignment BOOST_UBLAS_INLINE - compressed_matrix &operator = (const compressed_matrix &m) { + compressed_matrix &operator = (const compressed_matrix &m) { // Too unusual semantic. // BOOST_UBLAS_CHECK (this != &m, external_logic ()); if (this != &m) { @@ -2385,13 +2506,15 @@ namespace boost { namespace numeric { namespace ublas { filled1_ = m.filled1_; filled2_ = m.filled2_; index1_data () = m.index1_data (); + index2_data ().resize (non_zeros_); index2_data () = m.index2_data (); + value_data ().resize (non_zeros_); value_data () = m.value_data (); } return *this; } BOOST_UBLAS_INLINE - compressed_matrix &assign_temporary (compressed_matrix &m) { + compressed_matrix &assign_temporary (compressed_matrix &m) { swap (m); return *this; } @@ -2416,7 +2539,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE compressed_matrix &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -2432,8 +2555,8 @@ namespace boost { namespace numeric { namespace ublas { } template BOOST_UBLAS_INLINE - compressed_matrix &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + compressed_matrix &plus_assign (const matrix_expression &ae) { + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -2449,20 +2572,20 @@ namespace boost { namespace numeric { namespace ublas { } template BOOST_UBLAS_INLINE - compressed_matrix &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + compressed_matrix &minus_assign (const matrix_expression &ae) { + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE compressed_matrix& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE compressed_matrix& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -2495,58 +2618,113 @@ namespace boost { namespace numeric { namespace ublas { // Element insertion and erasure BOOST_UBLAS_INLINE - void insert (size_type i, size_type j, const_reference t) { -// FIXME: Doesn't work if the first element is zero. -// #ifdef BOOST_UBLAS_CHECK_FOR_ZERO -// if (t == value_type ()) -// return; -// #endif + void push_back (size_type i, size_type j, const_reference t) { + BOOST_UBLAS_CHECK (index1_data () [filled1_ - 1] == k_based (filled2_), internal_logic ()); + if (filled2_ >= non_zeros_) + reserve (2 * non_zeros_, true); size_type element1 = functor_type::element1 (i, size1_, j, size2_); size_type element2 = functor_type::element2 (i, size1_, j, size2_); - if (filled1_ < element1 + 1) { - do { - index1_data () [filled1_] = filled2_ + 1; - } while (++ filled1_ < element1 + 1); - } else { - BOOST_UBLAS_CHECK (filled1_ - 1 == element1, external_logic ()); - BOOST_UBLAS_CHECK (index2_data () [filled2_ - 1] < element2 + 1, external_logic ()); + while (filled1_ < element1 + 2) { + index1_data () [filled1_] = k_based (filled2_); + ++ filled1_; } - index2_data () [filled2_] = element2 + 1; - value_data () [filled2_] = t; + if (filled1_ == element1 + 2 && + (filled2_ == zero_based (index1_data () [filled1_ - 2]) || + index2_data () [filled2_ - 1] < k_based (element2))) { + ++ filled2_; + index1_data () [filled1_ - 1] = k_based (filled2_); + index2_data () [filled2_ - 1] = k_based (element2); + value_data () [filled2_ - 1] = t; + BOOST_UBLAS_CHECK (index1_data () [filled1_ - 1] == k_based (filled2_), internal_logic ()); + return; + } + // Raising exceptions abstracted as requested during review. + // throw external_logic (); + external_logic ().raise (); + } + BOOST_UBLAS_INLINE + void insert (size_type i, size_type j, const_reference t) { + BOOST_UBLAS_CHECK (index1_data () [filled1_ - 1] == k_based (filled2_), internal_logic ()); + if (filled2_ >= non_zeros_) + reserve (2 * non_zeros_, true); + size_type element1 = functor_type::element1 (i, size1_, j, size2_); + size_type element2 = functor_type::element2 (i, size1_, j, size2_); + while (filled1_ < element1 + 2) { + index1_data () [filled1_] = k_based (filled2_); + ++ filled1_; + } + vector_iterator_type itv (index1_data ().begin () + element1); + iterator_type it_begin (index2_data ().begin () + zero_based (*itv)); + iterator_type it_end (index2_data ().begin () + zero_based (*(itv + 1))); + iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + difference_type n = it - index2_data ().begin (); + BOOST_UBLAS_CHECK (it == it_end || *it != k_based (element2), external_logic ()); ++ filled2_; + it = index2_data ().begin () + n; + std::copy_backward (it, index2_data ().begin () + filled2_ - 1, index2_data ().begin () + filled2_); + *it = k_based (element2); + typename value_array_type::iterator itt (value_data ().begin () + n); + std::copy_backward (itt, value_data ().begin () + filled2_ - 1, value_data ().begin () + filled2_); + *itt = t; + while (element1 + 1 < filled1_) { + ++ index1_data () [element1 + 1]; + ++ element1; + } + BOOST_UBLAS_CHECK (index1_data () [filled1_ - 1] == k_based (filled2_), internal_logic ()); + } + BOOST_UBLAS_INLINE + void pop_back () { + BOOST_UBLAS_CHECK (index1_data () [filled1_ - 1] == k_based (filled2_), internal_logic ()); + if (filled2_ > zero_based (index1_data () [filled1_ - 2])) { + -- filled2_; + while (index1_data () [filled1_ - 2] > k_based (filled2_)) { + index1_data () [filled1_ - 1] = 0; + -- filled1_; + } + BOOST_UBLAS_CHECK (index1_data () [filled1_ - 1] == k_based (filled2_), internal_logic ()); + return; + } + // Raising exceptions abstracted as requested during review. + // throw external_logic (); + external_logic ().raise (); } BOOST_UBLAS_INLINE void erase (size_type i, size_type j) { -#ifdef BOOST_UBLAS_BOUNDS_CHECK + BOOST_UBLAS_CHECK (index1_data () [filled1_ - 1] == k_based (filled2_), internal_logic ()); size_type element1 = functor_type::element1 (i, size1_, j, size2_); - BOOST_UBLAS_CHECK (filled1_ == element1 + 1, external_logic ()); size_type element2 = functor_type::element2 (i, size1_, j, size2_); - BOOST_UBLAS_CHECK (filled2_ > 0 && index2_data () [filled2_ - 1] == element2 + 1, external_logic ()); -#endif - -- filled2_; - if (index1_data () [filled1_ - 1] > filled2_ + 1) { - index1_data () [filled1_ - 1] = 0; - -- filled1_; + vector_iterator_type itv (index1_data ().begin () + element1); + iterator_type it_begin (index2_data ().begin () + zero_based (*itv)); + iterator_type it_end (index2_data ().begin () + zero_based (*(itv + 1))); + iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + difference_type n = it - index2_data ().begin (); + if (filled2_ > size_type (n) && *it == k_based (element2)) { + std::copy (it + 1, index2_data ().begin () + filled2_, it); + typename value_array_type::iterator itt (value_data ().begin () + n); + std::copy (itt + 1, value_data ().begin () + filled2_, itt); + -- filled2_; + while (index1_data () [filled1_ - 2] > k_based (filled2_)) { + index1_data () [filled1_ - 1] = 0; + -- filled1_; + } + while (element1 + 1 < filled1_) { + -- index1_data () [element1 + 1]; + ++ element1; + } } + BOOST_UBLAS_CHECK (index1_data () [filled1_ - 1] == k_based (filled2_), internal_logic ()); } BOOST_UBLAS_INLINE void clear () { - filled1_ = 0; + filled1_ = 1; filled2_ = 0; - index1_data ().clear (); + index1_data_ [filled1_ - 1] = k_based (filled2_); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#else class const_iterator1; class iterator1; class const_iterator2; class iterator2; -#endif #ifdef BOOST_MSVC_STD_ITERATOR typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base1 reverse_iterator1; @@ -2566,45 +2744,28 @@ namespace boost { namespace numeric { namespace ublas { for (;;) { size_type element1 (functor_type::element1 (i, size1_, j, size2_)); size_type element2 (functor_type::element2 (i, size1_, j, size2_)); - vector_const_iterator_type itv (index1_data ().begin () + std::min (filled1_, element1)); - if (filled1_ <= element1) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else + vector_const_iterator_type itv (index1_data ().begin () + std::min (filled1_ - 1, element1)); + if (filled1_ <= element1 + 1) return const_iterator1 (*this, rank, i, j, itv, index2_data ().begin () + filled2_); -#endif - const_iterator_type it_begin (index2_data ().begin () + *itv - 1); - const_iterator_type it_end (index2_data ().begin () + filled2_); - if (filled1_ > element1 + 1) - it_end = index2_data ().begin () + *(itv + 1) - 1; + const_iterator_type it_begin (index2_data ().begin () + zero_based (*itv)); + const_iterator_type it_end (index2_data ().begin () + zero_based (*(itv + 1))); - const_iterator_type it (std::lower_bound (it_begin, it_end, element2 + 1, std::less ())); + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); if (it != it_end) { #ifdef BOOST_UBLAS_BOUNDS_CHECK - size_type index1 (functor_type::index1 (itv - index1_data ().begin (), (*it) - 1)); + size_type index1 (functor_type::index1 (itv - index1_data ().begin (), zero_based (*it))); BOOST_UBLAS_CHECK (index1 >= i, internal_logic ()); #endif - size_type index2 (functor_type::index2 (itv - index1_data ().begin (), (*it) - 1)); + size_type index2 (functor_type::index2 (itv - index1_data ().begin (), zero_based (*it))); BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); if ((rank == 0 && index2 >= j) || (rank == 1 && index2 == j)) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, rank, i, j, itv, it); -#endif } - if (rank == 0 || i >= size1_) { - if (rank == 1) - rank = 0; -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else - return const_iterator1 (*this, rank, i, j, itv, it_end); -#endif - } + if (rank == 0 || i >= size1_) + return const_iterator1 (*this, 0, i, j, itv, it_end); ++ i; } } @@ -2614,45 +2775,28 @@ namespace boost { namespace numeric { namespace ublas { for (;;) { size_type element1 (functor_type::element1 (i, size1_, j, size2_)); size_type element2 (functor_type::element2 (i, size1_, j, size2_)); - vector_iterator_type itv (index1_data ().begin () + std::min (filled1_, element1)); - if (filled1_ <= element1) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else + vector_iterator_type itv (index1_data ().begin () + std::min (filled1_ - 1, element1)); + if (filled1_ <= element1 + 1) return iterator1 (*this, rank, i, j, itv, index2_data ().begin () + filled2_); -#endif - iterator_type it_begin (index2_data ().begin () + *itv - 1); - iterator_type it_end (index2_data ().begin () + filled2_); - if (filled1_ > element1 + 1) - it_end = index2_data ().begin () + *(itv + 1) - 1; + iterator_type it_begin (index2_data ().begin () + zero_based (*itv)); + iterator_type it_end (index2_data ().begin () + zero_based (*(itv + 1))); - iterator_type it (std::lower_bound (it_begin, it_end, element2 + 1, std::less ())); + iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); if (it != it_end) { #ifdef BOOST_UBLAS_BOUNDS_CHECK - size_type index1 (functor_type::index1 (itv - index1_data ().begin (), (*it) - 1)); + size_type index1 (functor_type::index1 (itv - index1_data ().begin (), zero_based (*it))); BOOST_UBLAS_CHECK (index1 >= i, internal_logic ()); #endif - size_type index2 (functor_type::index2 (itv - index1_data ().begin (), (*it) - 1)); + size_type index2 (functor_type::index2 (itv - index1_data ().begin (), zero_based (*it))); BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); if ((rank == 0 && index2 >= j) || (rank == 1 && index2 == j)) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, rank, i, j, itv, it); -#endif } - if (rank == 0 || i == size1_) { - if (rank == 1) - rank = 0; -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else - return iterator1 (*this, rank, i, j, itv, it_end); -#endif - } + if (rank == 0 || i >= size1_) + return iterator1 (*this, 0, i, j, itv, it_end); ++ i; } } @@ -2662,45 +2806,28 @@ namespace boost { namespace numeric { namespace ublas { for (;;) { size_type element1 (functor_type::element1 (i, size1_, j, size2_)); size_type element2 (functor_type::element2 (i, size1_, j, size2_)); - vector_const_iterator_type itv (index1_data ().begin () + std::min (filled1_, element1)); - if (filled1_ <= element1) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else + vector_const_iterator_type itv (index1_data ().begin () + std::min (filled1_ - 1, element1)); + if (filled1_ <= element1 + 1) return const_iterator2 (*this, rank, i, j, itv, index2_data ().begin () + filled2_); -#endif - const_iterator_type it_begin (index2_data ().begin () + *itv - 1); - const_iterator_type it_end (index2_data ().begin () + filled2_); - if (filled1_ > element1 + 1) - it_end = index2_data ().begin () + *(itv + 1) - 1; + const_iterator_type it_begin (index2_data ().begin () + zero_based (*itv)); + const_iterator_type it_end (index2_data ().begin () + zero_based (*(itv + 1))); - const_iterator_type it (std::lower_bound (it_begin, it_end, element2 + 1, std::less ())); + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); if (it != it_end) { - size_type index1 (functor_type::index1 (itv - index1_data ().begin (), (*it) - 1)); + size_type index1 (functor_type::index1 (itv - index1_data ().begin (), zero_based (*it))); BOOST_UBLAS_CHECK (index1 >= i, internal_logic ()); #ifdef BOOST_UBLAS_BOUNDS_CHECK - size_type index2 (functor_type::index2 (itv - index1_data ().begin (), (*it) - 1)); + size_type index2 (functor_type::index2 (itv - index1_data ().begin (), zero_based (*it))); BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); #endif if ((rank == 0 && index1 >= i) || (rank == 1 && index1 == i)) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, rank, i, j, itv, it); -#endif } - if (rank == 0 || j == size2_) { - if (rank == 1) - rank = 0; -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else - return const_iterator2 (*this, rank, i, j, itv, it_end); -#endif - } + if (rank == 0 || j >= size2_) + return const_iterator2 (*this, 0, i, j, itv, it_end); ++ j; } } @@ -2710,45 +2837,28 @@ namespace boost { namespace numeric { namespace ublas { for (;;) { size_type element1 (functor_type::element1 (i, size1_, j, size2_)); size_type element2 (functor_type::element2 (i, size1_, j, size2_)); - vector_iterator_type itv (index1_data ().begin () + std::min (filled1_, element1)); - if (filled1_ <= element1) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else + vector_iterator_type itv (index1_data ().begin () + std::min (filled1_ - 1, element1)); + if (filled1_ <= element1 + 1) return iterator2 (*this, rank, i, j, itv, index2_data ().begin () + filled2_); -#endif - iterator_type it_begin (index2_data ().begin () + *itv - 1); - iterator_type it_end (index2_data ().begin () + filled2_); - if (filled1_ > element1 + 1) - it_end = index2_data ().begin () + *(itv + 1) - 1; + iterator_type it_begin (index2_data ().begin () + zero_based (*itv)); + iterator_type it_end (index2_data ().begin () + zero_based (*(itv + 1))); - iterator_type it (std::lower_bound (it_begin, it_end, element2 + 1, std::less ())); + iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); if (it != it_end) { - size_type index1 (functor_type::index1 (itv - index1_data ().begin (), (*it) - 1)); + size_type index1 (functor_type::index1 (itv - index1_data ().begin (), zero_based (*it))); BOOST_UBLAS_CHECK (index1 >= i, internal_logic ()); #ifdef BOOST_UBLAS_BOUNDS_CHECK - size_type index2 (functor_type::index2 (itv - index1_data ().begin (), (*it) - 1)); + size_type index2 (functor_type::index2 (itv - index1_data ().begin (), zero_based (*it))); BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); #endif if ((rank == 0 && index1 >= i) || (rank == 1 && index1 == i)) -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, rank, i, j, itv, it); -#endif } - if (rank == 0 || j == size2_) { - if (rank == 1) - rank = 0; -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else - return iterator2 (*this, rank, i, j, itv, it_end); -#endif - } + if (rank == 0 || j >= size2_) + return iterator2 (*this, 0, i, j, itv, it_end); ++ j; } } @@ -2787,7 +2897,6 @@ namespace boost { namespace numeric { namespace ublas { // Iterators simply are pointers. -#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR class const_iterator1: public container_const_reference, public bidirectional_iterator_base, public bidirectional_iterator_base, public bidirectional_iterator_base, public bidirectional_iterator_base - typename compressed_matrix::value_type compressed_matrix::zero_ = 0; + template + typename compressed_matrix::value_type compressed_matrix::zero_ = 0; -#ifdef BOOST_UBLAS_USE_SPARSE_MATRIX_PROD_SPECIALIZATION - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct matrix_vector_binary1_traits, - T2, E2> { + // Array based sparse matrix class + // Thanks to Kresimir Fresl for extending this to cover different index bases. + template + class coordinate_matrix: + public matrix_expression > { + public: +#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS + BOOST_UBLAS_USING matrix_expression >::operator (); +#endif + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T value_type; + // typedef const T &const_reference; + typedef typename type_traits::const_reference const_reference; +#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE + typedef T &reference; +#else + typedef sparse_matrix_element reference; +#endif + typedef const T *const_pointer; + typedef T *pointer; + typedef IA index_array_type; + typedef TA value_array_type; + typedef F functor_type; + typedef const coordinate_matrix const_self_type; + typedef coordinate_matrix self_type; + typedef const matrix_const_reference const_closure_type; + typedef matrix_reference closure_type; + typedef typename IA::const_iterator vector_const_iterator_type; + typedef typename IA::iterator vector_iterator_type; + typedef typename IA::const_iterator const_iterator_type; + typedef typename IA::iterator iterator_type; typedef sparse_tag storage_category; - typedef column_major_tag orientation_category; - typedef BOOST_UBLAS_TYPENAME promote_traits::promote_type promote_type; - typedef sparse_vector result_type; + typedef typename F::orientation_category orientation_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + coordinate_matrix (): + size1_ (0), size2_ (0), non_zeros_ (0), + filled_ (0), + sorted_ (true), index1_data_ (), + index2_data_ (), value_data_ () {} + BOOST_UBLAS_INLINE + coordinate_matrix (size_type size1, size_type size2, size_type non_zeros = 0): + size1_ (size1), size2_ (size2), non_zeros_ (non_zeros), + filled_ (0), + sorted_ (true), index1_data_ (non_zeros), + index2_data_ (non_zeros), value_data_ (non_zeros) { + reserve (non_zeros_); + } + BOOST_UBLAS_INLINE + coordinate_matrix (const coordinate_matrix &m): + size1_ (m.size1_), size2_ (m.size2_), non_zeros_ (m.non_zeros_), + filled_ (m.filled_), + sorted_ (m.sorted_), index1_data_ (m.index1_data_), + index2_data_ (m.index2_data_), value_data_ (m.value_data_) {} + template + BOOST_UBLAS_INLINE + coordinate_matrix (const matrix_expression &ae, size_type non_zeros = 0): + size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), non_zeros_ (non_zeros), + filled_ (0), + sorted_ (true), index1_data_ (non_zeros), + index2_data_ (non_zeros), value_data_ (non_zeros) { + reserve (non_zeros_); + matrix_assign (scalar_assign (), *this, ae); + } + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return size1_; + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return size2_; + } + BOOST_UBLAS_INLINE + size_type non_zeros () const { + return non_zeros_; + } + BOOST_UBLAS_INLINE + const index_array_type &index1_data () const { + return index1_data_; + } + BOOST_UBLAS_INLINE + index_array_type &index1_data () { + return index1_data_; + } + BOOST_UBLAS_INLINE + const index_array_type &index2_data () const { + return index2_data_; + } + BOOST_UBLAS_INLINE + index_array_type &index2_data () { + return index2_data_; + } + BOOST_UBLAS_INLINE + const value_array_type &value_data () const { + return value_data_; + } + BOOST_UBLAS_INLINE + value_array_type &value_data () { + return value_data_; + } + BOOST_UBLAS_INLINE + size_type index_base () { + return index_base_; + } + + // Resizing + BOOST_UBLAS_INLINE + void resize (size_type size1, size_type size2, size_type non_zeros = 0) { + size1_ = size1; + size2_ = size2; + non_zeros_ = std::max (non_zeros, std::min (size1_, size2_)); + filled_ = 0; + index1_data ().resize (non_zeros_); + index2_data ().resize (non_zeros_); + value_data ().resize (non_zeros_); + } + + // Reserving + BOOST_UBLAS_INLINE + void reserve (size_type non_zeros = 0, bool preserve = false) { + non_zeros_ = std::max (non_zeros, std::min (size1_, size2_)); + index1_data ().resize (non_zeros_, preserve); + index2_data ().resize (non_zeros_, preserve); + value_data ().resize (non_zeros_, preserve); + } + + // Proxy support +#ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE + pointer find_element (size_type i, size_type j) { + sort (); + size_type element1 (functor_type::element1 (i, size1_, j, size2_)); + size_type element2 (functor_type::element2 (i, size1_, j, size2_)); + vector_const_iterator_type itv_begin (detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + vector_const_iterator_type itv_end (detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + if (itv_begin == itv_end) + return 0; + const_iterator_type it_begin (index2_data ().begin () + (itv_begin - index1_data ().begin ())); + const_iterator_type it_end (index2_data ().begin () + (itv_end - index1_data ().begin ())); + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + if (it == it_end || *it != k_based (element2)) + return 0; + return &value_data () [it - index2_data ().begin ()]; + } +#endif + + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i, size_type j) const { + sort (); + size_type element1 (functor_type::element1 (i, size1_, j, size2_)); + size_type element2 (functor_type::element2 (i, size1_, j, size2_)); + vector_const_iterator_type itv_begin (detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + vector_const_iterator_type itv_end (detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + if (itv_begin == itv_end) + return zero_; + const_iterator_type it_begin (index2_data ().begin () + (itv_begin - index1_data ().begin ())); + const_iterator_type it_end (index2_data ().begin () + (itv_end - index1_data ().begin ())); + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + if (it == it_end || *it != k_based (element2)) + return zero_; + return value_data () [it - index2_data ().begin ()]; + } + BOOST_UBLAS_INLINE + reference operator () (size_type i, size_type j) { +#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE + sort (); + size_type element1 (functor_type::element1 (i, size1_, j, size2_)); + size_type element2 (functor_type::element2 (i, size1_, j, size2_)); + vector_const_iterator_type itv_begin (detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + vector_const_iterator_type itv_end (detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + if (itv_begin == itv_end) { + insert (i, j, value_type ()); + sort (); + itv_begin = detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ()); + itv_end = detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ()); + } + const_iterator_type it_begin (index2_data ().begin () + (itv_begin - index1_data ().begin ())); + const_iterator_type it_end (index2_data ().begin () + (itv_end - index1_data ().begin ())); + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + if (it == it_end || *it != k_based (element2)) { + insert (i, j, value_type ()); + sort (); + itv_begin = detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ()); + itv_end = detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ()); + it_begin = index2_data ().begin () + (itv_begin - index1_data ().begin ()); + it_end = index2_data ().begin () + (itv_end - index1_data ().begin ()); + it = detail::lower_bound (it_begin, it_end, k_based (element2), std::less ()); + } + return value_data () [it - index2_data ().begin ()]; +#else + return reference (*this, i, j); +#endif + } + + // Assignment + BOOST_UBLAS_INLINE + coordinate_matrix &operator = (const coordinate_matrix &m) { + // Too unusual semantic. + // BOOST_UBLAS_CHECK (this != &m, external_logic ()); + if (this != &m) { + BOOST_UBLAS_CHECK (size1_ == m.size1_, bad_size ()); + BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ()); + size1_ = m.size1_; + size2_ = m.size2_; + non_zeros_ = m.non_zeros_; + filled_ = m.filled_; + sorted_ = m.sorted_; + index1_data ().resize (non_zeros_); + index1_data () = m.index1_data (); + index2_data ().resize (non_zeros_); + index2_data () = m.index2_data (); + value_data ().resize (non_zeros_); + value_data () = m.value_data (); + } + return *this; + } + BOOST_UBLAS_INLINE + coordinate_matrix &assign_temporary (coordinate_matrix &m) { + swap (m); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_matrix &operator = (const matrix_expression &ae) { +#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY + return assign_temporary (self_type (ae, non_zeros_)); +#else + // return assign (self_type (ae, non_zeros_)); + self_type temporary (ae, non_zeros_); + return assign_temporary (temporary); +#endif + } + template + BOOST_UBLAS_INLINE + coordinate_matrix &reset(const matrix_expression &ae) { + self_type temporary (ae, non_zeros_); + resize (temporary.size1 (), temporary.size2 (), non_zeros_); + return assign_temporary (temporary); + } + template + BOOST_UBLAS_INLINE + coordinate_matrix &assign (const matrix_expression &ae) { + matrix_assign (scalar_assign (), *this, ae); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_matrix& operator += (const matrix_expression &ae) { +#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY + return assign_temporary (self_type (*this + ae, non_zeros_)); +#else + // return assign (self_type (*this + ae, non_zeros_)); + self_type temporary (*this + ae, non_zeros_); + return assign_temporary (temporary); +#endif + } + template + BOOST_UBLAS_INLINE + coordinate_matrix &plus_assign (const matrix_expression &ae) { + matrix_assign (scalar_plus_assign (), *this, ae); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_matrix& operator -= (const matrix_expression &ae) { +#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY + return assign_temporary (self_type (*this - ae, non_zeros_)); +#else + // return assign (self_type (*this - ae, non_zeros_)); + self_type temporary (*this - ae, non_zeros_); + return assign_temporary (temporary); +#endif + } + template + BOOST_UBLAS_INLINE + coordinate_matrix &minus_assign (const matrix_expression &ae) { + matrix_assign (scalar_minus_assign (), *this, ae); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_matrix& operator *= (const AT &at) { + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_matrix& operator /= (const AT &at) { + matrix_assign_scalar (scalar_divides_assign (), *this, at); + return *this; + } + + // Swapping + BOOST_UBLAS_INLINE + void swap (coordinate_matrix &m) { + // Too unusual semantic. + // BOOST_UBLAS_CHECK (this != &m, external_logic ()); + if (this != &m) { + // Precondition for container relaxed as requested during review. + // BOOST_UBLAS_CHECK (size1_ == m.size1_, bad_size ()); + // BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ()); + // BOOST_UBLAS_CHECK (non_zeros_ == m.non_zeros_, bad_size ()); + std::swap (size1_, m.size1_); + std::swap (size2_, m.size2_); + std::swap (non_zeros_, m.non_zeros_); + std::swap (filled_, m.filled_); + std::swap (sorted_, m.sorted_); + index1_data ().swap (m.index1_data ()); + index2_data ().swap (m.index2_data ()); + value_data ().swap (m.value_data ()); + } + } +#ifdef BOOST_UBLAS_FRIEND_FUNCTION + BOOST_UBLAS_INLINE + friend void swap (coordinate_matrix &m1, coordinate_matrix &m2) { + m1.swap (m2); + } +#endif + + // Sorting + BOOST_UBLAS_INLINE + void sort () const { + if (! sorted_) { + typedef std::pair pair_type; + typedef std::pair triple_type; + unbounded_array a (filled_); + size_type i; + for (i = 0; i < filled_; ++ i) + a [i] = triple_type (pair_type (index1_data_ [i], index2_data_ [i]), value_data_ [i]); + std::sort (a.begin (), a.end (), detail::less_triple ()); + for (i = 0; i < filled_; ++ i) { + index1_data_ [i] = a [i].first.first; + index2_data_ [i] = a [i].first.second; + value_data_ [i] = a [i].second; + } + sorted_ = true; + } + } + + // Element insertion and erasure + BOOST_UBLAS_INLINE + void push_back (size_type i, size_type j, const_reference t) { + if (filled_ >= non_zeros_) + reserve (2 * non_zeros_, true); + size_type element1 = functor_type::element1 (i, size1_, j, size2_); + size_type element2 = functor_type::element2 (i, size1_, j, size2_); + if (filled_ == 0 || + index1_data () [filled_ - 1] < k_based (element1) || + (index1_data () [filled_ - 1] == k_based (element1) && index2_data () [filled_ - 1] < k_based (element2))) { + ++ filled_; + index1_data () [filled_ - 1] = k_based (element1); + index2_data () [filled_ - 1] = k_based (element2); + value_data () [filled_ - 1] = t; + return; + } + // Raising exceptions abstracted as requested during review. + // throw external_logic (); + external_logic ().raise (); + } + BOOST_UBLAS_INLINE + void insert (size_type i, size_type j, const_reference t) { + if (filled_ >= non_zeros_) + reserve (2 * non_zeros_, true); + size_type element1 = functor_type::element1 (i, size1_, j, size2_); + size_type element2 = functor_type::element2 (i, size1_, j, size2_); + ++ filled_; + index1_data () [filled_ - 1] = k_based (element1); + index2_data () [filled_ - 1] = k_based (element2); + value_data () [filled_ - 1] = t; + sorted_ = false; + } + BOOST_UBLAS_INLINE + void pop_back () { + if (filled_ > 0) { + -- filled_; + return; + } + // Raising exceptions abstracted as requested during review. + // throw external_logic (); + external_logic ().raise (); + } + BOOST_UBLAS_INLINE + void erase (size_type i, size_type j) { + size_type element1 = functor_type::element1 (i, size1_, j, size2_); + size_type element2 = functor_type::element2 (i, size1_, j, size2_); + sort (); + vector_iterator_type itv_begin (detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + vector_iterator_type itv_end (detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + if (itv_begin == itv_end) + return; + iterator_type it_begin (index2_data ().begin () + (itv_begin - index1_data ().begin ())); + iterator_type it_end (index2_data ().begin () + (itv_end - index1_data ().begin ())); + iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + difference_type n = it - index2_data ().begin (); + if (filled_ > size_type (n) && *it == k_based (element2)) { + vector_iterator_type itv (index1_data ().begin () + n); + std::copy (itv + 1, index1_data ().begin () + filled_, itv); + std::copy (it + 1, index2_data ().begin () + filled_, it); + typename value_array_type::iterator itt (value_data ().begin () + n); + std::copy (itt + 1, value_data ().begin () + filled_, itt); + -- filled_; + } + } + BOOST_UBLAS_INLINE + void clear () { + filled_ = 0; + } + + class const_iterator1; + class iterator1; + class const_iterator2; + class iterator2; +#ifdef BOOST_MSVC_STD_ITERATOR + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base1 reverse_iterator1; + typedef reverse_iterator_base2 const_reverse_iterator2; + typedef reverse_iterator_base2 reverse_iterator2; +#else + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base1 reverse_iterator1; + typedef reverse_iterator_base2 const_reverse_iterator2; + typedef reverse_iterator_base2 reverse_iterator2; +#endif + + // Element lookup + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + const_iterator1 find1 (int rank, size_type i, size_type j) const { + sort (); + for (;;) { + size_type element1 (functor_type::element1 (i, size1_, j, size2_)); + size_type element2 (functor_type::element2 (i, size1_, j, size2_)); + vector_const_iterator_type itv_begin (detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + vector_const_iterator_type itv_end (detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + + const_iterator_type it_begin (index2_data ().begin () + (itv_begin - index1_data ().begin ())); + const_iterator_type it_end (index2_data ().begin () + (itv_end - index1_data ().begin ())); + + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + vector_const_iterator_type itv (index1_data ().begin () + (it - index2_data ().begin ())); + if (it != it_end) { +#ifdef BOOST_UBLAS_BOUNDS_CHECK + size_type index1 (functor_type::index1 (zero_based (*itv), zero_based (*it))); + BOOST_UBLAS_CHECK (index1 >= i, internal_logic ()); +#endif + size_type index2 (functor_type::index2 (zero_based (*itv), zero_based (*it))); + BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); + if ((rank == 0 && index2 >= j) || + (rank == 1 && index2 == j)) + return const_iterator1 (*this, rank, i, j, itv, it); + } + + if (rank == 0 || i >= size1_) + return const_iterator1 (*this, 0, i, j, itv, it_end); + ++ i; + } + } + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + iterator1 find1 (int rank, size_type i, size_type j) { + sort (); + for (;;) { + size_type element1 (functor_type::element1 (i, size1_, j, size2_)); + size_type element2 (functor_type::element2 (i, size1_, j, size2_)); + vector_iterator_type itv_begin (detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + vector_iterator_type itv_end (detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + + iterator_type it_begin (index2_data ().begin () + (itv_begin - index1_data ().begin ())); + iterator_type it_end (index2_data ().begin () + (itv_end - index1_data ().begin ())); + + iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + vector_iterator_type itv (index1_data ().begin () + (it - index2_data ().begin ())); + if (it != it_end) { +#ifdef BOOST_UBLAS_BOUNDS_CHECK + size_type index1 (functor_type::index1 (zero_based (*itv), zero_based (*it))); + BOOST_UBLAS_CHECK (index1 >= i, internal_logic ()); +#endif + size_type index2 (functor_type::index2 (zero_based (*itv), zero_based (*it))); + BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); + if ((rank == 0 && index2 >= j) || + (rank == 1 && index2 == j)) + return iterator1 (*this, rank, i, j, itv, it); + } + + if (rank == 0 || i >= size1_) + return iterator1 (*this, 0, i, j, itv, it_end); + ++ i; + } + } + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + const_iterator2 find2 (int rank, size_type i, size_type j) const { + sort (); + for (;;) { + size_type element1 (functor_type::element1 (i, size1_, j, size2_)); + size_type element2 (functor_type::element2 (i, size1_, j, size2_)); + vector_const_iterator_type itv_begin (detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + vector_const_iterator_type itv_end (detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + + const_iterator_type it_begin (index2_data ().begin () + (itv_begin - index1_data ().begin ())); + const_iterator_type it_end (index2_data ().begin () + (itv_end - index1_data ().begin ())); + + const_iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + vector_const_iterator_type itv (index1_data ().begin () + (it - index2_data ().begin ())); + if (it != it_end) { + size_type index1 (functor_type::index1 (zero_based (*itv), zero_based (*it))); + BOOST_UBLAS_CHECK (index1 >= i, internal_logic ()); +#ifdef BOOST_UBLAS_BOUNDS_CHECK + size_type index2 (functor_type::index2 (zero_based (*itv), zero_based (*it))); + BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); +#endif + if ((rank == 0 && index1 >= i) || + (rank == 1 && index1 == i)) + return const_iterator2 (*this, rank, i, j, itv, it); + } + + if (rank == 0 || j >= size2_) + return const_iterator2 (*this, 0, i, j, itv, it_end); + ++ j; + } + } + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + iterator2 find2 (int rank, size_type i, size_type j) { + sort (); + for (;;) { + size_type element1 (functor_type::element1 (i, size1_, j, size2_)); + size_type element2 (functor_type::element2 (i, size1_, j, size2_)); + vector_iterator_type itv_begin (detail::lower_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + vector_iterator_type itv_end (detail::upper_bound (index1_data ().begin (), index1_data ().begin () + filled_, k_based (element1), std::less ())); + + iterator_type it_begin (index2_data ().begin () + (itv_begin - index1_data ().begin ())); + iterator_type it_end (index2_data ().begin () + (itv_end - index1_data ().begin ())); + + iterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); + vector_iterator_type itv (index1_data ().begin () + (it - index2_data ().begin ())); + if (it != it_end) { + size_type index1 (functor_type::index1 (zero_based (*itv), zero_based (*it))); + BOOST_UBLAS_CHECK (index1 >= i, internal_logic ()); +#ifdef BOOST_UBLAS_BOUNDS_CHECK + size_type index2 (functor_type::index2 (zero_based (*itv), zero_based (*it))); + BOOST_UBLAS_CHECK (index2 >= j, internal_logic ()); +#endif + if ((rank == 0 && index1 >= i) || + (rank == 1 && index1 == i)) + return iterator2 (*this, rank, i, j, itv, it); + } + + if (rank == 0 || j >= size2_) + return iterator2 (*this, 0, i, j, itv, it_end); + ++ j; + } + } + BOOST_UBLAS_INLINE + const_iterator1 find_first1 (int rank, size_type i, size_type j) const { + return find1 (rank, i, j); + } + BOOST_UBLAS_INLINE + iterator1 find_first1 (int rank, size_type i, size_type j) { + return find1 (rank, i, j); + } + BOOST_UBLAS_INLINE + const_iterator1 find_last1 (int rank, size_type i, size_type j) const { + return find1 (rank, i, j); + } + BOOST_UBLAS_INLINE + iterator1 find_last1 (int rank, size_type i, size_type j) { + return find1 (rank, i, j); + } + BOOST_UBLAS_INLINE + const_iterator2 find_first2 (int rank, size_type i, size_type j) const { + return find2 (rank, i, j); + } + BOOST_UBLAS_INLINE + iterator2 find_first2 (int rank, size_type i, size_type j) { + return find2 (rank, i, j); + } + BOOST_UBLAS_INLINE + const_iterator2 find_last2 (int rank, size_type i, size_type j) const { + return find2 (rank, i, j); + } + BOOST_UBLAS_INLINE + iterator2 find_last2 (int rank, size_type i, size_type j) { + return find2 (rank, i, j); + } + + // Iterators simply are pointers. + + class const_iterator1: + public container_const_reference, + public bidirectional_iterator_base { + public: + typedef sparse_bidirectional_iterator_tag iterator_category; +#ifdef BOOST_MSVC_STD_ITERATOR + typedef const_reference reference; +#else + typedef typename coordinate_matrix::difference_type difference_type; + typedef typename coordinate_matrix::value_type value_type; + typedef typename coordinate_matrix::const_reference reference; + typedef typename coordinate_matrix::const_pointer pointer; +#endif + 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 (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const coordinate_matrix &m, int rank, size_type i, size_type j, const vector_const_iterator_type &itv, const const_iterator_type &it): + container_const_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} + BOOST_UBLAS_INLINE + const_iterator1 (const iterator1 &it): + container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator1 &operator ++ () { + const coordinate_matrix &m = (*this) (); + if (rank_ == 1 && functor_type::fast1 ()) + ++ it_; + else { + i_ = index1 () + 1; + if (rank_ == 1) + *this = m.find1 (rank_, i_, j_); + } + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -- () { + const coordinate_matrix &m = (*this) (); + if (rank_ == 1 && functor_type::fast1 ()) + -- it_; + else { + i_ = index1 () - 1; + if (rank_ == 1) + *this = m.find1 (rank_, i_, j_); + } + return *this; + } + + // Dereference + BOOST_UBLAS_INLINE + reference operator * () const { + if (rank_ == 1) { + BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); + BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); + return (*this) ().value_data () [it_ - (*this) ().index2_data ().begin ()]; + } else { + return (*this) () (i_, j_); + } + } + + BOOST_UBLAS_INLINE + const_iterator2 begin () const { + const coordinate_matrix &m = (*this) (); + return m.find_first2 (1, index1 (), 0); + } + BOOST_UBLAS_INLINE + const_iterator2 end () const { + const coordinate_matrix &m = (*this) (); + return m.find_last2 (1, index1 (), m.size2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin () const { + return const_reverse_iterator2 (end ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend () const { + return const_reverse_iterator2 (begin ()); + } + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + if (rank_ == 1) { + return functor_type::index1 ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); + } else { + return i_; + } + } + BOOST_UBLAS_INLINE + size_type index2 () const { + if (rank_ == 1) { + return functor_type::index2 ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); + } else { + return j_; + } + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator1 &operator = (const const_iterator1 &it) { + container_const_reference::assign (&it ()); + rank_ = it.rank_; + i_ = it.i_; + j_ = it.j_; + itv_ = it.itv_; + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); + // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); + if (rank_ == 1 || it.rank_ == 1) { + return it_ == it.it_; + } else { + return i_ == it.i_ && j_ == it.j_; + } + } + + private: + int rank_; + size_type i_; + size_type j_; + vector_const_iterator_type itv_; + const_iterator_type it_; + }; + + BOOST_UBLAS_INLINE + const_iterator1 begin1 () const { + return find_first1 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator1 end1 () const { + return find_last1 (0, size1_, 0); + } + + class iterator1: + public container_reference, + public bidirectional_iterator_base { + public: + typedef sparse_bidirectional_iterator_tag iterator_category; +#ifndef BOOST_MSVC_STD_ITERATOR + typedef typename coordinate_matrix::difference_type difference_type; + typedef typename coordinate_matrix::value_type value_type; + typedef typename coordinate_matrix::reference reference; + typedef typename coordinate_matrix::pointer pointer; +#endif + typedef iterator2 dual_iterator_type; + typedef reverse_iterator2 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + iterator1 (): + container_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} + BOOST_UBLAS_INLINE + iterator1 (coordinate_matrix &m, int rank, size_type i, size_type j, const vector_iterator_type &itv, const iterator_type &it): + container_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} + + // Arithmetic + BOOST_UBLAS_INLINE + iterator1 &operator ++ () { + coordinate_matrix &m = (*this) (); + if (rank_ == 1 && functor_type::fast1 ()) + ++ it_; + else { + i_ = index1 () + 1; + if (rank_ == 1) + *this = m.find1 (rank_, i_, j_); + } + return *this; + } + BOOST_UBLAS_INLINE + iterator1 &operator -- () { + coordinate_matrix &m = (*this) (); + if (rank_ == 1 && functor_type::fast1 ()) + -- it_; + else { + i_ = index1 () - 1; + if (rank_ == 1) + *this = m.find1 (rank_, i_, j_); + } + return *this; + } + + // Dereference + BOOST_UBLAS_INLINE + reference operator * () const { + if (rank_ == 1) { + BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); + BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); +#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE + return (*this) ().value_data () [it_ - (*this) ().index2_data ().begin ()]; +#else + return reference ((*this) (), &(*this) ().value_data () [it_ - (*this) ().index2_data ().begin ()], index1 (), index2 ()); +#endif + } else { + return (*this) () (i_, j_); + } + } + + BOOST_UBLAS_INLINE + iterator2 begin () const { + coordinate_matrix &m = (*this) (); + return m.find_first2 (1, index1 (), 0); + } + BOOST_UBLAS_INLINE + iterator2 end () const { + coordinate_matrix &m = (*this) (); + return m.find_last2 (1, index1 (), m.size2 ()); + } + BOOST_UBLAS_INLINE + reverse_iterator2 rbegin () const { + return reverse_iterator2 (end ()); + } + BOOST_UBLAS_INLINE + reverse_iterator2 rend () const { + return reverse_iterator2 (begin ()); + } + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + if (rank_ == 1) { + return functor_type::index1 ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); + } else { + return i_; + } + } + BOOST_UBLAS_INLINE + size_type index2 () const { + if (rank_ == 1) { + return functor_type::index2 ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); + } else { + return j_; + } + } + + // Assignment + BOOST_UBLAS_INLINE + iterator1 &operator = (const iterator1 &it) { + container_reference::assign (&it ()); + rank_ = it.rank_; + i_ = it.i_; + j_ = it.j_; + itv_ = it.itv_; + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const iterator1 &it) const { + BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); + // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); + if (rank_ == 1 || it.rank_ == 1) { + return it_ == it.it_; + } else { + return i_ == it.i_ && j_ == it.j_; + } + } + + private: + int rank_; + size_type i_; + size_type j_; + vector_iterator_type itv_; + iterator_type it_; + + friend class const_iterator1; + }; + + BOOST_UBLAS_INLINE + iterator1 begin1 () { + return find_first1 (0, 0, 0); + } + BOOST_UBLAS_INLINE + iterator1 end1 () { + return find_last1 (0, size1_, 0); + } + + class const_iterator2: + public container_const_reference, + public bidirectional_iterator_base { + public: + typedef sparse_bidirectional_iterator_tag iterator_category; +#ifdef BOOST_MSVC_STD_ITERATOR + typedef const_reference reference; +#else + typedef typename coordinate_matrix::difference_type difference_type; + typedef typename coordinate_matrix::value_type value_type; + typedef typename coordinate_matrix::const_reference reference; + typedef typename coordinate_matrix::const_pointer pointer; +#endif + 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 (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const coordinate_matrix &m, int rank, size_type i, size_type j, const vector_const_iterator_type itv, const const_iterator_type &it): + container_const_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} + BOOST_UBLAS_INLINE + const_iterator2 (const iterator2 &it): + container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator2 &operator ++ () { + const coordinate_matrix &m = (*this) (); + if (rank_ == 1 && functor_type::fast2 ()) + ++ it_; + else { + j_ = index2 () + 1; + if (rank_ == 1) + *this = m.find2 (rank_, i_, j_); + } + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -- () { + const coordinate_matrix &m = (*this) (); + if (rank_ == 1 && functor_type::fast2 ()) + -- it_; + else { + j_ = index2 () - 1; + if (rank_ == 1) + *this = m.find2 (rank_, i_, j_); + } + return *this; + } + + // Dereference + BOOST_UBLAS_INLINE + reference operator * () const { + if (rank_ == 1) { + BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); + BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); + return (*this) ().value_data () [it_ - (*this) ().index2_data ().begin ()]; + } else { + return (*this) () (i_, j_); + } + } + + BOOST_UBLAS_INLINE + const_iterator1 begin () const { + const coordinate_matrix &m = (*this) (); + return m.find_first1 (1, 0, index2 ()); + } + BOOST_UBLAS_INLINE + const_iterator1 end () const { + const coordinate_matrix &m = (*this) (); + return m.find_last1 (1, m.size1 (), index2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin () const { + return const_reverse_iterator1 (end ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend () const { + return const_reverse_iterator1 (begin ()); + } + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + if (rank_ == 1) { + return functor_type::index1 ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); + } else { + return i_; + } + } + BOOST_UBLAS_INLINE + size_type index2 () const { + if (rank_ == 1) { + return functor_type::index2 ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); + } else { + return j_; + } + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator2 &operator = (const const_iterator2 &it) { + container_const_reference::assign (&it ()); + rank_ = it.rank_; + i_ = it.i_; + j_ = it.j_; + itv_ = it.itv_; + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); + // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); + if (rank_ == 1 || it.rank_ == 1) { + return it_ == it.it_; + } else { + return i_ == it.i_ && j_ == it.j_; + } + } + + private: + int rank_; + size_type i_; + size_type j_; + vector_const_iterator_type itv_; + const_iterator_type it_; + }; + + BOOST_UBLAS_INLINE + const_iterator2 begin2 () const { + return find_first2 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator2 end2 () const { + return find_last2 (0, 0, size2_); + } + + class iterator2: + public container_reference, + public bidirectional_iterator_base { + public: + typedef sparse_bidirectional_iterator_tag iterator_category; +#ifndef BOOST_MSVC_STD_ITERATOR + typedef typename coordinate_matrix::difference_type difference_type; + typedef typename coordinate_matrix::value_type value_type; + typedef typename coordinate_matrix::reference reference; + typedef typename coordinate_matrix::pointer pointer; +#endif + typedef iterator1 dual_iterator_type; + typedef reverse_iterator1 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + iterator2 (): + container_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} + BOOST_UBLAS_INLINE + iterator2 (coordinate_matrix &m, int rank, size_type i, size_type j, const vector_iterator_type &itv, const iterator_type &it): + container_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} + + // Arithmetic + BOOST_UBLAS_INLINE + iterator2 &operator ++ () { + coordinate_matrix &m = (*this) (); + if (rank_ == 1 && functor_type::fast2 ()) + ++ it_; + else { + j_ = index2 () + 1; + if (rank_ == 1) + *this = m.find2 (rank_, i_, j_); + } + return *this; + } + BOOST_UBLAS_INLINE + iterator2 &operator -- () { + coordinate_matrix &m = (*this) (); + if (rank_ == 1 && functor_type::fast2 ()) + -- it_; + else { + j_ = index2 (); + if (rank_ == 1) + *this = m.find2 (rank_, i_, j_); + } + return *this; + } + + // Dereference + BOOST_UBLAS_INLINE + reference operator * () const { + if (rank_ == 1) { + BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); + BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); +#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE + return (*this) ().value_data () [it_ - (*this) ().index2_data ().begin ()]; +#else + return reference ((*this) (), &(*this) ().value_data () [it_ - (*this) ().index2_data ().begin ()], index1 (), index2 ()); +#endif + } else { + return (*this) () (i_, j_); + } + } + + BOOST_UBLAS_INLINE + iterator1 begin () const { + coordinate_matrix &m = (*this) (); + return m.find_first1 (1, 0, index2 ()); + } + BOOST_UBLAS_INLINE + iterator1 end () const { + coordinate_matrix &m = (*this) (); + return m.find_last1 (1, m.size1 (), index2 ()); + } + BOOST_UBLAS_INLINE + reverse_iterator1 rbegin () const { + return reverse_iterator1 (end ()); + } + BOOST_UBLAS_INLINE + reverse_iterator1 rend () const { + return reverse_iterator1 (begin ()); + } + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + if (rank_ == 1) { + return functor_type::index1 ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); + } else { + return i_; + } + } + BOOST_UBLAS_INLINE + size_type index2 () const { + if (rank_ == 1) { + return functor_type::index2 ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); + } else { + return j_; + } + } + + // Assignment + BOOST_UBLAS_INLINE + iterator2 &operator = (const iterator2 &it) { + container_reference::assign (&it ()); + rank_ = it.rank_; + i_ = it.i_; + j_ = it.j_; + itv_ = it.itv_; + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const iterator2 &it) const { + BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); + // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); + if (rank_ == 1 || it.rank_ == 1) { + return it_ == it.it_; + } else { + return i_ == it.i_ && j_ == it.j_; + } + } + + private: + int rank_; + size_type i_; + size_type j_; + vector_iterator_type itv_; + iterator_type it_; + + friend class const_iterator2; + }; + + BOOST_UBLAS_INLINE + iterator2 begin2 () { + return find_first2 (0, 0, 0); + } + BOOST_UBLAS_INLINE + iterator2 end2 () { + return find_last2 (0, 0, size2_); + } + + // Reverse iterators + + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin1 () const { + return const_reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend1 () const { + return const_reverse_iterator1 (begin1 ()); + } + + BOOST_UBLAS_INLINE + reverse_iterator1 rbegin1 () { + return reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + reverse_iterator1 rend1 () { + return reverse_iterator1 (begin1 ()); + } + + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin2 () const { + return const_reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend2 () const { + return const_reverse_iterator2 (begin2 ()); + } + + BOOST_UBLAS_INLINE + reverse_iterator2 rbegin2 () { + return reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + reverse_iterator2 rend2 () { + return reverse_iterator2 (begin2 ()); + } + + private: + BOOST_STATIC_CONSTANT (size_type, index_base_ = IB); + size_type size1_; + size_type size2_; + size_type non_zeros_; + size_type filled_; + mutable bool sorted_; + mutable index_array_type index1_data_; + mutable index_array_type index2_data_; + mutable value_array_type value_data_; + static value_type zero_; + + BOOST_UBLAS_INLINE + static size_type zero_based (size_type k_based_index) { + return k_based_index - index_base_; + } + BOOST_UBLAS_INLINE + static size_type k_based (size_type zero_based_index) { + return zero_based_index + index_base_; + } + + friend class iterator1; + friend class iterator2; + friend class const_iterator1; + friend class const_iterator2; }; -#endif - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - sparse_vector::promote_type> -#else - typename matrix_vector_binary1_traits::result_type -#endif - prod (const matrix_expression &e1, - const vector_expression &e2, - sparse_tag, - column_major_tag) { -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - typedef sparse_vector::promote_type> result_type; -#else - typedef BOOST_UBLAS_TYPENAME matrix_vector_binary1_traits::result_type result_type; -#endif - typedef BOOST_UBLAS_TYPENAME result_type::size_type size_type; - typedef BOOST_UBLAS_TYPENAME result_type::value_type value_type; - -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ()); - result_type r (e1 ().size2 ()); - r.clear (); - typename E1::const_iterator2 it2e1 (e1 ().begin2 ()); - typename E1::const_iterator2 it2e1_end (e1 ().end2 ()); - while (it2e1 != it2e1_end) { - typename matrix_column::const_iterator it1e1 ((*it2e1).begin ()); - typename matrix_column::const_iterator it1e1_end ((*it2e1).end ()); - typename E2::const_iterator ite2 (e2 ().begin ()); - typename E2::const_iterator ite2_end (e2 ().end ()); - size_type i = std::min (it1e1.index (), ite2.index ()); - while (it1e1 != it1e1_end && ite2 != ite2_end) { - value_type t1 = i - it1e1.index () ? value_type () : *it1e1; - value_type t2 = i - ite2.index () ? value_type () : *ite2; - r (i) += t1 * t2; - if (it1e1.index () <= i) - ++ it1e1; - if (ite2.index () <= i) - ++ ite2; - i = std::min (it1e1.index (), ite2.index ()); - } - ++ it2e1; - } - return r; -#else - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ()); - result_type r (e1 ().size2 ()); - r.clear (); - typename E1::const_iterator2 it2e1 (e1 ().begin2 ()); - typename E1::const_iterator2 it2e1_end (e1 ().end2 ()); - while (it2e1 != it2e1_end) { - typename E1::const_iterator1 it1e1 (it2e1.begin ()); - typename E1::const_iterator1 it1e1_end (it2e1.end ()); - typename E2::const_iterator ite2 (e2 ().begin ()); - typename E2::const_iterator ite2_end (e2 ().end ()); - size_type i = std::min (it1e1.index1 (), ite2.index ()); - while (it1e1 != it1e1_end && ite2 != ite2_end) { - value_type t1 = i - it1e1.index1 () ? value_type () : *it1e1; - value_type t2 = i - ite2.index () ? value_type () : *ite2; - r (i) += t1 * t2; - if (it1e1.index1 () <= i) - ++ it1e1; - if (ite2.index () <= i) - ++ ite2; - i = std::min (it1e1.index1 (), ite2.index ()); - } - ++ it2e1; - } - return r; -#endif - } - - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - sparse_vector::promote_type>::precision_type> -#else - typename matrix_vector_binary1_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type -#endif - prec_prod (const matrix_expression &e1, - const vector_expression &e2, - sparse_tag, - column_major_tag) { -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - typedef sparse_vector::promote_type>::precision_type> result_type; -#else - typedef BOOST_UBLAS_TYPENAME matrix_vector_binary1_traits::precision_type, E1, - BOOST_UBLAS_TYPENAME type_traits::precision_type, E2>::result_type result_type; -#endif - typedef BOOST_UBLAS_TYPENAME result_type::size_type size_type; - typedef BOOST_UBLAS_TYPENAME result_type::value_type value_type; - -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ()); - result_type r (e1 ().size2 ()); - r.clear (); - typename E1::const_iterator2 it2e1 (e1 ().begin2 ()); - typename E1::const_iterator2 it2e1_end (e1 ().end2 ()); - while (it2e1 != it2e1_end) { - typename matrix_column::const_iterator it1e1 ((*it2e1).begin ()); - typename matrix_column::const_iterator it1e1_end ((*it2e1).end ()); - typename E2::const_iterator ite2 (e2 ().begin ()); - typename E2::const_iterator ite2_end (e2 ().end ()); - size_type i = std::min (it1e1.index (), ite2.index ()); - while (it1e1 != it1e1_end && ite2 != ite2_end) { - value_type t1 = i - it1e1.index () ? value_type () : *it1e1; - value_type t2 = i - ite2.index () ? value_type () : *ite2; - r (i) += t1 * t2; - if (it1e1.index () <= i) - ++ it1e1; - if (ite2.index () <= i) - ++ ite2; - i = std::min (it1e1.index (), ite2.index ()); - } - ++ it2e1; - } - return r; -#else - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ()); - result_type r (e1 ().size2 ()); - r.clear (); - typename E1::const_iterator2 it2e1 (e1 ().begin2 ()); - typename E1::const_iterator2 it2e1_end (e1 ().end2 ()); - while (it2e1 != it2e1_end) { - typename E1::const_iterator1 it1e1 (it2e1.begin ()); - typename E1::const_iterator1 it1e1_end (it2e1.end ()); - typename E2::const_iterator ite2 (e2 ().begin ()); - typename E2::const_iterator ite2_end (e2 ().end ()); - size_type i = std::min (it1e1.index1 (), ite2.index ()); - while (it1e1 != it1e1_end && ite2 != ite2_end) { - value_type t1 = i - it1e1.index1 () ? value_type () : *it1e1; - value_type t2 = i - ite2.index () ? value_type () : *ite2; - r (i) += t1 * t2; - if (it1e1.index1 () <= i) - ++ it1e1; - if (ite2.index () <= i) - ++ ite2; - i = std::min (it1e1.index1 (), ite2.index ()); - } - ++ it2e1; - } - return r; -#endif - } - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct matrix_vector_binary2_traits > { - typedef sparse_tag storage_category; - typedef row_major_tag orientation_category; - typedef BOOST_UBLAS_TYPENAME promote_traits::promote_type promote_type; - typedef sparse_vector result_type; - }; -#endif - - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - sparse_vector::promote_type> -#else - typename matrix_vector_binary2_traits::result_type -#endif - prod (const vector_expression &e1, - const matrix_expression &e2, - sparse_tag, - row_major_tag) { -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - typedef sparse_vector::promote_type> result_type; -#else - typedef BOOST_UBLAS_TYPENAME matrix_vector_binary2_traits::result_type result_type; -#endif - typedef BOOST_UBLAS_TYPENAME result_type::size_type size_type; - typedef BOOST_UBLAS_TYPENAME result_type::value_type value_type; - -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ()); - result_type r (e2 ().size2 ()); - r.clear (); - typename E2::const_iterator1 it1e2 (e2 ().begin1 ()); - typename E2::const_iterator1 it1e2_end (e2 ().end1 ()); - while (it1e2 != it1e2_end) { - typename matrix_row::const_iterator it2e2 ((*it1e2).begin ()); - typename matrix_row::const_iterator it2e2_end ((*it1e2).end ()); - typename E1::const_iterator ite1 (e1 ().begin ()); - typename E1::const_iterator ite1_end (e1 ().end ()); - size_type i = std::min (it2e2.index (), ite1.index ()); - while (it2e2 != it2e2_end && ite1 != ite1_end) { - value_type t2 = i - it2e2.index () ? value_type () : *it2e2; - value_type t1 = i - ite1.index () ? value_type () : *ite1; - r (i) += t2 * t1; - if (it2e2.index () <= i) - ++ it2e2; - if (ite1.index () <= i) - ++ ite1; - i = std::min (it2e2.index (), ite1.index ()); - } - ++ it1e2; - } - return r; -#else - BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ()); - result_type r (e2 ().size2 ()); - r.clear (); - typename E2::const_iterator1 it1e2 (e2 ().begin1 ()); - typename E2::const_iterator1 it1e2_end (e2 ().end1 ()); - while (it1e2 != it1e2_end) { - typename E2::const_iterator2 it2e2 (it1e2.begin ()); - typename E2::const_iterator2 it2e2_end (it1e2.end ()); - typename E1::const_iterator ite1 (e1 ().begin ()); - typename E1::const_iterator ite1_end (e1 ().end ()); - size_type i = std::min (it2e2.index2 (), ite1.index ()); - while (it2e2 != it2e2_end && ite1 != ite1_end) { - value_type t2 = i - it2e2.index2 () ? value_type () : *it2e2; - value_type t1 = i - ite1.index () ? value_type () : *ite1; - r (i) += t2 * t1; - if (it2e2.index2 () <= i) - ++ it2e2; - if (ite1.index () <= i) - ++ ite1; - i = std::min (it2e2.index2 (), ite1.index ()); - } - ++ it1e2; - } - return r; -#endif - } - - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - sparse_vector::promote_type>::precision_type> -#else - typename matrix_vector_binary2_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type -#endif - prec_prod (const vector_expression &e1, - const matrix_expression &e2, - sparse_tag, - row_major_tag) { -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - typedef sparse_vector::promote_type>::precision_type> result_type; -#else - typedef BOOST_UBLAS_TYPENAME matrix_vector_binary2_traits::precision_type, E1, - BOOST_UBLAS_TYPENAME type_traits::precision_type, E2>::result_type result_type; -#endif - typedef BOOST_UBLAS_TYPENAME result_type::size_type size_type; - typedef BOOST_UBLAS_TYPENAME result_type::value_type value_type; - -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ()); - result_type r (e2 ().size2 ()); - r.clear (); - typename E2::const_iterator1 it1e2 (e2 ().begin1 ()); - typename E2::const_iterator1 it1e2_end (e2 ().end1 ()); - while (it1e2 != it1e2_end) { - typename matrix_row::const_iterator it2e2 ((*it1e2).begin ()); - typename matrix_row::const_iterator it2e2_end ((*it1e2).end ()); - typename E1::const_iterator ite1 (e1 ().begin ()); - typename E1::const_iterator ite1_end (e1 ().end ()); - size_type i = std::min (it2e2.index (), ite1.index ()); - while (it2e2 != it2e2_end && ite1 != ite1_end) { - value_type t2 = i - it2e2.index () ? value_type () : *it2e2; - value_type t1 = i - ite1.index () ? value_type () : *ite1; - r (i) += t2 * t1; - if (it2e2.index () <= i) - ++ it2e2; - if (ite1.index () <= i) - ++ ite1; - i = std::min (it2e2.index (), ite1.index ()); - } - ++ it1e2; - } - return r; -#else - BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ()); - result_type r (e2 ().size2 ()); - r.clear (); - typename E2::const_iterator1 it1e2 (e2 ().begin1 ()); - typename E2::const_iterator1 it1e2_end (e2 ().end1 ()); - while (it1e2 != it1e2_end) { - typename E2::const_iterator2 it2e2 (it1e2.begin ()); - typename E2::const_iterator2 it2e2_end (it1e2.end ()); - typename E1::const_iterator ite1 (e1 ().begin ()); - typename E1::const_iterator ite1_end (e1 ().end ()); - size_type i = std::min (it2e2.index2 (), ite1.index ()); - while (it2e2 != it2e2_end && ite1 != ite1_end) { - value_type t2 = i - it2e2.index2 () ? value_type () : *it2e2; - value_type t1 = i - ite1.index () ? value_type () : *ite1; - r (i) += t2 * t1; - if (it2e2.index2 () <= i) - ++ it2e2; - if (ite1.index () <= i) - ++ ite1; - i = std::min (it2e2.index2 (), ite1.index ()); - } - ++ it1e2; - } - return r; -#endif - } - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct matrix_matrix_binary_traits , - T2, sparse_matrix > { - typedef sparse_tag storage_category; - typedef column_major_tag orientation_category; - typedef BOOST_UBLAS_TYPENAME promote_traits::promote_type promote_type; - typedef sparse_matrix result_type; - }; -#endif - - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - sparse_matrix::promote_type, row_major> -#else - typename matrix_matrix_binary_traits::result_type -#endif - prod (const matrix_expression &e1, - const matrix_expression &e2, - sparse_tag, - column_major_tag) { -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - typedef sparse_matrix::promote_type, row_major> result_type; -#else - typedef BOOST_UBLAS_TYPENAME matrix_matrix_binary_traits::result_type result_type; -#endif - typedef BOOST_UBLAS_TYPENAME result_type::size_type size_type; - typedef BOOST_UBLAS_TYPENAME result_type::value_type value_type; - -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ()); - result_type r (e1 ().size1 (), e2 ().size2 ()); - r.clear (); - typename E2::const_iterator2 it2e2 (e2 ().begin2 ()); - typename E2::const_iterator2 it2e2_end (e2 ().end2 ()); - while (it2e2 != it2e2_end) { - typename matrix_column::const_iterator it2e1 ((*it2e2).begin ()); - typename matrix_column::const_iterator it2e1_end ((*it2e2).end ()); - while (it2e1 != it2e1_end) { - value_type t2 = *it2e1; - typename matrix_column::const_iterator it1e (column (e1 (), it2e1.index ()).begin ()); - typename matrix_column::const_iterator it1e_end (column (e1 (), it2e1.index ()).end ()); - while (it1e != it1e_end) { - // FIXME: wrong indices. - // r (it1e2.index (), it2e1.index ()) += *it1e2 * t2; - r (it1e.index (), it2e2.index ()) += *it1e * t2; - ++ it1e; - } - ++ it2e1; - } - ++ it2e2; - } - return r; -#else - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ()); - result_type r (e1 ().size1 (), e2 ().size2 ()); - r.clear (); - typename E2::const_iterator2 it2e2 (e2 ().begin2 ()); - typename E2::const_iterator2 it2e2_end (e2 ().end2 ()); - while (it2e2 != it2e2_end) { - typename E2::const_iterator1 it2e1 (it2e2.begin ()); - typename E2::const_iterator1 it2e1_end (it2e2.end ()); - while (it2e1 != it2e1_end) { - value_type t2 = *it2e1; - typename E1::const_iterator1 it1e1 (e1 ().find_first1 (1, 0, it2e1.index1 ())); - typename E1::const_iterator1 it1e1_end (e1 ().find_last1 (1, e1 ().size1 (), it2e1.index1 ())); - while (it1e1 != it1e1_end) { - BOOST_UBLAS_CHECK (it1e1.index2 () == it2e1.index1 (), internal_logic ()); - // FIXME: wrong indices. - // r (it1e2.index2 (), it2e1.index2 ()) += *it1e2 * t2; - r (it1e1.index1 (), it2e1.index2 ()) += *it1e1 * t2; - ++ it1e1; - } - ++ it2e1; - } - ++ it2e2; - } - return r; -#endif - } - - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - sparse_matrix::promote_type>::precision_type, row_major> -#else - typename matrix_matrix_binary_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type -#endif - prec_prod (const matrix_expression &e1, - const matrix_expression &e2, - sparse_tag, - column_major_tag) { -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - typedef sparse_matrix::promote_type>::precision_type, row_major> result_type; -#else - typedef BOOST_UBLAS_TYPENAME matrix_matrix_binary_traits::precision_type, E1, - BOOST_UBLAS_TYPENAME type_traits::precision_type, E2>::result_type result_type; -#endif - typedef BOOST_UBLAS_TYPENAME result_type::size_type size_type; - typedef BOOST_UBLAS_TYPENAME result_type::value_type value_type; - -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ()); - result_type r (e1 ().size1 (), e2 ().size2 ()); - r.clear (); - typename E2::const_iterator2 it2e2 (e2 ().begin2 ()); - typename E2::const_iterator2 it2e2_end (e2 ().end2 ()); - while (it2e2 != it2e2_end) { - typename matrix_column::const_iterator it2e1 ((*it2e2).begin ()); - typename matrix_column::const_iterator it2e1_end ((*it2e2).end ()); - while (it2e1 != it2e1_end) { - value_type t2 = *it2e1; - typename matrix_column::const_iterator it1e (column (e1 (), it2e1.index ()).begin ()); - typename matrix_column::const_iterator it1e_end (column (e1 (), it2e1.index ()).end ()); - while (it1e != it1e_end) { - // FIXME: wrong indices. - // r (it1e2.index (), it2e1.index ()) += *it1e2 * t2; - r (it1e.index (), it2e2.index ()) += *it1e * t2; - ++ it1e; - } - ++ it2e1; - } - ++ it2e2; - } - return r; -#else - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ()); - result_type r (e1 ().size1 (), e2 ().size2 ()); - r.clear (); - typename E2::const_iterator2 it2e2 (e2 ().begin2 ()); - typename E2::const_iterator2 it2e2_end (e2 ().end2 ()); - while (it2e2 != it2e2_end) { - typename E2::const_iterator1 it2e1 (it2e2.begin ()); - typename E2::const_iterator1 it2e1_end (it2e2.end ()); - while (it2e1 != it2e1_end) { - value_type t2 = *it2e1; - typename E1::const_iterator1 it1e1 (e1 ().find_first1 (1, 0, it2e1.index1 ())); - typename E1::const_iterator1 it1e1_end (e1 ().find_last1 (1, e1 ().size1 (), it2e1.index1 ())); - while (it1e1 != it1e1_end) { - BOOST_UBLAS_CHECK (it1e1.index2 () == it2e1.index1 (), internal_logic ()); - // FIXME: wrong indices. - // r (it1e2.index2 (), it2e1.index2 ()) += *it1e2 * t2; - r (it1e1.index1 (), it2e1.index2 ()) += *it1e1 * t2; - ++ it1e1; - } - ++ it2e1; - } - ++ it2e2; - } - return r; -#endif - } - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct matrix_matrix_binary_traits , - T2, sparse_matrix > { - typedef sparse_tag storage_category; - typedef row_major_tag orientation_category; - typedef BOOST_UBLAS_TYPENAME promote_traits::promote_type promote_type; - typedef sparse_matrix result_type; - }; -#endif - - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - sparse_matrix::promote_type, column_major> -#else - typename matrix_matrix_binary_traits::result_type -#endif - prod (const matrix_expression &e1, - const matrix_expression &e2, - sparse_tag, - row_major_tag) { -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - typedef sparse_matrix::promote_type, column_major> result_type; -#else - typedef BOOST_UBLAS_TYPENAME matrix_matrix_binary_traits::result_type result_type; -#endif - typedef BOOST_UBLAS_TYPENAME result_type::size_type size_type; - typedef BOOST_UBLAS_TYPENAME result_type::value_type value_type; - -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ()); - result_type r (e1 ().size1 (), e2 ().size2 ()); - r.clear (); - typename E1::const_iterator1 it1e1 (e1 ().begin1 ()); - typename E1::const_iterator1 it1e1_end (e1 ().end1 ()); - while (it1e1 != it1e1_end) { - typename matrix_row::const_iterator it1e2 ((*it1e1).begin ()); - typename matrix_row::const_iterator it1e2_end ((*it1e1).end ()); - while (it1e2 != it1e2_end) { - value_type t1 = *it1e2; - typename matrix_row::const_iterator it2e (row (e2 (), it1e2.index ()).begin ()); - typename matrix_row::const_iterator it2e_end (row (e2 (), it1e2.index ()).end ()); - while (it2e != it2e_end) { - // FIXME: wrong indices. - // r (it2e1.index (), it1e2.index ()) += t1 * *it2e1; - r (it1e1.index (), it2e.index ()) += t1 * *it2e; - ++ it2e; - } - ++ it1e2; - } - ++ it1e1; - } - return r; -#else - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ()); - result_type r (e1 ().size1 (), e2 ().size2 ()); - r.clear (); - typename E1::const_iterator1 it1e1 (e1 ().begin1 ()); - typename E1::const_iterator1 it1e1_end (e1 ().end1 ()); - while (it1e1 != it1e1_end) { - typename E1::const_iterator2 it1e2 (it1e1.begin ()); - typename E1::const_iterator2 it1e2_end (it1e1.end ()); - while (it1e2 != it1e2_end) { - value_type t1 = *it1e2; - typename E2::const_iterator2 it2e2 (e2 ().find_first2 (1, it1e2.index2 (), 0)); - typename E2::const_iterator2 it2e2_end (e2 ().find_last2 (1, it1e2.index2 (), e2 ().size2 ())); - while (it2e2 != it2e2_end) { - BOOST_UBLAS_CHECK (it1e2.index2 () == it2e2.index1 (), internal_logic ()); - // FIXME: wrong indices. - // r (it2e1.index1 (), it1e2.index1 ()) += t1 * *it2e1; - r (it1e2.index1 (), it2e2.index2 ()) += t1 * *it2e2; - ++ it2e2; - } - ++ it1e2; - } - ++ it1e1; - } - return r; -#endif - } - - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - sparse_matrix::promote_type>::precision_type, column_major> -#else - typename matrix_matrix_binary_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type -#endif - prec_prod (const matrix_expression &e1, - const matrix_expression &e2, - sparse_tag, - row_major_tag) { -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - typedef sparse_matrix::promote_type>::precision_type, column_major> result_type; -#else - typedef BOOST_UBLAS_TYPENAME matrix_matrix_binary_traits::precision_type, E1, - BOOST_UBLAS_TYPENAME type_traits::precision_type, E2>::result_type result_type; -#endif - typedef BOOST_UBLAS_TYPENAME result_type::size_type size_type; - typedef BOOST_UBLAS_TYPENAME result_type::value_type value_type; - -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ()); - result_type r (e1 ().size1 (), e2 ().size2 ()); - r.clear (); - typename E1::const_iterator1 it1e1 (e1 ().begin1 ()); - typename E1::const_iterator1 it1e1_end (e1 ().end1 ()); - while (it1e1 != it1e1_end) { - typename matrix_row::const_iterator it1e2 ((*it1e1).begin ()); - typename matrix_row::const_iterator it1e2_end ((*it1e1).end ()); - while (it1e2 != it1e2_end) { - value_type t1 = *it1e2; - typename matrix_row::const_iterator it2e (row (e2 (), it1e2.index ()).begin ()); - typename matrix_row::const_iterator it2e_end (row (e2 (), it1e2.index ()).end ()); - while (it2e != it2e_end) { - // FIXME: wrong indices. - // r (it2e1.index (), it1e2.index ()) += t1 * *it2e1; - r (it1e1.index (), it2e.index ()) += t1 * *it2e; - ++ it2e; - } - ++ it1e2; - } - ++ it1e1; - } - return r; -#else - BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ()); - result_type r (e1 ().size1 (), e2 ().size2 ()); - r.clear (); - typename E1::const_iterator1 it1e1 (e1 ().begin1 ()); - typename E1::const_iterator1 it1e1_end (e1 ().end1 ()); - while (it1e1 != it1e1_end) { - typename E1::const_iterator2 it1e2 (it1e1.begin ()); - typename E1::const_iterator2 it1e2_end (it1e1.end ()); - while (it1e2 != it1e2_end) { - value_type t1 = *it1e2; - typename E2::const_iterator2 it2e2 (e2 ().find_first2 (1, it1e2.index2 (), 0)); - typename E2::const_iterator2 it2e2_end (e2 ().find_last2 (1, it1e2.index2 (), e2 ().size2 ())); - while (it2e2 != it2e2_end) { - BOOST_UBLAS_CHECK (it1e2.index2 () == it2e2.index1 (), internal_logic ()); - // FIXME: wrong indices. - // r (it2e1.index1 (), it1e2.index1 ()) += t1 * *it2e1; - r (it1e2.index1 (), it2e2.index2 ()) += t1 * *it2e2; - ++ it2e2; - } - ++ it1e2; - } - ++ it1e1; - } - return r; -#endif - } - -#endif + template + typename coordinate_matrix::value_type coordinate_matrix::zero_ = 0; }}} #endif + + + + + + + + + + + + + diff --git a/include/boost/numeric/ublas/storage.hpp b/include/boost/numeric/ublas/storage.hpp index 0f7bd721..caecca8c 100644 --- a/include/boost/numeric/ublas/storage.hpp +++ b/include/boost/numeric/ublas/storage.hpp @@ -63,6 +63,8 @@ namespace boost { namespace numeric { namespace ublas { #define BOOST_UBLAS_SAME(size1, size2) (size1) #endif + struct no_init {}; + // Unbounded array template class unbounded_array { @@ -83,9 +85,14 @@ namespace boost { namespace numeric { namespace ublas { // Assuming std compliant allocator as requested during review. // if (! data_) // throw std::bad_alloc (); -#ifdef BOOST_UBLAS_SAFE std::fill (data_, data_ + size_, value_type ()); -#endif + } + BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE + unbounded_array (no_init): + size_ (0), data_ (new value_type [0]) { + // Assuming std compliant allocator as requested during review. + // if (! data_) + // throw std::bad_alloc (); } BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE unbounded_array (size_type size): @@ -93,9 +100,14 @@ namespace boost { namespace numeric { namespace ublas { // Assuming std compliant allocator as requested during review. // if (! data_) // throw std::bad_alloc (); -#ifdef BOOST_UBLAS_SAFE std::fill (data_, data_ + size_, value_type ()); -#endif + } + BOOST_UBLAS_INLINE + unbounded_array (size_type size, no_init): + size_ (size), data_ (new value_type [size]) { + // Assuming std compliant allocator as requested during review. + // if (! data_) + // throw std::bad_alloc (); } BOOST_UBLAS_INLINE unbounded_array (const unbounded_array &a): @@ -115,7 +127,7 @@ namespace boost { namespace numeric { namespace ublas { // Resizing BOOST_UBLAS_INLINE - void resize (size_type size) { + void resize (size_type size, bool preserve = true) { if (size != size_) { pointer data = new value_type [size]; // Assuming std compliant allocator as requested during review. @@ -123,19 +135,19 @@ namespace boost { namespace numeric { namespace ublas { // throw std::bad_alloc (); // if (! data_) // throw std::bad_alloc (); - // The content of the array is intentionally not copied. + if (preserve) { + std::copy (data_, data_ + std::min (size, size_), data); + std::fill (data + std::min (size, size_), data + size, value_type ()); + } delete [] data_; size_ = size; data_ = data; } -#ifdef BOOST_UBLAS_SAFE - std::fill (data_, data_ + size_, value_type ()); -#endif } BOOST_UBLAS_INLINE - size_type size () const { - return size_; + size_type size () const { + return size_; } // Element access @@ -303,23 +315,34 @@ namespace boost { namespace numeric { namespace ublas { typedef T *pointer; // Construction and destruction - BOOST_UBLAS_INLINE + BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE bounded_array (): - size_ (0) /* , data_ () */ { -#ifdef BOOST_UBLAS_SAFE + // Kresimir Fresl suggested to change the default back to the template argument. + // size_ (0) /* , data_ () */ { + size_ (N) /* , data_ () */ { std::fill (data_, data_ + size_, value_type ()); -#endif } BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE + bounded_array (no_init): + // Kresimir Fresl suggested to change the default back to the template argument. + // size_ (0) /* , data_ () */ { + size_ (N) /* , data_ () */ {} + BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE bounded_array (size_type size): size_ (size) /* , data_ () */ { if (size_ > N) // Raising exceptions abstracted as requested during review. // throw std::bad_alloc (); bad_size ().raise (); -#ifdef BOOST_UBLAS_SAFE std::fill (data_, data_ + size_, value_type ()); -#endif + } + BOOST_UBLAS_INLINE + bounded_array (size_type size, no_init): + size_ (size) /* , data_ () */ { + if (size_ > N) + // Raising exceptions abstracted as requested during review. + // throw std::bad_alloc (); + bad_size ().raise (); } BOOST_UBLAS_INLINE bounded_array (const bounded_array &a): @@ -333,16 +356,14 @@ namespace boost { namespace numeric { namespace ublas { // Resizing BOOST_UBLAS_INLINE - void resize (size_type size) { + void resize (size_type size, bool preserve = true) { if (size > N) // Raising exceptions abstracted as requested during review. // throw std::bad_alloc (); bad_size ().raise (); - // The content of the array is intentionally not copied. + if (preserve) + std::fill (data_ + std::min (size, size_), data_ + size, value_type ()); size_ = size; -#ifdef BOOST_UBLAS_SAFE - std::fill (data_, data_ + size_, value_type ()); -#endif } BOOST_UBLAS_INLINE @@ -520,19 +541,25 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE array_adaptor (): size_ (0), own_ (true), data_ (new value_type [0]) { -#ifdef BOOST_UBLAS_SAFE std::fill (data_, data_ + size_, value_type ()); -#endif } BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE + array_adaptor (no_init): + size_ (0), own_ (true), data_ (new value_type [0]) {} + BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE array_adaptor (size_type size): size_ (size), own_ (true), data_ (new value_type [size]) { // Assuming std compliant allocator as requested during review. // if (! data_) // throw std::bad_alloc (); -#ifdef BOOST_UBLAS_SAFE std::fill (data_, data_ + size_, value_type ()); -#endif + } + BOOST_UBLAS_INLINE + array_adaptor (size_type size, no_init): + size_ (size), own_ (true), data_ (new value_type [size]) { + // Assuming std compliant allocator as requested during review. + // if (! data_) + // throw std::bad_alloc (); } BOOST_UBLAS_INLINE array_adaptor (size_type size, pointer data): @@ -568,31 +595,36 @@ namespace boost { namespace numeric { namespace ublas { // Resizing BOOST_UBLAS_INLINE - void resize (size_type size) { - if (own_) { + void resize (size_type size, bool preserve = true) { + if (size != size_) { + data = new value_type [size]; // Assuming std compliant allocator as requested during review. + // if (! data) + // throw std::bad_alloc (); // if (! data_) // throw std::bad_alloc (); - delete [] data_; + if (preserve) { + std::copy (data_, data_ + std::min (size, size_), data); + std::fill (data + std::min (size, size_), data + size, value_type ()); + } + if (own_) + delete [] data_; + size_ = size; + own_ = true; + data_ = data; } - size_ = size; - own_ = true; - data_ = new value_type [size]; + } + BOOST_UBLAS_INLINE + void resize (size_type size, pointer data, bool preserve = true) { // Assuming std compliant allocator as requested during review. // if (! data_) // throw std::bad_alloc (); -#ifdef BOOST_UBLAS_SAFE - std::fill (data_, data_ + size_, value_type ()); -#endif - } - BOOST_UBLAS_INLINE - void resize (size_type size, pointer data) { - if (own_) { - // Assuming std compliant allocator as requested during review. - // if (! data_) - // throw std::bad_alloc (); - delete [] data_; + if (preserve) { + std::copy (data_, data_ + std::min (size, size_), data); + std::fill (data + std::min (size, size_), data + size, value_type ()); } + if (own_) + delete [] data_; size_ = size; own_ = false; data_ = data; @@ -781,19 +813,25 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE array_adaptor (): size_ (0), own_ (true), data_ (new value_type [0]) { -#ifdef BOOST_UBLAS_SAFE std::fill (data_, data_ + size_, value_type ()); -#endif } BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE + array_adaptor (no_init): + size_ (0), own_ (true), data_ (new value_type [0]) {} + BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE array_adaptor (size_type size): size_ (size), own_ (true), data_ (new value_type [size]) { // Assuming std compliant allocator as requested during review. // if (! data_.get ()) // throw std::bad_alloc (); -#ifdef BOOST_UBLAS_SAFE std::fill (data_, data_ + size_, value_type ()); -#endif + } + BOOST_UBLAS_INLINE + array_adaptor (size_type size, no_init): + size_ (size), own_ (true), data_ (new value_type [size]) { + // Assuming std compliant allocator as requested during review. + // if (! data_.get ()) + // throw std::bad_alloc (); } BOOST_UBLAS_INLINE array_adaptor (size_type size, pointer data): @@ -821,24 +859,31 @@ namespace boost { namespace numeric { namespace ublas { // Resizing BOOST_UBLAS_INLINE - void resize (size_type size) { - // Assuming std compliant allocator as requested during review. - // if (! data_.get ()) - // throw std::bad_alloc (); - size_ = size; - data_ = shared_array (new value_type [size]); - // Assuming std compliant allocator as requested during review. - // if (! data_.get ()) - // throw std::bad_alloc (); -#ifdef BOOST_UBLAS_SAFE - std::fill (data_.get (), data_.get () + size_, value_type ()); -#endif + void resize (size_type size, bool preserve = true) { + if (size != size_) { + shared_array data (new value_type [size]); + // Assuming std compliant allocator as requested during review. + // if (! data.get ()) + // throw std::bad_alloc (); + // if (! data_.get ()) + // throw std::bad_alloc (); + if (preserve) { + std::copy (data_.get (), data_.get () + std::min (size, size_), data.get ()); + std::fill (data.get () + std::min (size, size_), data.get () + size, value_type ()); + } + size_ = size; + data_ = data; + } } BOOST_UBLAS_INLINE - void resize (size_type size, pointer data) { + void resize (size_type size, pointer data, bool preserve = true) { // Assuming std compliant allocator as requested during review. // if (! data_.get ()) // throw std::bad_alloc (); + if (preserve) { + std::copy (data_.get (), data_.get () + std::min (size, size_), data); + std::fill (data + std::min (size, size_), data + size, value_type ()); + } size_ = size; data_ = data; } @@ -1292,7 +1337,7 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE slice compose (const slice &s) const { - BOOST_UBLAS_CHECK (s.start_ + s.stride_ * s.size_ <= size_, bad_size ()); + BOOST_UBLAS_CHECK (s.start_ + s.stride_ * (s.size_ - (s.size_ > 0)) <= size_, bad_size ()); return slice (start_ + stride_ * s.start_, stride_ * s.stride_, s.size_); } @@ -1356,22 +1401,31 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE difference_type operator - (const const_iterator &it) const { - BOOST_UBLAS_CHECK ((*this) ().stride () != 0, divide_by_zero ()); - return (it_ - it.it_) / (*this) ().stride (); + // Stationary slice must remain at start OR stride must be non zero + // Thanks to Michael Stevens for this extension. + BOOST_UBLAS_CHECK ((it_ == difference_type ((*this) ().start ()) && it.it_ == difference_type ((*this) ().start ())) || + (*this) ().stride () != 0, divide_by_zero ()); + return (*this) ().stride () != 0 ? (it_ - it.it_) / (*this) ().stride () : 0; } // Dereference BOOST_UBLAS_INLINE reference operator * () const { - BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); + // Stationary slice must remain at start OR index must remain within size + // Thanks to Michael Stevens for this extension. + BOOST_UBLAS_CHECK (((*this) ().stride () == 0 && it_ == difference_type ((*this) ().start ())) || + index () < (*this) ().size (), bad_index ()); return it_; } // Index BOOST_UBLAS_INLINE size_type index () const { - BOOST_UBLAS_CHECK ((*this) ().stride () != 0, divide_by_zero ()); - return (it_ - difference_type ((*this) ().start ())) / (*this) ().stride (); + // Stationary slice must remain at start OR stride must be non zero + // Thanks to Michael Stevens for this extension. + BOOST_UBLAS_CHECK (it_ == difference_type ((*this) ().start ()) || + (*this) ().stride () != 0, divide_by_zero ()); + return (*this) ().stride () != 0 ? (it_ - difference_type ((*this) ().start ())) / (*this) ().stride () : 0; } // Assignment @@ -1546,7 +1600,7 @@ namespace boost { namespace numeric { namespace ublas { #else indirect_array compose (const slice &s) const { #endif - BOOST_UBLAS_CHECK (s.start () + s.stride () * s.size () <= size (), bad_size ()); + BOOST_UBLAS_CHECK (s.start () + s.stride () * (s.size () - (s.size () > 0)) <= size (), bad_size ()); array_type data (s.size ()); for (size_type i = 0; i < s.size (); ++ i) data [i] = data_ [s.start () + s.stride () * i]; diff --git a/include/boost/numeric/ublas/storage_sparse.hpp b/include/boost/numeric/ublas/storage_sparse.hpp index a8534431..d797e88d 100644 --- a/include/boost/numeric/ublas/storage_sparse.hpp +++ b/include/boost/numeric/ublas/storage_sparse.hpp @@ -26,70 +26,218 @@ #include #include -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -// This fixes a [1] = a [0] = 1, but won't work on broken compilers. -// Thanks to Marc Duflot for spotting this. -#define BOOST_UBLAS_STRICT_SPARSE_ELEMENT_ASSIGN -#include -#endif - namespace boost { namespace numeric { namespace ublas { - template - struct less { - BOOST_UBLAS_INLINE - bool operator () (const P &p1, const P &p2) { - return p1.first < p2.first; - } - }; + namespace detail { + template + BOOST_UBLAS_INLINE + I lower_bound (const I &begin, const I &end, const T &t, C compare) { + // t <= *begin <=> ! (*begin < t) + if (begin == end || ! compare (*begin, t)) + return begin; + if (compare (*(end - 1), t)) + return end; + return std::lower_bound (begin, end, t, compare); + } + template + BOOST_UBLAS_INLINE + I upper_bound (const I &begin, const I &end, const T &t, C compare) { + if (begin == end || compare (t, *begin)) + return begin; + // (*end - 1) <= t <=> ! (t < *end) + if (! compare (t, *(end - 1))) + return end; + return std::upper_bound (begin, end, t, compare); + } + + template + struct less_pair { + BOOST_UBLAS_INLINE + bool operator () (const P &p1, const P &p2) { + return p1.first < p2.first; + } + }; + template + struct less_triple { + BOOST_UBLAS_INLINE + bool operator () (const T &t1, const T &t2) { + return t1.first.first < t2.first.first || + (t1.first.first == t2.first.first && t1.first.second < t2.first.second); + } + }; + + } + +#ifdef BOOST_UBLAS_STRICT_STORAGE_SPARSE template - struct map_value_traits { + struct sparse_storage_element_traits { typedef typename D::index_type index_type; typedef typename D::data_const_reference data_const_reference; typedef typename D::data_reference data_reference; }; template<> - struct map_value_traits { + struct sparse_storage_element_traits { typedef std::size_t index_type; typedef void data_const_reference; typedef void data_reference; }; template<> - struct map_value_traits { + struct sparse_storage_element_traits { typedef std::size_t index_type; typedef void data_const_reference; typedef void data_reference; }; #ifdef BOOST_UBLAS_USE_LONG_DOUBLE template<> - struct map_value_traits { + struct sparse_storage_element_traits { typedef std::size_t index_type; typedef void data_const_reference; typedef void data_reference; }; #endif template<> - struct map_value_traits > { + struct sparse_storage_element_traits > { typedef std::size_t index_type; typedef void data_const_reference; typedef void data_reference; }; template<> - struct map_value_traits > { + struct sparse_storage_element_traits > { typedef std::size_t index_type; typedef void data_const_reference; typedef void data_reference; }; #ifdef BOOST_UBLAS_USE_LONG_DOUBLE template<> - struct map_value_traits > { + struct sparse_storage_element_traits > { typedef std::size_t index_type; typedef void data_const_reference; typedef void data_reference; }; #endif + template + class sparse_storage_element: + public container_reference { + public: + typedef A array_type; + typedef typename A::index_type index_type; + typedef typename A::data_value_type data_value_type; + // typedef const data_value_type &data_const_reference; + typedef typename type_traits::const_reference data_const_reference; + typedef data_value_type &data_reference; + typedef std::pair value_type; + typedef std::pair *pointer; + + // Construction and destruction + BOOST_UBLAS_INLINE + sparse_storage_element (array_type &a, pointer it): + container_reference (a), it_ (it), i_ (it->first), d_ (it->second) {} + BOOST_UBLAS_INLINE + sparse_storage_element (array_type &a, index_type i): + container_reference (a), it_ (), i_ (i), d_ () { + pointer it = (*this) ().find (i_); + if (it == (*this) ().end ()) + it = (*this) ().insert ((*this) ().end (), value_type (i_, d_)); + d_ = it->second; + } + BOOST_UBLAS_INLINE + ~sparse_storage_element () { + if (! it_) + it_ = (*this) ().find (i_); + BOOST_UBLAS_CHECK (it_ != (*this) ().end (), internal_logic ()); + it_->second = d_; + } + + // Element access + // FIXME: GCC 3.1 warn's, if enabled + // BOOST_UBLAS_INLINE + // const sparse_storage_element_traits::data_const_reference + // operator [] (typename sparse_storage_element_traits::index_type i) const { + // return d_ [i]; + // } + BOOST_UBLAS_INLINE + typename sparse_storage_element_traits::data_reference + operator [] (typename sparse_storage_element_traits::index_type i) { + return d_ [i]; + } + + // Assignment + template + BOOST_UBLAS_INLINE + sparse_storage_element &operator = (const D &d) { + d_ = d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_storage_element &operator = (const sparse_storage_element &p) { + d_ = p.d_; + return *this; + } + template + BOOST_UBLAS_INLINE + sparse_storage_element &operator += (const D &d) { + d_ += d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_storage_element &operator += (const sparse_storage_element &p) { + d_ += p.d_; + return *this; + } + template + BOOST_UBLAS_INLINE + sparse_storage_element &operator -= (const D &d) { + d_ -= d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_storage_element &operator -= (const sparse_storage_element &p) { + d_ -= p.d_; + return *this; + } + template + BOOST_UBLAS_INLINE + sparse_storage_element &operator *= (const D &d) { + d_ *= d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_storage_element &operator *= (const sparse_storage_element &p) { + d_ *= p.d_; + return *this; + } + template + BOOST_UBLAS_INLINE + sparse_storage_element &operator /= (const D &d) { + d_ /= d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_storage_element &operator /= (const sparse_storage_element &p) { + d_ /= p.d_; + return *this; + } + + // FIXME: GCC 3.1 warn's, if enabled + // Conversion + BOOST_UBLAS_INLINE + // operator const data_const_reference () const { + // return d_; + // } + BOOST_UBLAS_INLINE + operator data_reference () { + return d_; + } + + private: + pointer it_; + index_type i_; + data_value_type d_; + }; +#endif + // Map array template class map_array { @@ -100,11 +248,10 @@ namespace boost { namespace numeric { namespace ublas { typedef T data_value_type; // typedef const T &data_const_reference; typedef typename type_traits::const_reference data_const_reference; -#ifndef BOOST_UBLAS_STRICT_SPARSE_ELEMENT_ASSIGN +#ifndef BOOST_UBLAS_STRICT_STORAGE_SPARSE typedef T &data_reference; #else - class proxy; - typedef proxy data_reference; + typedef sparse_storage_element data_reference; #endif typedef std::pair value_type; typedef const std::pair &const_reference; @@ -146,6 +293,7 @@ namespace boost { namespace numeric { namespace ublas { // Resizing BOOST_UBLAS_INLINE void resize (size_type size) { + BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ()); if (size > capacity_) { pointer data = new value_type [size << 1]; // Assuming std compliant allocator as requested during review. @@ -165,6 +313,7 @@ namespace boost { namespace numeric { namespace ublas { // Reserving BOOST_UBLAS_INLINE void reserve (size_type capacity) { + BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ()); if (capacity > capacity_) { pointer data = new value_type [capacity]; // Assuming std compliant allocator as requested during review. @@ -185,146 +334,16 @@ namespace boost { namespace numeric { namespace ublas { return size_; } -#ifdef BOOST_UBLAS_STRICT_SPARSE_ELEMENT_ASSIGN - class proxy: - public container_reference { - public: -#ifdef BOOST_MSVC - typedef I index_type; - typedef T data_value_type; - // typedef const T &data_const_reference; - typedef typename type_traits::const_reference data_const_reference; - typedef T &data_reference; - typedef std::pair *pointer; -#else - typedef typename map_array::index_type index_type; - typedef typename map_array::data_value_type data_value_type; - // typedef const typename map_array::data_value_type &data_const_reference; - typedef typename type_traits::const_reference data_const_reference; - typedef typename map_array::data_value_type &data_reference; - typedef std::pair *pointer; -#endif - - // Construction and destruction - BOOST_UBLAS_INLINE - proxy (map_array &a, pointer it): - container_reference (a), it_ (it), i_ (it->first), d_ (it->second) {} - BOOST_UBLAS_INLINE - proxy (map_array &a, index_type i): - container_reference (a), it_ (), i_ (i), d_ () { - pointer it = (*this) ().find (i_); - if (it == (*this) ().end ()) - it = (*this) ().insert ((*this) ().end (), value_type (i_, d_)); - d_ = it->second; - } - BOOST_UBLAS_INLINE - ~proxy () { - if (! it_) - it_ = (*this) ().find (i_); - BOOST_UBLAS_CHECK (it_ != (*this) ().end (), internal_logic ()); - it_->second = d_; - } - - // Element access - // FIXME: GCC 3.1 warn's, if enabled - // BOOST_UBLAS_INLINE - // const map_value_traits::data_const_reference - // operator [] (typename map_value_traits::index_type i) const { - // return d_ [i]; - // } - BOOST_UBLAS_INLINE - typename map_value_traits::data_reference - operator [] (typename map_value_traits::index_type i) { - return d_ [i]; - } - - // Assignment - template - BOOST_UBLAS_INLINE - proxy &operator = (const D &d) { - d_ = d; - return *this; - } - BOOST_UBLAS_INLINE - proxy &operator = (const proxy &p) { - d_ = p.d_; - return *this; - } - template - BOOST_UBLAS_INLINE - proxy &operator += (const D &d) { - d_ += d; - return *this; - } - BOOST_UBLAS_INLINE - proxy &operator += (const proxy &p) { - d_ += p.d_; - return *this; - } - template - BOOST_UBLAS_INLINE - proxy &operator -= (const D &d) { - d_ -= d; - return *this; - } - BOOST_UBLAS_INLINE - proxy &operator -= (const proxy &p) { - d_ -= p.d_; - return *this; - } - template - BOOST_UBLAS_INLINE - proxy &operator *= (const D &d) { - d_ *= d; - return *this; - } - BOOST_UBLAS_INLINE - proxy &operator *= (const proxy &p) { - d_ *= p.d_; - return *this; - } - template - BOOST_UBLAS_INLINE - proxy &operator /= (const D &d) { - d_ /= d; - return *this; - } - BOOST_UBLAS_INLINE - proxy &operator /= (const proxy &p) { - d_ /= p.d_; - return *this; - } - - // Conversion - // FIXME: GCC 3.1 warn's, if enabled - // BOOST_UBLAS_INLINE - // operator const data_const_reference () const { - // return d_; - // } - BOOST_UBLAS_INLINE - operator data_reference () { - return d_; - } - - private: - pointer it_; - index_type i_; - data_value_type d_; - }; -#endif - // Element access BOOST_UBLAS_INLINE data_reference operator [] (index_type i) { -#ifndef BOOST_UBLAS_STRICT_SPARSE_ELEMENT_ASSIGN +#ifndef BOOST_UBLAS_STRICT_STORAGE_SPARSE pointer it = find (i); if (it == end ()) it = insert (end (), value_type (i, data_value_type ())); BOOST_UBLAS_CHECK (it != end (), internal_logic ()); return it->second; #else - // This fixes a [1] = a [0] = 1. - // Thanks to Marc Duflot for spotting this. return data_reference (*this, i); #endif } @@ -368,28 +387,28 @@ namespace boost { namespace numeric { namespace ublas { // Element insertion and deletion // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - pointer insert (pointer it, const value_type &p) { + pointer push_back (pointer it, const value_type &p) { if (size () == 0 || (it = end () - 1)->first < p.first) { resize (size () + 1); *(it = end () - 1) = p; return it; } -#ifdef BOOST_UBLAS_APPEND_ONLY // Raising exceptions abstracted as requested during review. // throw external_logic (); external_logic ().raise (); return it; -#else - it = std::upper_bound (begin (), end (), p, less ()); - BOOST_UBLAS_CHECK (it != end (), internal_logic ()); - BOOST_UBLAS_CHECK (it->first != p.first, external_logic ()); + } + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + pointer insert (pointer it, const value_type &p) { + it = detail::lower_bound (begin (), end (), p, detail::less_pair ()); difference_type n = it - begin (); + BOOST_UBLAS_CHECK (size () == 0 || size () == size_type (n) || it->first != p.first, external_logic ()); resize (size () + 1); it = begin () + n; std::copy_backward (it, end () - 1, end ()); *it = p; return it; -#endif } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE @@ -404,7 +423,7 @@ namespace boost { namespace numeric { namespace ublas { resize (size () + it2 - it1); it = begin () + n; std::copy (it1, it2, it); - std::sort (begin (), end (), less ()); + std::sort (begin (), end (), detail::less_pair ()); #endif } // This function seems to be big. So we do not let the compiler inline it. @@ -441,7 +460,7 @@ namespace boost { namespace numeric { namespace ublas { const_pointer find (index_type i) const { #ifdef BOOST_UBLAS_DEPRECATED std::pair pit; - pit = std::equal_range (begin (), end (), value_type (i, data_value_type ()), less ()); + pit = std::equal_range (begin (), end (), value_type (i, data_value_type ()), detail::less_pair ()); if (pit.first->first == i) return pit.first; else if (pit.second->first == i) @@ -449,7 +468,7 @@ namespace boost { namespace numeric { namespace ublas { else return end (); #else - const_pointer it (std::lower_bound (begin (), end (), value_type (i, data_value_type ()), less ())); + const_pointer it (detail::lower_bound (begin (), end (), value_type (i, data_value_type ()), detail::less_pair ())); if (it == end () || it->first != i) it = end (); return it; @@ -460,7 +479,7 @@ namespace boost { namespace numeric { namespace ublas { pointer find (index_type i) { #ifdef BOOST_UBLAS_DEPRECATED std::pair pit; - pit = std::equal_range (begin (), end (), value_type (i, data_value_type ()), less ()); + pit = std::equal_range (begin (), end (), value_type (i, data_value_type ()), detail::less_pair ()); if (pit.first->first == i) return pit.first; else if (pit.second->first == i) @@ -468,7 +487,7 @@ namespace boost { namespace numeric { namespace ublas { else return end (); #else - pointer it (std::lower_bound (begin (), end (), value_type (i, data_value_type ()), less ())); + pointer it (detail::lower_bound (begin (), end (), value_type (i, data_value_type ()), detail::less_pair ())); if (it == end () || it->first != i) it = end (); return it; @@ -477,23 +496,23 @@ namespace boost { namespace numeric { namespace ublas { // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE const_pointer lower_bound (index_type i) const { - return std::lower_bound (begin (), end (), value_type (i, data_value_type ()), less ()); + return detail::lower_bound (begin (), end (), value_type (i, data_value_type ()), detail::less_pair ()); } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE pointer lower_bound (index_type i) { - return std::lower_bound (begin (), end (), value_type (i, data_value_type ()), less ()); + return detail::lower_bound (begin (), end (), value_type (i, data_value_type ()), detail::less_pair ()); } #ifdef BOOST_UBLAS_DEPRECATED // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE const_pointer upper_bound (index_type i) const { - return std::upper_bound (begin (), end (), value_type (i, data_value_type ()), less ()); + return detail::upper_bound (begin (), end (), value_type (i, data_value_type ()), detail::less_pair ()); } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE pointer upper_bound (index_type i) { - return std::upper_bound (begin (), end (), value_type (i, data_value_type ()), less ()); + return detail::upper_bound (begin (), end (), value_type (i, data_value_type ()), detail::less_pair ()); } #endif @@ -586,9 +605,7 @@ namespace boost { namespace numeric { namespace ublas { #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template - struct map_traits { - typedef void proxy; - }; + struct map_traits {}; template struct map_traits > { typedef typename std::map::size_type size_type; @@ -662,6 +679,7 @@ namespace boost { namespace numeric { namespace ublas { // Resizing BOOST_UBLAS_INLINE void resize (size_type size) { + BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ()); if (size > capacity_) { pointer data = new value_type [size << 1]; // Assuming std compliant allocator as requested during review. @@ -681,6 +699,7 @@ namespace boost { namespace numeric { namespace ublas { // Reserving BOOST_UBLAS_INLINE void reserve (size_type capacity) { + BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ()); if (capacity > capacity_) { pointer data = new value_type [capacity]; // Assuming std compliant allocator as requested during review. @@ -750,28 +769,28 @@ namespace boost { namespace numeric { namespace ublas { // Element insertion and deletion // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - pointer insert (pointer it, const value_type &p) { + pointer push_back (pointer it, const value_type &p) { if (size () == 0 || (*(it = end () - 1)) < p) { resize (size () + 1); *(it = end () - 1) = p; return it; - } -#ifdef BOOST_UBLAS_APPEND_ONLY + } // Raising exceptions abstracted as requested during review. // throw external_logic (); external_logic ().raise (); return it; -#else - it = std::upper_bound (begin (), end (), p, std::less ()); - BOOST_UBLAS_CHECK (it != end (), internal_logic ()); - BOOST_UBLAS_CHECK (*it != p, external_logic ()); + } + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + pointer insert (pointer it, const value_type &p) { + it = detail::lower_bound (begin (), end (), p, std::less ()); difference_type n = it - begin (); + BOOST_UBLAS_CHECK (size () == 0 || size () == size_type (n) || *it != p, external_logic ()); resize (size () + 1); it = begin () + n; std::copy_backward (it, end () - 1, end ()); *it = p; return it; -#endif } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE @@ -823,7 +842,7 @@ namespace boost { namespace numeric { namespace ublas { else return end (); #else - const_pointer it (std::lower_bound (begin (), end (), i, std::less ())); + const_pointer it (detail::lower_bound (begin (), end (), i, std::less ())); if (it == end () || *it != i) it = end (); return it; @@ -842,7 +861,7 @@ namespace boost { namespace numeric { namespace ublas { else return end (); #else - pointer it (std::lower_bound (begin (), end (), i, std::less ())); + pointer it (detail::lower_bound (begin (), end (), i, std::less ())); if (it == end () || *it != i) it = end (); return it; @@ -851,23 +870,23 @@ namespace boost { namespace numeric { namespace ublas { // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE const_pointer lower_bound (index_type i) const { - return std::lower_bound (begin (), end (), i, std::less ()); + return detail::lower_bound (begin (), end (), i, std::less ()); } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE pointer lower_bound (index_type i) { - return std::lower_bound (begin (), end (), i, std::less ()); + return detail::lower_bound (begin (), end (), i, std::less ()); } #ifdef BOOST_UBLAS_DEPRECATED // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE const_pointer upper_bound (index_type i) const { - return std::upper_bound (begin (), end (), i, std::less ()); + return detail::upper_bound (begin (), end (), i, std::less ()); } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE pointer upper_bound (index_type i) { - return std::upper_bound (begin (), end (), i, std::less ()); + return detail::upper_bound (begin (), end (), i, std::less ()); } #endif diff --git a/include/boost/numeric/ublas/symmetric.hpp b/include/boost/numeric/ublas/symmetric.hpp index 583f4b10..23a1be44 100644 --- a/include/boost/numeric/ublas/symmetric.hpp +++ b/include/boost/numeric/ublas/symmetric.hpp @@ -97,7 +97,7 @@ namespace boost { namespace numeric { namespace ublas { symmetric_matrix (const matrix_expression &ae): size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())), data_ (functor1_type::packed_size (ae ().size1 (), ae ().size2 ())) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); } // Accessors @@ -184,7 +184,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE symmetric_matrix &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -201,7 +201,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE symmetric_matrix &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -218,19 +218,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE symmetric_matrix &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE symmetric_matrix& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE symmetric_matrix& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -260,18 +260,21 @@ namespace boost { namespace numeric { namespace ublas { void insert (size_type i, size_type j, const_reference t) { BOOST_UBLAS_CHECK (i < size_, bad_index ()); BOOST_UBLAS_CHECK (j < size_, bad_index ()); -#ifndef BOOST_UBLAS_USE_ET - if (t == value_type ()) - return; -#endif +// FIXME: is this ugly check still needed?! +// #ifndef BOOST_UBLAS_USE_ET +// if (t == value_type ()) +// return; +// #endif if (functor1_type::other (i, j)) { size_type k = functor1_type::element (functor2_type (), i, size_, j, size_); - BOOST_UBLAS_CHECK (data () [k] == value_type () || data () [k] == t, bad_index ()); + BOOST_UBLAS_CHECK (type_traits::equals (data () [k], value_type ()) || + type_traits::equals (data () [k], t), bad_index ()); // data ().insert (data ().begin () + k, t); data () [k] = t; } else { size_type k = functor1_type::element (functor2_type (), j, size_, i, size_); - BOOST_UBLAS_CHECK (data () [k] == value_type () || data () [k] == t, bad_index ()); + BOOST_UBLAS_CHECK (type_traits::equals (data () [k], value_type ()) || + type_traits::equals (data () [k], t), bad_index ()); // data ().insert (data ().begin () + k, t); data () [k] = t; } @@ -296,23 +299,6 @@ namespace boost { namespace numeric { namespace ublas { std::fill (data ().begin (), data ().end (), value_type ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -334,86 +320,53 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_first1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor1_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_last1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor1_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_first2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor1_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_last2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor1_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif typedef const symmetric_adaptor const_self_type; typedef symmetric_adaptor self_type; typedef const matrix_const_reference const_closure_type; @@ -1043,7 +1007,7 @@ namespace boost { namespace numeric { namespace ublas { // Assignment BOOST_UBLAS_INLINE symmetric_adaptor &operator = (const symmetric_adaptor &m) { - matrix_assign > () (*this, m); + matrix_assign (scalar_assign (), *this, m); return *this; } BOOST_UBLAS_INLINE @@ -1054,49 +1018,49 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE symmetric_adaptor &operator = (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (ae)); + matrix_assign (scalar_assign (), *this, matrix (ae)); return *this; } template BOOST_UBLAS_INLINE symmetric_adaptor &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE symmetric_adaptor& operator += (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this + ae)); + matrix_assign (scalar_assign (), *this, matrix (*this + ae)); return *this; } template BOOST_UBLAS_INLINE symmetric_adaptor &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE symmetric_adaptor& operator -= (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this - ae)); + matrix_assign (scalar_assign (), *this, matrix (*this - ae)); return *this; } template BOOST_UBLAS_INLINE symmetric_adaptor &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE symmetric_adaptor& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE symmetric_adaptor& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -1106,7 +1070,7 @@ namespace boost { namespace numeric { namespace ublas { // Too unusual semantic // BOOST_UBLAS_CHECK (this != &m, external_logic ()); if (this != &m) - matrix_swap > () (*this, m); + matrix_swap (scalar_swap (), *this, m); } #ifdef BOOST_UBLAS_FRIEND_FUNCTION BOOST_UBLAS_INLINE @@ -1115,23 +1079,6 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -1153,86 +1100,53 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup BOOST_UBLAS_INLINE const_iterator1 find_first1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_first1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_last1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_first2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_last2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base - class triangular_matrix: + class triangular_matrix: public matrix_expression > { public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS @@ -76,7 +76,7 @@ namespace boost { namespace numeric { namespace ublas { triangular_matrix (const matrix_expression &ae): size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (functor1_type::packed_size (ae ().size1 (), ae ().size2 ())) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); } // Accessors @@ -172,7 +172,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE triangular_matrix &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template @@ -189,7 +189,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE triangular_matrix &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -206,19 +206,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE triangular_matrix &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE triangular_matrix& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE triangular_matrix& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -250,14 +250,16 @@ namespace boost { namespace numeric { namespace ublas { void insert (size_type i, size_type j, const_reference t) { BOOST_UBLAS_CHECK (i < size1_, bad_index ()); BOOST_UBLAS_CHECK (j < size2_, bad_index ()); -#ifndef BOOST_UBLAS_USE_ET - if (t == value_type ()) - return; -#endif +// FIXME: is this ugly check still needed?! +// #ifndef BOOST_UBLAS_USE_ET +// if (t == value_type ()) +// return; +// #endif if (functor1_type::other (i, j)) { - BOOST_UBLAS_CHECK (data () [functor1_type::element (functor2_type (), i, size1_, j, size2_)] == value_type (), bad_index ()); - // data ().insert (data ().begin () + functor1_type::element (functor2_type (), i, size1_, j, size2_), t); - data () [functor1_type::element (functor2_type (), i, size1_, j, size2_)] = t; + size_type k = functor1_type::element (functor2_type (), i, size1_, j, size2_); + BOOST_UBLAS_CHECK (type_traits::equals (data () [k], value_type ()), bad_index ()); + // data ().insert (data ().begin () + k, t); + data () [k] = t; } else { // Raising exceptions abstracted as requested during review. // throw external_logic (); @@ -268,9 +270,11 @@ namespace boost { namespace numeric { namespace ublas { void erase (size_type i, size_type j) { BOOST_UBLAS_CHECK (i < size1_, bad_index ()); BOOST_UBLAS_CHECK (j < size2_, bad_index ()); - if (functor1_type::other (i, j)) - // data ().erase (data ().begin () + functor1_type::element (functor2_type (), i, size1_, j, size2_)); - data () [functor1_type::element (functor2_type (), i, size1_, j, size2_)] = value_type (); + if (functor1_type::other (i, j)) { + size_type k = functor1_type::element (functor2_type (), i, size1_, j, size2_); + // data ().erase (data ().begin () + k); + data () [k] = value_type (); + } } BOOST_UBLAS_INLINE void clear () { @@ -278,23 +282,6 @@ namespace boost { namespace numeric { namespace ublas { std::fill (data ().begin (), data ().end (), value_type ()); } -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -316,7 +303,6 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup @@ -324,86 +310,54 @@ namespace boost { namespace numeric { namespace ublas { const_iterator1 find_first1 (int rank, size_type i, size_type j) const { if (rank == 1) i = functor1_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_first1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor1_type::mutable_restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { if (rank == 1) i = functor1_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_last1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor1_type::mutable_restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { if (rank == 1) j = functor1_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_first2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor1_type::mutable_restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { if (rank == 1) j = functor1_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_last2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor1_type::mutable_restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base::value, + typename M::const_reference, + typename M::reference>::type reference; + typedef typename M::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename M::const_pointer, + typename M::pointer>::type pointer; +#endif typedef const triangular_adaptor const_self_type; typedef triangular_adaptor self_type; typedef const matrix_const_reference const_closure_type; @@ -1045,7 +1010,7 @@ namespace boost { namespace numeric { namespace ublas { // Assignment BOOST_UBLAS_INLINE triangular_adaptor &operator = (const triangular_adaptor &m) { - matrix_assign > () (*this, m); + matrix_assign (scalar_assign (), *this, m); return *this; } BOOST_UBLAS_INLINE @@ -1056,49 +1021,49 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE triangular_adaptor &operator = (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (ae)); + matrix_assign (scalar_assign (), *this, matrix (ae)); return *this; } template BOOST_UBLAS_INLINE triangular_adaptor &assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE triangular_adaptor& operator += (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this + ae)); + matrix_assign (scalar_assign (), *this, matrix (*this + ae)); return *this; } template BOOST_UBLAS_INLINE triangular_adaptor &plus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE triangular_adaptor& operator -= (const matrix_expression &ae) { - matrix_assign > () (*this, matrix (*this - ae)); + matrix_assign (scalar_assign (), *this, matrix (*this - ae)); return *this; } template BOOST_UBLAS_INLINE triangular_adaptor &minus_assign (const matrix_expression &ae) { - matrix_assign > () (*this, ae); + matrix_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE triangular_adaptor& operator *= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE triangular_adaptor& operator /= (const AT &at) { - matrix_assign_scalar > () (*this, at); + matrix_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -1108,7 +1073,7 @@ namespace boost { namespace numeric { namespace ublas { // Too unusual semantic. // BOOST_UBLAS_CHECK (this != &m, external_logic ()); if (this != &m) - matrix_swap > () (*this, m); + matrix_swap (scalar_swap (), *this, m); } #ifdef BOOST_UBLAS_FRIEND_FUNCTION BOOST_UBLAS_INLINE @@ -1117,23 +1082,6 @@ namespace boost { namespace numeric { namespace ublas { } #endif -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - typedef matrix_row_iterator iterator1; - typedef matrix_column_iterator iterator2; - typedef matrix_row_const_iterator const_iterator1; - typedef matrix_column_const_iterator const_iterator2; -#ifdef BOOST_MSVC_STD_ITERATOR - typedef reverse_iterator_base, typename matrix_row > const_reverse_iterator1; - typedef reverse_iterator_base, typename matrix_row > reverse_iterator1; - typedef reverse_iterator_base, typename matrix_column > const_reverse_iterator2; - typedef reverse_iterator_base, typename matrix_column > reverse_iterator2; -#else - typedef reverse_iterator_base const_reverse_iterator1; - typedef reverse_iterator_base reverse_iterator1; - typedef reverse_iterator_base const_reverse_iterator2; - typedef reverse_iterator_base reverse_iterator2; -#endif -#else #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1 iterator1; typedef indexed_iterator2 iterator2; @@ -1155,7 +1103,6 @@ namespace boost { namespace numeric { namespace ublas { typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; -#endif #endif // Element lookup @@ -1163,86 +1110,54 @@ namespace boost { namespace numeric { namespace ublas { const_iterator1 find_first1 (int rank, size_type i, size_type j) const { if (rank == 1) i = functor_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_first1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor_type::mutable_restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator1 find_last1 (int rank, size_type i, size_type j) const { if (rank == 1) i = functor_type::restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator1 (*this, i); -#else return const_iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator1 find_last1 (int rank, size_type i, size_type j) { if (rank == 1) i = functor_type::mutable_restrict1 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator1 (*this, i); -#else return iterator1 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_first2 (int rank, size_type i, size_type j) const { if (rank == 1) j = functor_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_first2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor_type::mutable_restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE const_iterator2 find_last2 (int rank, size_type i, size_type j) const { if (rank == 1) j = functor_type::restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return const_iterator2 (*this, j); -#else return const_iterator2 (*this, i, j); -#endif } BOOST_UBLAS_INLINE iterator2 find_last2 (int rank, size_type i, size_type j) { if (rank == 1) j = functor_type::mutable_restrict2 (i, j); -#ifdef BOOST_UBLAS_USE_CANONICAL_ITERATOR - return iterator2 (*this, j); -#else return iterator2 (*this, i, j); -#endif } // Iterators simply are indices. -#if ! defined (BOOST_UBLAS_USE_CANONICAL_ITERATOR) && ! defined (BOOST_UBLAS_USE_INDEXED_ITERATOR) +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base, public random_access_iterator_base &ae): size_ (ae ().size ()), data_ (ae ().size ()) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); } // Accessors BOOST_UBLAS_INLINE - size_type size () const { + size_type size () const { return size_; } BOOST_UBLAS_INLINE @@ -147,7 +147,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE vector &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template @@ -164,7 +164,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE vector &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -181,19 +181,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE vector &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE vector &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -1250,7 +1250,7 @@ namespace boost { namespace numeric { namespace ublas { // Raising exceptions abstracted as requested during review. // throw std::bad_alloc (); bad_size ().raise (); - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); } // Accessors @@ -1325,7 +1325,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE c_vector &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template @@ -1342,7 +1342,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE c_vector &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -1359,19 +1359,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE c_vector &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE c_vector &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE c_vector &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } diff --git a/include/boost/numeric/ublas/vector_assign.hpp b/include/boost/numeric/ublas/vector_assign.hpp index 844e7d68..c380c2b4 100644 --- a/include/boost/numeric/ublas/vector_assign.hpp +++ b/include/boost/numeric/ublas/vector_assign.hpp @@ -45,7 +45,26 @@ namespace boost { namespace numeric { namespace ublas { #endif } -#ifdef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN + // Restart for sparse (proxy) assignments + template + BOOST_UBLAS_INLINE + void restart (const vector_expression &e, typename E::size_type index, + typename E::const_iterator &ite, typename E::const_iterator &ite_end) { + ite = e ().find_first (index); + ite_end = e ().find_last (e ().size ()); + if (ite != ite_end && ite.index () == index) + ++ ite; + } + template + BOOST_UBLAS_INLINE + void restart (vector_expression &e, typename E::size_type index, + typename E::iterator &ite, typename E::iterator &ite_end) { + ite = e ().find_first (index); + ite_end = e ().find_last (e ().size ()); + if (ite != ite_end && ite.index () == index) + ++ ite; + } + // Iterating case template // This function seems to be big. So we do not let the compiler inline it. @@ -84,7 +103,7 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_vector_assign_scalar (const F &f, V &v, const T &t, dense_proxy_tag) { + void vector_assign_scalar (const F &f, V &v, const T &t, dense_proxy_tag) { typedef F functor_type; #ifdef BOOST_UBLAS_USE_INDEXING indexing_vector_assign_scalar (functor_type (), v, t); @@ -103,7 +122,7 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_vector_assign_scalar (const F &f, V &v, const T &t, packed_proxy_tag) { + void vector_assign_scalar (const F &f, V &v, const T &t, packed_proxy_tag) { typedef F functor_type; typedef typename V::difference_type difference_type; typename V::iterator it (v.begin ()); @@ -115,107 +134,22 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_vector_assign_scalar (const F &f, V &v, const T &t, sparse_proxy_tag) { + void vector_assign_scalar (const F &f, V &v, const T &t, sparse_proxy_tag) { typedef F functor_type; typename V::iterator it (v.begin ()); typename V::iterator it_end (v.end ()); while (it != it_end) functor_type () (*it, t), ++ it; } -#endif - // vector assignment_operation scalar - template - struct vector_assign_scalar { + // Dispatcher + template + BOOST_UBLAS_INLINE + void vector_assign_scalar (const F &f, V &v, const T &t) { typedef F functor_type; - typedef typename F::assign_category assign_category; - -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - // Iterating case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void iterating_assign (V &v, const T &t) { - typedef typename V::difference_type difference_type; - difference_type size (v.size ()); - typename V::iterator it (v.begin ()); - BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ()); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- size >= 0) - functor_type () (*it, t), ++ it; -#else - DD (size, 4, r, (functor_type () (*it, t), ++ it)); -#endif - } - // Indexing case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void indexing_assign (V &v, const T &t) { - typedef typename V::difference_type difference_type; - difference_type size (v.size ()); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - for (difference_type i = 0; i < size; ++ i) - functor_type () (v (i), t); -#else - difference_type i (0); - DD (size, 4, r, (functor_type () (v (i), t), ++ i)); -#endif - } - - // Dense (proxy) case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (V &v, const T &t, dense_proxy_tag) { -#ifdef BOOST_UBLAS_USE_INDEXING - indexing_assign (v, t); -#elif BOOST_UBLAS_USE_ITERATING - iterating_assign (v, t); -#else - typedef typename V::difference_type difference_type; - difference_type size (v.size ()); - if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) - iterating_assign (v, t); - else - indexing_assign (v, t); -#endif - } - // Packed (proxy) case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (V &v, const T &t, packed_proxy_tag) { - typedef typename V::difference_type difference_type; - typename V::iterator it (v.begin ()); - difference_type size (v.end () - it); - while (-- size >= 0) - functor_type () (*it, t), ++ it; - } - // Sparse (proxy) case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (V &v, const T &t, sparse_proxy_tag) { - typename V::iterator it (v.begin ()); - typename V::iterator it_end (v.end ()); - while (it != it_end) - functor_type () (*it, t), ++ it; - } -#endif - - // Dispatcher - template - BOOST_UBLAS_INLINE - void operator () (V &v, const T &t) { - typedef typename V::storage_category storage_category; -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - operator () (v, t, storage_category ()); -#else - evaluate_vector_assign_scalar (functor_type (), v, t, storage_category ()); -#endif - } - }; + typedef typename V::storage_category storage_category; + vector_assign_scalar (functor_type (), v, t, storage_category ()); + } template struct vector_assign_traits { @@ -287,7 +221,6 @@ namespace boost { namespace numeric { namespace ublas { typedef sparse_proxy_tag storage_category; }; -#ifdef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN // Iterating case template // This function seems to be big. So we do not let the compiler inline it. @@ -328,7 +261,7 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_vector_assign (const F &f, V &v, const vector_expression &e, dense_proxy_tag) { + void vector_assign (const F &f, V &v, const vector_expression &e, dense_proxy_tag) { typedef F functor_type; #ifdef BOOST_UBLAS_USE_INDEXING indexing_vector_assign (functor_type (), v, e); @@ -347,7 +280,7 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_vector_assign (const F &f, V &v, const vector_expression &e, packed_proxy_tag) { + void vector_assign (const F &f, V &v, const vector_expression &e, packed_proxy_tag) { BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ()); typedef F functor_type; typedef typename V::size_type size_type; @@ -383,21 +316,36 @@ namespace boost { namespace numeric { namespace ublas { template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_vector_assign (const F &f, V &v, const vector_expression &e, sparse_tag) { + void vector_assign (const F &f, V &v, const vector_expression &e, sparse_tag) { BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ()); + typedef F functor_type; + typedef typename V::value_type value_type; +#ifdef BOOST_UBLAS_TYPE_CHECK + vector cv (v.size ()); + indexing_vector_assign (scalar_assign (), cv, v); + indexing_vector_assign (functor_type (), cv, e); +#endif v.clear (); typename E::const_iterator ite (e ().begin ()); typename E::const_iterator ite_end (e ().end ()); - while (ite != ite_end) - v.insert (ite.index (), *ite), ++ ite; + while (ite != ite_end) { + value_type t (*ite); + if (t != value_type ()) + v.insert (ite.index (), t); + ++ ite; + } +#ifdef BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (equals (v, cv), external_logic ()); +#endif } // Sparse proxy case template // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE - void evaluate_vector_assign (const F &f, V &v, const vector_expression &e, sparse_proxy_tag) { + void vector_assign (const F &f, V &v, const vector_expression &e, sparse_proxy_tag) { BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ()); typedef F functor_type; + typedef typename V::size_type size_type; typedef typename V::value_type value_type; #ifdef BOOST_UBLAS_TYPE_CHECK vector cv (v.size ()); @@ -417,9 +365,23 @@ namespace boost { namespace numeric { namespace ublas { functor_type () (*it, value_type ()); ++ it; } else if (compare > 0) { - ++ ite; + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index (ite.index ()); + functor_type () (v (index), e () (index)); + restart (v, index, it, it_end); + // The proxies could reference the same container. + restart (e, index, ite, ite_end); } } + while (ite != ite_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index (ite.index ()); + functor_type () (v (index), e () (index)); + // The proxies could reference the same container. + restart (e, index, ite, ite_end); + } while (it != it_end) { functor_type () (*it, value_type ()); ++ it; @@ -428,175 +390,122 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_CHECK (equals (v, cv), external_logic ()); #endif } -#endif - // vector assignment_operation vector_expression - template - struct vector_assign { + // Dispatcher + template + BOOST_UBLAS_INLINE + void vector_assign (const F &f, V &v, const vector_expression &e) { typedef F functor_type; - typedef typename F::assign_category assign_category; + typedef typename vector_assign_traits::storage_category storage_category; + vector_assign (functor_type (), v, e, storage_category ()); + } -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - // Iterating case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void iterating_assign (V &v, const vector_expression &e) { - typedef typename V::difference_type difference_type; - difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ())); - typename V::iterator it (v.begin ()); - BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ()); - typename E::const_iterator ite (e ().begin ()); - BOOST_UBLAS_CHECK (e ().end () - ite == size, bad_size ()); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - while (-- size >= 0) - functor_type () (*it, *ite), ++ it, ++ ite; -#else - DD (size, 2, r, (functor_type () (*it, *ite), ++ it, ++ ite)); -#endif - } - // Indexing case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void indexing_assign (V &v, const vector_expression &e) { - typedef typename V::difference_type difference_type; - difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ())); -#ifndef BOOST_UBLAS_USE_DUFF_DEVICE - for (difference_type i = 0; i < size; ++ i) - functor_type () (v (i), e () (i)); -#else - difference_type i (0); - DD (size, 2, r, (functor_type () (v (i), e () (i)), ++ i)); -#endif - } + template + struct vector_swap_traits { + typedef LS storage_category; + }; - // Dense (proxy) case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (V &v, const vector_expression &e, dense_proxy_tag) { -#ifdef BOOST_UBLAS_USE_INDEXING - indexing_assign (v, e); -#elif BOOST_UBLAS_USE_ITERATING - iterating_assign (v, e); -#else - typedef typename V::difference_type difference_type; - difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ())); - if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) - iterating_assign (v, e); - else - indexing_assign (v, e); -#endif - } - // Packed (proxy) case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (V &v, const vector_expression &e, packed_proxy_tag) { - BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ()); - typedef typename V::size_type size_type; - typedef typename V::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - vector cv (v.size ()); - vector_assign > ().indexing_assign (cv, v); - vector_assign ().indexing_assign (cv, e); -#endif - typename V::iterator it (v.begin ()); - typename V::iterator it_end (v.end ()); - typename E::const_iterator ite (e ().begin ()); - typename E::const_iterator ite_end (e ().end ()); - if (ite != ite_end && ite.index () < it.index ()) - ite += std::min (it.index () - ite.index (), size_type (ite_end - ite)); - while (it != it_end && ite != ite_end && it.index () < ite.index ()) { - functor_type () (*it, value_type ()); - ++ it; - } - while (it != it_end && ite != ite_end) { + template<> + struct vector_swap_traits { + typedef sparse_proxy_tag storage_category; + }; + + template<> + struct vector_swap_traits { + typedef sparse_proxy_tag storage_category; + }; + + // Dense (proxy) case + template + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + void vector_swap (const F &f, V &v, vector_expression &e, dense_proxy_tag) { + typedef F functor_type; + typedef typename V::difference_type difference_type; + difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ())); + typename V::iterator it (v.begin ()); + typename E::iterator ite (e ().begin ()); + while (-- size >= 0) + functor_type () (*it, *ite), ++ it, ++ ite; + } + // Packed (proxy) case + template + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + void vector_swap (const F &f, V &v, vector_expression &e, packed_proxy_tag) { + typedef F functor_type; + typedef typename V::difference_type difference_type; + difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ())); + typename V::iterator it (v.begin ()); + typename E::iterator ite (e ().begin ()); + while (-- size >= 0) + functor_type () (*it, *ite), ++ it, ++ ite; + } + // Sparse proxy case + template + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + void vector_swap (const F &f, V &v, vector_expression &e, sparse_proxy_tag) { + BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ()); + typedef F functor_type; + typedef typename V::size_type size_type; + typedef typename V::value_type value_type; + typename V::iterator it (v.begin ()); + typename V::iterator it_end (v.end ()); + typename E::iterator ite (e ().begin ()); + typename E::iterator ite_end (e ().end ()); + while (it != it_end && ite != ite_end) { + int compare = it.index () - ite.index (); + if (compare == 0) { functor_type () (*it, *ite); ++ it, ++ ite; + } else if (compare < 0) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index (it.index ()); + functor_type () (v (index), e () (index)); + restart (v, index, it, it_end); + // The proxies could reference the same container. + restart (e, index, ite, ite_end); + } else if (compare > 0) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index (ite.index ()); + functor_type () (v (index), e () (index)); + restart (e, index, ite, ite_end); + // The proxies could reference the same container. + restart (v, index, it, it_end); } - while (it != it_end) { - functor_type () (*it, value_type ()); - ++ it; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (v, cv), external_logic ()); -#endif } - // Sparse case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (V &v, const vector_expression &e, sparse_tag) { - BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ()); - typedef typename V::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - vector cv (v.size ()); - vector_assign > ().indexing_assign (cv, v); - vector_assign ().indexing_assign (cv, e); -#endif - v.clear (); - typename E::const_iterator ite (e ().begin ()); - typename E::const_iterator ite_end (e ().end ()); - while (ite != ite_end) - v.insert (ite.index (), *ite), ++ ite; -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (v, cv), external_logic ()); -#endif + while (ite != ite_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index (ite.index ()); + functor_type () (v (index), e () (index)); + // The proxies could reference the same container. + restart (e, index, ite, ite_end); } - // Sparse proxy case - template - // This function seems to be big. So we do not let the compiler inline it. - // BOOST_UBLAS_INLINE - void operator () (V &v, const vector_expression &e, sparse_proxy_tag) { - BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ()); - typedef typename V::value_type value_type; -#ifdef BOOST_UBLAS_TYPE_CHECK - vector cv (v.size ()); - vector_assign > ().indexing_assign (cv, v); - vector_assign ().indexing_assign (cv, e); -#endif - typename V::iterator it (v.begin ()); - typename V::iterator it_end (v.end ()); - typename E::const_iterator ite (e ().begin ()); - typename E::const_iterator ite_end (e ().end ()); - while (it != it_end && ite != ite_end) { - int compare = it.index () - ite.index (); - if (compare == 0) { - functor_type () (*it, *ite); - ++ it, ++ ite; - } else if (compare < 0) { - functor_type () (*it, value_type ()); - ++ it; - } else if (compare > 0) { - ++ ite; - } - } - while (it != it_end) { - functor_type () (*it, value_type ()); - ++ it; - } -#ifdef BOOST_UBLAS_TYPE_CHECK - BOOST_UBLAS_CHECK (equals (v, cv), external_logic ()); -#endif + while (it != it_end) { + // Sparse proxies don't need to be conformant. + // Thanks to Michael Stevens for suggesting this. + size_type index (it.index ()); + functor_type () (v (index), e () (index)); + // The proxies could reference the same container. + restart (v, index, it, it_end); } -#endif + } - // Dispatcher - template - BOOST_UBLAS_INLINE - void operator () (V &v, const vector_expression &e) { - typedef typename vector_assign_traits::storage_category storage_category; -#ifndef BOOST_UBLAS_ENABLE_SPECIALIZED_ASSIGN - operator () (v, e, storage_category ()); -#else - evaluate_vector_assign (functor_type (), v, e, storage_category ()); -#endif - } - }; + // Dispatcher + template + BOOST_UBLAS_INLINE + void vector_swap (const F &f, V &v, vector_expression &e) { + typedef F functor_type; + typedef typename vector_swap_traits::storage_category storage_category; + vector_swap (functor_type (), v, e, storage_category ()); + } }}} diff --git a/include/boost/numeric/ublas/vector_proxy.hpp b/include/boost/numeric/ublas/vector_proxy.hpp index 8a4cf621..53f8dc60 100644 --- a/include/boost/numeric/ublas/vector_proxy.hpp +++ b/include/boost/numeric/ublas/vector_proxy.hpp @@ -37,10 +37,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename V::size_type size_type; typedef typename V::difference_type difference_type; typedef typename V::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename V::const_reference const_reference; typedef typename V::reference reference; typedef typename V::const_pointer const_pointer; typedef typename V::pointer pointer; +#else + typedef typename V::const_reference const_reference; + typedef typename detail::ct_if::value, + typename V::const_reference, + typename V::reference>::type reference; + typedef typename V::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename V::const_pointer, + typename V::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const vector_const_reference > const_closure_type; typedef vector_reference > closure_type; @@ -49,8 +60,15 @@ namespace boost { namespace numeric { namespace ublas { typedef const vector_range const_closure_type; typedef vector_range closure_type; #endif +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename V::const_iterator const_iterator_type; typedef typename V::iterator iterator_type; +#else + typedef typename V::const_iterator const_iterator_type; + typedef typename detail::ct_if::value, + typename V::const_iterator, + typename V::iterator>::type iterator_type; +#endif typedef typename storage_restrict_traits::storage_category storage_category; @@ -61,11 +79,19 @@ namespace boost { namespace numeric { namespace ublas { #ifdef BOOST_UBLAS_ENABLE_INDEX_SET_ALL BOOST_UBLAS_INLINE vector_range (vector_type &data, const range<> &r): - data_ (data), r_ (r.preprocess (data.size ())) {} + data_ (data), r_ (r.preprocess (data.size ())) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (r_.start () <= data_.size () && + r_.start () + r_.size () <= data_.size (), bad_index ()); + } #else BOOST_UBLAS_INLINE vector_range (vector_type &data, const range &r): - data_ (data), r_ (r) {} + data_ (data), r_ (r) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (r_.start () <= data_.size () && + r_.start () + r_.size () <= data_.size (), bad_index ()); + } #endif // Accessors @@ -137,62 +163,62 @@ namespace boost { namespace numeric { namespace ublas { vector_range &operator = (const vector_range &vr) { // FIXME: the ranges could be differently sized. // std::copy (vr.begin (), vr.end (), begin ()); - vector_assign > () (*this, vector (vr)); + vector_assign (scalar_assign (), *this, vector (vr)); return *this; } BOOST_UBLAS_INLINE vector_range &assign_temporary (vector_range &vr) { // FIXME: this is suboptimal. // return *this = vr; - vector_assign > () (*this, vr); + vector_assign (scalar_assign (), *this, vr); return *this; } template BOOST_UBLAS_INLINE vector_range &operator = (const vector_expression &ae) { - vector_assign > () (*this, vector (ae)); + vector_assign (scalar_assign (), *this, vector (ae)); return *this; } template BOOST_UBLAS_INLINE vector_range &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_range &operator += (const vector_expression &ae) { - vector_assign > () (*this, vector (*this + ae)); + vector_assign (scalar_assign (), *this, vector (*this + ae)); return *this; } template BOOST_UBLAS_INLINE vector_range &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_range &operator -= (const vector_expression &ae) { - vector_assign > () (*this, vector (*this - ae)); + vector_assign (scalar_assign (), *this, vector (*this - ae)); return *this; } template BOOST_UBLAS_INLINE vector_range &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_range &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE vector_range &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -203,7 +229,9 @@ namespace boost { namespace numeric { namespace ublas { // BOOST_UBLAS_CHECK (this != &vr, external_logic ()); if (this != &vr) { BOOST_UBLAS_CHECK (size () == vr.size (), bad_size ()); - std::swap_ranges (begin (), end (), vr.begin ()); + // Sparse ranges may be nonconformant now. + // std::swap_ranges (begin (), end (), vr.begin ()); + vector_swap (scalar_swap (), *this, vr); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -215,9 +243,9 @@ namespace boost { namespace numeric { namespace ublas { #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator, - BOOST_UBLAS_TYPENAME vector_type::iterator::iterator_category> iterator; + BOOST_UBLAS_TYPENAME iterator_type::iterator_category> iterator; typedef indexed_const_iterator, - BOOST_UBLAS_TYPENAME vector_type::const_iterator::iterator_category> const_iterator; + BOOST_UBLAS_TYPENAME const_iterator_type::iterator_category> const_iterator; #else class const_iterator; class iterator; @@ -267,18 +295,18 @@ namespace boost { namespace numeric { namespace ublas { class const_iterator: public container_const_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { #endif public: - typedef typename V::const_iterator::iterator_category iterator_category; - typedef typename V::const_iterator::difference_type difference_type; - typedef typename V::const_iterator::value_type value_type; - typedef typename V::const_iterator::reference reference; - typedef typename V::const_iterator::pointer pointer; + typedef typename const_iterator_type::iterator_category iterator_category; + typedef typename const_iterator_type::difference_type difference_type; + typedef typename const_iterator_type::value_type value_type; + typedef typename const_iterator_type::reference reference; + typedef typename const_iterator_type::pointer pointer; // Construction and destruction BOOST_UBLAS_INLINE @@ -374,18 +402,18 @@ namespace boost { namespace numeric { namespace ublas { class iterator: public container_reference, #ifdef BOOST_UBLAS_USE_ITERATOR_BASE_TRAITS - public iterator_base_traits::template + public iterator_base_traits::template iterator_base::type { #else - public random_access_iterator_base { #endif public: - typedef typename V::iterator::iterator_category iterator_category; - typedef typename V::iterator::difference_type difference_type; - typedef typename V::iterator::value_type value_type; - typedef typename V::iterator::reference reference; - typedef typename V::iterator::pointer pointer; + typedef typename iterator_type::iterator_category iterator_category; + typedef typename iterator_type::difference_type difference_type; + typedef typename iterator_type::value_type value_type; + typedef typename iterator_type::reference reference; + typedef typename iterator_type::pointer pointer; // Construction and destruction BOOST_UBLAS_INLINE @@ -567,10 +595,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename V::size_type size_type; typedef typename V::difference_type difference_type; typedef typename V::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename V::const_reference const_reference; typedef typename V::reference reference; typedef typename V::const_pointer const_pointer; typedef typename V::pointer pointer; +#else + typedef typename V::const_reference const_reference; + typedef typename detail::ct_if::value, + typename V::const_reference, + typename V::reference>::type reference; + typedef typename V::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename V::const_pointer, + typename V::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const vector_const_reference > const_closure_type; typedef vector_reference > closure_type; @@ -596,11 +635,19 @@ namespace boost { namespace numeric { namespace ublas { #ifdef BOOST_UBLAS_ENABLE_INDEX_SET_ALL BOOST_UBLAS_INLINE vector_slice (vector_type &data, const slice<> &s): - data_ (data), s_ (s.preprocess (data.size ())) {} + data_ (data), s_ (s.preprocess (data.size ())) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (s_.start () <= data_.size () && + s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ()); + } #else BOOST_UBLAS_INLINE vector_slice (vector_type &data, const slice &s): - data_ (data), s_ (s) {} + data_ (data), s_ (s) { + // Early checking of preconditions. + BOOST_UBLAS_CHECK (s_.start () <= data_.size () && + s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ()); + } #endif // Accessors @@ -681,65 +728,65 @@ namespace boost { namespace numeric { namespace ublas { // Assignment BOOST_UBLAS_INLINE - vector_slice &operator = (const vector_slice &vs) { + vector_slice &operator = (const vector_slice &vs) { // FIXME: the slices could be differently sized. // std::copy (vs.begin (), vs.end (), begin ()); - vector_assign > () (*this, vector (vs)); + vector_assign (scalar_assign (), *this, vector (vs)); return *this; } BOOST_UBLAS_INLINE vector_slice &assign_temporary (vector_slice &vs) { // FIXME: this is suboptimal. // return *this = vs; - vector_assign > () (*this, vs); + vector_assign (scalar_assign (), *this, vs); return *this; } template BOOST_UBLAS_INLINE vector_slice &operator = (const vector_expression &ae) { - vector_assign > () (*this, vector (ae)); + vector_assign (scalar_assign (), *this, vector (ae)); return *this; } template BOOST_UBLAS_INLINE vector_slice &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_slice &operator += (const vector_expression &ae) { - vector_assign > () (*this, vector (*this + ae)); + vector_assign (scalar_assign (), *this, vector (*this + ae)); return *this; } template BOOST_UBLAS_INLINE vector_slice &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_slice &operator -= (const vector_expression &ae) { - vector_assign > () (*this, vector (*this - ae)); + vector_assign (scalar_assign (), *this, vector (*this - ae)); return *this; } template BOOST_UBLAS_INLINE vector_slice &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_slice &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE vector_slice &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -750,7 +797,9 @@ namespace boost { namespace numeric { namespace ublas { // BOOST_UBLAS_CHECK (this != &vs, external_logic ()); if (this != &vs) { BOOST_UBLAS_CHECK (size () == vs.size (), bad_size ()); - std::swap_ranges (begin (), end (), vs.begin ()); + // Sparse ranges may be nonconformant now. + // std::swap_ranges (begin (), end (), vs.begin ()); + vector_swap (scalar_swap (), *this, vs); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -1128,10 +1177,21 @@ namespace boost { namespace numeric { namespace ublas { typedef typename V::size_type size_type; typedef typename V::difference_type difference_type; typedef typename V::value_type value_type; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef typename V::const_reference const_reference; typedef typename V::reference reference; typedef typename V::const_pointer const_pointer; typedef typename V::pointer pointer; +#else + typedef typename V::const_reference const_reference; + typedef typename detail::ct_if::value, + typename V::const_reference, + typename V::reference>::type reference; + typedef typename V::const_pointer const_pointer; + typedef typename detail::ct_if::value, + typename V::const_pointer, + typename V::pointer>::type pointer; +#endif #ifdef BOOST_UBLAS_ET_CLOSURE_REFERENCE typedef const vector_const_reference > const_closure_type; typedef vector_reference > closure_type; @@ -1247,62 +1307,62 @@ namespace boost { namespace numeric { namespace ublas { vector_indirect &operator = (const vector_indirect &vi) { // FIXME: the indirect_arrays could be differently sized. // std::copy (vi.begin (), vi.end (), begin ()); - vector_assign > () (*this, vector (vi)); + vector_assign (scalar_assign (), *this, vector (vi)); return *this; } BOOST_UBLAS_INLINE vector_indirect &assign_temporary (vector_indirect &vi) { // FIXME: this is suboptimal. // return *this = vi; - vector_assign > () (*this, vi); + vector_assign (scalar_assign (), *this, vi); return *this; } template BOOST_UBLAS_INLINE vector_indirect &operator = (const vector_expression &ae) { - vector_assign > () (*this, vector (ae)); + vector_assign (scalar_assign (), *this, vector (ae)); return *this; } template BOOST_UBLAS_INLINE vector_indirect &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_indirect &operator += (const vector_expression &ae) { - vector_assign > () (*this, vector (*this + ae)); + vector_assign (scalar_assign (), *this, vector (*this + ae)); return *this; } template BOOST_UBLAS_INLINE vector_indirect &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_indirect &operator -= (const vector_expression &ae) { - vector_assign > () (*this, vector (*this - ae)); + vector_assign (scalar_assign (), *this, vector (*this - ae)); return *this; } template BOOST_UBLAS_INLINE vector_indirect &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE vector_indirect &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE vector_indirect &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -1313,7 +1373,9 @@ namespace boost { namespace numeric { namespace ublas { // BOOST_UBLAS_CHECK (this != &vi, external_logic ()); if (this != &vi) { BOOST_UBLAS_CHECK (size () == vi.size (), bad_size ()); - std::swap_ranges (begin (), end (), vi.begin ()); + // Sparse ranges may be nonconformant now. + // std::swap_ranges (begin (), end (), vi.begin ()); + vector_swap (scalar_swap (), *this, vi); } } #ifdef BOOST_UBLAS_FRIEND_FUNCTION @@ -1645,7 +1707,7 @@ namespace boost { namespace numeric { namespace ublas { } #endif #endif - // These signatures are to general for MSVC + // These signatures are too general for MSVC // template // BOOST_UBLAS_INLINE // vector_indirect project (V &data, const IA &ia) { diff --git a/include/boost/numeric/ublas/vector_sparse.hpp b/include/boost/numeric/ublas/vector_sparse.hpp index b1127e17..aad24ca1 100644 --- a/include/boost/numeric/ublas/vector_sparse.hpp +++ b/include/boost/numeric/ublas/vector_sparse.hpp @@ -25,6 +25,147 @@ namespace boost { namespace numeric { namespace ublas { +#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE + + template + class sparse_vector_element: + public container_reference { + public: + typedef V vector_type; + typedef typename V::size_type size_type; + typedef typename V::value_type value_type; + // typedef const value_type &const_reference; + typedef typename type_traits::const_reference const_reference; + typedef value_type &reference; + typedef value_type *pointer; + + // Construction and destruction + BOOST_UBLAS_INLINE + sparse_vector_element (vector_type &v, pointer it, size_type i): + container_reference (v), it_ (it), i_ (i), d_ (*it) {} + BOOST_UBLAS_INLINE + sparse_vector_element (vector_type &v, size_type i): + container_reference (v), it_ (), i_ (i), d_ () { + pointer it = (*this) ().find_element (i_); + if (! it) + (*this) ().insert (i_, d_); + else + d_ = *it; + } + BOOST_UBLAS_INLINE + ~sparse_vector_element () { + if (! it_) + it_ = (*this) ().find_element (i_); + BOOST_UBLAS_CHECK (it_, internal_logic ()); + *it_ = d_; + } + + // Assignment + template + BOOST_UBLAS_INLINE + sparse_vector_element &operator = (const D &d) { + d_ = d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_vector_element &operator = (const sparse_vector_element &p) { + d_ = p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_vector_element &operator = (const sparse_vector_element &p) { + // d_ = p.d_; + // return *this; + // } + template + BOOST_UBLAS_INLINE + sparse_vector_element &operator += (const D &d) { + d_ += d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_vector_element &operator += (const sparse_vector_element &p) { + d_ += p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_vector_element &operator += (const sparse_vector_element &p) { + // d_ += p.d_; + // return *this; + // } + template + BOOST_UBLAS_INLINE + sparse_vector_element &operator -= (const D &d) { + d_ -= d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_vector_element &operator -= (const sparse_vector_element &p) { + d_ -= p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_vector_element &operator -= (const sparse_vector_element &p) { + // d_ -= p.d_; + // return *this; + // } + template + BOOST_UBLAS_INLINE + sparse_vector_element &operator *= (const D &d) { + d_ *= d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_vector_element &operator *= (const sparse_vector_element &p) { + d_ *= p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_vector_element &operator *= (const sparse_vector_element &p) { + // d_ *= p.d_; + // return *this; + // } + template + BOOST_UBLAS_INLINE + sparse_vector_element &operator /= (const D &d) { + d_ /= d; + return *this; + } + BOOST_UBLAS_INLINE + sparse_vector_element &operator /= (const sparse_vector_element &p) { + d_ /= p.d_; + return *this; + } + // template + // BOOST_UBLAS_INLINE + // sparse_vector_element &operator /= (const sparse_vector_element &p) { + // d_ /= p.d_; + // return *this; + // } + + // Conversion + // FIXME: GCC 3.1 warn's, if enabled + // BOOST_UBLAS_INLINE + // operator const const_reference () const { + // return d_; + // } + BOOST_UBLAS_INLINE + operator reference () { + return d_; + } + + private: + pointer it_; + size_type i_; + value_type d_; + }; + +#endif + // Array based sparse vector class template class sparse_vector: @@ -38,9 +179,11 @@ namespace boost { namespace numeric { namespace ublas { typedef T value_type; // typedef const T &const_reference; typedef typename type_traits::const_reference const_reference; -#ifndef BOOST_UBLAS_STRICT_SPARSE_ELEMENT_ASSIGN +#if ! defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) && ! defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE) typedef T &reference; -#else +#elif defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE) + typedef sparse_vector_element reference; +#elif defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) typedef typename map_traits::reference reference; #endif typedef const T *const_pointer; @@ -62,10 +205,7 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE sparse_vector (size_type size, size_type non_zeros = 0): size_ (size), non_zeros_ (non_zeros), data_ () { -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - non_zeros_ = std::max (non_zeros_, size_type (1)); - map_traits::reserve (data_, non_zeros_); -#endif + reserve (non_zeros_); } BOOST_UBLAS_INLINE sparse_vector (const sparse_vector &v): @@ -74,11 +214,8 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE sparse_vector (const vector_expression &ae, size_type non_zeros = 0): size_ (ae ().size ()), non_zeros_ (non_zeros), data_ () { -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - non_zeros_ = std::max (non_zeros_, size_type (1)); - map_traits::reserve (data_, non_zeros_); -#endif - vector_assign > () (*this, ae); + reserve (non_zeros_); + vector_assign (scalar_assign (), *this, ae); } // Accessors @@ -103,14 +240,32 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE void resize (size_type size, size_type non_zeros = 0) { size_ = size; - non_zeros_ = non_zeros; + non_zeros_ = std::max (non_zeros, size_type (1)); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - non_zeros_ = std::max (non_zeros_, size_type (1)); map_traits::reserve (data (), non_zeros_); #endif data ().clear (); } + // Reserving + BOOST_UBLAS_INLINE + void reserve (size_type non_zeros = 0) { + non_zeros_ = std::max (non_zeros, size_type (1)); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + map_traits::reserve (data (), non_zeros_); +#endif + } + + // Proxy support +#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE + pointer find_element (size_type i) { + iterator_type it (data ().find (i)); + if (it == data ().end () || (*it).first != i) + return 0; + return &(*it).second; + } +#endif + // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i) const { @@ -121,7 +276,11 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE reference operator () (size_type i) { +#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE return data () [i]; +#else + return reference (*this, i); +#endif } BOOST_UBLAS_INLINE @@ -172,7 +331,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE sparse_vector &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template @@ -189,7 +348,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE sparse_vector &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -206,19 +365,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE sparse_vector &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE sparse_vector &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE sparse_vector &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -246,10 +405,6 @@ namespace boost { namespace numeric { namespace ublas { // Element insertion and erasure BOOST_UBLAS_INLINE void insert (size_type i, const_reference t) { -#ifdef BOOST_UBLAS_CHECK_FOR_ZERO - if (t == value_type ()) - return; -#endif BOOST_UBLAS_CHECK (data ().find (i) == data ().end (), bad_index ()); data ().insert (data ().end (), std::pair (i, t)); } @@ -420,9 +575,11 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE reference operator * () const { BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); -#ifndef BOOST_UBLAS_STRICT_SPARSE_ELEMENT_ASSIGN +#if ! defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) && ! defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE) return (*it_).second; -#else +#elif defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE) + return reference ((*this) (), &(*it_).second, index ()); +#elif defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) return map_traits::make_reference ((*this) ().data (), it_); #endif } @@ -506,25 +663,30 @@ namespace boost { namespace numeric { namespace ublas { typename sparse_vector::value_type sparse_vector::zero_ = 0; // Array based sparse vector class - template + // Thanks to Kresimir Fresl for extending this to cover different index bases. + template class compressed_vector: - public vector_expression > { + public vector_expression > { public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - BOOST_UBLAS_USING vector_expression >::operator (); + BOOST_UBLAS_USING vector_expression >::operator (); #endif typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef T value_type; // typedef const T &const_reference; typedef typename type_traits::const_reference const_reference; +#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE typedef T &reference; +#else + typedef sparse_vector_element reference; +#endif typedef const T *const_pointer; typedef T *pointer; typedef IA index_array_type; typedef TA value_array_type; - typedef const compressed_vector const_self_type; - typedef compressed_vector self_type; + typedef const compressed_vector const_self_type; + typedef compressed_vector self_type; typedef const vector_const_reference const_closure_type; typedef vector_reference closure_type; typedef typename IA::const_iterator const_iterator_type; @@ -533,29 +695,32 @@ namespace boost { namespace numeric { namespace ublas { // Construction and destruction BOOST_UBLAS_INLINE - compressed_vector (): + compressed_vector (): size_ (0), non_zeros_ (0), filled_ (0), index_data_ (), value_data_ () {} BOOST_UBLAS_INLINE compressed_vector (size_type size, size_type non_zeros = 0): size_ (size), non_zeros_ (non_zeros), filled_ (0), - index_data_ (non_zeros), value_data_ (non_zeros) {} + index_data_ (non_zeros), value_data_ (non_zeros) { + reserve (non_zeros_); + } BOOST_UBLAS_INLINE - compressed_vector (const compressed_vector &v): + compressed_vector (const compressed_vector &v): size_ (v.size_), non_zeros_ (v.non_zeros_), filled_ (v.filled_), index_data_ (v.index_data_), value_data_ (v.value_data_) {} template BOOST_UBLAS_INLINE compressed_vector (const vector_expression &ae, size_type non_zeros = 0): size_ (ae ().size ()), non_zeros_ (non_zeros), filled_ (0), - index_data_ (non_zeros), value_data_ (non_zeros) { - vector_assign > () (*this, ae); + index_data_ (non_zeros), value_data_ (non_zeros) { + reserve (non_zeros_); + vector_assign (scalar_assign (), *this, ae); } // Accessors BOOST_UBLAS_INLINE - size_type size () const { - return size_; + size_type size () const { + return size_; } BOOST_UBLAS_INLINE size_type non_zeros () const { @@ -577,39 +742,67 @@ namespace boost { namespace numeric { namespace ublas { value_array_type &value_data () { return value_data_; } + BOOST_UBLAS_INLINE + size_type index_base () { + return index_base_; + } // Resizing BOOST_UBLAS_INLINE void resize (size_type size, size_type non_zeros = 0) { size_ = size; - non_zeros_ = non_zeros; + non_zeros_ = std::max (non_zeros, size_type (1)); filled_ = 0; - index_data ().resize (non_zeros); - value_data ().resize (non_zeros); + index_data ().resize (non_zeros_); + value_data ().resize (non_zeros_); } + // Reserving + BOOST_UBLAS_INLINE + void reserve (size_type non_zeros = 0, bool preserve = false) { + non_zeros_ = std::max (non_zeros, size_type (1)); + index_data ().resize (non_zeros_, preserve); + value_data ().resize (non_zeros_, preserve); + } + + // Proxy support +#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE + pointer find_element (size_type i) { + iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + if (it == index_data ().begin () + filled_ || *it != k_based (i)) + return 0; + return &value_data () [it - index_data ().begin ()]; + } +#endif + // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i) const { - const_iterator_type it (std::lower_bound (index_data ().begin (), index_data ().begin () + filled_, i + 1, std::less ())); - if (it == index_data ().begin () + filled_ || *it != i + 1) + const_iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + if (it == index_data ().begin () + filled_ || *it != k_based (i)) return zero_; return value_data () [it - index_data ().begin ()]; } BOOST_UBLAS_INLINE reference operator () (size_type i) { - iterator_type it (std::lower_bound (index_data ().begin (), index_data ().begin () + filled_, i + 1, std::less ())); - if (it == index_data ().begin () + filled_ || *it != i + 1) +#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE + iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + if (it == index_data ().begin () + filled_ || *it != k_based (i)) { insert (i, value_type ()); + it = detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ()); + } return value_data () [it - index_data ().begin ()]; +#else + return reference (*this, i); +#endif } BOOST_UBLAS_INLINE - const_reference operator [] (size_type i) const { - return (*this) (i); + const_reference operator [] (size_type i) const { + return (*this) (i); } BOOST_UBLAS_INLINE - reference operator [] (size_type i) { + reference operator [] (size_type i) { return (*this) (i); } @@ -624,6 +817,7 @@ namespace boost { namespace numeric { namespace ublas { non_zeros_ = v.non_zeros_; filled_ = v.filled_; index_data () = v.index_data (); + value_data ().resize (non_zeros_); value_data () = v.value_data (); } return *this; @@ -654,7 +848,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE compressed_vector &assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_assign (), *this, ae); return *this; } template @@ -671,7 +865,7 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE compressed_vector &plus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_plus_assign (), *this, ae); return *this; } template @@ -688,19 +882,19 @@ namespace boost { namespace numeric { namespace ublas { template BOOST_UBLAS_INLINE compressed_vector &minus_assign (const vector_expression &ae) { - vector_assign > () (*this, ae); + vector_assign (scalar_minus_assign (), *this, ae); return *this; } template BOOST_UBLAS_INLINE compressed_vector &operator *= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_multiplies_assign (), *this, at); return *this; } template BOOST_UBLAS_INLINE compressed_vector &operator /= (const AT &at) { - vector_assign_scalar > () (*this, at); + vector_assign_scalar (scalar_divides_assign (), *this, at); return *this; } @@ -729,21 +923,54 @@ namespace boost { namespace numeric { namespace ublas { // Element insertion and erasure BOOST_UBLAS_INLINE + void push_back (size_type i, const_reference t) { + if (filled_ >= non_zeros_) + reserve (2 * non_zeros_, true); + if (filled_ == 0 || index_data () [filled_ - 1] < k_based (i)) { + ++ filled_; + index_data () [filled_ - 1] = k_based (i); + value_data () [filled_ - 1] = t; + return; + } + // Raising exceptions abstracted as requested during review. + // throw external_logic (); + external_logic ().raise (); + } + BOOST_UBLAS_INLINE void insert (size_type i, const_reference t) { -// FIXME: Doesn't work if the first element is zero. -// #ifdef BOOST_UBLAS_CHECK_FOR_ZERO -// if (t == value_type ()) -// return; -// #endif - BOOST_UBLAS_CHECK (filled_ == 0 || index_data () [filled_ - 1] < i + 1, external_logic ()); - index_data () [filled_] = i + 1; - value_data () [filled_] = t; + if (filled_ >= non_zeros_) + reserve (2 * non_zeros_, true); + iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + difference_type n = it - index_data ().begin (); + BOOST_UBLAS_CHECK (filled_ == 0 || filled_ == size_type (n) || *it != k_based (i), external_logic ()); ++ filled_; + it = index_data ().begin () + n; + std::copy_backward (it, index_data ().begin () + filled_ - 1, index_data ().begin () + filled_); + *it = k_based (i); + typename value_array_type::iterator itt (value_data ().begin () + n); + std::copy_backward (itt, value_data ().begin () + filled_ - 1, value_data ().begin () + filled_); + *itt = t; + } + BOOST_UBLAS_INLINE + void pop_back () { + if (filled_ > 0) { + -- filled_; + return; + } + // Raising exceptions abstracted as requested during review. + // throw external_logic (); + external_logic ().raise (); } BOOST_UBLAS_INLINE void erase (size_type i) { - BOOST_UBLAS_CHECK (filled_ > 0 && index_data () [filled_ - 1] == i + 1, external_logic ()); - -- filled_; + iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + difference_type n = it - index_data ().begin (); + if (filled_ > size_type (n) && *it == k_based (i)) { + std::copy (it + 1, index_data ().begin () + filled_, it); + typename value_array_type::iterator itt (value_data ().begin () + n); + std::copy (itt + 1, value_data ().begin () + filled_, itt); + -- filled_; + } } BOOST_UBLAS_INLINE void clear () { @@ -757,12 +984,12 @@ namespace boost { namespace numeric { namespace ublas { // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE const_iterator find (size_type i) const { - return const_iterator (*this, std::lower_bound (index_data ().begin (), index_data ().begin () + filled_, i + 1, std::less ())); + return const_iterator (*this, detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); } // This function seems to be big. So we do not let the compiler inline it. // BOOST_UBLAS_INLINE iterator find (size_type i) { - return iterator (*this, std::lower_bound (index_data ().begin (), index_data ().begin () + filled_, i + 1, std::less ())); + return iterator (*this, detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); } BOOST_UBLAS_INLINE const_iterator find_first (size_type i) const { @@ -836,7 +1063,7 @@ namespace boost { namespace numeric { namespace ublas { // Index BOOST_UBLAS_INLINE size_type index () const { - return (*it_) - 1; + return (*this) ().zero_based (*it_); } // Assignment @@ -904,13 +1131,17 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE reference operator * () const { BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); +#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE return (*this) ().value_data () [it_ - (*this) ().index_data ().begin ()]; +#else + return reference ((*this) (), &(*this) ().value_data () [it_ - (*this) ().index_data ().begin ()], index ()); +#endif } // Index BOOST_UBLAS_INLINE size_type index () const { - return (*it_) - 1; + return (*this) ().zero_based (*it_); } // Assignment @@ -976,19 +1207,626 @@ namespace boost { namespace numeric { namespace ublas { } private: + BOOST_STATIC_CONSTANT (size_type, index_base_ = IB); size_type size_; size_type non_zeros_; size_type filled_; index_array_type index_data_; value_array_type value_data_; static value_type zero_; + + BOOST_UBLAS_INLINE + static size_type zero_based (size_type k_based_index) { + return k_based_index - index_base_; + } + BOOST_UBLAS_INLINE + static size_type k_based (size_type zero_based_index) { + return zero_based_index + index_base_; + } + + friend class iterator; + friend class const_iterator; }; - template - typename compressed_vector::value_type compressed_vector::zero_ = 0; + template + typename compressed_vector::value_type compressed_vector::zero_ = 0; + + // Array based sparse vector class + // Thanks to Kresimir Fresl for extending this to cover different index bases. + template + class coordinate_vector: + public vector_expression > { + public: +#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS + BOOST_UBLAS_USING vector_expression >::operator (); +#endif + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T value_type; + // typedef const T &const_reference; + typedef typename type_traits::const_reference const_reference; +#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE + typedef T &reference; +#else + typedef sparse_vector_element reference; +#endif + typedef const T *const_pointer; + typedef T *pointer; + typedef IA index_array_type; + typedef TA value_array_type; + typedef const coordinate_vector const_self_type; + typedef coordinate_vector self_type; + typedef const vector_const_reference const_closure_type; + typedef vector_reference closure_type; + typedef typename IA::const_iterator const_iterator_type; + typedef typename IA::iterator iterator_type; + typedef sparse_tag storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + coordinate_vector (): + size_ (0), non_zeros_ (0), filled_ (0), + sorted_ (true), index_data_ (), value_data_ () {} + BOOST_UBLAS_INLINE + coordinate_vector (size_type size, size_type non_zeros = 0): + size_ (size), non_zeros_ (non_zeros), filled_ (0), + sorted_ (true), index_data_ (non_zeros), value_data_ (non_zeros) { + reserve (non_zeros_); + } + BOOST_UBLAS_INLINE + coordinate_vector (const coordinate_vector &v): + size_ (v.size_), non_zeros_ (v.non_zeros_), filled_ (v.filled_), + sorted_ (v.sorted_), index_data_ (v.index_data_), value_data_ (v.value_data_) {} + template + BOOST_UBLAS_INLINE + coordinate_vector (const vector_expression &ae, size_type non_zeros = 0): + size_ (ae ().size ()), non_zeros_ (non_zeros), filled_ (0), + sorted_ (true), index_data_ (non_zeros), value_data_ (non_zeros) { + reserve (non_zeros_); + vector_assign (scalar_assign (), *this, ae); + } + + // Accessors + BOOST_UBLAS_INLINE + size_type size () const { + return size_; + } + BOOST_UBLAS_INLINE + size_type non_zeros () const { + return non_zeros_; + } + BOOST_UBLAS_INLINE + const index_array_type &index_data () const { + return index_data_; + } + BOOST_UBLAS_INLINE + index_array_type &index_data () { + return index_data_; + } + BOOST_UBLAS_INLINE + const value_array_type &value_data () const { + return value_data_; + } + BOOST_UBLAS_INLINE + value_array_type &value_data () { + return value_data_; + } + BOOST_UBLAS_INLINE + size_type index_base () { + return index_base_; + } + + // Resizing + BOOST_UBLAS_INLINE + void resize (size_type size, size_type non_zeros = 0) { + size_ = size; + non_zeros_ = std::max (non_zeros, size_type (1)); + filled_ = 0; + index_data ().resize (non_zeros_); + value_data ().resize (non_zeros_); + } + + // Reserving + BOOST_UBLAS_INLINE + void reserve (size_type non_zeros = 0, bool preserve = false) { + non_zeros_ = std::max (non_zeros, size_type (1)); + index_data ().resize (non_zeros_, preserve); + value_data ().resize (non_zeros_, preserve); + } + + // Proxy support +#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE + pointer find_element (size_type i) { + sort (); + iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + if (it == index_data ().begin () + filled_ || *it != k_based (i)) + return 0; + return &value_data () [it - index_data ().begin ()]; + } +#endif + + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i) const { + sort (); + const_iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + if (it == index_data ().begin () + filled_ || *it != k_based (i)) + return zero_; + return value_data () [it - index_data ().begin ()]; + } + BOOST_UBLAS_INLINE + reference operator () (size_type i) { +#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE + sort (); + iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + if (it == index_data ().begin () + filled_ || *it != k_based (i)) { + insert (i, value_type ()); + sort (); + it = detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ()); + } + return value_data () [it - index_data ().begin ()]; +#else + return reference (*this, i); +#endif + } + + BOOST_UBLAS_INLINE + const_reference operator [] (size_type i) const { + return (*this) (i); + } + BOOST_UBLAS_INLINE + reference operator [] (size_type i) { + return (*this) (i); + } + + // Assignment + BOOST_UBLAS_INLINE + coordinate_vector &operator = (const coordinate_vector &v) { + // Too unusual semantic. + // BOOST_UBLAS_CHECK (this != &v, external_logic ()); + if (this != &v) { + BOOST_UBLAS_CHECK (size_ == v.size_, bad_size ()); + size_ = v.size_; + non_zeros_ = v.non_zeros_; + filled_ = v.filled_; + sorted_ = v.sorted_; + index_data () = v.index_data (); + value_data ().resize (non_zeros_); + value_data () = v.value_data (); + } + return *this; + } + BOOST_UBLAS_INLINE + coordinate_vector &assign_temporary (coordinate_vector &v) { + swap (v); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_vector &operator = (const vector_expression &ae) { +#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY + return assign_temporary (self_type (ae, non_zeros_)); +#else + // return assign (self_type (ae, non_zeros_)); + self_type temporary (ae, non_zeros_); + return assign_temporary (temporary); +#endif + } + template + BOOST_UBLAS_INLINE + coordinate_vector &reset (const vector_expression &ae) { + self_type temporary (ae, non_zeros_); + resize (temporary.size (), non_zeros_); + return assign_temporary (temporary); + } + template + BOOST_UBLAS_INLINE + coordinate_vector &assign (const vector_expression &ae) { + vector_assign (scalar_assign (), *this, ae); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_vector &operator += (const vector_expression &ae) { +#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY + return assign_temporary (self_type (*this + ae, non_zeros_)); +#else + // return assign (self_type (*this + ae, non_zeros_)); + self_type temporary (*this + ae, non_zeros_); + return assign_temporary (temporary); +#endif + } + template + BOOST_UBLAS_INLINE + coordinate_vector &plus_assign (const vector_expression &ae) { + vector_assign (scalar_plus_assign (), *this, ae); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_vector &operator -= (const vector_expression &ae) { +#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY + return assign_temporary (self_type (*this - ae, non_zeros_)); +#else + // return assign (self_type (*this - ae, non_zeros_)); + self_type temporary (*this - ae, non_zeros_); + return assign_temporary (temporary); +#endif + } + template + BOOST_UBLAS_INLINE + coordinate_vector &minus_assign (const vector_expression &ae) { + vector_assign (scalar_minus_assign (), *this, ae); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_vector &operator *= (const AT &at) { + vector_assign_scalar (scalar_multiplies_assign (), *this, at); + return *this; + } + template + BOOST_UBLAS_INLINE + coordinate_vector &operator /= (const AT &at) { + vector_assign_scalar (scalar_divides_assign (), *this, at); + return *this; + } + + // Swapping + BOOST_UBLAS_INLINE + void swap (coordinate_vector &v) { + // Too unusual semantic. + // BOOST_UBLAS_CHECK (this != &v, external_logic ()); + if (this != &v) { + // Precondition for container relaxed as requested during review. + // BOOST_UBLAS_CHECK (size_ == v.size_, bad_size ()); + // BOOST_UBLAS_CHECK (non_zeros_ == v.non_zeros_, bad_size ()); + std::swap (size_, v.size_); + std::swap (non_zeros_, v.non_zeros_); + std::swap (filled_, v.filled_); + std::swap (sorted_, v.sorted_); + index_data ().swap (v.index_data ()); + value_data ().swap (v.value_data ()); + } + } +#ifdef BOOST_UBLAS_FRIEND_FUNCTION + BOOST_UBLAS_INLINE + friend void swap (coordinate_vector &v1, coordinate_vector &v2) { + v1.swap (v2); + } +#endif + + // Sorting + BOOST_UBLAS_INLINE + void sort () const { + if (! sorted_) { + typedef std::pair pair_type; + unbounded_array a (filled_); + size_type i; + for (i = 0; i < filled_; ++ i) + a [i] = pair_type (index_data_ [i], value_data_ [i]); + std::sort (a.begin (), a.end (), detail::less_pair ()); + for (i = 0; i < filled_; ++ i) { + index_data_ [i] = a [i].first; + value_data_ [i] = a [i].second; + } + sorted_ = true; + } + } + + // Element insertion and erasure + BOOST_UBLAS_INLINE + void push_back (size_type i, const_reference t) { + if (filled_ >= non_zeros_) + reserve (2 * non_zeros_, true); + if (filled_ == 0 || index_data () [filled_ - 1] < k_based (i)) { + ++ filled_; + index_data () [filled_ - 1] = k_based (i); + value_data () [filled_ - 1] = t; + return; + } + // Raising exceptions abstracted as requested during review. + // throw external_logic (); + external_logic ().raise (); + } + BOOST_UBLAS_INLINE + void insert (size_type i, const_reference t) { + if (filled_ >= non_zeros_) + reserve (2 * non_zeros_, true); + ++ filled_; + index_data () [filled_ - 1] = k_based (i); + value_data () [filled_ - 1] = t; + sorted_ = false; + } + BOOST_UBLAS_INLINE + void pop_back () { + if (filled_ > 0) { + -- filled_; + return; + } + // Raising exceptions abstracted as requested during review. + // throw external_logic (); + external_logic ().raise (); + } + BOOST_UBLAS_INLINE + void erase (size_type i) { + sort (); + iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + difference_type n = it - index_data ().begin (); + if (filled_ > size_type (n) && *it == k_based (i)) { + std::copy (it + 1, index_data ().begin () + filled_, it); + typename value_array_type::iterator itt (value_data ().begin () + n); + std::copy (itt + 1, value_data ().begin () + filled_, itt); + -- filled_; + } + } + BOOST_UBLAS_INLINE + void clear () { + filled_ = 0; + } + + class const_iterator; + class iterator; + + // Element lookup + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + const_iterator find (size_type i) const { + sort (); + return const_iterator (*this, detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + } + // This function seems to be big. So we do not let the compiler inline it. + // BOOST_UBLAS_INLINE + iterator find (size_type i) { + sort (); + return iterator (*this, detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less ())); + } + BOOST_UBLAS_INLINE + const_iterator find_first (size_type i) const { + return find (i); + } + BOOST_UBLAS_INLINE + iterator find_first (size_type i) { + return find (i); + } + BOOST_UBLAS_INLINE + const_iterator find_last (size_type i) const { + return find (i); + } + BOOST_UBLAS_INLINE + iterator find_last (size_type i) { + return find (i); + } + + // Iterators simply are pointers. + + class const_iterator: + public container_const_reference, + public bidirectional_iterator_base { + public: + typedef sparse_bidirectional_iterator_tag iterator_category; +#ifdef BOOST_MSVC_STD_ITERATOR + typedef const_reference reference; +#else + typedef typename coordinate_vector::difference_type difference_type; + typedef typename coordinate_vector::value_type value_type; + typedef typename coordinate_vector::const_reference reference; + typedef typename coordinate_vector::const_pointer pointer; +#endif + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator (): + container_const_reference (), it_ () {} + BOOST_UBLAS_INLINE + const_iterator (const coordinate_vector &v, const const_iterator_type &it): + container_const_reference (v), it_ (it) {} +#ifndef BOOST_UBLAS_QUALIFIED_TYPENAME + BOOST_UBLAS_INLINE + const_iterator (const iterator &it): + container_const_reference (it ()), it_ (it.it_) {} +#else + BOOST_UBLAS_INLINE + const_iterator (const typename coordinate_vector::iterator &it): + container_const_reference (it ()), it_ (it.it_) {} +#endif + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator &operator ++ () { + ++ it_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator &operator -- () { + -- it_; + return *this; + } + + // Dereference + BOOST_UBLAS_INLINE + reference operator * () const { + BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); + return (*this) ().value_data () [it_ - (*this) ().index_data ().begin ()]; + } + + // Index + BOOST_UBLAS_INLINE + size_type index () const { + return (*this) ().zero_based (*it_); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator &operator = (const const_iterator &it) { + container_const_reference::assign (&it ()); + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator &it) const { + BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); + return it_ == it.it_; + } + + private: + const_iterator_type it_; + }; + + BOOST_UBLAS_INLINE + const_iterator begin () const { + return find_first (0); + } + BOOST_UBLAS_INLINE + const_iterator end () const { + return find_last (size_); + } + + class iterator: + public container_reference, + public bidirectional_iterator_base { + public: + typedef sparse_bidirectional_iterator_tag iterator_category; +#ifndef BOOST_MSVC_STD_ITERATOR + typedef typename coordinate_vector::difference_type difference_type; + typedef typename coordinate_vector::value_type value_type; + typedef typename coordinate_vector::reference reference; + typedef typename coordinate_vector::pointer pointer; +#endif + + // Construction and destruction + BOOST_UBLAS_INLINE + iterator (): + container_reference (), it_ () {} + BOOST_UBLAS_INLINE + iterator (coordinate_vector &v, const iterator_type &it): + container_reference (v), it_ (it) {} + + // Arithmetic + BOOST_UBLAS_INLINE + iterator &operator ++ () { + ++ it_; + return *this; + } + BOOST_UBLAS_INLINE + iterator &operator -- () { + -- it_; + return *this; + } + + // Dereference + BOOST_UBLAS_INLINE + reference operator * () const { + BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); +#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE + return (*this) ().value_data () [it_ - (*this) ().index_data ().begin ()]; +#else + return reference ((*this) (), &(*this) ().value_data () [it_ - (*this) ().index_data ().begin ()], index ()); +#endif + } + + // Index + BOOST_UBLAS_INLINE + size_type index () const { + return (*this) ().zero_based (*it_); + } + + // Assignment + BOOST_UBLAS_INLINE + iterator &operator = (const iterator &it) { + container_reference::assign (&it ()); + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const iterator &it) const { + BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); + return it_ == it.it_; + } + + private: + iterator_type it_; + + friend class const_iterator; + }; + + BOOST_UBLAS_INLINE + iterator begin () { + return find_first (0); + } + BOOST_UBLAS_INLINE + iterator end () { + return find_last (size_); + } + + // Reverse iterator + +#ifdef BOOST_MSVC_STD_ITERATOR + typedef reverse_iterator_base const_reverse_iterator; +#else + typedef reverse_iterator_base const_reverse_iterator; +#endif + + BOOST_UBLAS_INLINE + const_reverse_iterator rbegin () const { + return const_reverse_iterator (end ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator rend () const { + return const_reverse_iterator (begin ()); + } + +#ifdef BOOST_MSVC_STD_ITERATOR + typedef reverse_iterator_base reverse_iterator; +#else + typedef reverse_iterator_base reverse_iterator; +#endif + + BOOST_UBLAS_INLINE + reverse_iterator rbegin () { + return reverse_iterator (end ()); + } + BOOST_UBLAS_INLINE + reverse_iterator rend () { + return reverse_iterator (begin ()); + } + + private: + BOOST_STATIC_CONSTANT (size_type, index_base_ = IB); + size_type size_; + size_type non_zeros_; + size_type filled_; + mutable bool sorted_; + mutable index_array_type index_data_; + mutable value_array_type value_data_; + static value_type zero_; + + BOOST_UBLAS_INLINE + static size_type zero_based (size_type k_based_index) { + return k_based_index - index_base_; + } + BOOST_UBLAS_INLINE + static size_type k_based (size_type zero_based_index) { + return zero_based_index + index_base_; + } + + friend class iterator; + friend class const_iterator; + }; + + template + typename coordinate_vector::value_type coordinate_vector::zero_ = 0; }}} #endif + + diff --git a/test1/Jamfile b/test1/Jamfile index b93b9d53..9d550341 100644 --- a/test1/Jamfile +++ b/test1/Jamfile @@ -5,8 +5,8 @@ SOURCES = test1 test11 test12 test13 ; exe test1 : $(SOURCES).cpp : $(BOOST_ROOT) + BOOST_UBLAS_SAFE USE_RANGE - BOOST_UBLAS_TYPE_CHECK <*>"-w-8026 -w-8027 -w-8057 -w-8084 -w-8092" ; diff --git a/test1/test1.hpp b/test1/test1.hpp index fa5acfe4..5b4e6efe 100644 --- a/test1/test1.hpp +++ b/test1/test1.hpp @@ -25,6 +25,10 @@ void test_matrix_vector (); void test_matrix (); +// #define USE_FLOAT +#define USE_DOUBLE +// #define USE_STD_COMPLEX + // #define USE_RANGE // #define USE_SLICE diff --git a/test1/test11.cpp b/test1/test11.cpp index 3ffe1fcd..4c4d618b 100644 --- a/test1/test11.cpp +++ b/test1/test11.cpp @@ -163,45 +163,75 @@ void test_vector () { std::cout << "test_vector" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_vector, ublas::bounded_array, 3> >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_vector, ublas::bounded_array, 3> >, 3 > () (); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_vector, ublas::unbounded_array > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_vector, ublas::unbounded_array > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_vector, std::vector > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_vector, std::vector > >, 3 > () (); #endif +#endif +#endif } diff --git a/test1/test12.cpp b/test1/test12.cpp index 5e606c71..4a11fe1f 100644 --- a/test1/test12.cpp +++ b/test1/test12.cpp @@ -102,115 +102,175 @@ void test_matrix_vector () { #ifdef USE_MATRIX #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix_vector >, ublas::matrix >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix_vector >, ublas::matrix >, 3> () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::matrix >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::matrix >, 3> () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix_vector, ublas::unbounded_array > >, ublas::matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix_vector, ublas::unbounded_array > >, ublas::matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix_vector >, ublas::matrix >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix_vector >, ublas::matrix >, 3> () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix_vector, std::vector > >, ublas::matrix, ublas::row_major, std::vector > >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_matrix_vector, std::vector > >, ublas::matrix, ublas::row_major, std::vector > >, 3> () (); #endif #endif +#endif +#endif #ifdef USE_VECTOR_OF_VECTOR #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix_vector >, ublas::vector_of_vector, 3 + 1> >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix_vector >, ublas::vector_of_vector, 3 + 1> >, 3> () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::vector_of_vector, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::vector_of_vector, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3> () (); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::vector_of_vector > >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::vector_of_vector > >, 3> () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix_vector, ublas::unbounded_array > >, ublas::vector_of_vector, ublas::row_major, ublas::unbounded_array > > >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix_vector, ublas::unbounded_array > >, ublas::vector_of_vector, ublas::row_major, ublas::unbounded_array > > >, 3> () (); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix_vector >, ublas::vector_of_vector > >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix_vector >, ublas::vector_of_vector > >, 3> () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix_vector, std::vector > >, ublas::vector_of_vector, ublas::row_major, std::vector > > >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_matrix_vector, std::vector > >, ublas::vector_of_vector, ublas::row_major, std::vector > > >, 3> () (); #endif #endif +#endif +#endif } diff --git a/test1/test13.cpp b/test1/test13.cpp index 5c85729f..c1b9a278 100644 --- a/test1/test13.cpp +++ b/test1/test13.cpp @@ -155,91 +155,151 @@ void test_matrix () { #ifdef USE_MATRIX #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); #endif #endif +#endif +#endif #ifdef USE_VECTOR_OF_VECTOR #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix, 3 + 1> >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix, 3 + 1> >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3 > () (); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix > >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::unbounded_array > > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::unbounded_array > > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix > >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::row_major, std::vector > > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::row_major, std::vector > > >, 3 > () (); #endif #endif +#endif +#endif } diff --git a/test2/Jamfile b/test2/Jamfile index 904a5e42..208e1302 100644 --- a/test2/Jamfile +++ b/test2/Jamfile @@ -5,7 +5,7 @@ SOURCES = test2 test21 test22 test23 ; exe test2 : $(SOURCES).cpp : $(BOOST_ROOT) - BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_SAFE <*>"-w-8026 -w-8027 -w-8057 -w-8084 -w-8092" ; diff --git a/test2/test2.cpp b/test2/test2.cpp index 44f3c45b..7c7a3602 100644 --- a/test2/test2.cpp +++ b/test2/test2.cpp @@ -33,49 +33,76 @@ int main () { std::cout << "test_blas_1" << std::endl; +#ifdef USE_FLOAT std::cout << "float" << std::endl; test_blas_1, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "double" << std::endl; test_blas_1, 3> () (); +#endif #ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex" << std::endl; test_blas_1 >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex" << std::endl; test_blas_1 >, 3> () (); +#endif #endif std::cout << "test_blas_2" << std::endl; +#ifdef USE_FLOAT std::cout << "float" << std::endl; test_blas_2, ublas::matrix, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "double" << std::endl; test_blas_2, ublas::matrix, 3> () (); +#endif #ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex" << std::endl; test_blas_2 >, ublas::matrix >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex" << std::endl; test_blas_2 >, ublas::matrix >, 3> () (); +#endif #endif + std::cout << "test_blas_3" << std::endl; + +#ifdef USE_FLOAT std::cout << "float" << std::endl; test_blas_3, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "double" << std::endl; test_blas_3, 3> () (); +#endif #ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex" << std::endl; test_blas_3 >, 3> () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex" << std::endl; test_blas_3 >, 3> () (); #endif +#endif + return 0; } diff --git a/test2/test2.hpp b/test2/test2.hpp index 2e24c43d..b67cb9a2 100644 --- a/test2/test2.hpp +++ b/test2/test2.hpp @@ -65,8 +65,10 @@ struct test_blas_3 { void operator () (); }; -// #define USE_STD_COMPLEX +#define USE_FLOAT +#define USE_DOUBLE +#define USE_STD_COMPLEX -#endif +#endif diff --git a/test2/test21.cpp b/test2/test21.cpp index 269fc801..a4a74a7b 100644 --- a/test2/test21.cpp +++ b/test2/test21.cpp @@ -88,10 +88,20 @@ void test_blas_1::operator () () { } } +#ifdef USE_FLOAT template struct test_blas_1, 3>; +#endif + +#ifdef USE_DOUBLE template struct test_blas_1, 3>; +#endif #ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT template struct test_blas_1 >, 3>; +#endif + +#ifdef USE_DOUBLE template struct test_blas_1 >, 3>; #endif +#endif diff --git a/test2/test22.cpp b/test2/test22.cpp index e05b28e4..a65692f0 100644 --- a/test2/test22.cpp +++ b/test2/test22.cpp @@ -140,11 +140,21 @@ void test_blas_2::operator () () { } } +#ifdef USE_FLOAT template struct test_blas_2, ublas::matrix, 3>; -template struct test_blas_2, ublas::matrix, 3>; - -#ifdef USE_STD_COMPLEX -template struct test_blas_2 >, ublas::matrix >, 3>; -template struct test_blas_2 >, ublas::matrix >, 3>; +#endif + +#ifdef USE_DOUBLE +template struct test_blas_2, ublas::matrix, 3>; +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT +template struct test_blas_2 >, ublas::matrix >, 3>; +#endif + +#ifdef USE_DOUBLE +template struct test_blas_2 >, ublas::matrix >, 3>; +#endif #endif diff --git a/test2/test23.cpp b/test2/test23.cpp index 7eb94cba..013288f7 100644 --- a/test2/test23.cpp +++ b/test2/test23.cpp @@ -201,10 +201,20 @@ void test_blas_3::operator () () { } } +#ifdef USE_FLOAT template struct test_blas_3, 3>; +#endif + +#ifdef USE_DOUBLE template struct test_blas_3, 3>; +#endif #ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT template struct test_blas_3 >, 3>; +#endif + +#ifdef USE_DOUBLE template struct test_blas_3 >, 3>; #endif +#endif diff --git a/test3/Jamfile b/test3/Jamfile index c0675e5c..6e43adef 100644 --- a/test3/Jamfile +++ b/test3/Jamfile @@ -5,8 +5,8 @@ SOURCES = test3 test31 test32 test33 ; exe test3 : $(SOURCES).cpp : $(BOOST_ROOT) + BOOST_UBLAS_SAFE USE_RANGE - BOOST_UBLAS_TYPE_CHECK <*>"-w-8026 -w-8027 -w-8057 -w-8084 -w-8092" ; diff --git a/test3/test3.hpp b/test3/test3.hpp index 689ca85e..74f82e59 100644 --- a/test3/test3.hpp +++ b/test3/test3.hpp @@ -25,6 +25,10 @@ void test_matrix_vector (); void test_matrix (); +// #define USE_FLOAT +#define USE_DOUBLE +// #define USE_STD_COMPLEX + // #define USE_RANGE // #define USE_SLICE @@ -32,11 +36,13 @@ void test_matrix (); // #define USE_STD_MAP #define USE_SPARSE_VECTOR -// #define USE_COMPRESSED_VECTOR +#define USE_COMPRESSED_VECTOR +#define USE_COORDINATE_VECTOR #define USE_SPARSE_MATRIX // #define USE_SPARSE_VECTOR_OF_SPARSE_VECTOR -// #define USE_COMPRESSED_MATRIX +#define USE_COMPRESSED_MATRIX +#define USE_COORDINATE_MATRIX #endif diff --git a/test3/test31.cpp b/test3/test31.cpp index 33698f6d..665a9350 100644 --- a/test3/test31.cpp +++ b/test3/test31.cpp @@ -166,46 +166,100 @@ void test_vector () { #ifdef USE_SPARSE_VECTOR #ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT std::cout << "float, map_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, map_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, map_array" << std::endl; test_my_vector, ublas::map_array > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, map_array" << std::endl; test_my_vector, ublas::map_array > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_MAP +#ifdef USE_FLOAT std::cout << "float, std::map" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::map" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::map" << std::endl; test_my_vector, std::map > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::map" << std::endl; test_my_vector, std::map > > , 3 > () (); #endif #endif +#endif +#endif #ifdef USE_COMPRESSED_VECTOR +#ifdef USE_FLOAT std::cout << "float" << std::endl; test_my_vector, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double" << std::endl; test_my_vector, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex" << std::endl; test_my_vector >, 3 > () (); #endif +#endif +#endif + +#ifdef USE_COORDINATE_VECTOR +#ifdef USE_FLOAT + std::cout << "float" << std::endl; + test_my_vector, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double" << std::endl; + test_my_vector, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex" << std::endl; + test_my_vector >, 3 > () (); +#endif +#endif +#endif } diff --git a/test3/test32.cpp b/test3/test32.cpp index 371e5c5c..ced4f232 100644 --- a/test3/test32.cpp +++ b/test3/test32.cpp @@ -27,6 +27,7 @@ struct test_my_matrix_vector { try { // Rows and columns initialize_matrix (m1); + std::cout << "m1 = " << m1 << std::endl; for (int i = 0; i < N; ++ i) { v1 = ublas::row (m1, i); std::cout << "row (m, " << i << ") = " << v1 << std::endl; @@ -105,32 +106,48 @@ void test_matrix_vector () { #ifdef USE_SPARSE_MATRIX #ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT std::cout << "float, map_array" << std::endl; test_my_matrix_vector >, ublas::sparse_matrix >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, map_array" << std::endl; test_my_matrix_vector >, ublas::sparse_matrix >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, map_array" << std::endl; test_my_matrix_vector, ublas::map_array > >, ublas::sparse_matrix, ublas::row_major, ublas::map_array > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, map_array" << std::endl; test_my_matrix_vector, ublas::map_array > >, ublas::sparse_matrix, ublas::row_major, ublas::map_array > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_MAP +#ifdef USE_FLOAT std::cout << "float, std::map" << std::endl; test_my_matrix_vector >, ublas::sparse_matrix >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::map" << std::endl; test_my_matrix_vector >, ublas::sparse_matrix >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::map" << std::endl; test_my_matrix_vector, std::map > >, ublas::sparse_matrix, ublas::row_major, std::map > >, 3 > () (); @@ -140,17 +157,25 @@ void test_matrix_vector () { ublas::sparse_matrix, ublas::row_major, std::map > >, 3 > () (); #endif #endif +#endif +#endif #ifdef USE_SPARSE_VECTOR_OF_SPARSE_VECTOR #ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT std::cout << "float, map_array" << std::endl; test_my_matrix_vector >, ublas::sparse_vector_of_sparse_vector > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, map_array" << std::endl; test_my_matrix_vector >, ublas::sparse_vector_of_sparse_vector > >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, map_array" << std::endl; test_my_matrix_vector, ublas::map_array > >, ublas::sparse_vector_of_sparse_vector, ublas::row_major, ublas::map_array > > >, 3 > () (); @@ -159,35 +184,53 @@ void test_matrix_vector () { test_my_matrix_vector, ublas::map_array > >, ublas::sparse_vector_of_sparse_vector, ublas::row_major, ublas::map_array > > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_MAP +#ifdef USE_FLOAT std::cout << "float, std::map" << std::endl; test_my_matrix_vector >, ublas::sparse_vector_of_sparse_vector > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::map" << std::endl; test_my_matrix_vector >, ublas::sparse_vector_of_sparse_vector > >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::map" << std::endl; test_my_matrix_vector, std::map > >, ublas::sparse_vector_of_sparse_vector, ublas::row_major, std::map > > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::map" << std::endl; test_my_matrix_vector, std::map > >, ublas::sparse_vector_of_sparse_vector, ublas::row_major, std::map > > >, 3 > () (); #endif #endif +#endif +#endif #ifdef USE_COMPRESSED_MATRIX +#ifdef USE_FLOAT std::cout << "float" << std::endl; test_my_matrix_vector, ublas::compressed_matrix, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double" << std::endl; test_my_matrix_vector, ublas::compressed_matrix, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex" << std::endl; test_my_matrix_vector >, ublas::compressed_matrix >, 3 > () (); @@ -196,5 +239,33 @@ void test_matrix_vector () { test_my_matrix_vector >, ublas::compressed_matrix >, 3 > () (); #endif +#endif +#endif + +#ifdef USE_COORDINATE_MATRIX +#ifdef USE_FLOAT + std::cout << "float" << std::endl; + test_my_matrix_vector, + ublas::coordinate_matrix, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double" << std::endl; + test_my_matrix_vector, + ublas::coordinate_matrix, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex" << std::endl; + test_my_matrix_vector >, + ublas::coordinate_matrix >, 3 > () (); + + std::cout << "std::complex" << std::endl; + test_my_matrix_vector >, + ublas::coordinate_matrix >, 3 > () (); +#endif +#endif +#endif } diff --git a/test3/test33.cpp b/test3/test33.cpp index 2fe8f3a4..59c682cb 100644 --- a/test3/test33.cpp +++ b/test3/test33.cpp @@ -151,83 +151,157 @@ struct test_my_matrix { } }; -// Test matrix +// Test matrix void test_matrix () { std::cout << "test_matrix" << std::endl; #ifdef USE_SPARSE_MATRIX #ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT std::cout << "float, map_array" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, map_array" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, map_array" << std::endl; test_my_matrix, ublas::row_major, ublas::map_array > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, map_array" << std::endl; test_my_matrix, ublas::row_major, ublas::map_array > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_MAP +#ifdef USE_FLOAT std::cout << "float, std::map" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::map" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::map" << std::endl; test_my_matrix, ublas::row_major, std::map > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::map" << std::endl; test_my_matrix, ublas::row_major, std::map > >, 3 > () (); #endif #endif +#endif +#endif #ifdef USE_SPARSE_VECTOR_OF_SPARSE_VECTOR #ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT std::cout << "float, map_array" << std::endl; test_my_matrix > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, map_array" << std::endl; test_my_matrix > >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, map_array" << std::endl; test_my_matrix, ublas::row_major, ublas::map_array > > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, map_array" << std::endl; test_my_matrix, ublas::row_major, ublas::map_array > > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_MAP +#ifdef USE_FLOAT std::cout << "float, std::map" << std::endl; test_my_matrix > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::map" << std::endl; test_my_matrix > >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::map" << std::endl; test_my_matrix, ublas::row_major, std::map > > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::map" << std::endl; test_my_matrix, ublas::row_major, std::map > > >, 3 > () (); #endif #endif +#endif +#endif #ifdef USE_COMPRESSED_MATRIX +#ifdef USE_FLOAT std::cout << "float" << std::endl; test_my_matrix, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double" << std::endl; test_my_matrix, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex" << std::endl; test_my_matrix >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex" << std::endl; test_my_matrix >, 3 > () (); #endif +#endif +#endif + +#ifdef USE_COORDINATE_MATRIX +#ifdef USE_FLOAT + std::cout << "float" << std::endl; + test_my_matrix, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double" << std::endl; + test_my_matrix, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex" << std::endl; + test_my_matrix >, 3 > () (); +#endif +#endif +#endif } diff --git a/test4/Jamfile b/test4/Jamfile index 85f6978e..d977617d 100644 --- a/test4/Jamfile +++ b/test4/Jamfile @@ -5,9 +5,9 @@ SOURCES = test4 test41 test42 test43 ; exe test4 : $(SOURCES).cpp : $(BOOST_ROOT) + BOOST_UBLAS_SAFE USE_RANGE USE_ADAPTOR - BOOST_UBLAS_TYPE_CHECK <*>"-w-8026 -w-8027 -w-8057 -w-8084 -w-8092" ; diff --git a/test4/test4.hpp b/test4/test4.hpp index 9c6a1954..c960c790 100644 --- a/test4/test4.hpp +++ b/test4/test4.hpp @@ -25,6 +25,10 @@ void test_matrix_vector (); void test_matrix (); +// #define USE_FLOAT +#define USE_DOUBLE +// #define USE_STD_COMPLEX + // #define USE_RANGE // #define USE_SLICE diff --git a/test4/test41.cpp b/test4/test41.cpp index ac647c94..75a4f7a1 100644 --- a/test4/test41.cpp +++ b/test4/test41.cpp @@ -164,45 +164,75 @@ void test_vector () { std::cout << "test_vector" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_vector, ublas::bounded_array, 3> >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_vector, ublas::bounded_array, 3> >, 3 > () (); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_vector, ublas::unbounded_array > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_vector, ublas::unbounded_array > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_vector, std::vector > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_vector, std::vector > >, 3 > () (); #endif +#endif +#endif } diff --git a/test4/test42.cpp b/test4/test42.cpp index c6d85fa6..99edb9a1 100644 --- a/test4/test42.cpp +++ b/test4/test42.cpp @@ -148,81 +148,111 @@ void test_matrix_vector () { std::cout << "test_matrix_vector" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix_vector >, ublas::banded_matrix >, 3> () (); test_my_matrix_vector >, ublas::banded_matrix >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix_vector >, ublas::banded_matrix >, 3> () (); test_my_matrix_vector >, ublas::banded_matrix >, 3> () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::banded_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::banded_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::banded_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::banded_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::banded_matrix >, 3> () (); test_my_matrix_vector >, ublas::banded_matrix >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::banded_matrix >, 3> () (); test_my_matrix_vector >, ublas::banded_matrix >, 3> () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix_vector, ublas::unbounded_array > >, ublas::banded_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); test_my_matrix_vector, ublas::unbounded_array > >, ublas::banded_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix_vector, ublas::unbounded_array > >, ublas::banded_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); test_my_matrix_vector, ublas::unbounded_array > >, ublas::banded_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (0); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix_vector >, ublas::banded_matrix >, 3> () (); test_my_matrix_vector >, ublas::banded_matrix >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix_vector >, ublas::banded_matrix >, 3> () (); test_my_matrix_vector >, ublas::banded_matrix >, 3> () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix_vector, std::vector > >, ublas::banded_matrix, ublas::row_major, std::vector > >, 3> () (); test_my_matrix_vector, std::vector > >, ublas::banded_matrix, ublas::row_major, std::vector > >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_matrix_vector, std::vector > >, ublas::banded_matrix, ublas::row_major, std::vector > >, 3> () (); test_my_matrix_vector, std::vector > >, ublas::banded_matrix, ublas::row_major, std::vector > >, 3> () (0); #endif +#endif +#endif } diff --git a/test4/test43.cpp b/test4/test43.cpp index 0b6118e1..6d24637b 100644 --- a/test4/test43.cpp +++ b/test4/test43.cpp @@ -195,63 +195,93 @@ struct test_my_matrix { } }; -// Test matrix +// Test matrix void test_matrix () { std::cout << "test_matrix" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (0); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (0); #endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#endif +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); test_my_matrix, ublas::row_major, std::vector > >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); test_my_matrix, ublas::row_major, std::vector > >, 3 > () (0); #endif +#endif +#endif } diff --git a/test5/Jamfile b/test5/Jamfile index 919fc387..bafafa5d 100644 --- a/test5/Jamfile +++ b/test5/Jamfile @@ -5,9 +5,9 @@ SOURCES = test5 test51 test52 test53 ; exe test5 : $(SOURCES).cpp : $(BOOST_ROOT) + BOOST_UBLAS_SAFE USE_RANGE USE_ADAPTOR - BOOST_UBLAS_TYPE_CHECK <*>"-w-8026 -w-8027 -w-8057 -w-8084 -w-8092" ; diff --git a/test5/test5.hpp b/test5/test5.hpp index 0b06a63d..3f67faa6 100644 --- a/test5/test5.hpp +++ b/test5/test5.hpp @@ -50,6 +50,10 @@ void test_matrix_vector (); void test_matrix (); +// #define USE_FLOAT +#define USE_DOUBLE +// #define USE_STD_COMPLEX + // #define USE_RANGE // #define USE_SLICE diff --git a/test5/test51.cpp b/test5/test51.cpp index 8168bf8d..85210802 100644 --- a/test5/test51.cpp +++ b/test5/test51.cpp @@ -164,45 +164,75 @@ void test_vector () { std::cout << "test_vector" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_vector, ublas::bounded_array, 3> >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_vector, ublas::bounded_array, 3> >, 3 > () (); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_vector, ublas::unbounded_array > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_vector, ublas::unbounded_array > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_vector, std::vector > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_vector, std::vector > >, 3 > () (); #endif +#endif +#endif } diff --git a/test5/test52.cpp b/test5/test52.cpp index a5e2f335..e3df19f8 100644 --- a/test5/test52.cpp +++ b/test5/test52.cpp @@ -148,44 +148,60 @@ void test_matrix_vector () { std::cout << "test_matrix_vector" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (); test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (); test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (); test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (); test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix_vector, ublas::unbounded_array > >, ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (); @@ -198,20 +214,28 @@ void test_matrix_vector () { test_my_matrix_vector, ublas::unbounded_array > >, ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (0); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (); test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (); test_my_matrix_vector >, ublas::triangular_matrix >, 3> () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix_vector, std::vector > >, ublas::triangular_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (); @@ -224,5 +248,7 @@ void test_matrix_vector () { test_my_matrix_vector, std::vector > >, ublas::triangular_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (0); #endif +#endif +#endif } diff --git a/test5/test53.cpp b/test5/test53.cpp index d5580069..602f282c 100644 --- a/test5/test53.cpp +++ b/test5/test53.cpp @@ -200,58 +200,88 @@ void test_matrix () { std::cout << "test_matrix" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (0); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (0); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (0); +#endif - std::cout << "std::complex, std::vector" << std::endl; +#ifdef USE_DOUBLE +std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (0); #endif +#endif +#endif } diff --git a/test6/Jamfile b/test6/Jamfile index 94791ec5..4ebf4c6b 100644 --- a/test6/Jamfile +++ b/test6/Jamfile @@ -5,9 +5,9 @@ SOURCES = test6 test61 test62 test63 ; exe test6 : $(SOURCES).cpp : $(BOOST_ROOT) + BOOST_UBLAS_SAFE USE_RANGE USE_ADAPTOR - BOOST_UBLAS_TYPE_CHECK <*>"-w-8026 -w-8027 -w-8057 -w-8084 -w-8092" ; diff --git a/test6/test6.hpp b/test6/test6.hpp index 93a2a39d..132a2f4a 100644 --- a/test6/test6.hpp +++ b/test6/test6.hpp @@ -50,6 +50,10 @@ void test_matrix_vector (); void test_matrix (); +// #define USE_FLOAT +#define USE_DOUBLE +// #define USE_STD_COMPLEX + // #define USE_RANGE // #define USE_SLICE diff --git a/test6/test61.cpp b/test6/test61.cpp index 6fafccbe..738cc8e1 100644 --- a/test6/test61.cpp +++ b/test6/test61.cpp @@ -165,45 +165,75 @@ void test_vector () { std::cout << "test_vector" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_vector, ublas::bounded_array, 3> >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_vector, ublas::bounded_array, 3> >, 3 > () (); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_vector, ublas::unbounded_array > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_vector, ublas::unbounded_array > >, 3 > () (); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_vector >, 3 > () (); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_vector, std::vector > >, 3 > () (); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_vector, std::vector > >, 3 > () (); #endif +#endif +#endif } diff --git a/test6/test62.cpp b/test6/test62.cpp index 6f5b97f1..36f6fd59 100644 --- a/test6/test62.cpp +++ b/test6/test62.cpp @@ -151,81 +151,111 @@ void test_matrix_vector () { std::cout << "test_matrix_vector" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (); test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (); test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); test_my_matrix_vector, ublas::bounded_array, 3> >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (); test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (); test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix_vector, ublas::unbounded_array > >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (); test_my_matrix_vector, ublas::unbounded_array > >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix_vector, ublas::unbounded_array > >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (); test_my_matrix_vector, ublas::unbounded_array > >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (0); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (); test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (); test_my_matrix_vector >, ublas::symmetric_matrix >, 3> () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix_vector, std::vector > >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (); test_my_matrix_vector, std::vector > >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_matrix_vector, std::vector > >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (); test_my_matrix_vector, std::vector > >, ublas::symmetric_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (0); #endif +#endif +#endif } diff --git a/test6/test63.cpp b/test6/test63.cpp index 0e1b10f3..8fe91660 100644 --- a/test6/test63.cpp +++ b/test6/test63.cpp @@ -201,58 +201,88 @@ void test_matrix () { std::cout << "test_matrix" << std::endl; #ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, bounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, bounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, bounded_array" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (0); #endif +#endif +#endif #ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT std::cout << "float, unbounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, unbounded_array" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, unbounded_array" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (0); #endif +#endif +#endif #ifdef USE_STD_VECTOR +#ifdef USE_FLOAT std::cout << "float, std::vector" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "double, std::vector" << std::endl; test_my_matrix >, 3 > () (); test_my_matrix >, 3 > () (0); +#endif +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (0); +#endif +#ifdef USE_DOUBLE std::cout << "std::complex, std::vector" << std::endl; test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (); test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (0); #endif +#endif +#endif }