summaryrefslogtreecommitdiff
path: root/boost/numeric/ublas
diff options
context:
space:
mode:
Diffstat (limited to 'boost/numeric/ublas')
-rw-r--r--boost/numeric/ublas/assignment.hpp59
-rw-r--r--boost/numeric/ublas/detail/concepts.hpp114
-rw-r--r--boost/numeric/ublas/detail/matrix_assign.hpp161
-rw-r--r--boost/numeric/ublas/detail/returntype_deduction.hpp4
-rw-r--r--boost/numeric/ublas/detail/vector_assign.hpp47
-rw-r--r--boost/numeric/ublas/functional.hpp74
-rw-r--r--boost/numeric/ublas/matrix.hpp43
-rw-r--r--boost/numeric/ublas/matrix_expression.hpp10262
-rw-r--r--boost/numeric/ublas/matrix_sparse.hpp6
-rw-r--r--boost/numeric/ublas/matrix_vector.hpp128
-rw-r--r--boost/numeric/ublas/opencl.hpp16
-rw-r--r--boost/numeric/ublas/opencl/elementwise.hpp508
-rw-r--r--boost/numeric/ublas/opencl/library.hpp38
-rw-r--r--boost/numeric/ublas/opencl/matrix.hpp123
-rw-r--r--boost/numeric/ublas/opencl/misc.hpp182
-rw-r--r--boost/numeric/ublas/opencl/operations.hpp18
-rw-r--r--boost/numeric/ublas/opencl/prod.hpp364
-rw-r--r--boost/numeric/ublas/opencl/transpose.hpp142
-rw-r--r--boost/numeric/ublas/opencl/vector.hpp90
-rw-r--r--boost/numeric/ublas/operation/begin.hpp566
-rw-r--r--boost/numeric/ublas/storage.hpp43
-rw-r--r--boost/numeric/ublas/storage_sparse.hpp7
-rw-r--r--boost/numeric/ublas/tensor.hpp26
-rw-r--r--boost/numeric/ublas/tensor/algorithms.hpp345
-rw-r--r--boost/numeric/ublas/tensor/expression.hpp181
-rw-r--r--boost/numeric/ublas/tensor/expression_evaluation.hpp288
-rw-r--r--boost/numeric/ublas/tensor/extents.hpp335
-rw-r--r--boost/numeric/ublas/tensor/functions.hpp558
-rw-r--r--boost/numeric/ublas/tensor/index.hpp89
-rw-r--r--boost/numeric/ublas/tensor/multi_index.hpp110
-rw-r--r--boost/numeric/ublas/tensor/multi_index_utility.hpp364
-rw-r--r--boost/numeric/ublas/tensor/multiplication.hpp945
-rw-r--r--boost/numeric/ublas/tensor/operators_arithmetic.hpp244
-rw-r--r--boost/numeric/ublas/tensor/operators_comparison.hpp175
-rw-r--r--boost/numeric/ublas/tensor/ostream.hpp122
-rw-r--r--boost/numeric/ublas/tensor/storage_traits.hpp84
-rw-r--r--boost/numeric/ublas/tensor/strides.hpp251
-rw-r--r--boost/numeric/ublas/tensor/tensor.hpp734
-rw-r--r--boost/numeric/ublas/traits.hpp28
-rw-r--r--boost/numeric/ublas/vector.hpp17
-rw-r--r--boost/numeric/ublas/vector_expression.hpp26
-rw-r--r--boost/numeric/ublas/vector_of_vector.hpp4
-rw-r--r--boost/numeric/ublas/vector_sparse.hpp33
43 files changed, 12314 insertions, 5640 deletions
diff --git a/boost/numeric/ublas/assignment.hpp b/boost/numeric/ublas/assignment.hpp
index d2079e13dc..d14ada02bd 100644
--- a/boost/numeric/ublas/assignment.hpp
+++ b/boost/numeric/ublas/assignment.hpp
@@ -8,6 +8,7 @@
#ifndef ASSIGNMENT_HPP
#define ASSIGNMENT_HPP
+
#include <boost/numeric/ublas/vector_expression.hpp>
#include <boost/numeric/ublas/matrix_expression.hpp>
@@ -174,7 +175,11 @@ template <std::ptrdiff_t I>
class static_vector_move_manip: public index_manipulator<static_vector_move_manip<I> > {
public:
template <typename V>
- BOOST_UBLAS_INLINE void manip(V &k) const { k+=I; }
+ BOOST_UBLAS_INLINE void manip(V &k) const {
+ // With the equivalent expression using '+=' operator, mscv reports waring C4245:
+ // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch
+ k = k + I;
+ }
};
/**
@@ -375,8 +380,10 @@ public:
template <typename V, typename K>
BOOST_UBLAS_INLINE
void manip(V &k, K &l) const {
- k+=I;
- l+=J;
+ // With the equivalent expression using '+=' operator, mscv reports waring C4245:
+ // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch
+ k = k + I;
+ l = l + J;
}
};
@@ -926,29 +933,29 @@ public:
typedef typename E::expression_type::size_type size_type;
BOOST_UBLAS_INLINE
- vector_expression_assigner(E &e):ve(e), i(0) {
+ vector_expression_assigner(E &e):ve(&e), i(0) {
}
BOOST_UBLAS_INLINE
- vector_expression_assigner(size_type k, E &e):ve(e), i(k) {
+ vector_expression_assigner(size_type k, E &e):ve(&e), i(k) {
// Overloaded like that so it can be differentiated from (E, val).
// Otherwise there would be an ambiquity when value_type == size_type.
}
BOOST_UBLAS_INLINE
- vector_expression_assigner(E &e, value_type val):ve(e), i(0) {
+ vector_expression_assigner(E &e, value_type val):ve(&e), i(0) {
operator,(val);
}
template <class AE>
BOOST_UBLAS_INLINE
- vector_expression_assigner(E &e, const vector_expression<AE> &nve):ve(e), i(0) {
+ vector_expression_assigner(E &e, const vector_expression<AE> &nve):ve(&e), i(0) {
operator,(nve);
}
template <typename T>
BOOST_UBLAS_INLINE
- vector_expression_assigner(E &e, const index_manipulator<T> &ta):ve(e), i(0) {
+ vector_expression_assigner(E &e, const index_manipulator<T> &ta):ve(&e), i(0) {
operator,(ta);
}
@@ -976,18 +983,18 @@ public:
template <class T>
BOOST_UBLAS_INLINE
vector_expression_assigner<E, T> operator, (fill_policy_wrapper<T>) const {
- return vector_expression_assigner<E, T>(i, ve);
+ return vector_expression_assigner<E, T>(i, *ve);
}
private:
BOOST_UBLAS_INLINE
vector_expression_assigner &apply(const typename E::expression_type::value_type& val) {
- Fill_Policy::apply(ve, i++, val);
+ Fill_Policy::apply(*ve, i++, val);
return *this;
}
private:
- E &ve;
+ E *ve;
size_type i;
};
@@ -1101,39 +1108,39 @@ public:
typedef typename E::expression_type::size_type size_type;
BOOST_UBLAS_INLINE
- matrix_expression_assigner(E &e): me(e), i(0), j(0) {
+ matrix_expression_assigner(E &e): me(&e), i(0), j(0) {
}
BOOST_UBLAS_INLINE
- matrix_expression_assigner(E &e, size_type k, size_type l): me(e), i(k), j(l) {
+ matrix_expression_assigner(E &e, size_type k, size_type l): me(&e), i(k), j(l) {
}
BOOST_UBLAS_INLINE
- matrix_expression_assigner(E &e, typename E::expression_type::value_type val): me(e), i(0), j(0) {
+ matrix_expression_assigner(E &e, typename E::expression_type::value_type val): me(&e), i(0), j(0) {
operator,(val);
}
template <class AE>
BOOST_UBLAS_INLINE
- matrix_expression_assigner(E &e, const vector_expression<AE> &nve):me(e), i(0), j(0) {
+ matrix_expression_assigner(E &e, const vector_expression<AE> &nve):me(&e), i(0), j(0) {
operator,(nve);
}
template <class AE>
BOOST_UBLAS_INLINE
- matrix_expression_assigner(E &e, const matrix_expression<AE> &nme):me(e), i(0), j(0) {
+ matrix_expression_assigner(E &e, const matrix_expression<AE> &nme):me(&e), i(0), j(0) {
operator,(nme);
}
template <typename T>
BOOST_UBLAS_INLINE
- matrix_expression_assigner(E &e, const index_manipulator<T> &ta):me(e), i(0), j(0) {
+ matrix_expression_assigner(E &e, const index_manipulator<T> &ta):me(&e), i(0), j(0) {
operator,(ta);
}
BOOST_UBLAS_INLINE
matrix_expression_assigner &operator, (const typename E::expression_type::value_type& val) {
- Traverse_Policy::apply_wrap(me, i ,j);
+ Traverse_Policy::apply_wrap(*me, i ,j);
return apply(val);
}
@@ -1162,21 +1169,21 @@ public:
template <class T>
BOOST_UBLAS_INLINE
matrix_expression_assigner<E, T, Traverse_Policy> operator, (fill_policy_wrapper<T>) const {
- return matrix_expression_assigner<E, T, Traverse_Policy>(me, i, j);
+ return matrix_expression_assigner<E, T, Traverse_Policy>(*me, i, j);
}
template <class T>
BOOST_UBLAS_INLINE
matrix_expression_assigner<E, Fill_Policy, T> operator, (traverse_policy_wrapper<T>) {
- Traverse_Policy::apply_wrap(me, i ,j);
- return matrix_expression_assigner<E, Fill_Policy, T>(me, i, j);
+ Traverse_Policy::apply_wrap(*me, i ,j);
+ return matrix_expression_assigner<E, Fill_Policy, T>(*me, i, j);
}
private:
BOOST_UBLAS_INLINE
matrix_expression_assigner &apply(const typename E::expression_type::value_type& val) {
- Fill_Policy::apply(me, i, j, val);
+ Fill_Policy::apply(*me, i, j, val);
Traverse_Policy::advance(i,j);
return *this;
}
@@ -1187,14 +1194,14 @@ private:
size_type bi = i;
size_type bj = j;
typename AE::size_type k=0, l=0;
- Fill_Policy::apply(me, i, j, nme()(k, l));
- while (Traverse_Policy::next(nme, me, i, j, bi, bj, k, l))
- Fill_Policy::apply(me, i, j, nme()(k, l));
+ Fill_Policy::apply(*me, i, j, nme()(k, l));
+ while (Traverse_Policy::next(nme, *me, i, j, bi, bj, k, l))
+ Fill_Policy::apply(*me, i, j, nme()(k, l));
return *this;
}
private:
- E &me;
+ E *me;
size_type i, j;
};
diff --git a/boost/numeric/ublas/detail/concepts.hpp b/boost/numeric/ublas/detail/concepts.hpp
index 674c610ed5..21d5501456 100644
--- a/boost/numeric/ublas/detail/concepts.hpp
+++ b/boost/numeric/ublas/detail/concepts.hpp
@@ -644,7 +644,7 @@ namespace boost { namespace numeric { namespace ublas {
template<class T>
T
ZeroElement (T) {
- return T(0.0);
+ return static_cast<T> (0);
}
template<class T>
@@ -662,13 +662,7 @@ namespace boost { namespace numeric { namespace ublas {
template<class T>
T
OneElement (T) {
- return T(0.0);
- }
-
- template<class T>
- vector<T>
- OneElement (vector<T>) {
- return zero_vector<T> ();
+ return static_cast<T> (1);
}
template<class T>
@@ -677,110 +671,6 @@ namespace boost { namespace numeric { namespace ublas {
return identity_matrix<T> ();
}
-// template<>
-// float
-// ZeroElement (float) {
-// return 0.f;
-// }
-// template<>
-// double
-// ZeroElement (double) {
-// return 0.;
-// }
-// template<>
-// vector<float>
-// ZeroElement (vector<float>) {
-// return zero_vector<float> ();
-// }
-// template<>
-// vector<double>
-// ZeroElement (vector<double>) {
-// return zero_vector<double> ();
-// }
-// template<>
-// matrix<float>
-// ZeroElement (matrix<float>) {
-// return zero_matrix<float> ();
-// }
-// template<>
-// matrix<double>
-// ZeroElement (matrix<double>) {
-// return zero_matrix<double> ();
-// }
-// template<>
-// std::complex<float>
-// ZeroElement (std::complex<float>) {
-// return std::complex<float> (0.f);
-// }
-// template<>
-// std::complex<double>
-// ZeroElement (std::complex<double>) {
-// return std::complex<double> (0.);
-// }
-// template<>
-// vector<std::complex<float> >
-// ZeroElement (vector<std::complex<float> >) {
-// return zero_vector<std::complex<float> > ();
-// }
-// template<>
-// vector<std::complex<double> >
-// ZeroElement (vector<std::complex<double> >) {
-// return zero_vector<std::complex<double> > ();
-// }
-// template<>
-// matrix<std::complex<float> >
-// ZeroElement (matrix<std::complex<float> >) {
-// return zero_matrix<std::complex<float> > ();
-// }
-// template<>
-// matrix<std::complex<double> >
-// ZeroElement (matrix<std::complex<double> >) {
-// return zero_matrix<std::complex<double> > ();
-// }
-
-// template<class T>
-// T
-// OneElement (T);
-// template<>
-// float
-// OneElement (float) {
-// return 1.f;
-// }
-// template<>
-// double
-// OneElement (double) {
-// return 1.;
-// }
-// template<>
-// matrix<float>
-// OneElement (matrix<float>) {
-// return identity_matrix<float> ();
-// }
-// template<>
-// matrix<double>
-// OneElement (matrix<double>) {
-// return identity_matrix<double> ();
-// }
-// template<>
-// std::complex<float>
-// OneElement (std::complex<float>) {
-// return std::complex<float> (1.f);
-// }
-// template<>
-// std::complex<double>
-// OneElement (std::complex<double>) {
-// return std::complex<double> (1.);
-// }
-// template<>
-// matrix<std::complex<float> >
-// OneElement (matrix<std::complex<float> >) {
-// return identity_matrix<std::complex<float> > ();
-// }
-// template<>
-// matrix<std::complex<double> >
-// OneElement (matrix<std::complex<double> >) {
-// return identity_matrix<std::complex<double> > ();
-// }
template<class E1, class E2>
bool
diff --git a/boost/numeric/ublas/detail/matrix_assign.hpp b/boost/numeric/ublas/detail/matrix_assign.hpp
index be172dd63d..b6de2586fa 100644
--- a/boost/numeric/ublas/detail/matrix_assign.hpp
+++ b/boost/numeric/ublas/detail/matrix_assign.hpp
@@ -30,7 +30,7 @@ namespace detail {
template<class E1, class E2, class S>
BOOST_UBLAS_INLINE
bool equals (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2, S epsilon, S min_norm) {
- return norm_inf (e1 - e2) < epsilon *
+ return norm_inf (e1 - e2) <= epsilon *
std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
}
@@ -74,7 +74,7 @@ namespace detail {
#endif
if (it2 != it2_end && it2e != it2e_end) {
size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
- while (true) {
+ for (;;) {
difference_type compare2 = it2_index - it2e_index;
if (compare2 == 0) {
++ it2, ++ it2e;
@@ -177,7 +177,7 @@ namespace detail {
#endif
if (it1 != it1_end && it1e != it1e_end) {
size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
- while (true) {
+ for (;;) {
difference_type compare2 = it1_index - it1e_index;
if (compare2 == 0) {
++ it1, ++ it1e;
@@ -670,7 +670,15 @@ namespace detail {
size1 = (std::min) (- diff1, it1_size);
if (size1 > 0) {
it1_size -= size1;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size1 >= 0) { // zeroing
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename M::iterator2 it2 (it1.begin ());
@@ -719,7 +727,15 @@ namespace detail {
size2 = (std::min) (- diff2, it2_size);
if (size2 > 0) {
it2_size -= size2;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size2 >= 0) // zeroing
functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
} else {
@@ -734,7 +750,15 @@ namespace detail {
while (-- size2 >= 0)
functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
size2 = it2_size;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size2 >= 0) // zeroing
functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
} else {
@@ -743,7 +767,15 @@ namespace detail {
++ it1, ++ it1e;
}
size1 = it1_size;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size1 >= 0) { // zeroing
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename M::iterator2 it2 (it1.begin ());
@@ -802,7 +834,15 @@ namespace detail {
size2 = (std::min) (- diff2, it2_size);
if (size2 > 0) {
it2_size -= size2;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size2 >= 0) { // zeroing
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename M::iterator1 it1 (it2.begin ());
@@ -851,7 +891,15 @@ namespace detail {
size1 = (std::min) (- diff1, it1_size);
if (size1 > 0) {
it1_size -= size1;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size1 >= 0) // zeroing
functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
} else {
@@ -866,7 +914,16 @@ namespace detail {
while (-- size1 >= 0)
functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
size1 = it1_size;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size1 >= 0) // zeroing
functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
} else {
@@ -875,7 +932,15 @@ namespace detail {
++ it2, ++ it2e;
}
size2 = it2_size;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size2 >= 0) { // zeroing
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename M::iterator1 it1 (it2.begin ());
@@ -903,7 +968,16 @@ namespace detail {
void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, row_major_tag) {
typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
// R unnecessary, make_conformant not required
+
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
BOOST_STATIC_ASSERT ((!functor_type::computed));
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
typedef typename M::value_type value_type;
@@ -935,7 +1009,16 @@ namespace detail {
void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, column_major_tag) {
typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
// R unnecessary, make_conformant not required
+
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
BOOST_STATIC_ASSERT ((!functor_type::computed));
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
typedef typename M::value_type value_type;
@@ -1002,7 +1085,7 @@ namespace detail {
#endif
if (it2 != it2_end && it2e != it2e_end) {
size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
- while (true) {
+ for (;;) {
difference_type compare2 = it2_index - it2e_index;
if (compare2 == 0) {
functor_type::apply (*it2, *it2e);
@@ -1013,7 +1096,15 @@ namespace detail {
} else
break;
} else if (compare2 < 0) {
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
functor_type::apply (*it2, expr_value_type/*zero*/());
++ it2;
} else
@@ -1031,7 +1122,15 @@ namespace detail {
}
}
}
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (it2 != it2_end) { // zeroing
functor_type::apply (*it2, expr_value_type/*zero*/());
++ it2;
@@ -1041,7 +1140,15 @@ namespace detail {
}
++ it1, ++ it1e;
} else if (compare < 0) {
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename M::iterator2 it2 (it1.begin ());
typename M::iterator2 it2_end (it1.end ());
@@ -1061,7 +1168,15 @@ namespace detail {
increment (it1e, it1e_end, compare);
}
}
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (it1 != it1_end) {
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename M::iterator2 it2 (it1.begin ());
@@ -1125,7 +1240,7 @@ namespace detail {
#endif
if (it1 != it1_end && it1e != it1e_end) {
size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
- while (true) {
+ for (;;) {
difference_type compare2 = it1_index - it1e_index;
if (compare2 == 0) {
functor_type::apply (*it1, *it1e);
@@ -1136,7 +1251,15 @@ namespace detail {
} else
break;
} else if (compare2 < 0) {
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
functor_type::apply (*it1, expr_value_type/*zero*/()); // zeroing
++ it1;
} else
@@ -1154,7 +1277,15 @@ namespace detail {
}
}
}
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (it1 != it1_end) { // zeroing
functor_type::apply (*it1, expr_value_type/*zero*/());
++ it1;
@@ -1164,7 +1295,15 @@ namespace detail {
}
++ it2, ++ it2e;
} else if (compare < 0) {
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename M::iterator1 it1 (it2.begin ());
typename M::iterator1 it1_end (it2.end ());
@@ -1184,7 +1323,15 @@ namespace detail {
increment (it2e, it2e_end, compare);
}
}
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (it2 != it2_end) {
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename M::iterator1 it1 (it2.begin ());
@@ -1390,7 +1537,7 @@ namespace detail {
#endif
if (it2 != it2_end && it2e != it2e_end) {
size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
- while (true) {
+ for (;;) {
difference_type compare2 = it2_index - it2e_index;
if (compare2 == 0) {
functor_type::apply (*it2, *it2e);
@@ -1515,7 +1662,7 @@ namespace detail {
#endif
if (it1 != it1_end && it1e != it1e_end) {
size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
- while (true) {
+ for (;;) {
difference_type compare2 = it1_index - it1e_index;
if (compare2 == 0) {
functor_type::apply (*it1, *it1e);
diff --git a/boost/numeric/ublas/detail/returntype_deduction.hpp b/boost/numeric/ublas/detail/returntype_deduction.hpp
index 030d1f6b24..6ef1f0be08 100644
--- a/boost/numeric/ublas/detail/returntype_deduction.hpp
+++ b/boost/numeric/ublas/detail/returntype_deduction.hpp
@@ -126,13 +126,13 @@ struct error_cant_deduce_type {};
test(unsigned long const&);
template <typename X, typename Y>
- typename disable_if<
+ typename boost::disable_if<
is_basic<X>, x_value_type
>::type
test(X const&);
template <typename X, typename Y>
- typename disable_if<
+ typename boost::disable_if<
mpl::or_<
is_basic<Y>
, is_same<Y, asymmetric>
diff --git a/boost/numeric/ublas/detail/vector_assign.hpp b/boost/numeric/ublas/detail/vector_assign.hpp
index e612876df5..b0ffacfb62 100644
--- a/boost/numeric/ublas/detail/vector_assign.hpp
+++ b/boost/numeric/ublas/detail/vector_assign.hpp
@@ -59,7 +59,7 @@ namespace detail {
typename E::const_iterator ite_end (e ().end ());
if (it != it_end && ite != ite_end) {
size_type it_index = it.index (), ite_index = ite.index ();
- while (true) {
+ for (;;) {
difference_type compare = it_index - ite_index;
if (compare == 0) {
++ it, ++ ite;
@@ -316,7 +316,15 @@ namespace detail {
difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
if (size > 0) {
it_size -= size;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size >= 0) // zeroing
functor_type::apply (*it, value_type/*zero*/()), ++ it;
} else {
@@ -330,7 +338,15 @@ namespace detail {
while (-- size >= 0)
functor_type::apply (*it, *ite), ++ it, ++ ite;
size = it_size;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (-- size >= 0) // zeroing
functor_type::apply (*it, value_type/*zero*/()), ++ it;
} else {
@@ -348,7 +364,15 @@ namespace detail {
void vector_assign (V &v, const vector_expression<E> &e, sparse_tag) {
BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
BOOST_STATIC_ASSERT ((!functor_type::computed));
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
typedef typename V::value_type value_type;
#if BOOST_UBLAS_TYPE_CHECK
vector<value_type> cv (v.size ());
@@ -393,7 +417,7 @@ namespace detail {
typename E::const_iterator ite_end (e ().end ());
if (it != it_end && ite != ite_end) {
size_type it_index = it.index (), ite_index = ite.index ();
- while (true) {
+ for (;;) {
difference_type compare = it_index - ite_index;
if (compare == 0) {
functor_type::apply (*it, *ite);
@@ -404,7 +428,15 @@ namespace detail {
} else
break;
} else if (compare < 0) {
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
functor_type::apply (*it, value_type/*zero*/());
++ it;
} else
@@ -422,8 +454,15 @@ namespace detail {
}
}
}
-
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (!functor_type::computed) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
while (it != it_end) { // zeroing
functor_type::apply (*it, value_type/*zero*/());
++ it;
@@ -524,7 +563,7 @@ namespace detail {
typename E::iterator ite_end (e ().end ());
if (it != it_end && ite != ite_end) {
size_type it_index = it.index (), ite_index = ite.index ();
- while (true) {
+ for (;;) {
difference_type compare = it_index - ite_index;
if (compare == 0) {
functor_type::apply (*it, *ite);
diff --git a/boost/numeric/ublas/functional.hpp b/boost/numeric/ublas/functional.hpp
index c7c92614c0..571f510faa 100644
--- a/boost/numeric/ublas/functional.hpp
+++ b/boost/numeric/ublas/functional.hpp
@@ -433,20 +433,19 @@ namespace boost { namespace numeric { namespace ublas {
template<class E>
static BOOST_UBLAS_INLINE
result_type apply (const vector_expression<E> &e) {
-#ifndef BOOST_UBLAS_SCALED_NORM
- real_type t = real_type ();
typedef typename E::size_type vector_size_type;
vector_size_type size (e ().size ());
+#ifndef BOOST_UBLAS_SCALED_NORM
+ real_type t = real_type ();
for (vector_size_type i = 0; i < size; ++ i) {
real_type u (type_traits<value_type>::norm_2 (e () (i)));
t += u * u;
}
- return type_traits<real_type>::type_sqrt (t);
+ return static_cast<result_type>(type_traits<real_type>::type_sqrt (t));
#else
real_type scale = real_type ();
real_type sum_squares (1);
- size_type size (e ().size ());
- for (size_type i = 0; i < size; ++ i) {
+ for (vector_size_type i = 0; i < size; ++ i) {
real_type u (type_traits<value_type>::norm_2 (e () (i)));
if ( real_type () /* zero */ == u ) continue;
if (scale < u) {
@@ -458,7 +457,7 @@ namespace boost { namespace numeric { namespace ublas {
sum_squares += v * v;
}
}
- return scale * type_traits<real_type>::type_sqrt (sum_squares);
+ return static_cast<result_type>(scale * type_traits<real_type>::type_sqrt (sum_squares));
#endif
}
// Dense case
@@ -472,7 +471,7 @@ namespace boost { namespace numeric { namespace ublas {
t += u * u;
++ it;
}
- return type_traits<real_type>::type_sqrt (t);
+ return static_cast<result_type>(type_traits<real_type>::type_sqrt (t));
#else
real_type scale = real_type ();
real_type sum_squares (1);
@@ -488,7 +487,7 @@ namespace boost { namespace numeric { namespace ublas {
}
++ it;
}
- return scale * type_traits<real_type>::type_sqrt (sum_squares);
+ return static_cast<result_type>(scale * type_traits<real_type>::type_sqrt (sum_squares));
#endif
}
// Sparse case
@@ -502,7 +501,7 @@ namespace boost { namespace numeric { namespace ublas {
t += u * u;
++ it;
}
- return type_traits<real_type>::type_sqrt (t);
+ return static_cast<result_type>(type_traits<real_type>::type_sqrt (t));
#else
real_type scale = real_type ();
real_type sum_squares (1);
@@ -518,10 +517,56 @@ namespace boost { namespace numeric { namespace ublas {
}
++ it;
}
- return scale * type_traits<real_type>::type_sqrt (sum_squares);
+ return static_cast<result_type>(scale * type_traits<real_type>::type_sqrt (sum_squares));
#endif
}
};
+
+ template<class V>
+ struct vector_norm_2_square :
+ public vector_scalar_real_unary_functor<V> {
+ typedef typename vector_scalar_real_unary_functor<V>::value_type value_type;
+ typedef typename vector_scalar_real_unary_functor<V>::real_type real_type;
+ typedef typename vector_scalar_real_unary_functor<V>::result_type result_type;
+
+ template<class E>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_expression<E> &e) {
+ real_type t = real_type ();
+ typedef typename E::size_type vector_size_type;
+ vector_size_type size (e ().size ());
+ for (vector_size_type i = 0; i < size; ++ i) {
+ real_type u (type_traits<value_type>::norm_2 (e () (i)));
+ t += u * u;
+ }
+ return t;
+ }
+ // Dense case
+ template<class D, class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (D size, I it) {
+ real_type t = real_type ();
+ while (-- size >= 0) {
+ real_type u (type_traits<value_type>::norm_2 (*it));
+ t += u * u;
+ ++ it;
+ }
+ return t;
+ }
+ // Sparse case
+ template<class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I it, const I &it_end) {
+ real_type t = real_type ();
+ while (it != it_end) {
+ real_type u (type_traits<value_type>::norm_2 (*it));
+ t += u * u;
+ ++ it;
+ }
+ return t;
+ }
+ };
+
template<class V>
struct vector_norm_inf:
public vector_scalar_real_unary_functor<V> {
@@ -749,7 +794,7 @@ namespace boost { namespace numeric { namespace ublas {
result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) {
result_type t = result_type (0);
if (it1 != it1_end && it2 != it2_end) {
- while (true) {
+ for (;;) {
if (it1.index () == it2.index ()) {
t += *it1 * *it2, ++ it1, ++ it2;
if (it1 == it1_end || it2 == it2_end)
@@ -887,7 +932,7 @@ namespace boost { namespace numeric { namespace ublas {
result_type t = result_type (0);
if (it1 != it1_end && it2 != it2_end) {
size_type it1_index = it1.index2 (), it2_index = it2.index ();
- while (true) {
+ for (;;) {
difference_type compare = it1_index - it2_index;
if (compare == 0) {
t += *it1 * *it2, ++ it1, ++ it2;
@@ -1055,7 +1100,7 @@ namespace boost { namespace numeric { namespace ublas {
result_type t = result_type (0);
if (it1 != it1_end && it2 != it2_end) {
size_type it1_index = it1.index (), it2_index = it2.index1 ();
- while (true) {
+ for (;;) {
difference_type compare = it1_index - it2_index;
if (compare == 0) {
t += *it1 * *it2, ++ it1, ++ it2;
@@ -1232,7 +1277,7 @@ namespace boost { namespace numeric { namespace ublas {
result_type t = result_type (0);
if (it1 != it1_end && it2 != it2_end) {
size_type it1_index = it1.index2 (), it2_index = it2.index1 ();
- while (true) {
+ for (;;) {
difference_type compare = difference_type (it1_index - it2_index);
if (compare == 0) {
t += *it1 * *it2, ++ it1, ++ it2;
@@ -1674,6 +1719,7 @@ namespace boost { namespace numeric { namespace ublas {
BOOST_UBLAS_CHECK (i < size_i, bad_index ());
BOOST_UBLAS_CHECK (j < size_j, bad_index ());
BOOST_UBLAS_CHECK (i <= j, bad_index ());
+ boost::ignore_unused(size_i, size_j);
// FIXME size_type overflow
// sigma_j (j + 1) = (j + 1) * j / 2
// j = 0 1 2 3, sigma = 0 1 3 6
diff --git a/boost/numeric/ublas/matrix.hpp b/boost/numeric/ublas/matrix.hpp
index d06391077a..6e405d8494 100644
--- a/boost/numeric/ublas/matrix.hpp
+++ b/boost/numeric/ublas/matrix.hpp
@@ -258,6 +258,30 @@ namespace boost { namespace numeric {
return at_element (i, j);
}
+ /** Access a matrix element. Here we return a reference
+ * \param i the first coordinate of the element. By default it's the row
+ * \param j the second coordinate of the element. By default it's the column
+ * \return a reference to the element
+ */
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return data()[i];
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return data()[i];
+ }
+
+// /** Access a matrix element. Here we return a reference
+// * \param i the first coordinate of the element. By default it's the row
+// * \param j the second coordinate of the element. By default it's the column
+// * \return a reference to the element
+// */
+// BOOST_UBLAS_INLINE
+// const_reference operator () const (size_type i) {
+// return data()[i];
+// }
// Element assignment
/** Change the value of a matrix element. Return back a reference to it
@@ -1234,14 +1258,6 @@ namespace boost { namespace numeric {
matrix_container<self_type> (),
data_ () {}
- /// \brief Construct a fixed_matrix from a list of values
- /// The list may be included in curly braces. Typical syntax is choices are :
- /// fixed_matrix<double, 2,2> v = { 1, 2, 3, 4 } or fixed_matrix<double,4> v( {1, 2, 3, 4} ) or fixed_matrix<double,2,2> v( 1, 2, 3, 4 )
- template <typename... Types>
- fixed_matrix(value_type v0, Types... vrest) :
- matrix_container<self_type> (),
- data_{ { v0, vrest... } } {}
-
/** Dense fixed_matrix constructor with defined initial value for all the matrix elements
* \param init initial value assigned to all elements
*/
@@ -1278,6 +1294,15 @@ namespace boost { namespace numeric {
matrix_assign<scalar_assign> (*this, ae);
}
+ /// \brief Construct a fixed_matrix from a list of values
+ /// The list may be included in curly braces. Typical syntax is choices are :
+ /// fixed_matrix<double, 2,2> v = { 1, 2, 3, 4 } or fixed_matrix<double,4> v( {1, 2, 3, 4} ) or fixed_matrix<double,2,2> v( 1, 2, 3, 4 )
+ template <typename... Types>
+ BOOST_UBLAS_INLINE
+ fixed_matrix(value_type v0, Types... vrest) :
+ matrix_container<self_type> (),
+ data_( array_type{ v0, vrest... } ) {}
+
// Accessors
/** Return the number of rows of the fixed_matrix
* You can also use the free size<>() function in operation/size.hpp as size<1>(m) where m is a fixed_matrix
@@ -1384,7 +1409,7 @@ namespace boost { namespace numeric {
/*! @note "pass by value" the key idea to enable move semantics */
BOOST_UBLAS_INLINE
- fixed_matrix &operator = (matrix m) {
+ fixed_matrix &operator = (fixed_matrix m) {
assign_temporary(m);
return *this;
}
diff --git a/boost/numeric/ublas/matrix_expression.hpp b/boost/numeric/ublas/matrix_expression.hpp
index a36313096e..b09ad7fa90 100644
--- a/boost/numeric/ublas/matrix_expression.hpp
+++ b/boost/numeric/ublas/matrix_expression.hpp
@@ -22,5611 +22,5671 @@
namespace boost { namespace numeric { namespace ublas {
- template<class E>
- class matrix_reference:
- public matrix_expression<matrix_reference<E> > {
+template<class E>
+class matrix_reference:
+ public matrix_expression<matrix_reference<E> > {
- typedef matrix_reference<E> self_type;
- public:
+ typedef matrix_reference<E> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using matrix_expression<self_type>::operator ();
-#endif
- typedef typename E::size_type size_type;
- typedef typename E::difference_type difference_type;
- typedef typename E::value_type value_type;
- typedef typename E::const_reference const_reference;
- typedef typename boost::mpl::if_<boost::is_const<E>,
- typename E::const_reference,
- typename E::reference>::type reference;
- typedef E referred_type;
- typedef const self_type const_closure_type;
- typedef self_type closure_type;
- typedef typename E::orientation_category orientation_category;
- typedef typename E::storage_category storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- explicit matrix_reference (referred_type &e):
- e_ (e) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size1 () const {
- return e_.size1 ();
- }
- BOOST_UBLAS_INLINE
- size_type size2 () const {
- return e_.size2 ();
- }
-
- public:
- // Expression accessors - const correct
- BOOST_UBLAS_INLINE
- const referred_type &expression () const {
- return e_;
- }
- BOOST_UBLAS_INLINE
- referred_type &expression () {
- return e_;
- }
-
- public:
- // Element access
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E::size_type size_type;
+ typedef typename E::difference_type difference_type;
+ typedef typename E::value_type value_type;
+ typedef typename E::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<E>,
+ typename E::const_reference,
+ typename E::reference>::type reference;
+ typedef E referred_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename E::orientation_category orientation_category;
+ typedef typename E::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit matrix_reference (referred_type &e):
+ e_ (e) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e_.size2 ();
+ }
+
+public:
+ // Expression accessors - const correct
+ BOOST_UBLAS_INLINE
+ const referred_type &expression () const {
+ return e_;
+ }
+ BOOST_UBLAS_INLINE
+ referred_type &expression () {
+ return e_;
+ }
+
+public:
+ // Element access
#ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type i, size_type j) const {
- return expression () (i, j);
- }
- BOOST_UBLAS_INLINE
- reference operator () (size_type i, size_type j) {
- return expression () (i, j);
- }
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return expression () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ return expression () (i, j);
+ }
#else
- BOOST_UBLAS_INLINE
- reference operator () (size_type i, size_type j) const {
- return expression () (i, j);
- }
-#endif
-
- // Assignment
- BOOST_UBLAS_INLINE
- matrix_reference &operator = (const matrix_reference &m) {
- expression ().operator = (m);
- return *this;
- }
- template<class AE>
- BOOST_UBLAS_INLINE
- matrix_reference &operator = (const matrix_expression<AE> &ae) {
- expression ().operator = (ae);
- return *this;
- }
- template<class AE>
- BOOST_UBLAS_INLINE
- matrix_reference &assign (const matrix_expression<AE> &ae) {
- expression ().assign (ae);
- return *this;
- }
- template<class AE>
- BOOST_UBLAS_INLINE
- matrix_reference &operator += (const matrix_expression<AE> &ae) {
- expression ().operator += (ae);
- return *this;
- }
- template<class AE>
- BOOST_UBLAS_INLINE
- matrix_reference &plus_assign (const matrix_expression<AE> &ae) {
- expression ().plus_assign (ae);
- return *this;
- }
- template<class AE>
- BOOST_UBLAS_INLINE
- matrix_reference &operator -= (const matrix_expression<AE> &ae) {
- expression ().operator -= (ae);
- return *this;
- }
- template<class AE>
- BOOST_UBLAS_INLINE
- matrix_reference &minus_assign (const matrix_expression<AE> &ae) {
- expression ().minus_assign (ae);
- return *this;
- }
- template<class AT>
- BOOST_UBLAS_INLINE
- matrix_reference &operator *= (const AT &at) {
- expression ().operator *= (at);
- return *this;
- }
- template<class AT>
- BOOST_UBLAS_INLINE
- matrix_reference &operator /= (const AT &at) {
- expression ().operator /= (at);
- return *this;
- }
-
- // Swapping
- BOOST_UBLAS_INLINE
- void swap (matrix_reference &m) {
- expression ().swap (m.expression ());
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const matrix_reference &mr) const {
- return &(*this).e_ == &mr.e_;
- }
-
- // Iterator types
- typedef typename E::const_iterator1 const_iterator1;
- typedef typename boost::mpl::if_<boost::is_const<E>,
- typename E::const_iterator1,
- typename E::iterator1>::type iterator1;
- typedef typename E::const_iterator2 const_iterator2;
- typedef typename boost::mpl::if_<boost::is_const<E>,
- typename E::const_iterator2,
- typename E::iterator2>::type iterator2;
-
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator1 find1 (int rank, size_type i, size_type j) const {
- return expression ().find1 (rank, i, j);
- }
- BOOST_UBLAS_INLINE
- iterator1 find1 (int rank, size_type i, size_type j) {
- return expression ().find1 (rank, i, j);
- }
- BOOST_UBLAS_INLINE
- const_iterator2 find2 (int rank, size_type i, size_type j) const {
- return expression ().find2 (rank, i, j);
- }
- BOOST_UBLAS_INLINE
- iterator2 find2 (int rank, size_type i, size_type j) {
- return expression ().find2 (rank, i, j);
- }
-
- // Iterators are the iterators of the referenced expression.
-
- BOOST_UBLAS_INLINE
- const_iterator1 begin1 () const {
- return expression ().begin1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cbegin1 () const {
- return begin1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 end1 () const {
- return expression ().end1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cend1 () const {
- return end1 ();
- }
-
- BOOST_UBLAS_INLINE
- iterator1 begin1 () {
- return expression ().begin1 ();
- }
- BOOST_UBLAS_INLINE
- iterator1 end1 () {
- return expression ().end1 ();
- }
-
- BOOST_UBLAS_INLINE
- const_iterator2 begin2 () const {
- return expression ().begin2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cbegin2 () const {
- return begin2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 end2 () const {
- return expression ().end2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cend2 () const {
- return end2 ();
- }
-
- BOOST_UBLAS_INLINE
- iterator2 begin2 () {
- return expression ().begin2 ();
- }
- BOOST_UBLAS_INLINE
- iterator2 end2 () {
- return expression ().end2 ();
- }
-
- // Reverse iterators
- typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
- typedef reverse_iterator_base1<iterator1> reverse_iterator1;
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rbegin1 () const {
- return const_reverse_iterator1 (end1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crbegin1 () const {
- return rbegin1 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rend1 () const {
- return const_reverse_iterator1 (begin1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crend1 () const {
- return rend1 ();
- }
-
- BOOST_UBLAS_INLINE
- reverse_iterator1 rbegin1 () {
- return reverse_iterator1 (end1 ());
- }
- BOOST_UBLAS_INLINE
- reverse_iterator1 rend1 () {
- return reverse_iterator1 (begin1 ());
- }
-
- typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
- typedef reverse_iterator_base2<iterator2> reverse_iterator2;
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rbegin2 () const {
- return const_reverse_iterator2 (end2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crbegin2 () const {
- return rbegin2 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rend2 () const {
- return const_reverse_iterator2 (begin2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crend2 () const {
- return rend2 ();
- }
-
- BOOST_UBLAS_INLINE
- reverse_iterator2 rbegin2 () {
- return reverse_iterator2 (end2 ());
- }
- BOOST_UBLAS_INLINE
- reverse_iterator2 rend2 () {
- return reverse_iterator2 (begin2 ());
- }
-
- private:
- referred_type &e_;
- };
-
-
- template<class E1, class E2, class F>
- class vector_matrix_binary:
- public matrix_expression<vector_matrix_binary<E1, E2, F> > {
-
- typedef E1 expression1_type;
- typedef E2 expression2_type;
- public:
- typedef typename E1::const_closure_type expression1_closure_type;
- typedef typename E2::const_closure_type expression2_closure_type;
- private:
- typedef vector_matrix_binary<E1, E2, F> self_type;
- public:
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) const {
+ return expression () (i, j);
+ }
+#endif
+
+#ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return expression () (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return expression () (i);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) const {
+ return expression () (i);
+ }
+#endif
+
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator = (const matrix_reference &m) {
+ expression ().operator = (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator = (const matrix_expression<AE> &ae) {
+ expression ().operator = (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &assign (const matrix_expression<AE> &ae) {
+ expression ().assign (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator += (const matrix_expression<AE> &ae) {
+ expression ().operator += (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &plus_assign (const matrix_expression<AE> &ae) {
+ expression ().plus_assign (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator -= (const matrix_expression<AE> &ae) {
+ expression ().operator -= (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &minus_assign (const matrix_expression<AE> &ae) {
+ expression ().minus_assign (ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator *= (const AT &at) {
+ expression ().operator *= (at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator /= (const AT &at) {
+ expression ().operator /= (at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_reference &m) {
+ expression ().swap (m.expression ());
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_reference &mr) const {
+ return &(*this).e_ == &mr.e_;
+ }
+
+ // Iterator types
+ typedef typename E::const_iterator1 const_iterator1;
+ typedef typename boost::mpl::if_<boost::is_const<E>,
+ typename E::const_iterator1,
+ typename E::iterator1>::type iterator1;
+ typedef typename E::const_iterator2 const_iterator2;
+ typedef typename boost::mpl::if_<boost::is_const<E>,
+ typename E::const_iterator2,
+ typename E::iterator2>::type iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ return expression ().find1 (rank, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ return expression ().find1 (rank, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ return expression ().find2 (rank, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ return expression ().find2 (rank, i, j);
+ }
+
+ // Iterators are the iterators of the referenced expression.
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return expression ().begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cbegin1 () const {
+ return begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return expression ().end1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cend1 () const {
+ return end1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return expression ().begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return expression ().end1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return expression ().begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cbegin2 () const {
+ return begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return expression ().end2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cend2 () const {
+ return end2 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return expression ().begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return expression ().end2 ();
+ }
+
+ // Reverse iterators
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin1 () const {
+ return rbegin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crend1 () const {
+ return rend1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin2 () const {
+ return rbegin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crend2 () const {
+ return rend2 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+private:
+ referred_type &e_;
+};
+
+
+template<class E1, class E2, class F>
+class vector_matrix_binary:
+ public matrix_expression<vector_matrix_binary<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+private:
+ typedef vector_matrix_binary<E1, E2, F> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using matrix_expression<self_type>::operator ();
-#endif
- typedef F functor_type;
- typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
- typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
- typedef typename F::result_type value_type;
- typedef value_type const_reference;
- typedef const_reference reference;
- typedef const self_type const_closure_type;
- typedef const_closure_type closure_type;
- typedef unknown_orientation_tag orientation_category;
- typedef unknown_storage_tag storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- vector_matrix_binary (const expression1_type &e1, const expression2_type &e2):
- e1_ (e1), e2_ (e2) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size1 () const {
- return e1_.size ();
- }
- BOOST_UBLAS_INLINE
- size_type size2 () const {
- return e2_.size ();
- }
-
- public:
- // Expression accessors
- BOOST_UBLAS_INLINE
- const expression1_closure_type &expression1 () const {
- return e1_;
- }
- BOOST_UBLAS_INLINE
- const expression2_closure_type &expression2 () const {
- return e2_;
- }
-
- public:
- // Element access
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type i, size_type j) const {
- return functor_type::apply (e1_ (i), e2_ (j));
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const vector_matrix_binary &vmb) const {
- return (*this).expression1 ().same_closure (vmb.expression1 ()) &&
- (*this).expression2 ().same_closure (vmb.expression2 ());
- }
-
- // Iterator types
- private:
- typedef typename E1::const_iterator const_subiterator1_type;
- typedef typename E2::const_iterator const_subiterator2_type;
- typedef const value_type *const_pointer;
-
- public:
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef F functor_type;
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_orientation_tag orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_matrix_binary (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e1_.size ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e2_.size ();
+ }
+
+public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e1_ (i), e2_ (j));
+ }
+
+
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_matrix_binary &vmb) const {
+ return (*this).expression1 ().same_closure (vmb.expression1 ()) &&
+ (*this).expression2 ().same_closure (vmb.expression2 ());
+ }
+
+ // Iterator types
+private:
+ typedef typename E1::const_iterator const_subiterator1_type;
+ typedef typename E2::const_iterator const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
- typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
- typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
- typedef const_iterator1 iterator1;
- typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
- typedef const_iterator2 iterator2;
+ typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
+ typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
+ typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
#else
- class const_iterator1;
- typedef const_iterator1 iterator1;
- class const_iterator2;
- typedef const_iterator2 iterator2;
-#endif
- typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
- typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
-
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator1 find1 (int rank, size_type i, size_type j) const {
- const_subiterator1_type it1 (e1_.find (i));
- const_subiterator1_type it1_end (e1_.find (size1 ()));
- const_subiterator2_type it2 (e2_.find (j));
- const_subiterator2_type it2_end (e2_.find (size2 ()));
- if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == value_type/*zero*/()))) {
- it1 = it1_end;
- it2 = it2_end;
- }
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_subiterator1_type it1 (e1_.find (i));
+ const_subiterator1_type it1_end (e1_.find (size1 ()));
+ const_subiterator2_type it2 (e2_.find (j));
+ const_subiterator2_type it2_end (e2_.find (size2 ()));
+ if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == typename E2::value_type/*zero*/()))) {
+ it1 = it1_end;
+ it2 = it2_end;
+ }
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator1 (*this, it1.index (), it2.index ());
+ return const_iterator1 (*this, it1.index (), it2.index ());
#else
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : value_type/*zero*/());
+ return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : typename E2::value_type/*zero*/());
#else
- return const_iterator1 (*this, it1, it2);
-#endif
-#endif
- }
- BOOST_UBLAS_INLINE
- const_iterator2 find2 (int rank, size_type i, size_type j) const {
- const_subiterator2_type it2 (e2_.find (j));
- const_subiterator2_type it2_end (e2_.find (size2 ()));
- const_subiterator1_type it1 (e1_.find (i));
- const_subiterator1_type it1_end (e1_.find (size1 ()));
- if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == value_type/*zero*/()))) {
- it2 = it2_end;
- it1 = it1_end;
- }
+ return const_iterator1 (*this, it1, it2);
+#endif
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_subiterator2_type it2 (e2_.find (j));
+ const_subiterator2_type it2_end (e2_.find (size2 ()));
+ const_subiterator1_type it1 (e1_.find (i));
+ const_subiterator1_type it1_end (e1_.find (size1 ()));
+ if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == typename E1::value_type/*zero*/()))) {
+ it2 = it2_end;
+ it1 = it1_end;
+ }
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator2 (*this, it1.index (), it2.index ());
+ return const_iterator2 (*this, it1.index (), it2.index ());
#else
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : value_type/*zero*/());
+ return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : typename E1::value_type/*zero*/());
#else
- return const_iterator2 (*this, it1, it2);
+ return const_iterator2 (*this, it1, it2);
#endif
#endif
- }
+ }
- // Iterators enhance the iterators of the referenced expressions
- // with the binary functor.
+ // Iterators enhance the iterators of the referenced expressions
+ // with the binary functor.
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator1:
- public container_const_reference<vector_matrix_binary>,
- public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
- typename E2::const_iterator::iterator_category>::iterator_category>::template
- iterator_base<const_iterator1, value_type>::type {
- public:
- typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
- typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
- typedef typename vector_matrix_binary::difference_type difference_type;
- typedef typename vector_matrix_binary::value_type value_type;
- typedef typename vector_matrix_binary::const_reference reference;
- typedef typename vector_matrix_binary::const_pointer pointer;
-
- typedef const_iterator2 dual_iterator_type;
- typedef const_reverse_iterator2 dual_reverse_iterator_type;
-
- // Construction and destruction
+ class const_iterator1:
+ public container_const_reference<vector_matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
+ typedef typename vector_matrix_binary::difference_type difference_type;
+ typedef typename vector_matrix_binary::value_type value_type;
+ typedef typename vector_matrix_binary::const_reference reference;
+ typedef typename vector_matrix_binary::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- BOOST_UBLAS_INLINE
- const_iterator1 ():
- container_const_reference<self_type> (), it1_ (), it2_ (), t2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2):
- container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ (), t2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2):
+ container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {}
#else
- BOOST_UBLAS_INLINE
- const_iterator1 ():
- container_const_reference<self_type> (), it1_ (), it2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
- container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
-#endif
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator1 &operator ++ () {
- ++ it1_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -- () {
- -- it1_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator += (difference_type n) {
- it1_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -= (difference_type n) {
- it1_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ - it.it1_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
+#endif
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (*it1_, t2_);
+ return functor_type::apply (*it1_, t2_);
#else
- return functor_type::apply (*it1_, *it2_);
+ return functor_type::apply (*it1_, *it2_);
#endif
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 begin () const {
- return (*this) ().find2 (1, index1 (), 0);
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 end () const {
- return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rbegin () const {
- return const_reverse_iterator2 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rend () const {
- return const_reverse_iterator2 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator2 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it1_.index ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it2_.index ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator1 &operator = (const const_iterator1 &it) {
- container_const_reference<self_type>::assign (&it ());
- it1_ = it.it1_;
- it2_ = it.it2_;
+ typename self_type::
+#endif
+ const_reverse_iterator2 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- t2_ = it.t2_;
-#endif
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ == it.it1_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ < it.it1_;
- }
-
- private:
+ t2_ = it.t2_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- const_subiterator1_type it1_;
- // Mutable due to assignment
- /* const */ const_subiterator2_type it2_;
- value_type t2_;
+ const_subiterator1_type it1_;
+ // Mutable due to assignment
+ /* const */ const_subiterator2_type it2_;
+ value_type t2_;
#else
- const_subiterator1_type it1_;
- const_subiterator2_type it2_;
-#endif
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator1 begin1 () const {
- return find1 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cbegin1 () const {
- return begin1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 end1 () const {
- return find1 (0, size1 (), 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cend1 () const {
- return end1 ();
- }
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cbegin1 () const {
+ return begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cend1 () const {
+ return end1 ();
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator2:
- public container_const_reference<vector_matrix_binary>,
- public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
- typename E2::const_iterator::iterator_category>::iterator_category>::template
- iterator_base<const_iterator2, value_type>::type {
- public:
- typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
- typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
- typedef typename vector_matrix_binary::difference_type difference_type;
- typedef typename vector_matrix_binary::value_type value_type;
- typedef typename vector_matrix_binary::const_reference reference;
- typedef typename vector_matrix_binary::const_pointer pointer;
-
- typedef const_iterator1 dual_iterator_type;
- typedef const_reverse_iterator1 dual_reverse_iterator_type;
-
- // Construction and destruction
+ class const_iterator2:
+ public container_const_reference<vector_matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
+ typedef typename vector_matrix_binary::difference_type difference_type;
+ typedef typename vector_matrix_binary::value_type value_type;
+ typedef typename vector_matrix_binary::const_reference reference;
+ typedef typename vector_matrix_binary::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- BOOST_UBLAS_INLINE
- const_iterator2 ():
- container_const_reference<self_type> (), it1_ (), it2_ (), t1_ () {}
- BOOST_UBLAS_INLINE
- const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1):
- container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ (), t1_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1):
+ container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {}
#else
- BOOST_UBLAS_INLINE
- const_iterator2 ():
- container_const_reference<self_type> (), it1_ (), it2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
- container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
-#endif
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator2 &operator ++ () {
- ++ it2_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -- () {
- -- it2_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator += (difference_type n) {
- it2_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -= (difference_type n) {
- it2_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ());
- BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ - it.it2_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
+#endif
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (t1_, *it2_);
+ return functor_type::apply (t1_, *it2_);
#else
- return functor_type::apply (*it1_, *it2_);
+ return functor_type::apply (*it1_, *it2_);
#endif
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 begin () const {
- return (*this) ().find1 (1, 0, index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 end () const {
- return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rbegin () const {
- return const_reverse_iterator1 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rend () const {
- return const_reverse_iterator1 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator1 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it1_.index ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it2_.index ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator2 &operator = (const const_iterator2 &it) {
- container_const_reference<self_type>::assign (&it ());
- it1_ = it.it1_;
- it2_ = it.it2_;
+ typename self_type::
+#endif
+ const_reverse_iterator1 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- t1_ = it.t1_;
-#endif
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ());
- BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ == it.it2_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ < it.it2_;
- }
-
- private:
+ t1_ = it.t1_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- // Mutable due to assignment
- /* const */ const_subiterator1_type it1_;
- const_subiterator2_type it2_;
- value_type t1_;
+ // Mutable due to assignment
+ /* const */ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ value_type t1_;
#else
- const_subiterator1_type it1_;
- const_subiterator2_type it2_;
-#endif
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator2 begin2 () const {
- return find2 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cbegin2 () const {
- return begin2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 end2 () const {
- return find2 (0, 0, size2 ());
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cend2 () const {
- return end2 ();
- }
-
- // Reverse iterators
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rbegin1 () const {
- return const_reverse_iterator1 (end1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crbegin1 () const {
- return rbegin1 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rend1 () const {
- return const_reverse_iterator1 (begin1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crend1 () const {
- return rend1 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rbegin2 () const {
- return const_reverse_iterator2 (end2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crbegin2 () const {
- return rbegin2 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rend2 () const {
- return const_reverse_iterator2 (begin2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crend2 () const {
- return rend2 ();
- }
-
- private:
- expression1_closure_type e1_;
- expression2_closure_type e2_;
- };
-
- template<class E1, class E2, class F>
- struct vector_matrix_binary_traits {
- typedef vector_matrix_binary<E1, E2, F> expression_type;
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cbegin2 () const {
+ return begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cend2 () const {
+ return end2 ();
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin1 () const {
+ return rbegin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crend1 () const {
+ return rend1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin2 () const {
+ return rbegin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crend2 () const {
+ return rend2 ();
+ }
+
+private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+};
+
+template<class E1, class E2, class F>
+struct vector_matrix_binary_traits {
+ typedef vector_matrix_binary<E1, E2, F> expression_type;
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- // ISSUE matrix is arbitary temporary type
- typedef matrix<typename F::value_type> result_type;
-#endif
- };
-
- // (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j]
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::result_type
- outer_prod (const vector_expression<E1> &e1,
- const vector_expression<E2> &e2) {
- BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
- typedef typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- template<class E, class F>
- class matrix_unary1:
- public matrix_expression<matrix_unary1<E, F> > {
-
- typedef E expression_type;
- typedef F functor_type;
- public:
- typedef typename E::const_closure_type expression_closure_type;
- private:
- typedef matrix_unary1<E, F> self_type;
- public:
+ // ISSUE matrix is arbitary temporary type
+ typedef matrix<typename F::value_type> result_type;
+#endif
+};
+
+// (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j]
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::result_type
+outer_prod (const vector_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
+ typedef typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+template<class E, class F>
+class matrix_unary1:
+ public matrix_expression<matrix_unary1<E, F> > {
+
+ typedef E expression_type;
+ typedef F functor_type;
+public:
+ typedef typename E::const_closure_type expression_closure_type;
+private:
+ typedef matrix_unary1<E, F> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using matrix_expression<self_type>::operator ();
-#endif
- typedef typename E::size_type size_type;
- typedef typename E::difference_type difference_type;
- typedef typename F::result_type value_type;
- typedef value_type const_reference;
- typedef const_reference reference;
- typedef const self_type const_closure_type;
- typedef const_closure_type closure_type;
- typedef typename E::orientation_category orientation_category;
- typedef unknown_storage_tag storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- explicit matrix_unary1 (const expression_type &e):
- e_ (e) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size1 () const {
- return e_.size1 ();
- }
- BOOST_UBLAS_INLINE
- size_type size2 () const {
- return e_.size2 ();
- }
-
- public:
- // Expression accessors
- BOOST_UBLAS_INLINE
- const expression_closure_type &expression () const {
- return e_;
- }
-
- public:
- // Element access
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type i, size_type j) const {
- return functor_type::apply (e_ (i, j));
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const matrix_unary1 &mu1) const {
- return (*this).expression ().same_closure (mu1.expression ());
- }
-
- // Iterator types
- private:
- typedef typename E::const_iterator1 const_subiterator1_type;
- typedef typename E::const_iterator2 const_subiterator2_type;
- typedef const value_type *const_pointer;
-
- public:
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E::size_type size_type;
+ typedef typename E::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef typename E::orientation_category orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit matrix_unary1 (const expression_type &e):
+ e_ (e) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e_.size2 ();
+ }
+
+public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression_closure_type &expression () const {
+ return e_;
+ }
+
+public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e_ (i, j));
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e_ (i));
+ }
+
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_unary1 &mu1) const {
+ return (*this).expression ().same_closure (mu1.expression ());
+ }
+
+ // Iterator types
+private:
+ typedef typename E::const_iterator1 const_subiterator1_type;
+ typedef typename E::const_iterator2 const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
- typedef const_iterator1 iterator1;
- typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
- typedef const_iterator2 iterator2;
+ typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
#else
- class const_iterator1;
- typedef const_iterator1 iterator1;
- class const_iterator2;
- typedef const_iterator2 iterator2;
-#endif
- typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
- typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
-
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator1 find1 (int rank, size_type i, size_type j) const {
- const_subiterator1_type it1 (e_.find1 (rank, i, j));
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_subiterator1_type it1 (e_.find1 (rank, i, j));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator1 (*this, it1.index1 (), it1.index2 ());
+ return const_iterator1 (*this, it1.index1 (), it1.index2 ());
#else
- return const_iterator1 (*this, it1);
+ return const_iterator1 (*this, it1);
#endif
- }
- BOOST_UBLAS_INLINE
- const_iterator2 find2 (int rank, size_type i, size_type j) const {
- const_subiterator2_type it2 (e_.find2 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_subiterator2_type it2 (e_.find2 (rank, i, j));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator2 (*this, it2.index1 (), it2.index2 ());
+ return const_iterator2 (*this, it2.index1 (), it2.index2 ());
#else
- return const_iterator2 (*this, it2);
+ return const_iterator2 (*this, it2);
#endif
- }
+ }
- // Iterators enhance the iterators of the referenced expression
- // with the unary functor.
+ // Iterators enhance the iterators of the referenced expression
+ // with the unary functor.
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator1:
- public container_const_reference<matrix_unary1>,
- public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
- iterator_base<const_iterator1, value_type>::type {
- public:
- typedef typename E::const_iterator1::iterator_category iterator_category;
- typedef typename matrix_unary1::difference_type difference_type;
- typedef typename matrix_unary1::value_type value_type;
- typedef typename matrix_unary1::const_reference reference;
- typedef typename matrix_unary1::const_pointer pointer;
-
- typedef const_iterator2 dual_iterator_type;
- typedef const_reverse_iterator2 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator1 ():
- container_const_reference<self_type> (), it_ () {}
- BOOST_UBLAS_INLINE
- const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
- container_const_reference<self_type> (mu), it_ (it) {}
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator1 &operator ++ () {
- ++ it_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -- () {
- -- it_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator += (difference_type n) {
- it_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -= (difference_type n) {
- it_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ - it.it_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return functor_type::apply (*it_);
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator1:
+ public container_const_reference<matrix_unary1>,
+ public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename E::const_iterator1::iterator_category iterator_category;
+ typedef typename matrix_unary1::difference_type difference_type;
+ typedef typename matrix_unary1::value_type value_type;
+ typedef typename matrix_unary1::const_reference reference;
+ typedef typename matrix_unary1::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
+ container_const_reference<self_type> (mu), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 begin () const {
- return (*this) ().find2 (1, index1 (), 0);
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 end () const {
- return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rbegin () const {
- return const_reverse_iterator2 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rend () const {
- return const_reverse_iterator2 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator2 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it_.index1 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it_.index2 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator1 &operator = (const const_iterator1 &it) {
- container_const_reference<self_type>::assign (&it ());
- it_ = it.it_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ == it.it_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ < it.it_;
- }
-
- private:
- const_subiterator1_type it_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator1 begin1 () const {
- return find1 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cbegin1 () const {
- return begin1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 end1 () const {
- return find1 (0, size1 (), 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cend1 () const {
- return end1 ();
- }
+ typename self_type::
+#endif
+ const_reverse_iterator2 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator1_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cbegin1 () const {
+ return begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cend1 () const {
+ return end1 ();
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator2:
- public container_const_reference<matrix_unary1>,
- public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
- iterator_base<const_iterator2, value_type>::type {
- public:
- typedef typename E::const_iterator2::iterator_category iterator_category;
- typedef typename matrix_unary1::difference_type difference_type;
- typedef typename matrix_unary1::value_type value_type;
- typedef typename matrix_unary1::const_reference reference;
- typedef typename matrix_unary1::const_pointer pointer;
-
- typedef const_iterator1 dual_iterator_type;
- typedef const_reverse_iterator1 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator2 ():
- container_const_reference<self_type> (), it_ () {}
- BOOST_UBLAS_INLINE
- const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
- container_const_reference<self_type> (mu), it_ (it) {}
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator2 &operator ++ () {
- ++ it_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -- () {
- -- it_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator += (difference_type n) {
- it_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -= (difference_type n) {
- it_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ - it.it_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return functor_type::apply (*it_);
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator2:
+ public container_const_reference<matrix_unary1>,
+ public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename E::const_iterator2::iterator_category iterator_category;
+ typedef typename matrix_unary1::difference_type difference_type;
+ typedef typename matrix_unary1::value_type value_type;
+ typedef typename matrix_unary1::const_reference reference;
+ typedef typename matrix_unary1::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
+ container_const_reference<self_type> (mu), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 begin () const {
- return (*this) ().find1 (1, 0, index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 end () const {
- return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rbegin () const {
- return const_reverse_iterator1 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rend () const {
- return const_reverse_iterator1 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator1 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it_.index1 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it_.index2 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator2 &operator = (const const_iterator2 &it) {
- container_const_reference<self_type>::assign (&it ());
- it_ = it.it_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ == it.it_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ < it.it_;
- }
-
- private:
- const_subiterator2_type it_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator2 begin2 () const {
- return find2 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cbegin2 () const {
- return begin2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 end2 () const {
- return find2 (0, 0, size2 ());
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cend2 () const {
- return end2 ();
- }
-
- // Reverse iterators
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rbegin1 () const {
- return const_reverse_iterator1 (end1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crbegin1 () const {
- return rbegin1 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rend1 () const {
- return const_reverse_iterator1 (begin1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crend1 () const {
- return rend1 ();
- }
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rbegin2 () const {
- return const_reverse_iterator2 (end2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crbegin2 () const {
- return rbegin2 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rend2 () const {
- return const_reverse_iterator2 (begin2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crend2 () const {
- return rend2 ();
- }
-
- private:
- expression_closure_type e_;
- };
-
- template<class E, class F>
- struct matrix_unary1_traits {
- typedef matrix_unary1<E, F> expression_type;
+ typename self_type::
+#endif
+ const_reverse_iterator1 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator2_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cbegin2 () const {
+ return begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cend2 () const {
+ return end2 ();
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin1 () const {
+ return rbegin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crend1 () const {
+ return rend1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin2 () const {
+ return rbegin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crend2 () const {
+ return rend2 ();
+ }
+
+private:
+ expression_closure_type e_;
+};
+
+template<class E, class F>
+struct matrix_unary1_traits {
+ typedef matrix_unary1<E, F> expression_type;
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- typedef typename E::matrix_temporary_type result_type;
-#endif
- };
-
- // (- m) [i] [j] = - m [i] [j]
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::result_type
- operator - (const matrix_expression<E> &e) {
- typedef typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
- return expression_type (e ());
- }
-
- // (conj m) [i] [j] = conj (m [i] [j])
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::result_type
- conj (const matrix_expression<E> &e) {
- typedef typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
- return expression_type (e ());
- }
-
- // (real m) [i] [j] = real (m [i] [j])
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::result_type
- real (const matrix_expression<E> &e) {
- typedef typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
- return expression_type (e ());
- }
-
- // (imag m) [i] [j] = imag (m [i] [j])
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::result_type
- imag (const matrix_expression<E> &e) {
- typedef typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
- return expression_type (e ());
- }
-
- template<class E, class F>
- class matrix_unary2:
- public matrix_expression<matrix_unary2<E, F> > {
-
- typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
- E,
- const E>::type expression_type;
- typedef F functor_type;
- public:
- typedef typename boost::mpl::if_<boost::is_const<expression_type>,
- typename E::const_closure_type,
- typename E::closure_type>::type expression_closure_type;
- private:
- typedef matrix_unary2<E, F> self_type;
- public:
+ typedef typename E::matrix_temporary_type result_type;
+#endif
+};
+
+// (- m) [i] [j] = - m [i] [j]
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::result_type
+operator - (const matrix_expression<E> &e) {
+ typedef typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+}
+
+// (conj m) [i] [j] = conj (m [i] [j])
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::result_type
+conj (const matrix_expression<E> &e) {
+ typedef typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+}
+
+// (real m) [i] [j] = real (m [i] [j])
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::result_type
+real (const matrix_expression<E> &e) {
+ typedef typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+}
+
+// (imag m) [i] [j] = imag (m [i] [j])
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::result_type
+imag (const matrix_expression<E> &e) {
+ typedef typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+}
+
+template<class E, class F>
+class matrix_unary2:
+ public matrix_expression<matrix_unary2<E, F> > {
+
+ typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
+ E,
+ const E>::type expression_type;
+ typedef F functor_type;
+public:
+ typedef typename boost::mpl::if_<boost::is_const<expression_type>,
+ typename E::const_closure_type,
+ typename E::closure_type>::type expression_closure_type;
+private:
+ typedef matrix_unary2<E, F> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using matrix_expression<self_type>::operator ();
-#endif
- typedef typename E::size_type size_type;
- typedef typename E::difference_type difference_type;
- typedef typename F::result_type value_type;
- typedef value_type const_reference;
- typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
- typename E::reference,
- value_type>::type reference;
-
- typedef const self_type const_closure_type;
- typedef self_type closure_type;
- typedef typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
- row_major_tag>,
- column_major_tag,
- typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
- column_major_tag>,
- row_major_tag,
- typename E::orientation_category>::type>::type orientation_category;
- typedef typename E::storage_category storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- // matrix_unary2 may be used as mutable expression -
- // this is the only non const expression constructor
- explicit matrix_unary2 (expression_type &e):
- e_ (e) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size1 () const {
- return e_.size2 ();
- }
- BOOST_UBLAS_INLINE
- size_type size2 () const {
- return e_.size1 ();
- }
-
- public:
- // Expression accessors
- BOOST_UBLAS_INLINE
- const expression_closure_type &expression () const {
- return e_;
- }
-
- public:
- // Element access
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type i, size_type j) const {
- return functor_type::apply (e_ (j, i));
- }
- BOOST_UBLAS_INLINE
- reference operator () (size_type i, size_type j) {
- BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
- return e_ (j, i);
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const matrix_unary2 &mu2) const {
- return (*this).expression ().same_closure (mu2.expression ());
- }
-
- // Iterator types
- private:
- typedef typename E::const_iterator1 const_subiterator2_type;
- typedef typename E::const_iterator2 const_subiterator1_type;
- typedef const value_type *const_pointer;
-
- public:
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E::size_type size_type;
+ typedef typename E::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
+ typename E::reference,
+ value_type>::type reference;
+
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
+ row_major_tag>,
+ column_major_tag,
+ typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
+ column_major_tag>,
+ row_major_tag,
+ typename E::orientation_category>::type>::type orientation_category;
+ typedef typename E::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ // matrix_unary2 may be used as mutable expression -
+ // this is the only non const expression constructor
+ explicit matrix_unary2 (expression_type &e):
+ e_ (e) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e_.size2 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e_.size1 ();
+ }
+
+public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression_closure_type &expression () const {
+ return e_;
+ }
+
+public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e_ (j, i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
+ return e_ (j, i);
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e_ (i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
+ return e_ (i);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_unary2 &mu2) const {
+ return (*this).expression ().same_closure (mu2.expression ());
+ }
+
+ // Iterator types
+private:
+ typedef typename E::const_iterator1 const_subiterator2_type;
+ typedef typename E::const_iterator2 const_subiterator1_type;
+ typedef const value_type *const_pointer;
+
+public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
- typedef const_iterator1 iterator1;
- typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
- typedef const_iterator2 iterator2;
+ typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
#else
- class const_iterator1;
- typedef const_iterator1 iterator1;
- class const_iterator2;
- typedef const_iterator2 iterator2;
-#endif
- typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
- typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
-
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator1 find1 (int rank, size_type i, size_type j) const {
- const_subiterator1_type it1 (e_.find2 (rank, j, i));
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_subiterator1_type it1 (e_.find2 (rank, j, i));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator1 (*this, it1.index2 (), it1.index1 ());
+ return const_iterator1 (*this, it1.index2 (), it1.index1 ());
#else
- return const_iterator1 (*this, it1);
+ return const_iterator1 (*this, it1);
#endif
- }
- BOOST_UBLAS_INLINE
- const_iterator2 find2 (int rank, size_type i, size_type j) const {
- const_subiterator2_type it2 (e_.find1 (rank, j, i));
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_subiterator2_type it2 (e_.find1 (rank, j, i));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator2 (*this, it2.index2 (), it2.index1 ());
+ return const_iterator2 (*this, it2.index2 (), it2.index1 ());
#else
- return const_iterator2 (*this, it2);
+ return const_iterator2 (*this, it2);
#endif
- }
+ }
- // Iterators enhance the iterators of the referenced expression
- // with the unary functor.
+ // Iterators enhance the iterators of the referenced expression
+ // with the unary functor.
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator1:
- public container_const_reference<matrix_unary2>,
- public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
- iterator_base<const_iterator1, value_type>::type {
- public:
- typedef typename E::const_iterator2::iterator_category iterator_category;
- typedef typename matrix_unary2::difference_type difference_type;
- typedef typename matrix_unary2::value_type value_type;
- typedef typename matrix_unary2::const_reference reference;
- typedef typename matrix_unary2::const_pointer pointer;
-
- typedef const_iterator2 dual_iterator_type;
- typedef const_reverse_iterator2 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator1 ():
- container_const_reference<self_type> (), it_ () {}
- BOOST_UBLAS_INLINE
- const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
- container_const_reference<self_type> (mu), it_ (it) {}
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator1 &operator ++ () {
- ++ it_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -- () {
- -- it_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator += (difference_type n) {
- it_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -= (difference_type n) {
- it_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ - it.it_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return functor_type::apply (*it_);
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator1:
+ public container_const_reference<matrix_unary2>,
+ public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename E::const_iterator2::iterator_category iterator_category;
+ typedef typename matrix_unary2::difference_type difference_type;
+ typedef typename matrix_unary2::value_type value_type;
+ typedef typename matrix_unary2::const_reference reference;
+ typedef typename matrix_unary2::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
+ container_const_reference<self_type> (mu), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 begin () const {
- return (*this) ().find2 (1, index1 (), 0);
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 end () const {
- return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rbegin () const {
- return const_reverse_iterator2 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rend () const {
- return const_reverse_iterator2 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator2 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it_.index2 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it_.index1 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator1 &operator = (const const_iterator1 &it) {
- container_const_reference<self_type>::assign (&it ());
- it_ = it.it_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ == it.it_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ < it.it_;
- }
-
- private:
- const_subiterator1_type it_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator1 begin1 () const {
- return find1 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cbegin1 () const {
- return begin1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 end1 () const {
- return find1 (0, size1 (), 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cend1 () const {
- return end1 ();
- }
+ typename self_type::
+#endif
+ const_reverse_iterator2 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index2 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index1 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator1_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cbegin1 () const {
+ return begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cend1 () const {
+ return end1 ();
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator2:
- public container_const_reference<matrix_unary2>,
- public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
- iterator_base<const_iterator2, value_type>::type {
- public:
- typedef typename E::const_iterator1::iterator_category iterator_category;
- typedef typename matrix_unary2::difference_type difference_type;
- typedef typename matrix_unary2::value_type value_type;
- typedef typename matrix_unary2::const_reference reference;
- typedef typename matrix_unary2::const_pointer pointer;
-
- typedef const_iterator1 dual_iterator_type;
- typedef const_reverse_iterator1 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator2 ():
- container_const_reference<self_type> (), it_ () {}
- BOOST_UBLAS_INLINE
- const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
- container_const_reference<self_type> (mu), it_ (it) {}
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator2 &operator ++ () {
- ++ it_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -- () {
- -- it_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator += (difference_type n) {
- it_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -= (difference_type n) {
- it_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ - it.it_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return functor_type::apply (*it_);
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator2:
+ public container_const_reference<matrix_unary2>,
+ public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename E::const_iterator1::iterator_category iterator_category;
+ typedef typename matrix_unary2::difference_type difference_type;
+ typedef typename matrix_unary2::value_type value_type;
+ typedef typename matrix_unary2::const_reference reference;
+ typedef typename matrix_unary2::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
+ container_const_reference<self_type> (mu), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 begin () const {
- return (*this) ().find1 (1, 0, index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 end () const {
- return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rbegin () const {
- return const_reverse_iterator1 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rend () const {
- return const_reverse_iterator1 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator1 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it_.index2 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it_.index1 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator2 &operator = (const const_iterator2 &it) {
- container_const_reference<self_type>::assign (&it ());
- it_ = it.it_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ == it.it_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it_ < it.it_;
- }
-
- private:
- const_subiterator2_type it_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator2 begin2 () const {
- return find2 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cbegin2 () const {
- return begin2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 end2 () const {
- return find2 (0, 0, size2 ());
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cend2 () const {
- return end2 ();
- }
-
- // Reverse iterators
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rbegin1 () const {
- return const_reverse_iterator1 (end1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crbegin1 () const {
- return rbegin1 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rend1 () const {
- return const_reverse_iterator1 (begin1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crend1 () const {
- return rend1 ();
- }
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rbegin2 () const {
- return const_reverse_iterator2 (end2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crbegin2 () const {
- return rbegin2 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rend2 () const {
- return const_reverse_iterator2 (begin2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crend2 () const {
- return rend2 ();
- }
-
- private:
- expression_closure_type e_;
- };
-
- template<class E, class F>
- struct matrix_unary2_traits {
- typedef matrix_unary2<E, F> expression_type;
+ typename self_type::
+#endif
+ const_reverse_iterator1 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index2 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index1 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator2_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cbegin2 () const {
+ return begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cend2 () const {
+ return end2 ();
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin1 () const {
+ return rbegin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crend1 () const {
+ return rend1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin2 () const {
+ return rbegin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crend2 () const {
+ return rend2 ();
+ }
+
+private:
+ expression_closure_type e_;
+};
+
+template<class E, class F>
+struct matrix_unary2_traits {
+ typedef matrix_unary2<E, F> expression_type;
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- typedef typename E::matrix_temporary_type result_type;
-#endif
- };
-
- // (trans m) [i] [j] = m [j] [i]
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::result_type
- trans (const matrix_expression<E> &e) {
- typedef typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
- return expression_type (e ());
- }
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::result_type
- trans (matrix_expression<E> &e) {
- typedef typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
- return expression_type (e ());
- }
-
- // (herm m) [i] [j] = conj (m [j] [i])
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::result_type
- herm (const matrix_expression<E> &e) {
- typedef typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
- return expression_type (e ());
- }
-
- template<class E1, class E2, class F>
- class matrix_binary:
- public matrix_expression<matrix_binary<E1, E2, F> > {
-
- typedef E1 expression1_type;
- typedef E2 expression2_type;
- typedef F functor_type;
- public:
- typedef typename E1::const_closure_type expression1_closure_type;
- typedef typename E2::const_closure_type expression2_closure_type;
- private:
- typedef matrix_binary<E1, E2, F> self_type;
- public:
+ typedef typename E::matrix_temporary_type result_type;
+#endif
+};
+
+// (trans m) [i] [j] = m [j] [i]
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::result_type
+trans (const matrix_expression<E> &e) {
+ typedef typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+}
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::result_type
+trans (matrix_expression<E> &e) {
+ typedef typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+}
+
+// (herm m) [i] [j] = conj (m [j] [i])
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::result_type
+herm (const matrix_expression<E> &e) {
+ typedef typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+}
+
+template<class E1, class E2, class F>
+class matrix_binary:
+ public matrix_expression<matrix_binary<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+private:
+ typedef matrix_binary<E1, E2, F> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using matrix_expression<self_type>::operator ();
-#endif
- typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
- typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
- typedef typename F::result_type value_type;
- typedef value_type const_reference;
- typedef const_reference reference;
- typedef const self_type const_closure_type;
- typedef const_closure_type closure_type;
- typedef unknown_orientation_tag orientation_category;
- typedef unknown_storage_tag storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- matrix_binary (const E1 &e1, const E2 &e2):
- e1_ (e1), e2_ (e2) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size1 () const {
- return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ());
- }
- BOOST_UBLAS_INLINE
- size_type size2 () const {
- return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ());
- }
-
- public:
- // Expression accessors
- BOOST_UBLAS_INLINE
- const expression1_closure_type &expression1 () const {
- return e1_;
- }
- BOOST_UBLAS_INLINE
- const expression2_closure_type &expression2 () const {
- return e2_;
- }
-
- public:
- // Element access
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type i, size_type j) const {
- return functor_type::apply (e1_ (i, j), e2_ (i, j));
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const matrix_binary &mb) const {
- return (*this).expression1 ().same_closure (mb.expression1 ()) &&
- (*this).expression2 ().same_closure (mb.expression2 ());
- }
-
- // Iterator types
- private:
- typedef typename E1::const_iterator1 const_iterator11_type;
- typedef typename E1::const_iterator2 const_iterator12_type;
- typedef typename E2::const_iterator1 const_iterator21_type;
- typedef typename E2::const_iterator2 const_iterator22_type;
- typedef const value_type *const_pointer;
-
- public:
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_orientation_tag orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_binary (const E1 &e1, const E2 &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ());
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ());
+ }
+
+public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e1_ (i, j), e2_ (i, j));
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e1_ (i), e2_ (i));
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_binary &mb) const {
+ return (*this).expression1 ().same_closure (mb.expression1 ()) &&
+ (*this).expression2 ().same_closure (mb.expression2 ());
+ }
+
+ // Iterator types
+private:
+ typedef typename E1::const_iterator1 const_iterator11_type;
+ typedef typename E1::const_iterator2 const_iterator12_type;
+ typedef typename E2::const_iterator1 const_iterator21_type;
+ typedef typename E2::const_iterator2 const_iterator22_type;
+ typedef const value_type *const_pointer;
+
+public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
- typename const_iterator21_type::iterator_category>::iterator_category iterator_category1;
- typedef indexed_const_iterator1<const_closure_type, iterator_category1> const_iterator1;
- typedef const_iterator1 iterator1;
- typedef typename iterator_restrict_traits<typename const_iterator12_type::iterator_category,
- typename const_iterator22_type::iterator_category>::iterator_category iterator_category2;
- typedef indexed_const_iterator2<const_closure_type, iterator_category2> const_iterator2;
- typedef const_iterator2 iterator2;
+ typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
+ typename const_iterator21_type::iterator_category>::iterator_category iterator_category1;
+ typedef indexed_const_iterator1<const_closure_type, iterator_category1> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef typename iterator_restrict_traits<typename const_iterator12_type::iterator_category,
+ typename const_iterator22_type::iterator_category>::iterator_category iterator_category2;
+ typedef indexed_const_iterator2<const_closure_type, iterator_category2> const_iterator2;
+ typedef const_iterator2 iterator2;
#else
- class const_iterator1;
- typedef const_iterator1 iterator1;
- class const_iterator2;
- typedef const_iterator2 iterator2;
-#endif
- typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
- typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
-
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator1 find1 (int rank, size_type i, size_type j) const {
- const_iterator11_type it11 (e1_.find1 (rank, i, j));
- const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j));
- const_iterator21_type it21 (e2_.find1 (rank, i, j));
- const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j));
- BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ())
- BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ())
- i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (),
- it21 != it21_end ? it21.index1 () : size1 ());
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_iterator11_type it11 (e1_.find1 (rank, i, j));
+ const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j));
+ const_iterator21_type it21 (e2_.find1 (rank, i, j));
+ const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j));
+ BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ())
+ BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ())
+ i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (),
+ it21 != it21_end ? it21.index1 () : size1 ());
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator1 (*this, i, j);
+ return const_iterator1 (*this, i, j);
#else
- return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end);
-#endif
- }
- BOOST_UBLAS_INLINE
- const_iterator2 find2 (int rank, size_type i, size_type j) const {
- const_iterator12_type it12 (e1_.find2 (rank, i, j));
- const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ()));
- const_iterator22_type it22 (e2_.find2 (rank, i, j));
- const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ()));
- BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ())
- BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ())
- j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (),
- it22 != it22_end ? it22.index2 () : size2 ());
+ return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_iterator12_type it12 (e1_.find2 (rank, i, j));
+ const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ()));
+ const_iterator22_type it22 (e2_.find2 (rank, i, j));
+ const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ()));
+ BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ())
+ BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ())
+ j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (),
+ it22 != it22_end ? it22.index2 () : size2 ());
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator2 (*this, i, j);
+ return const_iterator2 (*this, i, j);
#else
- return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end);
+ return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end);
#endif
- }
+ }
- // Iterators enhance the iterators of the referenced expression
- // with the binary functor.
+ // Iterators enhance the iterators of the referenced expression
+ // with the binary functor.
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator1:
- public container_const_reference<matrix_binary>,
- public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
- typename E2::const_iterator1::iterator_category>::iterator_category>::template
- iterator_base<const_iterator1, value_type>::type {
- public:
- typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
- typename E2::const_iterator1::iterator_category>::iterator_category iterator_category;
- typedef typename matrix_binary::difference_type difference_type;
- typedef typename matrix_binary::value_type value_type;
- typedef typename matrix_binary::const_reference reference;
- typedef typename matrix_binary::const_pointer pointer;
-
- typedef const_iterator2 dual_iterator_type;
- typedef const_reverse_iterator2 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator1 ():
- container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
- BOOST_UBLAS_INLINE
- const_iterator1 (const self_type &mb, size_type i, size_type j,
- const const_iterator11_type &it1, const const_iterator11_type &it1_end,
- const const_iterator21_type &it2, const const_iterator21_type &it2_end):
- container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
-
- private:
- // Dense specializations
- BOOST_UBLAS_INLINE
- void increment (dense_random_access_iterator_tag) {
- ++ i_; ++ it1_; ++ it2_;
- }
- BOOST_UBLAS_INLINE
- void decrement (dense_random_access_iterator_tag) {
- -- i_; -- it1_; -- it2_;
- }
- BOOST_UBLAS_INLINE
- void increment (dense_random_access_iterator_tag, difference_type n) {
- i_ += n; it1_ += n; it2_ += n;
- }
- BOOST_UBLAS_INLINE
- void decrement (dense_random_access_iterator_tag, difference_type n) {
- i_ -= n; it1_ -= n; it2_ -= n;
- }
- BOOST_UBLAS_INLINE
- value_type dereference (dense_random_access_iterator_tag) const {
- return functor_type::apply (*it1_, *it2_);
- }
-
- // Packed specializations
- BOOST_UBLAS_INLINE
- void increment (packed_random_access_iterator_tag) {
- if (it1_ != it1_end_)
- if (it1_.index1 () <= i_)
- ++ it1_;
- if (it2_ != it2_end_)
- if (it2_.index1 () <= i_)
- ++ it2_;
- ++ i_;
- }
- BOOST_UBLAS_INLINE
- void decrement (packed_random_access_iterator_tag) {
- if (it1_ != it1_end_)
- if (i_ <= it1_.index1 ())
- -- it1_;
- if (it2_ != it2_end_)
- if (i_ <= it2_.index1 ())
- -- it2_;
- -- i_;
- }
- BOOST_UBLAS_INLINE
- void increment (packed_random_access_iterator_tag, difference_type n) {
- while (n > 0) {
- increment (packed_random_access_iterator_tag ());
- --n;
- }
- while (n < 0) {
- decrement (packed_random_access_iterator_tag ());
- ++n;
- }
- }
- BOOST_UBLAS_INLINE
- void decrement (packed_random_access_iterator_tag, difference_type n) {
- while (n > 0) {
- decrement (packed_random_access_iterator_tag ());
- --n;
- }
- while (n < 0) {
- increment (packed_random_access_iterator_tag ());
- ++n;
- }
- }
- BOOST_UBLAS_INLINE
- value_type dereference (packed_random_access_iterator_tag) const {
- value_type t1 = value_type/*zero*/();
- if (it1_ != it1_end_) {
- BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
- if (it1_.index1 () == i_)
- t1 = *it1_;
- }
- value_type t2 = value_type/*zero*/();
- if (it2_ != it2_end_) {
- BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
- if (it2_.index1 () == i_)
- t2 = *it2_;
- }
- return functor_type::apply (t1, t2);
- }
-
- // Sparse specializations
- BOOST_UBLAS_INLINE
- void increment (sparse_bidirectional_iterator_tag) {
- size_type index1 = (*this) ().size1 ();
- if (it1_ != it1_end_) {
- if (it1_.index1 () <= i_)
- ++ it1_;
- if (it1_ != it1_end_)
- index1 = it1_.index1 ();
- }
- size_type index2 = (*this) ().size1 ();
- if (it2_ != it2_end_)
- if (it2_.index1 () <= i_)
- ++ it2_;
- if (it2_ != it2_end_) {
- index2 = it2_.index1 ();
- }
- i_ = (std::min) (index1, index2);
- }
- BOOST_UBLAS_INLINE
- void decrement (sparse_bidirectional_iterator_tag) {
- size_type index1 = (*this) ().size1 ();
- if (it1_ != it1_end_) {
- if (i_ <= it1_.index1 ())
- -- it1_;
- if (it1_ != it1_end_)
- index1 = it1_.index1 ();
- }
- size_type index2 = (*this) ().size1 ();
- if (it2_ != it2_end_) {
- if (i_ <= it2_.index1 ())
- -- it2_;
- if (it2_ != it2_end_)
- index2 = it2_.index1 ();
- }
- i_ = (std::max) (index1, index2);
- }
- BOOST_UBLAS_INLINE
- void increment (sparse_bidirectional_iterator_tag, difference_type n) {
- while (n > 0) {
- increment (sparse_bidirectional_iterator_tag ());
- --n;
- }
- while (n < 0) {
- decrement (sparse_bidirectional_iterator_tag ());
- ++n;
- }
- }
- BOOST_UBLAS_INLINE
- void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
- while (n > 0) {
- decrement (sparse_bidirectional_iterator_tag ());
- --n;
- }
- while (n < 0) {
- increment (sparse_bidirectional_iterator_tag ());
- ++n;
- }
- }
- BOOST_UBLAS_INLINE
- value_type dereference (sparse_bidirectional_iterator_tag) const {
- value_type t1 = value_type/*zero*/();
- if (it1_ != it1_end_) {
- BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
- if (it1_.index1 () == i_)
- t1 = *it1_;
- }
- value_type t2 = value_type/*zero*/();
- if (it2_ != it2_end_) {
- BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
- if (it2_.index1 () == i_)
- t2 = *it2_;
- }
- return functor_type::apply (t1, t2);
- }
-
- public:
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator1 &operator ++ () {
- increment (iterator_category ());
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -- () {
- decrement (iterator_category ());
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator += (difference_type n) {
- increment (iterator_category (), n);
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -= (difference_type n) {
- decrement (iterator_category (), n);
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
- return index1 () - it.index1 ();
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return dereference (iterator_category ());
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator1:
+ public container_const_reference<matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator1::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator1::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_binary::difference_type difference_type;
+ typedef typename matrix_binary::value_type value_type;
+ typedef typename matrix_binary::const_reference reference;
+ typedef typename matrix_binary::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mb, size_type i, size_type j,
+ const const_iterator11_type &it1, const const_iterator11_type &it1_end,
+ const const_iterator21_type &it2, const const_iterator21_type &it2_end):
+ container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
+
+ private:
+ // Dense specializations
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag) {
+ ++ i_; ++ it1_; ++ it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag) {
+ -- i_; -- it1_; -- it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag, difference_type n) {
+ i_ += n; it1_ += n; it2_ += n;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag, difference_type n) {
+ i_ -= n; it1_ -= n; it2_ -= n;
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ return functor_type::apply (*it1_, *it2_);
+ }
+
+ // Packed specializations
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (it1_.index1 () <= i_)
+ ++ it1_;
+ if (it2_ != it2_end_)
+ if (it2_.index1 () <= i_)
+ ++ it2_;
+ ++ i_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (i_ <= it1_.index1 ())
+ -- it1_;
+ if (it2_ != it2_end_)
+ if (i_ <= it2_.index1 ())
+ -- it2_;
+ -- i_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
+ typename E1::value_type t1 = typename E1::value_type/*zero*/();
+ if (it1_ != it1_end_) {
+ BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
+ if (it1_.index1 () == i_)
+ t1 = *it1_;
+ }
+ typename E2::value_type t2 = typename E2::value_type/*zero*/();
+ if (it2_ != it2_end_) {
+ BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
+ if (it2_.index1 () == i_)
+ t2 = *it2_;
+ }
+ return functor_type::apply (t1, t2);
+ }
+
+ // Sparse specializations
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size1 ();
+ if (it1_ != it1_end_) {
+ if (it1_.index1 () <= i_)
+ ++ it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index1 ();
+ }
+ size_type index2 = (*this) ().size1 ();
+ if (it2_ != it2_end_)
+ if (it2_.index1 () <= i_)
+ ++ it2_;
+ if (it2_ != it2_end_) {
+ index2 = it2_.index1 ();
+ }
+ i_ = (std::min) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size1 ();
+ if (it1_ != it1_end_) {
+ if (i_ <= it1_.index1 ())
+ -- it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index1 ();
+ }
+ size_type index2 = (*this) ().size1 ();
+ if (it2_ != it2_end_) {
+ if (i_ <= it2_.index1 ())
+ -- it2_;
+ if (it2_ != it2_end_)
+ index2 = it2_.index1 ();
+ }
+ i_ = (std::max) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
+ typename E1::value_type t1 = typename E1::value_type/*zero*/();
+ if (it1_ != it1_end_) {
+ BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
+ if (it1_.index1 () == i_)
+ t1 = *it1_;
+ }
+ typename E2::value_type t2 = typename E2::value_type/*zero*/();
+ if (it2_ != it2_end_) {
+ BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
+ if (it2_.index1 () == i_)
+ t2 = *it2_;
+ }
+ return functor_type::apply (t1, t2);
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ increment (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ decrement (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ increment (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ decrement (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
+ return index1 () - it.index1 ();
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 begin () const {
- return (*this) ().find2 (1, index1 (), 0);
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 end () const {
- return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rbegin () const {
- return const_reverse_iterator2 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rend () const {
- return const_reverse_iterator2 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator2 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return i_;
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- // if (it1_ != it1_end_ && it2_ != it2_end_)
- // return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ());
- // else
- return j_;
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator1 &operator = (const const_iterator1 &it) {
- container_const_reference<self_type>::assign (&it ());
- i_ = it.i_;
- j_ = it.j_;
- it1_ = it.it1_;
- it1_end_ = it.it1_end_;
- it2_ = it.it2_;
- it2_end_ = it.it2_end_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
- return index1 () == it.index1 ();
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
- return index1 () < it.index1 ();
- }
-
- private:
- size_type i_;
- size_type j_;
- const_iterator11_type it1_;
- const_iterator11_type it1_end_;
- const_iterator21_type it2_;
- const_iterator21_type it2_end_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator1 begin1 () const {
- return find1 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cbegin1 () const {
- return begin1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 end1 () const {
- return find1 (0, size1 (), 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cend1 () const {
- return end1 ();
- }
+ typename self_type::
+#endif
+ const_reverse_iterator2 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return i_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ // if (it1_ != it1_end_ && it2_ != it2_end_)
+ // return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ());
+ // else
+ return j_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ i_ = it.i_;
+ j_ = it.j_;
+ it1_ = it.it1_;
+ it1_end_ = it.it1_end_;
+ it2_ = it.it2_;
+ it2_end_ = it.it2_end_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
+ return index1 () == it.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
+ return index1 () < it.index1 ();
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ const_iterator11_type it1_;
+ const_iterator11_type it1_end_;
+ const_iterator21_type it2_;
+ const_iterator21_type it2_end_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cbegin1 () const {
+ return begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cend1 () const {
+ return end1 ();
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator2:
- public container_const_reference<matrix_binary>,
- public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
- typename E2::const_iterator2::iterator_category>::iterator_category>::template
- iterator_base<const_iterator2, value_type>::type {
- public:
- typedef typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
- typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
- typedef typename matrix_binary::difference_type difference_type;
- typedef typename matrix_binary::value_type value_type;
- typedef typename matrix_binary::const_reference reference;
- typedef typename matrix_binary::const_pointer pointer;
-
- typedef const_iterator1 dual_iterator_type;
- typedef const_reverse_iterator1 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator2 ():
- container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
- BOOST_UBLAS_INLINE
- const_iterator2 (const self_type &mb, size_type i, size_type j,
- const const_iterator12_type &it1, const const_iterator12_type &it1_end,
- const const_iterator22_type &it2, const const_iterator22_type &it2_end):
- container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
-
- private:
- // Dense access specializations
- BOOST_UBLAS_INLINE
- void increment (dense_random_access_iterator_tag) {
- ++ j_; ++ it1_; ++ it2_;
- }
- BOOST_UBLAS_INLINE
- void decrement (dense_random_access_iterator_tag) {
- -- j_; -- it1_; -- it2_;
- }
- BOOST_UBLAS_INLINE
- void increment (dense_random_access_iterator_tag, difference_type n) {
- j_ += n; it1_ += n; it2_ += n;
- }
- BOOST_UBLAS_INLINE
- void decrement (dense_random_access_iterator_tag, difference_type n) {
- j_ -= n; it1_ -= n; it2_ -= n;
- }
- BOOST_UBLAS_INLINE
- value_type dereference (dense_random_access_iterator_tag) const {
- return functor_type::apply (*it1_, *it2_);
- }
-
- // Packed specializations
- BOOST_UBLAS_INLINE
- void increment (packed_random_access_iterator_tag) {
- if (it1_ != it1_end_)
- if (it1_.index2 () <= j_)
- ++ it1_;
- if (it2_ != it2_end_)
- if (it2_.index2 () <= j_)
- ++ it2_;
- ++ j_;
- }
- BOOST_UBLAS_INLINE
- void decrement (packed_random_access_iterator_tag) {
- if (it1_ != it1_end_)
- if (j_ <= it1_.index2 ())
- -- it1_;
- if (it2_ != it2_end_)
- if (j_ <= it2_.index2 ())
- -- it2_;
- -- j_;
- }
- BOOST_UBLAS_INLINE
- void increment (packed_random_access_iterator_tag, difference_type n) {
- while (n > 0) {
- increment (packed_random_access_iterator_tag ());
- --n;
- }
- while (n < 0) {
- decrement (packed_random_access_iterator_tag ());
- ++n;
- }
- }
- BOOST_UBLAS_INLINE
- void decrement (packed_random_access_iterator_tag, difference_type n) {
- while (n > 0) {
- decrement (packed_random_access_iterator_tag ());
- --n;
- }
- while (n < 0) {
- increment (packed_random_access_iterator_tag ());
- ++n;
- }
- }
- BOOST_UBLAS_INLINE
- value_type dereference (packed_random_access_iterator_tag) const {
- value_type t1 = value_type/*zero*/();
- if (it1_ != it1_end_) {
- BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
- if (it1_.index2 () == j_)
- t1 = *it1_;
- }
- value_type t2 = value_type/*zero*/();
- if (it2_ != it2_end_) {
- BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
- if (it2_.index2 () == j_)
- t2 = *it2_;
- }
- return functor_type::apply (t1, t2);
- }
-
- // Sparse specializations
- BOOST_UBLAS_INLINE
- void increment (sparse_bidirectional_iterator_tag) {
- size_type index1 = (*this) ().size2 ();
- if (it1_ != it1_end_) {
- if (it1_.index2 () <= j_)
- ++ it1_;
- if (it1_ != it1_end_)
- index1 = it1_.index2 ();
- }
- size_type index2 = (*this) ().size2 ();
- if (it2_ != it2_end_) {
- if (it2_.index2 () <= j_)
- ++ it2_;
- if (it2_ != it2_end_)
- index2 = it2_.index2 ();
- }
- j_ = (std::min) (index1, index2);
- }
- BOOST_UBLAS_INLINE
- void decrement (sparse_bidirectional_iterator_tag) {
- size_type index1 = (*this) ().size2 ();
- if (it1_ != it1_end_) {
- if (j_ <= it1_.index2 ())
- -- it1_;
- if (it1_ != it1_end_)
- index1 = it1_.index2 ();
- }
- size_type index2 = (*this) ().size2 ();
- if (it2_ != it2_end_) {
- if (j_ <= it2_.index2 ())
- -- it2_;
- if (it2_ != it2_end_)
- index2 = it2_.index2 ();
- }
- j_ = (std::max) (index1, index2);
- }
- BOOST_UBLAS_INLINE
- void increment (sparse_bidirectional_iterator_tag, difference_type n) {
- while (n > 0) {
- increment (sparse_bidirectional_iterator_tag ());
- --n;
- }
- while (n < 0) {
- decrement (sparse_bidirectional_iterator_tag ());
- ++n;
- }
- }
- BOOST_UBLAS_INLINE
- void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
- while (n > 0) {
- decrement (sparse_bidirectional_iterator_tag ());
- --n;
- }
- while (n < 0) {
- increment (sparse_bidirectional_iterator_tag ());
- ++n;
- }
- }
- BOOST_UBLAS_INLINE
- value_type dereference (sparse_bidirectional_iterator_tag) const {
- value_type t1 = value_type/*zero*/();
- if (it1_ != it1_end_) {
- BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
- if (it1_.index2 () == j_)
- t1 = *it1_;
- }
- value_type t2 = value_type/*zero*/();
- if (it2_ != it2_end_) {
- BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
- if (it2_.index2 () == j_)
- t2 = *it2_;
- }
- return functor_type::apply (t1, t2);
- }
-
- public:
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator2 &operator ++ () {
- increment (iterator_category ());
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -- () {
- decrement (iterator_category ());
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator += (difference_type n) {
- increment (iterator_category (), n);
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -= (difference_type n) {
- decrement (iterator_category (), n);
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
- return index2 () - it.index2 ();
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return dereference (iterator_category ());
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator2:
+ public container_const_reference<matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_binary::difference_type difference_type;
+ typedef typename matrix_binary::value_type value_type;
+ typedef typename matrix_binary::const_reference reference;
+ typedef typename matrix_binary::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mb, size_type i, size_type j,
+ const const_iterator12_type &it1, const const_iterator12_type &it1_end,
+ const const_iterator22_type &it2, const const_iterator22_type &it2_end):
+ container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
+
+ private:
+ // Dense access specializations
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag) {
+ ++ j_; ++ it1_; ++ it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag) {
+ -- j_; -- it1_; -- it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag, difference_type n) {
+ j_ += n; it1_ += n; it2_ += n;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag, difference_type n) {
+ j_ -= n; it1_ -= n; it2_ -= n;
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ return functor_type::apply (*it1_, *it2_);
+ }
+
+ // Packed specializations
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (it1_.index2 () <= j_)
+ ++ it1_;
+ if (it2_ != it2_end_)
+ if (it2_.index2 () <= j_)
+ ++ it2_;
+ ++ j_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (j_ <= it1_.index2 ())
+ -- it1_;
+ if (it2_ != it2_end_)
+ if (j_ <= it2_.index2 ())
+ -- it2_;
+ -- j_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
+ typename E1::value_type t1 = typename E1::value_type/*zero*/();
+ if (it1_ != it1_end_) {
+ BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
+ if (it1_.index2 () == j_)
+ t1 = *it1_;
+ }
+ typename E2::value_type t2 = typename E2::value_type/*zero*/();
+ if (it2_ != it2_end_) {
+ BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
+ if (it2_.index2 () == j_)
+ t2 = *it2_;
+ }
+ return functor_type::apply (t1, t2);
+ }
+
+ // Sparse specializations
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size2 ();
+ if (it1_ != it1_end_) {
+ if (it1_.index2 () <= j_)
+ ++ it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index2 ();
+ }
+ size_type index2 = (*this) ().size2 ();
+ if (it2_ != it2_end_) {
+ if (it2_.index2 () <= j_)
+ ++ it2_;
+ if (it2_ != it2_end_)
+ index2 = it2_.index2 ();
+ }
+ j_ = (std::min) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size2 ();
+ if (it1_ != it1_end_) {
+ if (j_ <= it1_.index2 ())
+ -- it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index2 ();
+ }
+ size_type index2 = (*this) ().size2 ();
+ if (it2_ != it2_end_) {
+ if (j_ <= it2_.index2 ())
+ -- it2_;
+ if (it2_ != it2_end_)
+ index2 = it2_.index2 ();
+ }
+ j_ = (std::max) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
+ typename E1::value_type t1 = typename E1::value_type/*zero*/();
+ if (it1_ != it1_end_) {
+ BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
+ if (it1_.index2 () == j_)
+ t1 = *it1_;
+ }
+ typename E2::value_type t2 = typename E2::value_type/*zero*/();
+ if (it2_ != it2_end_) {
+ BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
+ if (it2_.index2 () == j_)
+ t2 = *it2_;
+ }
+ return functor_type::apply (t1, t2);
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ increment (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ decrement (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ increment (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ decrement (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
+ return index2 () - it.index2 ();
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 begin () const {
- return (*this) ().find1 (1, 0, index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 end () const {
- return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rbegin () const {
- return const_reverse_iterator1 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rend () const {
- return const_reverse_iterator1 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator1 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- // if (it1_ != it1_end_ && it2_ != it2_end_)
- // return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ());
- // else
- return i_;
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return j_;
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator2 &operator = (const const_iterator2 &it) {
- container_const_reference<self_type>::assign (&it ());
- i_ = it.i_;
- j_ = it.j_;
- it1_ = it.it1_;
- it1_end_ = it.it1_end_;
- it2_ = it.it2_;
- it2_end_ = it.it2_end_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
- return index2 () == it.index2 ();
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
- return index2 () < it.index2 ();
- }
-
- private:
- size_type i_;
- size_type j_;
- const_iterator12_type it1_;
- const_iterator12_type it1_end_;
- const_iterator22_type it2_;
- const_iterator22_type it2_end_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator2 begin2 () const {
- return find2 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cbegin2 () const {
- return begin2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 end2 () const {
- return find2 (0, 0, size2 ());
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cend2 () const {
- return end2 ();
- }
-
- // Reverse iterators
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rbegin1 () const {
- return const_reverse_iterator1 (end1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crbegin1 () const {
- return rbegin1 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rend1 () const {
- return const_reverse_iterator1 (begin1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crend1 () const {
- return rend1 ();
- }
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rbegin2 () const {
- return const_reverse_iterator2 (end2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crbegin2 () const {
- return rbegin2 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rend2 () const {
- return const_reverse_iterator2 (begin2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crend2 () const {
- return rend2 ();
- }
-
- private:
- expression1_closure_type e1_;
- expression2_closure_type e2_;
- };
-
- template<class E1, class E2, class F>
- struct matrix_binary_traits {
- typedef matrix_binary<E1, E2, F> expression_type;
+ typename self_type::
+#endif
+ const_reverse_iterator1 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ // if (it1_ != it1_end_ && it2_ != it2_end_)
+ // return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ());
+ // else
+ return i_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return j_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ i_ = it.i_;
+ j_ = it.j_;
+ it1_ = it.it1_;
+ it1_end_ = it.it1_end_;
+ it2_ = it.it2_;
+ it2_end_ = it.it2_end_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
+ return index2 () == it.index2 ();
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
+ return index2 () < it.index2 ();
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ const_iterator12_type it1_;
+ const_iterator12_type it1_end_;
+ const_iterator22_type it2_;
+ const_iterator22_type it2_end_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cbegin2 () const {
+ return begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cend2 () const {
+ return end2 ();
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin1 () const {
+ return rbegin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crend1 () const {
+ return rend1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin2 () const {
+ return rbegin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crend2 () const {
+ return rend2 ();
+ }
+
+private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+};
+
+template<class E1, class E2, class F>
+struct matrix_binary_traits {
+ typedef matrix_binary<E1, E2, F> expression_type;
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- typedef typename E1::matrix_temporary_type result_type;
-#endif
- };
-
- // (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j]
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
- typename E2::value_type> >::result_type
- operator + (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- typedef typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
- typename E2::value_type> >::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- // (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j]
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
- typename E2::value_type> >::result_type
- operator - (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- typedef typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
- typename E2::value_type> >::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- // (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j]
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
- typename E2::value_type> >::result_type
- element_prod (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- typedef typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
- typename E2::value_type> >::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- // (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j]
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
- typename E2::value_type> >::result_type
- element_div (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- typedef typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
- typename E2::value_type> >::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- template<class E1, class E2, class F>
- class matrix_binary_scalar1:
- public matrix_expression<matrix_binary_scalar1<E1, E2, F> > {
-
- typedef E1 expression1_type;
- typedef E2 expression2_type;
- typedef F functor_type;
- typedef const E1& expression1_closure_type;
- typedef typename E2::const_closure_type expression2_closure_type;
- typedef matrix_binary_scalar1<E1, E2, F> self_type;
- public:
+ typedef typename E1::matrix_temporary_type result_type;
+#endif
+};
+
+// (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j]
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
+typename E2::value_type> >::result_type
+operator + (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+// (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j]
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
+typename E2::value_type> >::result_type
+operator - (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+// (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j]
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
+typename E2::value_type> >::result_type
+element_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+// (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j]
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
+typename E2::value_type> >::result_type
+element_div (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+template<class E1, class E2, class F>
+class matrix_binary_scalar1:
+ public matrix_expression<matrix_binary_scalar1<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+ typedef const E1& expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ typedef matrix_binary_scalar1<E1, E2, F> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using matrix_expression<self_type>::operator ();
-#endif
- typedef typename E2::size_type size_type;
- typedef typename E2::difference_type difference_type;
- typedef typename F::result_type value_type;
- typedef value_type const_reference;
- typedef const_reference reference;
- typedef const self_type const_closure_type;
- typedef const_closure_type closure_type;
- typedef typename E2::orientation_category orientation_category;
- typedef unknown_storage_tag storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
- e1_ (e1), e2_ (e2) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size1 () const {
- return e2_.size1 ();
- }
- BOOST_UBLAS_INLINE
- size_type size2 () const {
- return e2_.size2 ();
- }
-
- public:
- // Element access
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type i, size_type j) const {
- return functor_type::apply (expression1_type (e1_), e2_ (i, j));
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const matrix_binary_scalar1 &mbs1) const {
- return &e1_ == &(mbs1.e1_) &&
- (*this).e2_.same_closure (mbs1.e2_);
- }
-
- // Iterator types
- private:
- typedef expression1_type const_subiterator1_type;
- typedef typename E2::const_iterator1 const_iterator21_type;
- typedef typename E2::const_iterator2 const_iterator22_type;
- typedef const value_type *const_pointer;
-
- public:
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef typename E2::orientation_category orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e2_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e2_.size2 ();
+ }
+
+public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (expression1_type (e1_), e2_ (i, j));
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (expression1_type (e1_), e2_ (i));
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_binary_scalar1 &mbs1) const {
+ return &e1_ == &(mbs1.e1_) &&
+ (*this).e2_.same_closure (mbs1.e2_);
+ }
+
+ // Iterator types
+private:
+ typedef expression1_type const_subiterator1_type;
+ typedef typename E2::const_iterator1 const_iterator21_type;
+ typedef typename E2::const_iterator2 const_iterator22_type;
+ typedef const value_type *const_pointer;
+
+public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- typedef indexed_const_iterator1<const_closure_type, typename const_iterator21_type::iterator_category> const_iterator1;
- typedef const_iterator1 iterator1;
- typedef indexed_const_iterator2<const_closure_type, typename const_iterator22_type::iterator_category> const_iterator2;
- typedef const_iterator2 iterator2;
+ typedef indexed_const_iterator1<const_closure_type, typename const_iterator21_type::iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, typename const_iterator22_type::iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
#else
- class const_iterator1;
- typedef const_iterator1 iterator1;
- class const_iterator2;
- typedef const_iterator2 iterator2;
-#endif
- typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
- typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
-
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator1 find1 (int rank, size_type i, size_type j) const {
- const_iterator21_type it21 (e2_.find1 (rank, i, j));
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_iterator21_type it21 (e2_.find1 (rank, i, j));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator1 (*this, it21.index1 (), it21.index2 ());
+ return const_iterator1 (*this, it21.index1 (), it21.index2 ());
#else
- return const_iterator1 (*this, const_subiterator1_type (e1_), it21);
+ return const_iterator1 (*this, const_subiterator1_type (e1_), it21);
#endif
- }
- BOOST_UBLAS_INLINE
- const_iterator2 find2 (int rank, size_type i, size_type j) const {
- const_iterator22_type it22 (e2_.find2 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_iterator22_type it22 (e2_.find2 (rank, i, j));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator2 (*this, it22.index1 (), it22.index2 ());
+ return const_iterator2 (*this, it22.index1 (), it22.index2 ());
#else
- return const_iterator2 (*this, const_subiterator1_type (e1_), it22);
+ return const_iterator2 (*this, const_subiterator1_type (e1_), it22);
#endif
- }
+ }
- // Iterators enhance the iterators of the referenced expression
- // with the binary functor.
+ // Iterators enhance the iterators of the referenced expression
+ // with the binary functor.
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator1:
- public container_const_reference<matrix_binary_scalar1>,
- public iterator_base_traits<typename E2::const_iterator1::iterator_category>::template
- iterator_base<const_iterator1, value_type>::type {
- public:
- typedef typename E2::const_iterator1::iterator_category iterator_category;
- typedef typename matrix_binary_scalar1::difference_type difference_type;
- typedef typename matrix_binary_scalar1::value_type value_type;
- typedef typename matrix_binary_scalar1::const_reference reference;
- typedef typename matrix_binary_scalar1::const_pointer pointer;
-
- typedef const_iterator2 dual_iterator_type;
- typedef const_reverse_iterator2 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator1 ():
- container_const_reference<self_type> (), it1_ (), it2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2):
- container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator1 &operator ++ () {
- ++ it2_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -- () {
- -- it2_ ;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator += (difference_type n) {
- it2_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -= (difference_type n) {
- it2_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ - it.it2_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return functor_type::apply (it1_, *it2_);
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator1:
+ public container_const_reference<matrix_binary_scalar1>,
+ public iterator_base_traits<typename E2::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename E2::const_iterator1::iterator_category iterator_category;
+ typedef typename matrix_binary_scalar1::difference_type difference_type;
+ typedef typename matrix_binary_scalar1::value_type value_type;
+ typedef typename matrix_binary_scalar1::const_reference reference;
+ typedef typename matrix_binary_scalar1::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2):
+ container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it2_ ;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 begin () const {
- return (*this) ().find2 (1, index1 (), 0);
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 end () const {
- return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rbegin () const {
- return const_reverse_iterator2 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rend () const {
- return const_reverse_iterator2 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator2 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it2_.index1 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it2_.index2 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator1 &operator = (const const_iterator1 &it) {
- container_const_reference<self_type>::assign (&it ());
- it1_ = it.it1_;
- it2_ = it.it2_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ == it.it2_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ < it.it2_;
- }
-
- private:
- const_subiterator1_type it1_;
- const_iterator21_type it2_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator1 begin1 () const {
- return find1 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cbegin1 () const {
- return begin1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 end1 () const {
- return find1 (0, size1 (), 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cend1 () const {
- return end1 ();
- }
+ typename self_type::
+#endif
+ const_reverse_iterator2 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_iterator21_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cbegin1 () const {
+ return begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cend1 () const {
+ return end1 ();
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator2:
- public container_const_reference<matrix_binary_scalar1>,
- public iterator_base_traits<typename E2::const_iterator2::iterator_category>::template
- iterator_base<const_iterator2, value_type>::type {
- public:
- typedef typename E2::const_iterator2::iterator_category iterator_category;
- typedef typename matrix_binary_scalar1::difference_type difference_type;
- typedef typename matrix_binary_scalar1::value_type value_type;
- typedef typename matrix_binary_scalar1::const_reference reference;
- typedef typename matrix_binary_scalar1::const_pointer pointer;
-
- typedef const_iterator1 dual_iterator_type;
- typedef const_reverse_iterator1 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator2 ():
- container_const_reference<self_type> (), it1_ (), it2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2):
- container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator2 &operator ++ () {
- ++ it2_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -- () {
- -- it2_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator += (difference_type n) {
- it2_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -= (difference_type n) {
- it2_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ - it.it2_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return functor_type::apply (it1_, *it2_);
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator2:
+ public container_const_reference<matrix_binary_scalar1>,
+ public iterator_base_traits<typename E2::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename E2::const_iterator2::iterator_category iterator_category;
+ typedef typename matrix_binary_scalar1::difference_type difference_type;
+ typedef typename matrix_binary_scalar1::value_type value_type;
+ typedef typename matrix_binary_scalar1::const_reference reference;
+ typedef typename matrix_binary_scalar1::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 begin () const {
- return (*this) ().find1 (1, 0, index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 end () const {
- return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rbegin () const {
- return const_reverse_iterator1 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rend () const {
- return const_reverse_iterator1 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator1 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it2_.index1 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it2_.index2 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator2 &operator = (const const_iterator2 &it) {
- container_const_reference<self_type>::assign (&it ());
- it1_ = it.it1_;
- it2_ = it.it2_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ == it.it2_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ < it.it2_;
- }
-
- private:
- const_subiterator1_type it1_;
- const_iterator22_type it2_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator2 begin2 () const {
- return find2 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cbegin2 () const {
- return begin2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 end2 () const {
- return find2 (0, 0, size2 ());
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cend2 () const {
- return end2 ();
- }
-
- // Reverse iterators
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rbegin1 () const {
- return const_reverse_iterator1 (end1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crbegin1 () const {
- return rbegin1 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rend1 () const {
- return const_reverse_iterator1 (begin1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crend1 () const {
- return rend1 ();
- }
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rbegin2 () const {
- return const_reverse_iterator2 (end2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crbegin2 () const {
- return rbegin2 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rend2 () const {
- return const_reverse_iterator2 (begin2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crend2 () const {
- return rend2 ();
- }
-
- private:
- expression1_closure_type e1_;
- expression2_closure_type e2_;
- };
-
- template<class E1, class E2, class F>
- struct matrix_binary_scalar1_traits {
- typedef matrix_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type
+ typename self_type::
+#endif
+ const_reverse_iterator1 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_iterator22_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cbegin2 () const {
+ return begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cend2 () const {
+ return end2 ();
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin1 () const {
+ return rbegin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crend1 () const {
+ return rend1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin2 () const {
+ return rbegin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crend2 () const {
+ return rend2 ();
+ }
+
+private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+};
+
+template<class E1, class E2, class F>
+struct matrix_binary_scalar1_traits {
+ typedef matrix_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- typedef typename E2::matrix_temporary_type result_type;
-#endif
- };
-
- // (t * m) [i] [j] = t * m [i] [j]
- template<class T1, class E2>
- BOOST_UBLAS_INLINE
- typename enable_if< is_convertible<T1, typename E2::value_type >,
- typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
- >::type
- operator * (const T1 &e1,
- const matrix_expression<E2> &e2) {
- typedef typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
- return expression_type (e1, e2 ());
- }
-
-
- template<class E1, class E2, class F>
- class matrix_binary_scalar2:
- public matrix_expression<matrix_binary_scalar2<E1, E2, F> > {
-
- typedef E1 expression1_type;
- typedef E2 expression2_type;
- typedef F functor_type;
- public:
- typedef typename E1::const_closure_type expression1_closure_type;
- typedef const E2& expression2_closure_type;
- private:
- typedef matrix_binary_scalar2<E1, E2, F> self_type;
- public:
+ typedef typename E2::matrix_temporary_type result_type;
+#endif
+};
+
+// (t * m) [i] [j] = t * m [i] [j]
+template<class T1, class E2>
+BOOST_UBLAS_INLINE
+typename boost::enable_if< is_convertible<T1, typename E2::value_type >,
+typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
+>::type
+operator * (const T1 &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1, e2 ());
+}
+
+
+template<class E1, class E2, class F>
+class matrix_binary_scalar2:
+ public matrix_expression<matrix_binary_scalar2<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef const E2& expression2_closure_type;
+private:
+ typedef matrix_binary_scalar2<E1, E2, F> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using matrix_expression<self_type>::operator ();
-#endif
- typedef typename E1::size_type size_type;
- typedef typename E1::difference_type difference_type;
- typedef typename F::result_type value_type;
- typedef value_type const_reference;
- typedef const_reference reference;
-
- typedef const self_type const_closure_type;
- typedef const_closure_type closure_type;
- typedef typename E1::orientation_category orientation_category;
- typedef unknown_storage_tag storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
- e1_ (e1), e2_ (e2) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size1 () const {
- return e1_.size1 ();
- }
- BOOST_UBLAS_INLINE
- size_type size2 () const {
- return e1_.size2 ();
- }
-
- public:
- // Element access
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type i, size_type j) const {
- return functor_type::apply (e1_ (i, j), expression2_type (e2_));
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const matrix_binary_scalar2 &mbs2) const {
- return (*this).e1_.same_closure (mbs2.e1_) &&
- &e2_ == &(mbs2.e2_);
- }
-
- // Iterator types
- private:
- typedef typename E1::const_iterator1 const_iterator11_type;
- typedef typename E1::const_iterator2 const_iterator12_type;
- typedef expression2_type const_subiterator2_type;
- typedef const value_type *const_pointer;
-
- public:
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E1::size_type size_type;
+ typedef typename E1::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef typename E1::orientation_category orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e1_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e1_.size2 ();
+ }
+
+public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e1_ (i, j), expression2_type (e2_));
+ }
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e1_ (i), expression2_type (e2_));
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_binary_scalar2 &mbs2) const {
+ return (*this).e1_.same_closure (mbs2.e1_) &&
+ &e2_ == &(mbs2.e2_);
+ }
+
+ // Iterator types
+private:
+ typedef typename E1::const_iterator1 const_iterator11_type;
+ typedef typename E1::const_iterator2 const_iterator12_type;
+ typedef expression2_type const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- typedef indexed_const_iterator1<const_closure_type, typename const_iterator11_type::iterator_category> const_iterator1;
- typedef const_iterator1 iterator1;
- typedef indexed_const_iterator2<const_closure_type, typename const_iterator12_type::iterator_category> const_iterator2;
- typedef const_iterator2 iterator2;
+ typedef indexed_const_iterator1<const_closure_type, typename const_iterator11_type::iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, typename const_iterator12_type::iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
#else
- class const_iterator1;
- typedef const_iterator1 iterator1;
- class const_iterator2;
- typedef const_iterator2 iterator2;
-#endif
- typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
- typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
-
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator1 find1 (int rank, size_type i, size_type j) const {
- const_iterator11_type it11 (e1_.find1 (rank, i, j));
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_iterator11_type it11 (e1_.find1 (rank, i, j));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator1 (*this, it11.index1 (), it11.index2 ());
+ return const_iterator1 (*this, it11.index1 (), it11.index2 ());
#else
- return const_iterator1 (*this, it11, const_subiterator2_type (e2_));
+ return const_iterator1 (*this, it11, const_subiterator2_type (e2_));
#endif
- }
- BOOST_UBLAS_INLINE
- const_iterator2 find2 (int rank, size_type i, size_type j) const {
- const_iterator12_type it12 (e1_.find2 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_iterator12_type it12 (e1_.find2 (rank, i, j));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator2 (*this, it12.index1 (), it12.index2 ());
+ return const_iterator2 (*this, it12.index1 (), it12.index2 ());
#else
- return const_iterator2 (*this, it12, const_subiterator2_type (e2_));
+ return const_iterator2 (*this, it12, const_subiterator2_type (e2_));
#endif
- }
+ }
- // Iterators enhance the iterators of the referenced expression
- // with the binary functor.
+ // Iterators enhance the iterators of the referenced expression
+ // with the binary functor.
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator1:
- public container_const_reference<matrix_binary_scalar2>,
- public iterator_base_traits<typename E1::const_iterator1::iterator_category>::template
- iterator_base<const_iterator1, value_type>::type {
- public:
- typedef typename E1::const_iterator1::iterator_category iterator_category;
- typedef typename matrix_binary_scalar2::difference_type difference_type;
- typedef typename matrix_binary_scalar2::value_type value_type;
- typedef typename matrix_binary_scalar2::const_reference reference;
- typedef typename matrix_binary_scalar2::const_pointer pointer;
-
- typedef const_iterator2 dual_iterator_type;
- typedef const_reverse_iterator2 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator1 ():
- container_const_reference<self_type> (), it1_ (), it2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2):
- container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator1 &operator ++ () {
- ++ it1_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -- () {
- -- it1_ ;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator += (difference_type n) {
- it1_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -= (difference_type n) {
- it1_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ - it.it1_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return functor_type::apply (*it1_, it2_);
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator1:
+ public container_const_reference<matrix_binary_scalar2>,
+ public iterator_base_traits<typename E1::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename E1::const_iterator1::iterator_category iterator_category;
+ typedef typename matrix_binary_scalar2::difference_type difference_type;
+ typedef typename matrix_binary_scalar2::value_type value_type;
+ typedef typename matrix_binary_scalar2::const_reference reference;
+ typedef typename matrix_binary_scalar2::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_ ;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 begin () const {
- return (*this) ().find2 (1, index1 (), 0);
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 end () const {
- return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rbegin () const {
- return const_reverse_iterator2 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rend () const {
- return const_reverse_iterator2 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator2 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it1_.index1 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it1_.index2 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator1 &operator = (const const_iterator1 &it) {
- container_const_reference<self_type>::assign (&it ());
- it1_ = it.it1_;
- it2_ = it.it2_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ == it.it1_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ < it.it1_;
- }
-
- private:
- const_iterator11_type it1_;
- const_subiterator2_type it2_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator1 begin1 () const {
- return find1 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cbegin1 () const {
- return begin1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 end1 () const {
- return find1 (0, size1 (), 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cend1 () const {
- return end1 ();
- }
+ typename self_type::
+#endif
+ const_reverse_iterator2 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_iterator11_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cbegin1 () const {
+ return begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cend1 () const {
+ return end1 ();
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator2:
- public container_const_reference<matrix_binary_scalar2>,
- public iterator_base_traits<typename E1::const_iterator2::iterator_category>::template
- iterator_base<const_iterator2, value_type>::type {
- public:
- typedef typename E1::const_iterator2::iterator_category iterator_category;
- typedef typename matrix_binary_scalar2::difference_type difference_type;
- typedef typename matrix_binary_scalar2::value_type value_type;
- typedef typename matrix_binary_scalar2::const_reference reference;
- typedef typename matrix_binary_scalar2::const_pointer pointer;
-
- typedef const_iterator1 dual_iterator_type;
- typedef const_reverse_iterator1 dual_reverse_iterator_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- const_iterator2 ():
- container_const_reference<self_type> (), it1_ (), it2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2):
- container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
-
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator2 &operator ++ () {
- ++ it1_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -- () {
- -- it1_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator += (difference_type n) {
- it1_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -= (difference_type n) {
- it1_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ - it.it1_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return functor_type::apply (*it1_, it2_);
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ class const_iterator2:
+ public container_const_reference<matrix_binary_scalar2>,
+ public iterator_base_traits<typename E1::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename E1::const_iterator2::iterator_category iterator_category;
+ typedef typename matrix_binary_scalar2::difference_type difference_type;
+ typedef typename matrix_binary_scalar2::value_type value_type;
+ typedef typename matrix_binary_scalar2::const_reference reference;
+ typedef typename matrix_binary_scalar2::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 begin () const {
- return (*this) ().find1 (1, 0, index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 end () const {
- return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rbegin () const {
- return const_reverse_iterator1 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rend () const {
- return const_reverse_iterator1 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator1 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it1_.index1 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it1_.index2 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator2 &operator = (const const_iterator2 &it) {
- container_const_reference<self_type>::assign (&it ());
- it1_ = it.it1_;
- it2_ = it.it2_;
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ == it.it1_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- // FIXME we shouldn't compare floats
- // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ < it.it1_;
- }
-
- private:
- const_iterator12_type it1_;
- const_subiterator2_type it2_;
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator2 begin2 () const {
- return find2 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cbegin2 () const {
- return begin2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 end2 () const {
- return find2 (0, 0, size2 ());
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cend2 () const {
- return end2 ();
- }
-
- // Reverse iterators
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rbegin1 () const {
- return const_reverse_iterator1 (end1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crbegin1 () const {
- return rbegin1 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rend1 () const {
- return const_reverse_iterator1 (begin1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crend1 () const {
- return rend1 ();
- }
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rbegin2 () const {
- return const_reverse_iterator2 (end2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crbegin2 () const {
- return rbegin2 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rend2 () const {
- return const_reverse_iterator2 (begin2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crend2 () const {
- return rend2 ();
- }
-
- private:
- expression1_closure_type e1_;
- expression2_closure_type e2_;
- };
-
- template<class E1, class E2, class F>
- struct matrix_binary_scalar2_traits {
- typedef matrix_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type
+ typename self_type::
+#endif
+ const_reverse_iterator1 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_iterator12_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cbegin2 () const {
+ return begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cend2 () const {
+ return end2 ();
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin1 () const {
+ return rbegin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crend1 () const {
+ return rend1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin2 () const {
+ return rbegin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crend2 () const {
+ return rend2 ();
+ }
+
+private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+};
+
+template<class E1, class E2, class F>
+struct matrix_binary_scalar2_traits {
+ typedef matrix_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- typedef typename E1::matrix_temporary_type result_type;
-#endif
- };
-
- // (m * t) [i] [j] = m [i] [j] * t
- template<class E1, class T2>
- BOOST_UBLAS_INLINE
- typename enable_if< is_convertible<T2, typename E1::value_type>,
- typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
- >::type
- operator * (const matrix_expression<E1> &e1,
- const T2 &e2) {
- typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
- return expression_type (e1 (), e2);
- }
-
- // (m / t) [i] [j] = m [i] [j] / t
- template<class E1, class T2>
- BOOST_UBLAS_INLINE
- typename enable_if< is_convertible<T2, typename E1::value_type>,
- typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
- >::type
- operator / (const matrix_expression<E1> &e1,
- const T2 &e2) {
- typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
- return expression_type (e1 (), e2);
- }
-
-
- template<class E1, class E2, class F>
- class matrix_vector_binary1:
- public vector_expression<matrix_vector_binary1<E1, E2, F> > {
-
- public:
- typedef E1 expression1_type;
- typedef E2 expression2_type;
- private:
- typedef F functor_type;
- public:
- typedef typename E1::const_closure_type expression1_closure_type;
- typedef typename E2::const_closure_type expression2_closure_type;
- private:
- typedef matrix_vector_binary1<E1, E2, F> self_type;
- public:
+ typedef typename E1::matrix_temporary_type result_type;
+#endif
+};
+
+// (m * t) [i] [j] = m [i] [j] * t
+template<class E1, class T2>
+BOOST_UBLAS_INLINE
+typename boost::enable_if< is_convertible<T2, typename E1::value_type>,
+typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
+>::type
+operator * (const matrix_expression<E1> &e1,
+ const T2 &e2) {
+ typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
+ return expression_type (e1 (), e2);
+}
+
+// (m / t) [i] [j] = m [i] [j] / t
+template<class E1, class T2>
+BOOST_UBLAS_INLINE
+typename boost::enable_if< is_convertible<T2, typename E1::value_type>,
+typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
+>::type
+operator / (const matrix_expression<E1> &e1,
+ const T2 &e2) {
+ typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
+ return expression_type (e1 (), e2);
+}
+
+
+template<class E1, class E2, class F>
+class matrix_vector_binary1:
+ public vector_expression<matrix_vector_binary1<E1, E2, F> > {
+
+public:
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+private:
+ typedef F functor_type;
+public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+private:
+ typedef matrix_vector_binary1<E1, E2, F> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using vector_expression<self_type>::operator ();
-#endif
- static const unsigned complexity = 1;
- typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
- typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
- typedef typename F::result_type value_type;
- typedef value_type const_reference;
- typedef const_reference reference;
- typedef const self_type const_closure_type;
- typedef const_closure_type closure_type;
- typedef unknown_storage_tag storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2):
- e1_ (e1), e2_ (e2) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size () const {
- return e1_.size1 ();
- }
-
- public:
- // Expression accessors
- BOOST_UBLAS_INLINE
- const expression1_closure_type &expression1 () const {
- return e1_;
- }
- BOOST_UBLAS_INLINE
- const expression2_closure_type &expression2 () const {
- return e2_;
- }
-
- public:
- // Element access
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type i) const {
- return functor_type::apply (e1_, e2_, i);
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const matrix_vector_binary1 &mvb1) const {
- return (*this).expression1 ().same_closure (mvb1.expression1 ()) &&
- (*this).expression2 ().same_closure (mvb1.expression2 ());
- }
-
- // Iterator types
- private:
- typedef typename E1::const_iterator1 const_subiterator1_type;
- typedef typename E2::const_iterator const_subiterator2_type;
- typedef const value_type *const_pointer;
-
- public:
+ using vector_expression<self_type>::operator ();
+#endif
+ static const unsigned complexity = 1;
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return e1_.size1 ();
+ }
+
+public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e1_, e2_, i);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_vector_binary1 &mvb1) const {
+ return (*this).expression1 ().same_closure (mvb1.expression1 ()) &&
+ (*this).expression2 ().same_closure (mvb1.expression2 ());
+ }
+
+ // Iterator types
+private:
+ typedef typename E1::const_iterator1 const_subiterator1_type;
+ typedef typename E2::const_iterator const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- typedef indexed_const_iterator<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator;
- typedef const_iterator iterator;
+ typedef indexed_const_iterator<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator;
+ typedef const_iterator iterator;
#else
- class const_iterator;
- typedef const_iterator iterator;
+ class const_iterator;
+ typedef const_iterator iterator;
#endif
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator find (size_type i) const {
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- const_subiterator1_type it1 (e1_.find1 (0, i, 0));
- return const_iterator (*this, it1.index1 ());
+ const_subiterator1_type it1 (e1_.find1 (0, i, 0));
+ return const_iterator (*this, it1.index1 ());
#else
- return const_iterator (*this, e1_.find1 (0, i, 0));
+ return const_iterator (*this, e1_.find1 (0, i, 0));
#endif
- }
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator:
- public container_const_reference<matrix_vector_binary1>,
- public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
- typename E2::const_iterator::iterator_category>::iterator_category>::template
- iterator_base<const_iterator, value_type>::type {
- public:
- typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
- typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
- typedef typename matrix_vector_binary1::difference_type difference_type;
- typedef typename matrix_vector_binary1::value_type value_type;
- typedef typename matrix_vector_binary1::const_reference reference;
- typedef typename matrix_vector_binary1::const_pointer pointer;
-
- // Construction and destruction
+ class const_iterator:
+ public container_const_reference<matrix_vector_binary1>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_vector_binary1::difference_type difference_type;
+ typedef typename matrix_vector_binary1::value_type value_type;
+ typedef typename matrix_vector_binary1::const_reference reference;
+ typedef typename matrix_vector_binary1::const_pointer pointer;
+
+ // Construction and destruction
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- BOOST_UBLAS_INLINE
- const_iterator ():
- container_const_reference<self_type> (), it1_ (), e2_begin_ (), e2_end_ () {}
- BOOST_UBLAS_INLINE
- const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
- container_const_reference<self_type> (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {}
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it1_ (), e2_begin_ (), e2_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
+ container_const_reference<self_type> (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {}
#else
- BOOST_UBLAS_INLINE
- const_iterator ():
- container_const_reference<self_type> (), it1_ () {}
- BOOST_UBLAS_INLINE
- const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
- container_const_reference<self_type> (mvb), it1_ (it1) {}
-#endif
-
- private:
- // Dense random access specialization
- BOOST_UBLAS_INLINE
- value_type dereference (dense_random_access_iterator_tag) const {
- const self_type &mvb = (*this) ();
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it1_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
+ container_const_reference<self_type> (mvb), it1_ (it1) {}
+#endif
+
+ private:
+ // Dense random access specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ const self_type &mvb = (*this) ();
#ifdef BOOST_UBLAS_USE_INDEXING
- return mvb (index ());
+ return mvb (index ());
#elif BOOST_UBLAS_USE_ITERATING
- difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
+ difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (size, it1_.begin (), e2_begin_);
+ return functor_type::apply (size, it1_.begin (), e2_begin_);
#else
- return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
+ return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
#endif
#else
- difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
- if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (size, it1_.begin (), e2_begin_);
+ return functor_type::apply (size, it1_.begin (), e2_begin_);
#else
- return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
+ return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
#endif
- else
- return mvb (index ());
+ else
+ return mvb (index ());
#endif
- }
+ }
- // Packed bidirectional specialization
- BOOST_UBLAS_INLINE
- value_type dereference (packed_random_access_iterator_tag) const {
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_);
+ return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_);
#else
- const self_type &mvb = (*this) ();
+ const self_type &mvb = (*this) ();
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- return functor_type::apply (it1_.begin (), it1_.end (),
- mvb.expression2 ().begin (), mvb.expression2 ().end ());
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ mvb.expression2 ().begin (), mvb.expression2 ().end ());
#else
- return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
- boost::numeric::ublas::end (it1_, iterator1_tag ()),
- mvb.expression2 ().begin (), mvb.expression2 ().end ());
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ mvb.expression2 ().begin (), mvb.expression2 ().end ());
#endif
#endif
- }
+ }
- // Sparse bidirectional specialization
- BOOST_UBLAS_INLINE
- value_type dereference (sparse_bidirectional_iterator_tag) const {
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ());
+ return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ());
#else
- const self_type &mvb = (*this) ();
+ const self_type &mvb = (*this) ();
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- return functor_type::apply (it1_.begin (), it1_.end (),
- mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
#else
- return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
- boost::numeric::ublas::end (it1_, iterator1_tag ()),
- mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
-#endif
-#endif
- }
-
- public:
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator &operator ++ () {
- ++ it1_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator &operator -- () {
- -- it1_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator &operator += (difference_type n) {
- it1_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator &operator -= (difference_type n) {
- it1_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it1_ - it.it1_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return dereference (iterator_category ());
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
-
- // Index
- BOOST_UBLAS_INLINE
- size_type index () const {
- return it1_.index1 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator &operator = (const const_iterator &it) {
- container_const_reference<self_type>::assign (&it ());
- it1_ = it.it1_;
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
+#endif
+#endif
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it1_.index1 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- e2_begin_ = it.e2_begin_;
- e2_end_ = it.e2_end_;
-#endif
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it1_ == it.it1_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it1_ < it.it1_;
- }
-
- private:
- const_subiterator1_type it1_;
+ e2_begin_ = it.e2_begin_;
+ e2_end_ = it.e2_end_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- // Mutable due to assignment
- /* const */ const_subiterator2_type e2_begin_;
- /* const */ const_subiterator2_type e2_end_;
-#endif
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator begin () const {
- return find (0);
- }
- BOOST_UBLAS_INLINE
- const_iterator cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
- const_iterator end () const {
- return find (size ());
- }
- BOOST_UBLAS_INLINE
- const_iterator cend () const {
- return end ();
- }
-
- // Reverse iterator
- typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator rbegin () const {
- return const_reverse_iterator (end ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator rend () const {
- return const_reverse_iterator (begin ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator crend () const {
- return rend ();
- }
-
- private:
- expression1_closure_type e1_;
- expression2_closure_type e2_;
- };
-
- template<class T1, class E1, class T2, class E2>
- struct matrix_vector_binary1_traits {
- typedef unknown_storage_tag storage_category;
- typedef row_major_tag orientation_category;
- typedef typename promote_traits<T1, T2>::promote_type promote_type;
- typedef matrix_vector_binary1<E1, E2, matrix_vector_prod1<E1, E2, promote_type> > expression_type;
+ // Mutable due to assignment
+ /* const */ const_subiterator2_type e2_begin_;
+ /* const */ const_subiterator2_type e2_end_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator cend () const {
+ return end ();
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator crend () const {
+ return rend ();
+ }
+
+private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+};
+
+template<class T1, class E1, class T2, class E2>
+struct matrix_vector_binary1_traits {
+ typedef unknown_storage_tag storage_category;
+ typedef row_major_tag orientation_category;
+ typedef typename promote_traits<T1, T2>::promote_type promote_type;
+ typedef matrix_vector_binary1<E1, E2, matrix_vector_prod1<E1, E2, promote_type> > expression_type;
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- typedef typename E1::vector_temporary_type result_type;
-#endif
- };
-
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_vector_binary1_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::result_type
- prod (const matrix_expression<E1> &e1,
- const vector_expression<E2> &e2,
- unknown_storage_tag,
- row_major_tag) {
- typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- // Dispatcher
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_vector_binary1_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::result_type
- prod (const matrix_expression<E1> &e1,
- const vector_expression<E2> &e2) {
- BOOST_STATIC_ASSERT (E2::complexity == 0);
- typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::storage_category storage_category;
- typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::orientation_category orientation_category;
- return prod (e1, e2, storage_category (), orientation_category ());
- }
-
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
- prec_prod (const matrix_expression<E1> &e1,
- const vector_expression<E2> &e2,
- unknown_storage_tag,
- row_major_tag) {
- typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- // Dispatcher
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
- prec_prod (const matrix_expression<E1> &e1,
- const vector_expression<E2> &e2) {
- BOOST_STATIC_ASSERT (E2::complexity == 0);
- typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
- typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
- return prec_prod (e1, e2, storage_category (), orientation_category ());
- }
-
- template<class V, class E1, class E2>
- BOOST_UBLAS_INLINE
- V &
- prod (const matrix_expression<E1> &e1,
- const vector_expression<E2> &e2,
- V &v) {
- return v.assign (prod (e1, e2));
- }
-
- template<class V, class E1, class E2>
- BOOST_UBLAS_INLINE
- V &
- prec_prod (const matrix_expression<E1> &e1,
- const vector_expression<E2> &e2,
- V &v) {
- return v.assign (prec_prod (e1, e2));
- }
-
- template<class V, class E1, class E2>
- BOOST_UBLAS_INLINE
- V
- prod (const matrix_expression<E1> &e1,
- const vector_expression<E2> &e2) {
- return V (prod (e1, e2));
- }
-
- template<class V, class E1, class E2>
- BOOST_UBLAS_INLINE
- V
- prec_prod (const matrix_expression<E1> &e1,
- const vector_expression<E2> &e2) {
- return V (prec_prod (e1, e2));
- }
-
- template<class E1, class E2, class F>
- class matrix_vector_binary2:
- public vector_expression<matrix_vector_binary2<E1, E2, F> > {
-
- typedef E1 expression1_type;
- typedef E2 expression2_type;
- typedef F functor_type;
- public:
- typedef typename E1::const_closure_type expression1_closure_type;
- typedef typename E2::const_closure_type expression2_closure_type;
- private:
- typedef matrix_vector_binary2<E1, E2, F> self_type;
- public:
+ typedef typename E1::vector_temporary_type result_type;
+#endif
+};
+
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+typename E2::value_type, E2>::result_type
+prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ unknown_storage_tag,
+ row_major_tag) {
+ typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+// Dispatcher
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+typename E2::value_type, E2>::result_type
+prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E2::complexity == 0);
+ typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::storage_category storage_category;
+ typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::orientation_category orientation_category;
+ return prod (e1, e2, storage_category (), orientation_category ());
+}
+
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+prec_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ unknown_storage_tag,
+ row_major_tag) {
+ typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+// Dispatcher
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+prec_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E2::complexity == 0);
+ typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
+ typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
+ return prec_prod (e1, e2, storage_category (), orientation_category ());
+}
+
+template<class V, class E1, class E2>
+BOOST_UBLAS_INLINE
+V &
+prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ V &v) {
+ return v.assign (prod (e1, e2));
+}
+
+template<class V, class E1, class E2>
+BOOST_UBLAS_INLINE
+V &
+prec_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ V &v) {
+ return v.assign (prec_prod (e1, e2));
+}
+
+template<class V, class E1, class E2>
+BOOST_UBLAS_INLINE
+V
+prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ return V (prod (e1, e2));
+}
+
+template<class V, class E1, class E2>
+BOOST_UBLAS_INLINE
+V
+prec_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ return V (prec_prod (e1, e2));
+}
+
+template<class E1, class E2, class F>
+class matrix_vector_binary2:
+ public vector_expression<matrix_vector_binary2<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+private:
+ typedef matrix_vector_binary2<E1, E2, F> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using vector_expression<self_type>::operator ();
-#endif
- static const unsigned complexity = 1;
- typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
- typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
- typedef typename F::result_type value_type;
- typedef value_type const_reference;
- typedef const_reference reference;
- typedef const self_type const_closure_type;
- typedef const_closure_type closure_type;
- typedef unknown_storage_tag storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2):
- e1_ (e1), e2_ (e2) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size () const {
- return e2_.size2 ();
- }
-
- public:
- // Expression accessors
- BOOST_UBLAS_INLINE
- const expression1_closure_type &expression1 () const {
- return e1_;
- }
- BOOST_UBLAS_INLINE
- const expression2_closure_type &expression2 () const {
- return e2_;
- }
- public:
-
- // Element access
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type j) const {
- return functor_type::apply (e1_, e2_, j);
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const matrix_vector_binary2 &mvb2) const {
- return (*this).expression1 ().same_closure (mvb2.expression1 ()) &&
- (*this).expression2 ().same_closure (mvb2.expression2 ());
- }
-
- // Iterator types
- private:
- typedef typename E1::const_iterator const_subiterator1_type;
- typedef typename E2::const_iterator2 const_subiterator2_type;
- typedef const value_type *const_pointer;
-
- public:
+ using vector_expression<self_type>::operator ();
+#endif
+ static const unsigned complexity = 1;
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return e2_.size2 ();
+ }
+
+public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+public:
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type j) const {
+ return functor_type::apply (e1_, e2_, j);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_vector_binary2 &mvb2) const {
+ return (*this).expression1 ().same_closure (mvb2.expression1 ()) &&
+ (*this).expression2 ().same_closure (mvb2.expression2 ());
+ }
+
+ // Iterator types
+private:
+ typedef typename E1::const_iterator const_subiterator1_type;
+ typedef typename E2::const_iterator2 const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
- typedef const_iterator iterator;
+ typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
+ typedef const_iterator iterator;
#else
- class const_iterator;
- typedef const_iterator iterator;
+ class const_iterator;
+ typedef const_iterator iterator;
#endif
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator find (size_type j) const {
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type j) const {
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- const_subiterator2_type it2 (e2_.find2 (0, 0, j));
- return const_iterator (*this, it2.index2 ());
+ const_subiterator2_type it2 (e2_.find2 (0, 0, j));
+ return const_iterator (*this, it2.index2 ());
#else
- return const_iterator (*this, e2_.find2 (0, 0, j));
+ return const_iterator (*this, e2_.find2 (0, 0, j));
#endif
- }
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator:
- public container_const_reference<matrix_vector_binary2>,
- public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
- typename E2::const_iterator2::iterator_category>::iterator_category>::template
- iterator_base<const_iterator, value_type>::type {
- public:
- typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
- typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
- typedef typename matrix_vector_binary2::difference_type difference_type;
- typedef typename matrix_vector_binary2::value_type value_type;
- typedef typename matrix_vector_binary2::const_reference reference;
- typedef typename matrix_vector_binary2::const_pointer pointer;
-
- // Construction and destruction
+ class const_iterator:
+ public container_const_reference<matrix_vector_binary2>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_vector_binary2::difference_type difference_type;
+ typedef typename matrix_vector_binary2::value_type value_type;
+ typedef typename matrix_vector_binary2::const_reference reference;
+ typedef typename matrix_vector_binary2::const_pointer pointer;
+
+ // Construction and destruction
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- BOOST_UBLAS_INLINE
- const_iterator ():
- container_const_reference<self_type> (), it2_ (), e1_begin_ (), e1_end_ () {}
- BOOST_UBLAS_INLINE
- const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
- container_const_reference<self_type> (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {}
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it2_ (), e1_begin_ (), e1_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {}
#else
- BOOST_UBLAS_INLINE
- const_iterator ():
- container_const_reference<self_type> (), it2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
- container_const_reference<self_type> (mvb), it2_ (it2) {}
-#endif
-
- private:
- // Dense random access specialization
- BOOST_UBLAS_INLINE
- value_type dereference (dense_random_access_iterator_tag) const {
- const self_type &mvb = (*this) ();
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mvb), it2_ (it2) {}
+#endif
+
+ private:
+ // Dense random access specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ const self_type &mvb = (*this) ();
#ifdef BOOST_UBLAS_USE_INDEXING
- return mvb (index ());
+ return mvb (index ());
#elif BOOST_UBLAS_USE_ITERATING
- difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
+ difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (size, e1_begin_, it2_.begin ());
+ return functor_type::apply (size, e1_begin_, it2_.begin ());
#else
- return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
+ return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
#endif
#else
- difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
- if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (size, e1_begin_, it2_.begin ());
+ return functor_type::apply (size, e1_begin_, it2_.begin ());
#else
- return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
+ return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
#endif
- else
- return mvb (index ());
+ else
+ return mvb (index ());
#endif
- }
+ }
- // Packed bidirectional specialization
- BOOST_UBLAS_INLINE
- value_type dereference (packed_random_access_iterator_tag) const {
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ());
+ return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ());
#else
- const self_type &mvb = (*this) ();
+ const self_type &mvb = (*this) ();
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
- it2_.begin (), it2_.end ());
+ return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
+ it2_.begin (), it2_.end ());
#else
- return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
- boost::numeric::ublas::begin (it2_, iterator2_tag ()),
- boost::numeric::ublas::end (it2_, iterator2_tag ()));
+ return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()));
#endif
#endif
- }
+ }
- // Sparse bidirectional specialization
- BOOST_UBLAS_INLINE
- value_type dereference (sparse_bidirectional_iterator_tag) const {
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+ return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
#else
- const self_type &mvb = (*this) ();
+ const self_type &mvb = (*this) ();
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
- it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+ return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
+ it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
#else
- return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
- boost::numeric::ublas::begin (it2_, iterator2_tag ()),
- boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
-#endif
-#endif
- }
-
- public:
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator &operator ++ () {
- ++ it2_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator &operator -- () {
- -- it2_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator &operator += (difference_type n) {
- it2_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator &operator -= (difference_type n) {
- it2_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it2_ - it.it2_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return dereference (iterator_category ());
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
-
- // Index
- BOOST_UBLAS_INLINE
- size_type index () const {
- return it2_.index2 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator &operator = (const const_iterator &it) {
- container_const_reference<self_type>::assign (&it ());
- it2_ = it.it2_;
+ return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
+#endif
+#endif
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it2_ = it.it2_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- e1_begin_ = it.e1_begin_;
- e1_end_ = it.e1_end_;
-#endif
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it2_ == it.it2_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- return it2_ < it.it2_;
- }
-
- private:
- const_subiterator2_type it2_;
+ e1_begin_ = it.e1_begin_;
+ e1_end_ = it.e1_end_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator2_type it2_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- // Mutable due to assignment
- /* const */ const_subiterator1_type e1_begin_;
- /* const */ const_subiterator1_type e1_end_;
-#endif
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator begin () const {
- return find (0);
- }
- BOOST_UBLAS_INLINE
- const_iterator cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
- const_iterator end () const {
- return find (size ());
- }
- BOOST_UBLAS_INLINE
- const_iterator cend () const {
- return end ();
- }
-
- // Reverse iterator
- typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator rbegin () const {
- return const_reverse_iterator (end ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator rend () const {
- return const_reverse_iterator (begin ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator crend () const {
- return rend ();
- }
-
- private:
- expression1_closure_type e1_;
- expression2_closure_type e2_;
- };
-
- template<class T1, class E1, class T2, class E2>
- struct matrix_vector_binary2_traits {
- typedef unknown_storage_tag storage_category;
- typedef column_major_tag orientation_category;
- typedef typename promote_traits<T1, T2>::promote_type promote_type;
- typedef matrix_vector_binary2<E1, E2, matrix_vector_prod2<E1, E2, promote_type> > expression_type;
+ // Mutable due to assignment
+ /* const */ const_subiterator1_type e1_begin_;
+ /* const */ const_subiterator1_type e1_end_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator cend () const {
+ return end ();
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator crend () const {
+ return rend ();
+ }
+
+private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+};
+
+template<class T1, class E1, class T2, class E2>
+struct matrix_vector_binary2_traits {
+ typedef unknown_storage_tag storage_category;
+ typedef column_major_tag orientation_category;
+ typedef typename promote_traits<T1, T2>::promote_type promote_type;
+ typedef matrix_vector_binary2<E1, E2, matrix_vector_prod2<E1, E2, promote_type> > expression_type;
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- typedef typename E2::vector_temporary_type result_type;
-#endif
- };
-
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_vector_binary2_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::result_type
- prod (const vector_expression<E1> &e1,
- const matrix_expression<E2> &e2,
- unknown_storage_tag,
- column_major_tag) {
- typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- // Dispatcher
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_vector_binary2_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::result_type
- prod (const vector_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- BOOST_STATIC_ASSERT (E1::complexity == 0);
- typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::storage_category storage_category;
- typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::orientation_category orientation_category;
- return prod (e1, e2, storage_category (), orientation_category ());
- }
-
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
- prec_prod (const vector_expression<E1> &e1,
- const matrix_expression<E2> &e2,
- unknown_storage_tag,
- column_major_tag) {
- typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- // Dispatcher
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
- prec_prod (const vector_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- BOOST_STATIC_ASSERT (E1::complexity == 0);
- typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
- typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
- return prec_prod (e1, e2, storage_category (), orientation_category ());
- }
-
- template<class V, class E1, class E2>
- BOOST_UBLAS_INLINE
- V &
- prod (const vector_expression<E1> &e1,
- const matrix_expression<E2> &e2,
- V &v) {
- return v.assign (prod (e1, e2));
- }
-
- template<class V, class E1, class E2>
- BOOST_UBLAS_INLINE
- V &
- prec_prod (const vector_expression<E1> &e1,
- const matrix_expression<E2> &e2,
- V &v) {
- return v.assign (prec_prod (e1, e2));
- }
-
- template<class V, class E1, class E2>
- BOOST_UBLAS_INLINE
- V
- prod (const vector_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- return V (prod (e1, e2));
- }
-
- template<class V, class E1, class E2>
- BOOST_UBLAS_INLINE
- V
- prec_prod (const vector_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- return V (prec_prod (e1, e2));
- }
-
- template<class E1, class E2, class F>
- class matrix_matrix_binary:
- public matrix_expression<matrix_matrix_binary<E1, E2, F> > {
-
- public:
- typedef E1 expression1_type;
- typedef E2 expression2_type;
- private:
- typedef F functor_type;
- public:
- typedef typename E1::const_closure_type expression1_closure_type;
- typedef typename E2::const_closure_type expression2_closure_type;
- private:
- typedef matrix_matrix_binary<E1, E2, F> self_type;
- public:
+ typedef typename E2::vector_temporary_type result_type;
+#endif
+};
+
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+typename E2::value_type, E2>::result_type
+prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ unknown_storage_tag,
+ column_major_tag) {
+ typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+// Dispatcher
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+typename E2::value_type, E2>::result_type
+prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0);
+ typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::storage_category storage_category;
+ typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::orientation_category orientation_category;
+ return prod (e1, e2, storage_category (), orientation_category ());
+}
+
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+prec_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ unknown_storage_tag,
+ column_major_tag) {
+ typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+// Dispatcher
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+prec_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0);
+ typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
+ typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
+ return prec_prod (e1, e2, storage_category (), orientation_category ());
+}
+
+template<class V, class E1, class E2>
+BOOST_UBLAS_INLINE
+V &
+prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ V &v) {
+ return v.assign (prod (e1, e2));
+}
+
+template<class V, class E1, class E2>
+BOOST_UBLAS_INLINE
+V &
+prec_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ V &v) {
+ return v.assign (prec_prod (e1, e2));
+}
+
+template<class V, class E1, class E2>
+BOOST_UBLAS_INLINE
+V
+prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ return V (prod (e1, e2));
+}
+
+template<class V, class E1, class E2>
+BOOST_UBLAS_INLINE
+V
+prec_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ return V (prec_prod (e1, e2));
+}
+
+template<class E1, class E2, class F>
+class matrix_matrix_binary:
+ public matrix_expression<matrix_matrix_binary<E1, E2, F> > {
+
+public:
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+private:
+ typedef F functor_type;
+public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+private:
+ typedef matrix_matrix_binary<E1, E2, F> self_type;
+public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
- using matrix_expression<self_type>::operator ();
-#endif
- static const unsigned complexity = 1;
- typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
- typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
- typedef typename F::result_type value_type;
- typedef value_type const_reference;
- typedef const_reference reference;
- typedef const self_type const_closure_type;
- typedef const_closure_type closure_type;
- typedef unknown_orientation_tag orientation_category;
- typedef unknown_storage_tag storage_category;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2):
- e1_ (e1), e2_ (e2) {}
-
- // Accessors
- BOOST_UBLAS_INLINE
- size_type size1 () const {
- return e1_.size1 ();
- }
- BOOST_UBLAS_INLINE
- size_type size2 () const {
- return e2_.size2 ();
- }
-
- public:
- // Expression accessors
- BOOST_UBLAS_INLINE
- const expression1_closure_type &expression1 () const {
- return e1_;
- }
- BOOST_UBLAS_INLINE
- const expression2_closure_type &expression2 () const {
- return e2_;
- }
-
- public:
- // Element access
- BOOST_UBLAS_INLINE
- const_reference operator () (size_type i, size_type j) const {
- return functor_type::apply (e1_, e2_, i, j);
- }
-
- // Closure comparison
- BOOST_UBLAS_INLINE
- bool same_closure (const matrix_matrix_binary &mmb) const {
- return (*this).expression1 ().same_closure (mmb.expression1 ()) &&
- (*this).expression2 ().same_closure (mmb.expression2 ());
- }
-
- // Iterator types
- private:
- typedef typename E1::const_iterator1 const_iterator11_type;
- typedef typename E1::const_iterator2 const_iterator12_type;
- typedef typename E2::const_iterator1 const_iterator21_type;
- typedef typename E2::const_iterator2 const_iterator22_type;
- typedef const value_type *const_pointer;
-
- public:
+ using matrix_expression<self_type>::operator ();
+#endif
+ static const unsigned complexity = 1;
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_orientation_tag orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e1_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e2_.size2 ();
+ }
+
+public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e1_, e2_, i, j);
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e1_, e2_, i);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_matrix_binary &mmb) const {
+ return (*this).expression1 ().same_closure (mmb.expression1 ()) &&
+ (*this).expression2 ().same_closure (mmb.expression2 ());
+ }
+
+ // Iterator types
+private:
+ typedef typename E1::const_iterator1 const_iterator11_type;
+ typedef typename E1::const_iterator2 const_iterator12_type;
+ typedef typename E2::const_iterator1 const_iterator21_type;
+ typedef typename E2::const_iterator2 const_iterator22_type;
+ typedef const value_type *const_pointer;
+
+public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
- typename const_iterator22_type::iterator_category>::iterator_category iterator_category;
- typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
- typedef const_iterator1 iterator1;
- typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
- typedef const_iterator2 iterator2;
+ typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
+ typename const_iterator22_type::iterator_category>::iterator_category iterator_category;
+ typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
#else
- class const_iterator1;
- typedef const_iterator1 iterator1;
- class const_iterator2;
- typedef const_iterator2 iterator2;
-#endif
- typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
- typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
-
- // Element lookup
- BOOST_UBLAS_INLINE
- const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
- // FIXME sparse matrix tests fail!
- // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
- const_iterator11_type it11 (e1_.find1 (0, i, 0));
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
+ // FIXME sparse matrix tests fail!
+ // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
+ const_iterator11_type it11 (e1_.find1 (0, i, 0));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator1 (*this, it11.index1 (), j);
+ return const_iterator1 (*this, it11.index1 (), j);
#else
- // FIXME sparse matrix tests fail!
- // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
- const_iterator22_type it22 (e2_.find2 (0, 0, j));
- return const_iterator1 (*this, it11, it22);
-#endif
- }
- BOOST_UBLAS_INLINE
- const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
- // FIXME sparse matrix tests fail!
- // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
- const_iterator22_type it22 (e2_.find2 (0, 0, j));
+ // FIXME sparse matrix tests fail!
+ // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
+ const_iterator22_type it22 (e2_.find2 (0, 0, j));
+ return const_iterator1 (*this, it11, it22);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
+ // FIXME sparse matrix tests fail!
+ // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
+ const_iterator22_type it22 (e2_.find2 (0, 0, j));
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
- return const_iterator2 (*this, i, it22.index2 ());
+ return const_iterator2 (*this, i, it22.index2 ());
#else
- // FIXME sparse matrix tests fail!
- // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
- const_iterator11_type it11 (e1_.find1 (0, i, 0));
- return const_iterator2 (*this, it11, it22);
+ // FIXME sparse matrix tests fail!
+ // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
+ const_iterator11_type it11 (e1_.find1 (0, i, 0));
+ return const_iterator2 (*this, it11, it22);
#endif
- }
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator1:
- public container_const_reference<matrix_matrix_binary>,
- public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
- typename E2::const_iterator2::iterator_category>::iterator_category>::template
- iterator_base<const_iterator1, value_type>::type {
- public:
- typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
- typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
- typedef typename matrix_matrix_binary::difference_type difference_type;
- typedef typename matrix_matrix_binary::value_type value_type;
- typedef typename matrix_matrix_binary::const_reference reference;
- typedef typename matrix_matrix_binary::const_pointer pointer;
-
- typedef const_iterator2 dual_iterator_type;
- typedef const_reverse_iterator2 dual_reverse_iterator_type;
-
- // Construction and destruction
+ class const_iterator1:
+ public container_const_reference<matrix_matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_matrix_binary::difference_type difference_type;
+ typedef typename matrix_matrix_binary::value_type value_type;
+ typedef typename matrix_matrix_binary::const_reference reference;
+ typedef typename matrix_matrix_binary::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- BOOST_UBLAS_INLINE
- const_iterator1 ():
- container_const_reference<self_type> (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {}
- BOOST_UBLAS_INLINE
- const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
- container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {}
#else
- BOOST_UBLAS_INLINE
- const_iterator1 ():
- container_const_reference<self_type> (), it1_ (), it2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
- container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
-#endif
-
- private:
- // Random access specialization
- BOOST_UBLAS_INLINE
- value_type dereference (dense_random_access_iterator_tag) const {
- const self_type &mmb = (*this) ();
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
+#endif
+
+ private:
+ // Random access specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ const self_type &mmb = (*this) ();
#ifdef BOOST_UBLAS_USE_INDEXING
- return mmb (index1 (), index2 ());
+ return mmb (index1 (), index2 ());
#elif BOOST_UBLAS_USE_ITERATING
- difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
+ difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (size, it1_.begin (), it2_begin_);
+ return functor_type::apply (size, it1_.begin (), it2_begin_);
#else
- return functor_type::apply (size, it1_.begin (), it2_.begin ());
+ return functor_type::apply (size, it1_.begin (), it2_.begin ());
#endif
#else
- difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
- if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (size, it1_.begin (), it2_begin_);
+ return functor_type::apply (size, it1_.begin (), it2_begin_);
#else
- return functor_type::apply (size, it1_.begin (), it2_.begin ());
+ return functor_type::apply (size, it1_.begin (), it2_.begin ());
#endif
- else
- return mmb (index1 (), index2 ());
+ else
+ return mmb (index1 (), index2 ());
#endif
- }
+ }
- // Packed bidirectional specialization
- BOOST_UBLAS_INLINE
- value_type dereference (packed_random_access_iterator_tag) const {
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (it1_.begin (), it1_.end (),
- it2_begin_, it2_end_, packed_random_access_iterator_tag ());
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_begin_, it2_end_, packed_random_access_iterator_tag ());
#else
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- return functor_type::apply (it1_.begin (), it1_.end (),
- it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
#else
- return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
- boost::numeric::ublas::end (it1_, iterator1_tag ()),
- boost::numeric::ublas::begin (it2_, iterator2_tag ()),
- boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
#endif
#endif
- }
+ }
- // Sparse bidirectional specialization
- BOOST_UBLAS_INLINE
- value_type dereference (sparse_bidirectional_iterator_tag) const {
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (it1_.begin (), it1_.end (),
- it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ());
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ());
#else
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- return functor_type::apply (it1_.begin (), it1_.end (),
- it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
#else
- return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
- boost::numeric::ublas::end (it1_, iterator1_tag ()),
- boost::numeric::ublas::begin (it2_, iterator2_tag ()),
- boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
-#endif
-#endif
- }
-
- public:
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator1 &operator ++ () {
- ++ it1_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -- () {
- -- it1_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator += (difference_type n) {
- it1_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator1 &operator -= (difference_type n) {
- it1_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ - it.it1_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return dereference (iterator_category ());
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
+#endif
+#endif
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 begin () const {
- return (*this) ().find2 (1, index1 (), 0);
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 end () const {
- return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator2 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator2 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rbegin () const {
- return const_reverse_iterator2 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator2 rend () const {
- return const_reverse_iterator2 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator2 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it1_.index1 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it2_.index2 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator1 &operator = (const const_iterator1 &it) {
- container_const_reference<self_type>::assign (&it ());
- it1_ = it.it1_;
- it2_ = it.it2_;
+ typename self_type::
+#endif
+ const_reverse_iterator2 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- it2_begin_ = it.it2_begin_;
- it2_end_ = it.it2_end_;
-#endif
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ == it.it1_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator1 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
- return it1_ < it.it1_;
- }
-
- private:
- const_iterator11_type it1_;
- // Mutable due to assignment
- /* const */ const_iterator22_type it2_;
+ it2_begin_ = it.it2_begin_;
+ it2_end_ = it.it2_end_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_iterator11_type it1_;
+ // Mutable due to assignment
+ /* const */ const_iterator22_type it2_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- /* const */ const_iterator21_type it2_begin_;
- /* const */ const_iterator21_type it2_end_;
-#endif
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator1 begin1 () const {
- return find1 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cbegin1 () const {
- return begin1 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator1 end1 () const {
- return find1 (0, size1 (), 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator1 cend1 () const {
- return end1 ();
- }
+ /* const */ const_iterator21_type it2_begin_;
+ /* const */ const_iterator21_type it2_end_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cbegin1 () const {
+ return begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 cend1 () const {
+ return end1 ();
+ }
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
- class const_iterator2:
- public container_const_reference<matrix_matrix_binary>,
- public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
- typename E2::const_iterator2::iterator_category>::iterator_category>::template
- iterator_base<const_iterator2, value_type>::type {
- public:
- typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
- typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
- typedef typename matrix_matrix_binary::difference_type difference_type;
- typedef typename matrix_matrix_binary::value_type value_type;
- typedef typename matrix_matrix_binary::const_reference reference;
- typedef typename matrix_matrix_binary::const_pointer pointer;
-
- typedef const_iterator1 dual_iterator_type;
- typedef const_reverse_iterator1 dual_reverse_iterator_type;
-
- // Construction and destruction
+ class const_iterator2:
+ public container_const_reference<matrix_matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_matrix_binary::difference_type difference_type;
+ typedef typename matrix_matrix_binary::value_type value_type;
+ typedef typename matrix_matrix_binary::const_reference reference;
+ typedef typename matrix_matrix_binary::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- BOOST_UBLAS_INLINE
- const_iterator2 ():
- container_const_reference<self_type> (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {}
- BOOST_UBLAS_INLINE
- const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
- container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {}
#else
- BOOST_UBLAS_INLINE
- const_iterator2 ():
- container_const_reference<self_type> (), it1_ (), it2_ () {}
- BOOST_UBLAS_INLINE
- const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
- container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
-#endif
-
- private:
- // Random access specialization
- BOOST_UBLAS_INLINE
- value_type dereference (dense_random_access_iterator_tag) const {
- const self_type &mmb = (*this) ();
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
+#endif
+
+ private:
+ // Random access specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ const self_type &mmb = (*this) ();
#ifdef BOOST_UBLAS_USE_INDEXING
- return mmb (index1 (), index2 ());
+ return mmb (index1 (), index2 ());
#elif BOOST_UBLAS_USE_ITERATING
- difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
+ difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (size, it1_begin_, it2_.begin ());
+ return functor_type::apply (size, it1_begin_, it2_.begin ());
#else
- return functor_type::apply (size, it1_.begin (), it2_.begin ());
+ return functor_type::apply (size, it1_.begin (), it2_.begin ());
#endif
#else
- difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
- if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (size, it1_begin_, it2_.begin ());
+ return functor_type::apply (size, it1_begin_, it2_.begin ());
#else
- return functor_type::apply (size, it1_.begin (), it2_.begin ());
+ return functor_type::apply (size, it1_.begin (), it2_.begin ());
#endif
- else
- return mmb (index1 (), index2 ());
+ else
+ return mmb (index1 (), index2 ());
#endif
- }
+ }
- // Packed bidirectional specialization
- BOOST_UBLAS_INLINE
- value_type dereference (packed_random_access_iterator_tag) const {
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (it1_begin_, it1_end_,
- it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
+ return functor_type::apply (it1_begin_, it1_end_,
+ it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
#else
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- return functor_type::apply (it1_.begin (), it1_.end (),
- it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
#else
- return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
- boost::numeric::ublas::end (it1_, iterator1_tag ()),
- boost::numeric::ublas::begin (it2_, iterator2_tag ()),
- boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
#endif
#endif
- }
+ }
- // Sparse bidirectional specialization
- BOOST_UBLAS_INLINE
- value_type dereference (sparse_bidirectional_iterator_tag) const {
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- return functor_type::apply (it1_begin_, it1_end_,
- it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+ return functor_type::apply (it1_begin_, it1_end_,
+ it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
#else
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- return functor_type::apply (it1_.begin (), it1_.end (),
- it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
#else
- return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
- boost::numeric::ublas::end (it1_, iterator1_tag ()),
- boost::numeric::ublas::begin (it2_, iterator2_tag ()),
- boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
-#endif
-#endif
- }
-
- public:
- // Arithmetic
- BOOST_UBLAS_INLINE
- const_iterator2 &operator ++ () {
- ++ it2_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -- () {
- -- it2_;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator += (difference_type n) {
- it2_ += n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- const_iterator2 &operator -= (difference_type n) {
- it2_ -= n;
- return *this;
- }
- BOOST_UBLAS_INLINE
- difference_type operator - (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ - it.it2_;
- }
-
- // Dereference
- BOOST_UBLAS_INLINE
- const_reference operator * () const {
- return dereference (iterator_category ());
- }
- BOOST_UBLAS_INLINE
- const_reference operator [] (difference_type n) const {
- return *(*this + n);
- }
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
+#endif
+#endif
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
- BOOST_UBLAS_INLINE
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 begin () const {
- return (*this) ().find1 (1, 0, index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cbegin () const {
- return begin ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cbegin () const {
+ return begin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 end () const {
- return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_iterator1 cend () const {
- return end ();
- }
- BOOST_UBLAS_INLINE
+ const_iterator1 cend () const {
+ return end ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rbegin () const {
- return const_reverse_iterator1 (end ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 crbegin () const {
- return rbegin ();
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin () const {
+ return rbegin ();
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
+ typename self_type::
#endif
- const_reverse_iterator1 rend () const {
- return const_reverse_iterator1 (begin ());
- }
- BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+ BOOST_UBLAS_INLINE
#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
- typename self_type::
-#endif
- const_reverse_iterator1 crend () const {
- return rend ();
- }
-#endif
-
- // Indices
- BOOST_UBLAS_INLINE
- size_type index1 () const {
- return it1_.index1 ();
- }
- BOOST_UBLAS_INLINE
- size_type index2 () const {
- return it2_.index2 ();
- }
-
- // Assignment
- BOOST_UBLAS_INLINE
- const_iterator2 &operator = (const const_iterator2 &it) {
- container_const_reference<self_type>::assign (&it ());
- it1_ = it.it1_;
- it2_ = it.it2_;
+ typename self_type::
+#endif
+ const_reverse_iterator1 crend () const {
+ return rend ();
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- it1_begin_ = it.it1_begin_;
- it1_end_ = it.it1_end_;
-#endif
- return *this;
- }
-
- // Comparison
- BOOST_UBLAS_INLINE
- bool operator == (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ == it.it2_;
- }
- BOOST_UBLAS_INLINE
- bool operator < (const const_iterator2 &it) const {
- BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
- BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
- return it2_ < it.it2_;
- }
-
- private:
- // Mutable due to assignment
- /* const */ const_iterator11_type it1_;
- const_iterator22_type it2_;
+ it1_begin_ = it.it1_begin_;
+ it1_end_ = it.it1_end_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ // Mutable due to assignment
+ /* const */ const_iterator11_type it1_;
+ const_iterator22_type it2_;
#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
- /* const */ const_iterator12_type it1_begin_;
- /* const */ const_iterator12_type it1_end_;
-#endif
- };
-#endif
-
- BOOST_UBLAS_INLINE
- const_iterator2 begin2 () const {
- return find2 (0, 0, 0);
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cbegin2 () const {
- return begin2 ();
- }
- BOOST_UBLAS_INLINE
- const_iterator2 end2 () const {
- return find2 (0, 0, size2 ());
- }
- BOOST_UBLAS_INLINE
- const_iterator2 cend2 () const {
- return end2 ();
- }
-
- // Reverse iterators
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rbegin1 () const {
- return const_reverse_iterator1 (end1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crbegin1 () const {
- return rbegin1 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 rend1 () const {
- return const_reverse_iterator1 (begin1 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator1 crend1 () const {
- return rend1 ();
- }
-
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rbegin2 () const {
- return const_reverse_iterator2 (end2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crbegin2 () const {
- return rbegin2 ();
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 rend2 () const {
- return const_reverse_iterator2 (begin2 ());
- }
- BOOST_UBLAS_INLINE
- const_reverse_iterator2 crend2 () const {
- return rend2 ();
- }
-
- private:
- expression1_closure_type e1_;
- expression2_closure_type e2_;
- };
-
- template<class T1, class E1, class T2, class E2>
- struct matrix_matrix_binary_traits {
- typedef unknown_storage_tag storage_category;
- typedef unknown_orientation_tag orientation_category;
- typedef typename promote_traits<T1, T2>::promote_type promote_type;
- typedef matrix_matrix_binary<E1, E2, matrix_matrix_prod<E1, E2, promote_type> > expression_type;
+ /* const */ const_iterator12_type it1_begin_;
+ /* const */ const_iterator12_type it1_end_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cbegin2 () const {
+ return begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 cend2 () const {
+ return end2 ();
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crbegin1 () const {
+ return rbegin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 crend1 () const {
+ return rend1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crbegin2 () const {
+ return rbegin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 crend2 () const {
+ return rend2 ();
+ }
+
+private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+};
+
+template<class T1, class E1, class T2, class E2>
+struct matrix_matrix_binary_traits {
+ typedef unknown_storage_tag storage_category;
+ typedef unknown_orientation_tag orientation_category;
+ typedef typename promote_traits<T1, T2>::promote_type promote_type;
+ typedef matrix_matrix_binary<E1, E2, matrix_matrix_prod<E1, E2, promote_type> > expression_type;
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- typedef typename E1::matrix_temporary_type result_type;
-#endif
- };
-
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_matrix_binary_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::result_type
- prod (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2,
- unknown_storage_tag,
- unknown_orientation_tag) {
- typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- // Dispatcher
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_matrix_binary_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::result_type
- prod (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
- typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::storage_category storage_category;
- typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
- typename E2::value_type, E2>::orientation_category orientation_category;
- return prod (e1, e2, storage_category (), orientation_category ());
- }
-
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
- prec_prod (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2,
- unknown_storage_tag,
- unknown_orientation_tag) {
- typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
- return expression_type (e1 (), e2 ());
- }
-
- // Dispatcher
- template<class E1, class E2>
- BOOST_UBLAS_INLINE
- typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
- prec_prod (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
- typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
- typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
- typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
- return prec_prod (e1, e2, storage_category (), orientation_category ());
- }
-
- template<class M, class E1, class E2>
- BOOST_UBLAS_INLINE
- M &
- prod (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2,
- M &m) {
- return m.assign (prod (e1, e2));
- }
-
- template<class M, class E1, class E2>
- BOOST_UBLAS_INLINE
- M &
- prec_prod (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2,
- M &m) {
- return m.assign (prec_prod (e1, e2));
- }
-
- template<class M, class E1, class E2>
- BOOST_UBLAS_INLINE
- M
- prod (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- return M (prod (e1, e2));
- }
-
- template<class M, class E1, class E2>
- BOOST_UBLAS_INLINE
- M
- prec_prod (const matrix_expression<E1> &e1,
- const matrix_expression<E2> &e2) {
- return M (prec_prod (e1, e2));
- }
-
- template<class E, class F>
- class matrix_scalar_unary:
- public scalar_expression<matrix_scalar_unary<E, F> > {
- public:
- typedef E expression_type;
- typedef F functor_type;
- typedef typename F::result_type value_type;
- typedef typename E::const_closure_type expression_closure_type;
-
- // Construction and destruction
- BOOST_UBLAS_INLINE
- explicit matrix_scalar_unary (const expression_type &e):
- e_ (e) {}
-
- private:
- // Expression accessors
- BOOST_UBLAS_INLINE
- const expression_closure_type &expression () const {
- return e_;
- }
-
- public:
- BOOST_UBLAS_INLINE
- operator value_type () const {
- return functor_type::apply (e_);
- }
-
- private:
- expression_closure_type e_;
- };
-
- template<class E, class F>
- struct matrix_scalar_unary_traits {
- typedef matrix_scalar_unary<E, F> expression_type;
+ typedef typename E1::matrix_temporary_type result_type;
+#endif
+};
+
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+typename E2::value_type, E2>::result_type
+prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ unknown_storage_tag,
+ unknown_orientation_tag) {
+ typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+// Dispatcher
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+typename E2::value_type, E2>::result_type
+prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
+ typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::storage_category storage_category;
+ typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::orientation_category orientation_category;
+ return prod (e1, e2, storage_category (), orientation_category ());
+}
+
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+prec_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ unknown_storage_tag,
+ unknown_orientation_tag) {
+ typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+}
+
+// Dispatcher
+template<class E1, class E2>
+BOOST_UBLAS_INLINE
+typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+prec_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
+ typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
+ typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
+ return prec_prod (e1, e2, storage_category (), orientation_category ());
+}
+
+template<class M, class E1, class E2>
+BOOST_UBLAS_INLINE
+M &
+prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m) {
+ return m.assign (prod (e1, e2));
+}
+
+template<class M, class E1, class E2>
+BOOST_UBLAS_INLINE
+M &
+prec_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m) {
+ return m.assign (prec_prod (e1, e2));
+}
+
+template<class M, class E1, class E2>
+BOOST_UBLAS_INLINE
+M
+prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ return M (prod (e1, e2));
+}
+
+template<class M, class E1, class E2>
+BOOST_UBLAS_INLINE
+M
+prec_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ return M (prec_prod (e1, e2));
+}
+
+template<class E, class F>
+class matrix_scalar_unary:
+ public scalar_expression<matrix_scalar_unary<E, F> > {
+public:
+ typedef E expression_type;
+ typedef F functor_type;
+ typedef typename F::result_type value_type;
+ typedef typename E::const_closure_type expression_closure_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit matrix_scalar_unary (const expression_type &e):
+ e_ (e) {}
+
+private:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression_closure_type &expression () const {
+ return e_;
+ }
+
+public:
+ BOOST_UBLAS_INLINE
+ operator value_type () const {
+ return functor_type::apply (e_);
+ }
+
+private:
+ expression_closure_type e_;
+};
+
+template<class E, class F>
+struct matrix_scalar_unary_traits {
+ typedef matrix_scalar_unary<E, F> expression_type;
#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
- typedef expression_type result_type;
+ typedef expression_type result_type;
#else
- typedef typename F::result_type result_type;
-#endif
- };
-
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::result_type
- norm_1 (const matrix_expression<E> &e) {
- typedef typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::expression_type expression_type;
- return expression_type (e ());
- }
-
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::result_type
- norm_frobenius (const matrix_expression<E> &e) {
- typedef typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::expression_type expression_type;
- return expression_type (e ());
- }
-
- template<class E>
- BOOST_UBLAS_INLINE
- typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::result_type
- norm_inf (const matrix_expression<E> &e) {
- typedef typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::expression_type expression_type;
- return expression_type (e ());
- }
+ typedef typename F::result_type result_type;
+#endif
+};
+
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::result_type
+norm_1 (const matrix_expression<E> &e) {
+ typedef typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::expression_type expression_type;
+ return expression_type (e ());
+}
+
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::result_type
+norm_frobenius (const matrix_expression<E> &e) {
+ typedef typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::expression_type expression_type;
+ return expression_type (e ());
+}
+
+template<class E>
+BOOST_UBLAS_INLINE
+typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::result_type
+norm_inf (const matrix_expression<E> &e) {
+ typedef typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::expression_type expression_type;
+ return expression_type (e ());
+}
}}}
diff --git a/boost/numeric/ublas/matrix_sparse.hpp b/boost/numeric/ublas/matrix_sparse.hpp
index b702743349..9a70029fbc 100644
--- a/boost/numeric/ublas/matrix_sparse.hpp
+++ b/boost/numeric/ublas/matrix_sparse.hpp
@@ -368,7 +368,7 @@ namespace boost { namespace numeric { namespace ublas {
// Reserving
BOOST_UBLAS_INLINE
- void reserve (size_type non_zeros, bool preserve = true) {
+ void reserve (size_type non_zeros, bool /*preserve*/ = true) {
detail::map_reserve (data (), restrict_capacity (non_zeros));
}
@@ -1461,7 +1461,7 @@ namespace boost { namespace numeric { namespace ublas {
data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
}
BOOST_UBLAS_INLINE
- mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type non_zeros = 0):
+ mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type /*non_zeros*/ = 0):
matrix_container<self_type> (),
size1_ (size1), size2_ (size2), data_ () {
data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
@@ -1472,7 +1472,7 @@ namespace boost { namespace numeric { namespace ublas {
size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
template<class AE>
BOOST_UBLAS_INLINE
- mapped_vector_of_mapped_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0):
+ mapped_vector_of_mapped_vector (const matrix_expression<AE> &ae, size_type /*non_zeros*/ = 0):
matrix_container<self_type> (),
size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () {
data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
diff --git a/boost/numeric/ublas/matrix_vector.hpp b/boost/numeric/ublas/matrix_vector.hpp
index fec1f65df5..cf032bffb1 100644
--- a/boost/numeric/ublas/matrix_vector.hpp
+++ b/boost/numeric/ublas/matrix_vector.hpp
@@ -9,7 +9,7 @@
#ifndef BOOST_UBLAS_MATRIX_VECTOR_HPP
#define BOOST_UBLAS_MATRIX_VECTOR_HPP
-#include <boost/numeric/ublas/matrix_proxy.hpp>//for matrix_row, matrix_column and matrix_expression
+#include <boost/numeric/ublas/matrix_proxy.hpp> //for matrix_row, matrix_column and matrix_expression
#include <boost/numeric/ublas/vector.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/range/iterator_range.hpp>
@@ -43,10 +43,12 @@ public:
matrix_vector_iterator(){}
///\brief constructs a matrix_vector_iterator as pointing to the i-th proxy
+ BOOST_UBLAS_INLINE
matrix_vector_iterator(Matrix& matrix, std::size_t position)
: matrix_(&matrix),position_(position) {}
template<class M, class R>
+ BOOST_UBLAS_INLINE
matrix_vector_iterator(matrix_vector_iterator<M,R> const& other)
: matrix_(other.matrix_),position_(other.position_) {}
@@ -54,28 +56,36 @@ private:
friend class boost::iterator_core_access;
template <class M,class R> friend class matrix_vector_iterator;
+ BOOST_UBLAS_INLINE
void increment() {
++position_;
}
+
+ BOOST_UBLAS_INLINE
void decrement() {
--position_;
}
+ BOOST_UBLAS_INLINE
void advance(std::ptrdiff_t n){
position_ += n;
}
template<class M,class R>
+ BOOST_UBLAS_INLINE
std::ptrdiff_t distance_to(matrix_vector_iterator<M,R> const& other) const{
BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ());
return (std::ptrdiff_t)other.position_ - (std::ptrdiff_t)position_;
}
template<class M,class R>
+ BOOST_UBLAS_INLINE
bool equal(matrix_vector_iterator<M,R> const& other) const{
BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ());
return (position_ == other.position_);
}
+
+ BOOST_UBLAS_INLINE
Reference dereference() const {
return Reference(*matrix_,position_);
}
@@ -109,81 +119,103 @@ public:
typedef typename boost::iterator_difference<iterator>::type difference_type;
typedef typename Matrix::size_type size_type;
- matrix_row_vector(Matrix& matrix) :
- matrix_(matrix) {
+ BOOST_UBLAS_INLINE
+ explicit matrix_row_vector(Matrix& matrix) :
+ matrix_(&matrix) {
}
-
+ BOOST_UBLAS_INLINE
iterator begin(){
- return iterator(matrix_, 0);
+ return iterator(*matrix_, 0);
}
+ BOOST_UBLAS_INLINE
const_iterator begin() const {
- return const_iterator(matrix_, 0);
+ return const_iterator(*matrix_, 0);
}
+ BOOST_UBLAS_INLINE
const_iterator cbegin() const {
return begin();
}
+ BOOST_UBLAS_INLINE
iterator end() {
- return iterator(matrix_, matrix_.size1());
+ return iterator(*matrix_, matrix_->size1());
}
+ BOOST_UBLAS_INLINE
const_iterator end() const {
- return const_iterator(matrix_, matrix_.size1());
+ return const_iterator(*matrix_, matrix_->size1());
}
+ BOOST_UBLAS_INLINE
const_iterator cend() const {
return end();
}
+ BOOST_UBLAS_INLINE
reverse_iterator rbegin() {
return reverse_iterator(end());
}
+ BOOST_UBLAS_INLINE
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
+ BOOST_UBLAS_INLINE
const_reverse_iterator crbegin() const {
return rbegin();
}
+ BOOST_UBLAS_INLINE
reverse_iterator rend() {
return reverse_iterator(begin());
}
+ BOOST_UBLAS_INLINE
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
+ BOOST_UBLAS_INLINE
const_reverse_iterator crend() const {
return end();
}
- value_type operator()(difference_type index) const {
- return value_type(matrix_, index);
+ BOOST_UBLAS_INLINE
+ value_type operator()(size_type index) {
+ return value_type(*matrix_, index);
+ }
+
+ BOOST_UBLAS_INLINE
+ value_type operator()(size_type index) const {
+ return value_type(*matrix_, index);
}
- reference operator[](difference_type index){
- return reference(matrix_, index);
+ BOOST_UBLAS_INLINE
+ reference operator[](size_type index){
+ return (*this) (index);
}
- const_reference operator[](difference_type index) const {
- return const_reference(matrix_, index);
+ BOOST_UBLAS_INLINE
+ const_reference operator[](size_type index) const {
+ return (*this) (index);
}
+ BOOST_UBLAS_INLINE
size_type size() const {
- return matrix_.size1();
+ return matrix_->size1();
}
+ BOOST_UBLAS_INLINE
void resize(size_type size, bool preserve = true) {
- matrix_.resize(size, matrix_.size2(), preserve);
+ matrix_->resize(size, matrix_->size2(), preserve);
}
private:
- Matrix& matrix_;
+ Matrix* matrix_;
};
@@ -196,6 +228,7 @@ private:
* \tparam Matrix the type of matrix that \c matrix_row_vector is referring.
*/
template<class Matrix>
+BOOST_UBLAS_INLINE
matrix_row_vector<Matrix> make_row_vector(matrix_expression<Matrix>& matrix){
return matrix_row_vector<Matrix>(matrix());
}
@@ -210,6 +243,7 @@ matrix_row_vector<Matrix> make_row_vector(matrix_expression<Matrix>& matrix){
* \tparam Matrix the type of matrix that \c matrix_row_vector is referring.
*/
template<class Matrix>
+BOOST_UBLAS_INLINE
matrix_row_vector<Matrix const> make_row_vector(matrix_expression<Matrix> const& matrix){
return matrix_row_vector<Matrix const>(matrix());
}
@@ -224,8 +258,7 @@ matrix_row_vector<Matrix const> make_row_vector(matrix_expression<Matrix> const&
* the underlaying matrix.
*/
template<class Matrix>
-class matrix_column_vector
-{
+class matrix_column_vector {
public:
typedef ublas::matrix_column<Matrix> value_type;
typedef ublas::matrix_column<Matrix> reference;
@@ -239,80 +272,103 @@ public:
typedef typename boost::iterator_difference<iterator>::type difference_type;
typedef typename Matrix::size_type size_type;
- matrix_column_vector(Matrix& matrix) :
- matrix_(matrix){
+ BOOST_UBLAS_INLINE
+ explicit matrix_column_vector(Matrix& matrix) :
+ matrix_(&matrix){
}
+ BOOST_UBLAS_INLINE
iterator begin() {
- return iterator(matrix_, 0);
+ return iterator(*matrix_, 0);
}
+ BOOST_UBLAS_INLINE
const_iterator begin() const {
- return const_iterator(matrix_, 0);
+ return const_iterator(*matrix_, 0);
}
+ BOOST_UBLAS_INLINE
const_iterator cbegin() const {
return begin();
}
+ BOOST_UBLAS_INLINE
iterator end() {
- return iterator(matrix_, matrix_.size2());
+ return iterator(*matrix_, matrix_->size2());
}
+ BOOST_UBLAS_INLINE
const_iterator end() const {
- return const_iterator(matrix_, matrix_.size2());
+ return const_iterator(*matrix_, matrix_->size2());
}
+ BOOST_UBLAS_INLINE
const_iterator cend() const {
return end();
}
+ BOOST_UBLAS_INLINE
reverse_iterator rbegin() {
return reverse_iterator(end());
}
+ BOOST_UBLAS_INLINE
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
+ BOOST_UBLAS_INLINE
const_reverse_iterator crbegin() const {
return rbegin();
- }
+ }
+ BOOST_UBLAS_INLINE
reverse_iterator rend() {
return reverse_iterator(begin());
}
+ BOOST_UBLAS_INLINE
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
+ BOOST_UBLAS_INLINE
const_reverse_iterator crend() const {
return rend();
}
- value_type operator()(difference_type index) const {
- return value_type(matrix_, index);
+ BOOST_UBLAS_INLINE
+ value_type operator()(size_type index) {
+ return value_type(*matrix_, index);
+ }
+
+ BOOST_UBLAS_INLINE
+ value_type operator()(size_type index) const {
+ return value_type(*matrix_, index);
}
- reference operator[](difference_type index) {
- return reference(matrix_, index);
+ BOOST_UBLAS_INLINE
+ reference operator[](size_type index) {
+ return (*this) (index);
}
- const_reference operator[](difference_type index) const {
- return const_reference(matrix_, index);
+ BOOST_UBLAS_INLINE
+ const_reference operator[](size_type index) const {
+ return (*this) (index);
}
+ BOOST_UBLAS_INLINE
size_type size() const {
- return matrix_.size2();
+ return matrix_->size2();
}
+ BOOST_UBLAS_INLINE
void resize(size_type size, bool preserve = true) {
- matrix_.resize(matrix_.size1(), size, preserve);
+ matrix_->resize(matrix_->size1(), size, preserve);
}
private:
- Matrix& matrix_;
+ Matrix* matrix_;
};
@@ -325,6 +381,7 @@ private:
* \tparam Matrix the type of matrix that \c matrix_column_vector is referring.
*/
template<class Matrix>
+BOOST_UBLAS_INLINE
matrix_column_vector<Matrix> make_column_vector(matrix_expression<Matrix>& matrix){
return matrix_column_vector<Matrix>(matrix());
}
@@ -339,6 +396,7 @@ matrix_column_vector<Matrix> make_column_vector(matrix_expression<Matrix>& matri
* \tparam Matrix the type of matrix that \c matrix_column_vector is referring.
*/
template<class Matrix>
+BOOST_UBLAS_INLINE
matrix_column_vector<Matrix const> make_column_vector(matrix_expression<Matrix> const& matrix){
return matrix_column_vector<Matrix const>(matrix());
}
diff --git a/boost/numeric/ublas/opencl.hpp b/boost/numeric/ublas/opencl.hpp
new file mode 100644
index 0000000000..9258046104
--- /dev/null
+++ b/boost/numeric/ublas/opencl.hpp
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef boost_numeric_ublas_opencl_hpp_
+#define boost_numeric_ublas_opencl_hpp_
+
+#include <boost/numeric/ublas/opencl/library.hpp>
+#include <boost/numeric/ublas/opencl/vector.hpp>
+#include <boost/numeric/ublas/opencl/matrix.hpp>
+#include <boost/numeric/ublas/opencl/operations.hpp>
+
+#endif
diff --git a/boost/numeric/ublas/opencl/elementwise.hpp b/boost/numeric/ublas/opencl/elementwise.hpp
new file mode 100644
index 0000000000..72da6a0de9
--- /dev/null
+++ b/boost/numeric/ublas/opencl/elementwise.hpp
@@ -0,0 +1,508 @@
+// Boost.uBLAS
+//
+// Copyright (c) 2018 Fady Essam
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef boost_numeric_ublas_opencl_elementwise_hpp_
+#define boost_numeric_ublas_opencl_elementwise_hpp_
+
+#include <boost/numeric/ublas/opencl/library.hpp>
+#include <boost/numeric/ublas/opencl/vector.hpp>
+#include <boost/numeric/ublas/opencl/matrix.hpp>
+
+namespace boost { namespace numeric { namespace ublas { namespace opencl {
+
+namespace compute = boost::compute;
+namespace lambda = boost::compute::lambda;
+
+template <typename T, typename L1, typename L2, typename L3, class O>
+void element_wise(ublas::matrix<T, L1, opencl::storage> const &a,
+ ublas::matrix<T, L2, opencl::storage> const &b,
+ ublas::matrix<T, L3, opencl::storage> &result,
+ O op, compute::command_queue& queue)
+{
+ assert(a.device() == b.device() &&
+ a.device() == result.device() &&
+ a.device() == queue.get_device());
+ assert(a.size1() == b.size1() && a.size2() == b.size2());
+
+ compute::transform(a.begin(),
+ a.end(),
+ b.begin(),
+ result.begin(),
+ op,
+ queue);
+ queue.finish();
+}
+
+template <typename T, typename L1, typename L2, typename L3, typename A, class O>
+void element_wise(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ ublas::matrix<T, L3, A> &result,
+ O op,
+ compute::command_queue &queue)
+{
+ ublas::matrix<T, L1, opencl::storage> adev(a, queue);
+ ublas::matrix<T, L2, opencl::storage> bdev(b, queue);
+ ublas::matrix<T, L3, opencl::storage> rdev(a.size1(), b.size2(), queue.get_context());
+ element_wise(adev, bdev, rdev, op, queue);
+ rdev.to_host(result, queue);
+}
+
+template <typename T, typename L1, typename L2, typename A, typename O>
+ublas::matrix<T, L1, A> element_wise(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ O op,
+ compute::command_queue &queue)
+{
+ ublas::matrix<T, L1, A> result(a.size1(), b.size2());
+ element_wise(a, b, result, op, queue);
+ return result;
+}
+
+template <typename T, typename O>
+void element_wise(ublas::vector<T, opencl::storage> const &a,
+ ublas::vector<T, opencl::storage> const &b,
+ ublas::vector<T, opencl::storage> &result,
+ O op,
+ compute::command_queue& queue)
+{
+ assert(a.device() == b.device() &&
+ a.device() == result.device() &&
+ a.device() == queue.get_device());
+ assert(a.size() == b.size());
+ compute::transform(a.begin(),
+ a.end(),
+ b.begin(),
+ result.begin(),
+ op,
+ queue);
+ queue.finish();
+}
+
+template <typename T, typename A, typename O>
+void element_wise(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ ublas::vector<T, A>& result,
+ O op,
+ compute::command_queue &queue)
+{
+ ublas::vector<T, opencl::storage> adev(a, queue);
+ ublas::vector<T, opencl::storage> bdev(b, queue);
+ ublas::vector<T, opencl::storage> rdev(a.size(), queue.get_context());
+ element_wise(adev, bdev, rdev, op, queue);
+ rdev.to_host(result, queue);
+}
+
+template <typename T, typename A, typename O>
+ublas::vector<T, A> element_wise(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ O op,
+ compute::command_queue &queue)
+{
+ ublas::vector<T, A> result(a.size());
+ element_wise(a, b, result, op, queue);
+ return result;
+}
+
+template <typename T, typename L1, typename L2, typename L3>
+void element_add(ublas::matrix<T, L1, opencl::storage> const &a,
+ ublas::matrix<T, L2, opencl::storage> const &b,
+ ublas::matrix<T, L3, opencl::storage> &result,
+ compute::command_queue &queue)
+{
+ element_wise(a, b, result, compute::plus<T>(), queue);
+}
+
+template <typename T, typename L1, typename L2, typename L3, typename A>
+void element_add(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ ublas::matrix<T, L3, A> &result,
+ compute::command_queue &queue)
+{
+ element_wise(a, b, result, compute::plus<T>(), queue);
+}
+
+template <typename T, typename L1, typename L2, typename A>
+ublas::matrix<T, L1, A> element_add(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ compute::command_queue &queue)
+{
+ return element_wise(a, b, compute::plus<T>(), queue);
+}
+
+template <typename T>
+void element_add(ublas::vector<T, opencl::storage> const &a,
+ ublas::vector<T, opencl::storage> const &b,
+ ublas::vector<T, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ element_wise(a, b, result, compute::plus<T>(), queue);
+}
+
+template <typename T, typename A>
+void element_add(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ ublas::vector<T, A> &result,
+ compute::command_queue &queue)
+{
+ element_wise(a, b, result, compute::plus<T>(), queue);
+}
+
+template <typename T, typename A>
+ublas::vector<T, A> element_add(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ compute::command_queue &queue)
+{
+ return element_wise(a, b, compute::plus<T>(), queue);
+}
+
+template<typename T, typename L>
+void element_add(ublas::matrix<T, L, opencl::storage> const &m, T value,
+ ublas::matrix<T, L, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ assert(m.device() == result.device() && m.device() == queue.get_device());
+ assert(m.size1() == result.size1() && m.size2() == result.size2());
+ compute::transform(m.begin(), m.end(), result.begin(), lambda::_1 + value, queue);
+ queue.finish();
+}
+
+template<typename T, typename L, typename A>
+void element_add(ublas::matrix<T, L, A> const &m, T value,
+ ublas::matrix<T, L, A> &result,
+ compute::command_queue& queue)
+{
+ ublas::matrix<T, L, opencl::storage> mdev(m, queue);
+ ublas::matrix<T, L, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context());
+ element_add(mdev, value, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template<typename T, typename L, typename A>
+ublas::matrix<T, L, A> element_add(ublas::matrix<T, L, A> const &m, T value,
+ compute::command_queue& queue)
+{
+ ublas::matrix<T, L, A> result(m.size1(), m.size2());
+ element_add(m, value, result, queue);
+ return result;
+}
+
+template<typename T>
+void element_add(ublas::vector<T, opencl::storage> const &v, T value,
+ ublas::vector<T, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ assert(v.device() == result.device() && v.device() == queue.get_device());
+ assert(v.size() == result.size());
+ compute::transform(v.begin(), v.end(), result.begin(), lambda::_1 + value, queue);
+ queue.finish();
+}
+
+template<typename T, typename A>
+void element_add(ublas::vector<T, A> const &v, T value,
+ ublas::vector<T, A> &result,
+ compute::command_queue& queue)
+{
+ ublas::vector<T, opencl::storage> vdev(v, queue);
+ ublas::vector<T, opencl::storage> rdev(v.size(), queue.get_context());
+ element_add(vdev, value, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template <typename T, typename A>
+ublas::vector<T, A> element_add(ublas::vector<T, A> const &v, T value,
+ compute::command_queue& queue)
+{
+ ublas::vector<T, A> result(v.size());
+ element_add(v, value, result, queue);
+ return result;
+}
+
+template <typename T, typename L1, typename L2, typename L3>
+void element_sub(ublas::matrix<T, L1, opencl::storage> const &a,
+ ublas::matrix<T, L2, opencl::storage> const &b,
+ ublas::matrix<T, L3, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ element_wise(a, b, compute::minus<T>(), result, queue);
+}
+
+template <typename T, typename L1, typename L2, typename L3, typename A>
+void element_sub(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ ublas::matrix<T, L3, A> &result,
+ compute::command_queue &queue)
+{
+ element_wise(a, b, result, compute::minus<T>(), queue);
+}
+
+template <typename T, typename L1, typename L2, typename A>
+ublas::matrix<T, L1, A> element_sub(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ compute::command_queue &queue)
+{
+ return element_wise(a, b, compute::minus<T>(), queue);
+}
+
+template <typename T>
+void element_sub(ublas::vector<T, opencl::storage> const &a,
+ ublas::vector<T, opencl::storage> const &b,
+ ublas::vector<T, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ element_wise(a, b, result, compute::minus<T>(), queue);
+}
+
+template <typename T, typename A>
+void element_sub(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ ublas::vector<T, A> &result,
+ compute::command_queue &queue)
+{
+ element_wise(a, b, result, compute::minus<T>(), queue);
+}
+
+template <typename T, typename A>
+ublas::vector<T, A> element_sub(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ compute::command_queue &queue)
+{
+ return element_wise(a, b, compute::minus<T>(), queue);
+}
+
+template <typename T, typename L>
+void element_sub(ublas::matrix<T, L, opencl::storage> const &m, T value,
+ ublas::matrix<T, L, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ assert(m.device() == result.device() && m.device() == queue.get_device());
+ assert(m.size1() == result.size1() && m.size2() == result.size2());
+ compute::transform(m.begin(), m.end(), result.begin(), lambda::_1 - value, queue);
+ queue.finish();
+}
+
+template <typename T, typename L, typename A>
+void element_sub(ublas::matrix<T, L, A> const &m, T value,
+ ublas::matrix<T, L, A> &result,
+ compute::command_queue& queue)
+{
+ ublas::matrix<T, L, opencl::storage> mdev(m, queue);
+ ublas::matrix<T, L, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context());
+ element_sub(mdev, value, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template <typename T, typename L, typename A>
+ublas::matrix<T, L, A> element_sub(ublas::matrix<T, L, A> const &m, T value,
+ compute::command_queue& queue)
+{
+ ublas::matrix<T, L, A> result(m.size1(), m.size2());
+ element_sub(m, value, result, queue);
+ return result;
+}
+
+template <typename T>
+void element_sub(ublas::vector<T, opencl::storage> const &v, T value,
+ ublas::vector<T, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ assert(v.device() == result.device() && v.device() == queue.get_device());
+ assert(v.size() == result.size());
+ compute::transform(v.begin(), v.end(), result.begin(), lambda::_1 - value, queue);
+ queue.finish();
+}
+
+template <typename T, typename A>
+void element_sub(ublas::vector<T, A> const &v, T value,
+ ublas::vector<T, A> &result,
+ compute::command_queue& queue)
+{
+ ublas::vector<T, opencl::storage> vdev(v, queue);
+ ublas::vector<T, opencl::storage> rdev(v.size(), queue.get_context());
+ element_sub(vdev, value, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template <typename T, typename A>
+ublas::vector<T, A> element_sub(ublas::vector<T, A> const &v, T value,
+ compute::command_queue& queue)
+{
+ ublas::vector<T, A> result(v.size());
+ element_sub(v, value, result, queue);
+ return result;
+}
+
+template <typename T, typename L1, typename L2, typename L3>
+void element_prod(ublas::matrix<T, L1, opencl::storage> const &a,
+ ublas::matrix<T, L2, opencl::storage> const &b,
+ ublas::matrix<T, L3, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ element_wise(a, b, result, compute::multiplies<T>(), queue);
+}
+
+template <typename T, typename L1, typename L2, typename L3, typename A>
+void element_prod(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ ublas::matrix<T, L3, A> &result,
+ compute::command_queue &queue)
+{
+ element_wise(a, b, result, compute::multiplies<T>(), queue);
+}
+
+template <typename T, typename L1, typename L2, typename A>
+ublas::matrix<T, L1, A> element_prod(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ compute::command_queue &queue)
+{
+ return element_wise(a, b, compute::multiplies<T>(), queue);
+}
+
+template <typename T>
+void element_prod(ublas::vector<T, opencl::storage> const &a,
+ ublas::vector<T, opencl::storage> const &b,
+ ublas::vector<T, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ element_wise(a, b, result, compute::multiplies<T>(), queue);
+}
+
+template <typename T, typename A>
+void element_prod(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ ublas::vector<T, A> &result,
+ compute::command_queue &queue)
+{
+ element_wise(a, b, result, compute::multiplies<T>(), queue);
+}
+
+template <typename T, typename A>
+ublas::vector<T, A> element_prod(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ compute::command_queue &queue)
+{
+ return element_wise(a, b, compute::multiplies<T>(), queue);
+}
+
+template <typename T, typename L>
+void element_scale(ublas::matrix<T, L, opencl::storage> const &m, T value,
+ ublas::matrix<T, L, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ assert(m.device() == result.device() && m.device() == queue.get_device());
+ assert(m.size1() == result.size1() && m.size2() == result.size2());
+ compute::transform(m.begin(), m.end(), result.begin(), lambda::_1 * value, queue);
+ queue.finish();
+}
+
+template <typename T, typename L, typename A>
+void element_scale(ublas::matrix<T, L, A> const &m, T value,
+ ublas::matrix<T, L, A> &result,
+ compute::command_queue& queue)
+{
+ ublas::matrix<T, L, opencl::storage> mdev(m, queue);
+ ublas::matrix<T, L, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context());
+ element_scale(mdev, value, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template <typename T, typename L, typename A>
+ublas::matrix<T, L, A> element_scale(ublas::matrix<T, L, A> const &m, T value,
+ compute::command_queue& queue)
+{
+ ublas::matrix<T, L, A> result(m.size1(), m.size2());
+ element_scale(m, value, result, queue);
+ return result;
+}
+
+template <typename T>
+void element_scale(ublas::vector<T, opencl::storage> const &v, T value,
+ ublas::vector<T, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ assert(v.device() == result.device() && v.device() == queue.get_device());
+ assert(v.size() == result.size());
+ compute::transform(v.begin(), v.end(), result.begin(), lambda::_1 * value, queue);
+ queue.finish();
+}
+
+template <typename T, typename A>
+void element_scale(ublas::vector<T, A> const &v, T value,
+ ublas::vector<T, A> & result,
+ compute::command_queue& queue)
+{
+ ublas::vector<T, opencl::storage> vdev(v, queue);
+ ublas::vector<T, opencl::storage> rdev(v.size(), queue.get_context());
+ element_scale(vdev, value, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template <typename T, typename A>
+ublas::vector<T,A> element_scale(ublas::vector<T, A> const &v, T value,
+ compute::command_queue& queue)
+{
+ ublas::vector<T, A> result(v.size());
+ element_scale(v, value, result, queue);
+ return result;
+}
+
+template <typename T, typename L1, typename L2, typename L3>
+void element_div(ublas::matrix<T, L1, opencl::storage> const &a,
+ ublas::matrix<T, L2, opencl::storage> const &b,
+ ublas::matrix<T, L3, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ element_wise(a, b, result, compute::divides<T>(), queue);
+}
+
+template <typename T, typename L1, typename L2, typename L3, typename A>
+void element_div(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ ublas::matrix<T, L3, A> &result,
+ compute::command_queue &queue)
+{
+ element_wise(a, b, result, compute::divides<T>(), queue);
+}
+
+template <typename T, typename L1, typename L2, typename A>
+ublas::matrix<T, L1, A> element_div(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ compute::command_queue &queue)
+{
+ return element_wise(a, b, compute::divides<T>(), queue);
+}
+
+template <typename T>
+void element_div(ublas::vector<T, opencl::storage> const &a,
+ ublas::vector<T, opencl::storage> const &b,
+ ublas::vector<T, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ element_wise(a, b, result, compute::divides<T>(), queue);
+}
+
+template <typename T, typename A>
+void element_div(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ ublas::vector<T, A> &result,
+ compute::command_queue &queue)
+{
+ element_wise(a, b, result, compute::divides<T>(), queue);
+}
+
+template <typename T, typename A>
+ublas::vector<T, A> element_div(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ compute::command_queue &queue)
+{
+ return element_wise(a, b, compute::divides<T>(), queue);
+}
+
+}}}}
+
+#endif
diff --git a/boost/numeric/ublas/opencl/library.hpp b/boost/numeric/ublas/opencl/library.hpp
new file mode 100644
index 0000000000..badee4d2ee
--- /dev/null
+++ b/boost/numeric/ublas/opencl/library.hpp
@@ -0,0 +1,38 @@
+// Boost.uBLAS
+//
+// Copyright (c) 2018 Fady Essam
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef boost_numeric_ublas_opencl_library_hpp_
+#define boost_numeric_ublas_opencl_library_hpp_
+
+#include <clBLAS.h>
+#include <type_traits>
+#include <complex>
+
+namespace boost { namespace numeric { namespace ublas { namespace opencl {
+
+class library
+{
+public:
+ library() { clblasSetup();}
+ ~library() { clblasTeardown();}
+};
+
+template <typename T>
+struct is_numeric
+{
+ static bool const value =
+ std::is_same<T, float>::value |
+ std::is_same<T, double>::value |
+ std::is_same<T, std::complex<float>>::value |
+ std::is_same<T, std::complex<double>>::value;
+};
+
+}}}}
+
+#endif
diff --git a/boost/numeric/ublas/opencl/matrix.hpp b/boost/numeric/ublas/opencl/matrix.hpp
new file mode 100644
index 0000000000..d8b400d542
--- /dev/null
+++ b/boost/numeric/ublas/opencl/matrix.hpp
@@ -0,0 +1,123 @@
+// Boost.uBLAS
+//
+// Copyright (c) 2018 Fady Essam
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef boost_numeric_ublas_opencl_matrix_hpp_
+#define boost_numeric_ublas_opencl_matrix_hpp_
+
+#include <boost/numeric/ublas/opencl/library.hpp>
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/numeric/ublas/functional.hpp>
+#include <boost/compute/core.hpp>
+#include <boost/compute/algorithm.hpp>
+#include <boost/compute/buffer.hpp>
+
+namespace boost { namespace numeric { namespace ublas { namespace opencl {
+
+class storage;
+
+namespace compute = boost::compute;
+
+} // namespace opencl
+
+template<class T, class L>
+class matrix<T, L, opencl::storage> : public matrix_container<matrix<T, L, opencl::storage> >
+{
+ typedef typename boost::compute::buffer_allocator<T>::size_type size_type;
+ typedef L layout_type;
+ typedef matrix<T, L, opencl::storage> self_type;
+public:
+ matrix()
+ : matrix_container<self_type>(),
+ size1_(0), size2_(0), data_() , device_()
+ {}
+
+ matrix(size_type size1, size_type size2, compute::context c)
+ : matrix_container<self_type>(),
+ size1_(size1), size2_(size2), device_(c.get_device())
+ {
+ compute::buffer_allocator<T> allocator(c);
+ data_ = allocator.allocate(layout_type::storage_size(size1, size2)).get_buffer();
+ }
+
+ matrix(size_type size1, size_type size2, T const &value, compute::command_queue &q)
+ : matrix_container<self_type>(),
+ size1_(size1), size2_(size2), device_(q.get_device())
+ {
+ compute::buffer_allocator<T> allocator(q.get_context());
+ data_ = allocator.allocate(layout_type::storage_size(size1, size2)).get_buffer();
+ compute::fill(this->begin(), this->end(), value, q);
+ q.finish();
+ }
+
+ template <typename A>
+ matrix(matrix<T, L, A> const &m, compute::command_queue &queue)
+ : matrix(m.size1(), m.size2(), queue.get_context())
+ {
+ this->from_host(m, queue);
+ }
+
+ size_type size1() const { return size1_;}
+ size_type size2() const { return size2_;}
+
+ const compute::buffer_iterator<T> begin() const { return compute::make_buffer_iterator<T>(data_);}
+ compute::buffer_iterator<T> begin() { return compute::make_buffer_iterator<T>(data_);}
+
+ compute::buffer_iterator<T> end() { return compute::make_buffer_iterator<T>(data_, layout_type::storage_size(size1_, size2_));}
+ const compute::buffer_iterator<T> end() const { return compute::make_buffer_iterator<T>(data_, layout_type::storage_size(size1_, size2_));}
+
+ const compute::device &device() const { return device_;}
+ compute::device &device() { return device_;}
+
+ void fill(T value, compute::command_queue &queue)
+ {
+ assert(device_ == queue.get_device());
+ compute::fill(this->begin(), this->end(), value, queue);
+ queue.finish();
+ }
+
+ /** Copies a matrix to a device
+ * \param m is a matrix that is not on the device _device and it is copied to it
+ * \param queue is the command queue that will execute the operation
+ */
+ template<class A>
+ void from_host(ublas::matrix<T, L, A> const &m, compute::command_queue &queue)
+ {
+ assert(device_ == queue.get_device());
+ compute::copy(m.data().begin(),
+ m.data().end(),
+ this->begin(),
+ queue);
+ queue.finish();
+ }
+
+ /** Copies a matrix from a device
+ * \param m is a matrix that will be reized to (size1_,size2) and the values of (*this) will be copied in it
+ * \param queue is the command queue that will execute the operation
+ */
+ template<class A>
+ void to_host(ublas::matrix<T, L, A> &m, compute::command_queue &queue) const
+ {
+ assert(device_ == queue.get_device());
+ compute::copy(this->begin(),
+ this->end(),
+ m.data().begin(),
+ queue);
+ queue.finish();
+ }
+
+private:
+ size_type size1_;
+ size_type size2_;
+ compute::buffer data_;
+ compute::device device_;
+};
+
+}}}
+
+#endif
diff --git a/boost/numeric/ublas/opencl/misc.hpp b/boost/numeric/ublas/opencl/misc.hpp
new file mode 100644
index 0000000000..5ed48f47f8
--- /dev/null
+++ b/boost/numeric/ublas/opencl/misc.hpp
@@ -0,0 +1,182 @@
+// Boost.uBLAS
+//
+// Copyright (c) 2018 Fady Essam
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef boost_numeric_ublas_opencl_misc_hpp_
+#define boost_numeric_ublas_opencl_misc_hpp_
+
+#include <boost/numeric/ublas/opencl/library.hpp>
+#include <boost/numeric/ublas/opencl/vector.hpp>
+#include <boost/numeric/ublas/opencl/matrix.hpp>
+
+namespace boost { namespace numeric { namespace ublas { namespace opencl {
+
+template <typename T>
+typename std::enable_if<is_numeric<T>::value, T>::type
+a_sum(ublas::vector<T, opencl::storage> const &v, compute::command_queue& queue)
+{
+ compute::vector<T> scratch_buffer(v.size(), queue.get_context());
+ compute::vector<T> result_buffer(1, queue.get_context());
+ cl_event event;
+ if (std::is_same<T, float>::value)
+ clblasSasum(v.size(),
+ result_buffer.begin().get_buffer().get(), //result buffer
+ 0, //offset in result buffer
+ v.begin().get_buffer().get(), //input buffer
+ 0, //offset in input buffer
+ 1, //increment in input buffer
+ scratch_buffer.begin().get_buffer().get(),
+ 1, //number of command queues
+ &(queue.get()), //queue
+ 0, // number of events waiting list
+ NULL, //event waiting list
+ &event); //event
+ else if (std::is_same<T, double>::value)
+ clblasDasum(v.size(),
+ result_buffer.begin().get_buffer().get(), //result buffer
+ 0, //offset in result buffer
+ v.begin().get_buffer().get(), //input buffer
+ 0, //offset in input buffer
+ 1, //increment in input buffer
+ scratch_buffer.begin().get_buffer().get(),
+ 1, //number of command queues
+ &(queue.get()), //queue
+ 0, // number of events waiting list
+ NULL, //event waiting list
+ &event); //event
+ else if (std::is_same<T, std::complex<float>>::value)
+ clblasScasum(v.size(),
+ result_buffer.begin().get_buffer().get(), //result buffer
+ 0, //offset in result buffer
+ v.begin().get_buffer().get(), //input buffer
+ 0, //offset in input buffer
+ 1, //increment in input buffer
+ scratch_buffer.begin().get_buffer().get(),
+ 1, //number of command queues
+ &(queue.get()), //queue
+ 0, // number of events waiting list
+ NULL, //event waiting list
+ &event); //event
+ else if (std::is_same<T, std::complex<double>>::value)
+ clblasDzasum(v.size(),
+ result_buffer.begin().get_buffer().get(), //result buffer
+ 0, //offset in result buffer
+ v.begin().get_buffer().get(), //input buffer
+ 0, //offset in input buffer
+ 1, //increment in input buffer
+ scratch_buffer.begin().get_buffer().get(),
+ 1, //number of command queues
+ &(queue.get()), //queue
+ 0, // number of events waiting list
+ NULL, //event waiting list
+ &event); //event
+ clWaitForEvents(1, &event);
+ return result_buffer[0];
+}
+
+template <typename T, typename A>
+typename std::enable_if<is_numeric<T>::value, T>::type
+a_sum(ublas::vector<T, A> const &v, compute::command_queue& queue)
+{
+ ublas::vector<T, opencl::storage> vdev(v, queue);
+ return a_sum(vdev, queue);
+}
+
+template <typename T>
+typename std::enable_if<std::is_same<T, float>::value |
+ std::is_same<T, double>::value,
+ T>::type
+norm_1(ublas::vector<T, opencl::storage> const &v, compute::command_queue& queue)
+{
+ return a_sum(v, queue);
+}
+
+template <typename T, typename A>
+typename std::enable_if<std::is_same<T, float>::value |
+ std::is_same<T, double>::value,
+ T>::type
+norm_1(ublas::vector<T, A> const &v, compute::command_queue& queue)
+{
+ ublas::vector<T, opencl::storage> vdev(v, queue);
+ return norm_1(vdev, queue);
+}
+
+template <typename T>
+typename std::enable_if<is_numeric<T>::value, T>::type
+norm_2(ublas::vector<T, opencl::storage> const &v, compute::command_queue& queue)
+{
+ compute::vector<T> scratch_buffer(2*v.size(), queue.get_context());
+ compute::vector<T> result_buffer(1, queue.get_context());
+ cl_event event;
+ if (std::is_same<T, float>::value)
+ clblasSnrm2(v.size(),
+ result_buffer.begin().get_buffer().get(), //result buffer
+ 0, //offset in result buffer
+ v.begin().get_buffer().get(), //input buffer
+ 0, //offset in input buffer
+ 1, //increment in input buffer
+ scratch_buffer.begin().get_buffer().get(),
+ 1, //number of command queues
+ &(queue.get()), //queue
+ 0, // number of events waiting list
+ NULL, //event waiting list
+ &event); //event
+ else if (std::is_same<T, double>::value)
+ clblasDnrm2(v.size(),
+ result_buffer.begin().get_buffer().get(), //result buffer
+ 0, //offset in result buffer
+ v.begin().get_buffer().get(), //input buffer
+ 0, //offset in input buffer
+ 1, //increment in input buffer
+ scratch_buffer.begin().get_buffer().get(),
+ 1, //number of command queues
+ &(queue.get()), //queue
+ 0, // number of events waiting list
+ NULL, //event waiting list
+ &event); //event
+ else if (std::is_same<T, std::complex<float>>::value)
+ clblasScnrm2(v.size(),
+ result_buffer.begin().get_buffer().get(), //result buffer
+ 0, //offset in result buffer
+ v.begin().get_buffer().get(), //input buffer
+ 0, //offset in input buffer
+ 1, //increment in input buffer
+ scratch_buffer.begin().get_buffer().get(),
+ 1, //number of command queues
+ &(queue.get()), //queue
+ 0, // number of events waiting list
+ NULL, //event waiting list
+ &event); //event
+ else if (std::is_same<T, std::complex<double>>::value)
+ clblasDznrm2(v.size(),
+ result_buffer.begin().get_buffer().get(), //result buffer
+ 0, //offset in result buffer
+ v.begin().get_buffer().get(), //input buffer
+ 0, //offset in input buffer
+ 1, //increment in input buffer
+ scratch_buffer.begin().get_buffer().get(),
+ 1, //number of command queues
+ &(queue.get()), //queue
+ 0, // number of events waiting list
+ NULL, //event waiting list
+ &event); //event
+ clWaitForEvents(1, &event);
+ return result_buffer[0];
+}
+
+template <typename T, typename A>
+typename std::enable_if<is_numeric<T>::value, T>::type
+norm_2(ublas::vector<T, A> const &v, compute::command_queue& queue)
+{
+ ublas::vector<T, opencl::storage> vdev(v, queue);
+ return norm_2(vdev, queue);
+}
+
+}}}}
+
+#endif
diff --git a/boost/numeric/ublas/opencl/operations.hpp b/boost/numeric/ublas/opencl/operations.hpp
new file mode 100644
index 0000000000..2c9e7348d6
--- /dev/null
+++ b/boost/numeric/ublas/opencl/operations.hpp
@@ -0,0 +1,18 @@
+// Boost.uBLAS
+//
+// Copyright (c) 2018 Fady Essam
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef boost_numeric_ublas_opencl_operations_hpp_
+#define boost_numeric_ublas_opencl_operations_hpp_
+
+#include <boost/numeric/ublas/opencl/transpose.hpp>
+#include <boost/numeric/ublas/opencl/prod.hpp>
+#include <boost/numeric/ublas/opencl/elementwise.hpp>
+#include <boost/numeric/ublas/opencl/misc.hpp>
+
+#endif
diff --git a/boost/numeric/ublas/opencl/prod.hpp b/boost/numeric/ublas/opencl/prod.hpp
new file mode 100644
index 0000000000..4318eff008
--- /dev/null
+++ b/boost/numeric/ublas/opencl/prod.hpp
@@ -0,0 +1,364 @@
+// Boost.uBLAS
+//
+// Copyright (c) 2018 Fady Essam
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef boost_numeric_ublas_opencl_prod_hpp_
+#define boost_numeric_ublas_opencl_prod_hpp_
+
+#include <boost/numeric/ublas/opencl/library.hpp>
+#include <boost/numeric/ublas/opencl/vector.hpp>
+#include <boost/numeric/ublas/opencl/matrix.hpp>
+#include <boost/numeric/ublas/opencl/transpose.hpp>
+#include <boost/compute/buffer.hpp>
+
+namespace boost { namespace numeric { namespace ublas { namespace opencl {
+
+#define ONE_DOUBLE_COMPLEX {{1.0, 00.0}}
+#define ONE_FLOAT_COMPLEX {{1.0f, 00.0f}}
+
+template <typename T, typename L1, typename L2>
+typename std::enable_if<is_numeric<T>::value>::type
+prod(ublas::matrix<T, L1, opencl::storage> const &a,
+ ublas::matrix<T, L2, opencl::storage> const &b,
+ ublas::matrix<T, L1, opencl::storage> &result,
+ compute::command_queue &queue)
+{
+ assert(a.device() == b.device() &&
+ a.device() == result.device() &&
+ a.device() == queue.get_device());
+ assert(a.size2() == b.size1());
+
+ result.fill(0, queue);
+
+ //to hold matrix b with layout 1 if the b has different layout
+ std::unique_ptr<ublas::matrix<T, L1, opencl::storage>> bl1;
+
+ cl_event event = NULL;
+
+ cl_mem buffer_a = a.begin().get_buffer().get();
+ cl_mem buffer_b = b.begin().get_buffer().get();
+ cl_mem buffer_result = result.begin().get_buffer().get();
+
+ if (!(std::is_same<L1, L2>::value))
+ {
+ bl1.reset(new ublas::matrix<T, L1, opencl::storage>(b.size1(), b.size2(), queue.get_context()));
+ change_layout(b, *bl1, queue);
+ buffer_b = bl1->begin().get_buffer().get();
+ }
+
+ clblasOrder Order = std::is_same<L1, ublas::basic_row_major<> >::value ? clblasRowMajor : clblasColumnMajor;
+ size_t lda = Order == clblasRowMajor ? a.size2() : a.size1();
+ size_t ldb = Order == clblasRowMajor ? b.size2() : a.size2();
+ size_t ldc = Order == clblasRowMajor ? b.size2() : a.size1();
+
+ if (std::is_same<T, float>::value)
+ clblasSgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size1(), b.size2(), a.size2(),
+ 1, buffer_a, 0, lda,
+ buffer_b, 0, ldb, 1,
+ buffer_result, 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, double>::value)
+ clblasDgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size1(), b.size2(), a.size2(),
+ 1, buffer_a, 0, lda,
+ buffer_b, 0, ldb, 1,
+ buffer_result, 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, std::complex<float>>::value)
+ clblasCgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size1(), b.size2(), a.size2(),
+ ONE_FLOAT_COMPLEX, buffer_a, 0, lda,
+ buffer_b, 0, ldb, ONE_FLOAT_COMPLEX,
+ buffer_result, 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, std::complex<double>>::value)
+ clblasZgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size1(), b.size2(), a.size2(),
+ ONE_DOUBLE_COMPLEX, buffer_a, 0, lda,
+ buffer_b, 0, ldb, ONE_DOUBLE_COMPLEX,
+ buffer_result, 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ clWaitForEvents(1, &event);
+}
+
+template <typename T, typename L1, typename L2, typename A>
+typename std::enable_if<is_numeric<T>::value>::type
+prod(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ ublas::matrix<T, L1, A> &result,
+ compute::command_queue &queue)
+{
+ ublas::matrix<T, L1, opencl::storage> adev(a, queue);
+ ublas::matrix<T, L2, opencl::storage> bdev(b, queue);
+ ublas::matrix<T, L1, opencl::storage> rdev(a.size1(), b.size2(), queue.get_context());
+ prod(adev, bdev, rdev, queue);
+ rdev.to_host(result,queue);
+}
+
+template <typename T, typename L1, typename L2, typename A>
+typename std::enable_if<is_numeric<T>::value, ublas::matrix<T, L1, A>>::type
+prod(ublas::matrix<T, L1, A> const &a,
+ ublas::matrix<T, L2, A> const &b,
+ compute::command_queue &queue)
+{
+ ublas::matrix<T, L1, A> result(a.size1(), b.size2());
+ prod(a, b, result, queue);
+ return result;
+}
+
+template <typename T, typename L>
+typename std::enable_if<is_numeric<T>::value>::type
+prod(ublas::matrix<T, L, opencl::storage> const &a,
+ ublas::vector<T, opencl::storage> const &b,
+ ublas::vector<T, opencl::storage> &result,
+ compute::command_queue &queue)
+{
+ assert(a.device() == b.device() &&
+ a.device() == result.device() &&
+ a.device() == queue.get_device());
+ assert(a.size2() == b.size());
+ result.fill(0, queue);
+
+ cl_event event = NULL;
+ clblasOrder Order = std::is_same<L, ublas::basic_row_major<> >::value ? clblasRowMajor : clblasColumnMajor;
+ int lda = Order == clblasRowMajor ? a.size2() : a.size1();
+ int ldb = Order == clblasRowMajor ? 1 : a.size2();
+ int ldc = Order == clblasRowMajor ? 1 : a.size1();
+
+ if (std::is_same<T, float>::value)
+ clblasSgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size1(), 1, a.size2(),
+ 1, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, 1,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, double>::value)
+ clblasDgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size1(), 1, a.size2(),
+ 1, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, 1,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, std::complex<float>>::value)
+ clblasCgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size1(), 1, a.size2(),
+ ONE_FLOAT_COMPLEX, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, ONE_FLOAT_COMPLEX,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, std::complex<double>>::value)
+ clblasZgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size1(), 1, a.size2(),
+ ONE_DOUBLE_COMPLEX, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, ONE_DOUBLE_COMPLEX,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ clWaitForEvents(1, &event);
+}
+
+template <typename T, typename L, typename A>
+typename std::enable_if<is_numeric<T>::value>::type
+prod(ublas::matrix<T, L, A> const &a,
+ ublas::vector<T, A> const &b,
+ ublas::vector<T, A> &result,
+ compute::command_queue &queue)
+{
+ ublas::matrix<T, L, opencl::storage> adev(a, queue);
+ ublas::vector<T, opencl::storage> bdev(b, queue);
+ ublas::vector<T, opencl::storage> rdev(a.size1(), queue.get_context());
+ prod(adev, bdev, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template <typename T, typename L, typename A>
+typename std::enable_if<is_numeric<T>::value, ublas::vector<T, A>>::type
+prod(ublas::matrix<T, L, A> const &a,
+ ublas::vector<T, A> const &b,
+ compute::command_queue &queue)
+{
+ ublas::vector<T, A> result(a.size1());
+ prod(a, b, result, queue);
+ return result;
+}
+
+template <typename T, typename L>
+typename std::enable_if<is_numeric<T>::value>::type
+prod(ublas::vector<T, opencl::storage> const &a,
+ ublas::matrix<T, L, opencl::storage> const &b,
+ ublas::vector<T, opencl::storage> &result,
+ compute::command_queue &queue)
+{
+ assert(a.device() == b.device() &&
+ a.device() == result.device() &&
+ a.device() == queue.get_device());
+ assert(a.size() == b.size1());
+ result.fill(0, queue);
+ cl_event event = NULL;
+ clblasOrder Order = std::is_same<L, ublas::basic_row_major<> >::value ? clblasRowMajor : clblasColumnMajor;
+ size_t lda = Order == clblasRowMajor ? a.size() : 1;
+ size_t ldb = Order == clblasRowMajor ? b.size2() : a.size();
+ size_t ldc = Order == clblasRowMajor ? b.size2() : 1;
+
+ if (std::is_same<T, float>::value)
+ clblasSgemm(Order, clblasNoTrans, clblasNoTrans,
+ 1, b.size2(), a.size(),
+ 1, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, 1,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, double>::value)
+ clblasDgemm(Order, clblasNoTrans, clblasNoTrans,
+ 1, b.size2(), a.size(),
+ 1, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, 1,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, std::complex<float>>::value)
+ clblasCgemm(Order, clblasNoTrans, clblasNoTrans,
+ 1, b.size2(), a.size(),
+ ONE_FLOAT_COMPLEX, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, ONE_FLOAT_COMPLEX,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, std::complex<double>>::value)
+ clblasZgemm(Order, clblasNoTrans, clblasNoTrans,
+ 1, b.size2(), a.size(),
+ ONE_DOUBLE_COMPLEX, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, ONE_DOUBLE_COMPLEX,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ clWaitForEvents(1, &event);
+}
+
+template <class T, class L, class A>
+typename std::enable_if<is_numeric<T>::value>::type
+prod(ublas::vector<T, A> const &a,
+ ublas::matrix<T, L, A> const &b,
+ ublas::vector<T, A> &result,
+ compute::command_queue &queue)
+{
+ ublas::vector<T, opencl::storage> adev(a, queue);
+ ublas::matrix<T, L, opencl::storage> bdev(b, queue);
+ ublas::vector<T, opencl::storage> rdev(b.size2(), queue.get_context());
+ prod(adev, bdev, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template <class T, class L, class A>
+typename std::enable_if<is_numeric<T>::value, ublas::vector<T, A>>::type
+prod(ublas::vector<T, A> const &a,
+ ublas::matrix<T, L, A> const &b,
+ compute::command_queue &queue)
+{
+ ublas::vector<T, A> result(b.size2());
+ prod(a, b, result, queue);
+ return result;
+}
+
+template<class T>
+typename std::enable_if<std::is_fundamental<T>::value, T>::type
+inner_prod(ublas::vector<T, opencl::storage> const &a,
+ ublas::vector<T, opencl::storage> const &b,
+ compute::command_queue &queue)
+{
+ assert(a.device() == b.device() && a.device() == queue.get_device());
+ assert(a.size() == b.size());
+ return compute::inner_product(a.begin(), a.end(), b.begin(), T(0), queue);
+}
+
+template<class T, class A>
+typename std::enable_if<std::is_fundamental<T>::value, T>::type
+inner_prod(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ compute::command_queue& queue)
+{
+ ublas::vector<T, opencl::storage> adev(a, queue);
+ ublas::vector<T, opencl::storage> bdev(b, queue);
+ return inner_prod(adev, bdev, queue);
+}
+
+template <class T, class L>
+typename std::enable_if<is_numeric<T>::value>::type
+outer_prod(ublas::vector<T, opencl::storage> const &a,
+ ublas::vector<T, opencl::storage> const &b,
+ ublas::matrix<T, L, opencl::storage> &result,
+ compute::command_queue & queue)
+{
+ assert(a.device() == b.device() &&
+ a.device() == result.device() &&
+ a.device() == queue.get_device());
+ result.fill(0, queue);
+ cl_event event = NULL;
+ clblasOrder Order = std::is_same<L, ublas::basic_row_major<> >::value ? clblasRowMajor : clblasColumnMajor;
+ size_t lda = Order == clblasRowMajor ? 1 : a.size();
+ size_t ldb = Order == clblasRowMajor ? b.size() : 1;
+ size_t ldc = Order == clblasRowMajor ? b.size() : a.size();
+
+ if (std::is_same<T, float>::value)
+ clblasSgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size(), b.size(), 1,
+ 1, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, 1,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, double>::value)
+ clblasDgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size(), b.size(), 1,
+ 1, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, 1,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, std::complex<float>>::value)
+ clblasCgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size(), b.size(), 1,
+ ONE_FLOAT_COMPLEX, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, ONE_FLOAT_COMPLEX,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ else if (std::is_same<T, std::complex<double>>::value)
+ clblasZgemm(Order, clblasNoTrans, clblasNoTrans,
+ a.size(), b.size(), 1,
+ ONE_DOUBLE_COMPLEX, a.begin().get_buffer().get(), 0, lda,
+ b.begin().get_buffer().get(), 0, ldb, ONE_DOUBLE_COMPLEX,
+ result.begin().get_buffer().get(), 0, ldc,
+ 1, &(queue.get()), 0, NULL, &event);
+ clWaitForEvents(1, &event);
+}
+
+template <class T, class L, class A>
+typename std::enable_if<is_numeric<T>::value>::type
+outer_prod(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ ublas::matrix<T, L, A> &result,
+ compute::command_queue &queue)
+{
+ ublas::vector<T, opencl::storage> adev(a, queue);
+ ublas::vector<T, opencl::storage> bdev(b, queue);
+ ublas::matrix<T, L, opencl::storage> rdev(a.size(), b.size(), queue.get_context());
+ outer_prod(adev, bdev, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template <class T,class L = ublas::basic_row_major<>, class A>
+typename std::enable_if<is_numeric<T>::value, ublas::matrix<T, L, A>>::type
+outer_prod(ublas::vector<T, A> const &a,
+ ublas::vector<T, A> const &b,
+ compute::command_queue &queue)
+{
+ ublas::matrix<T, L, A> result(a.size(), b.size());
+ outer_prod(a, b, result, queue);
+ return result;
+}
+
+#undef ONE_DOUBLE_COMPLEX
+#undef ONE_FLOAT_COMPLEX
+
+}}}}
+
+#endif
diff --git a/boost/numeric/ublas/opencl/transpose.hpp b/boost/numeric/ublas/opencl/transpose.hpp
new file mode 100644
index 0000000000..93508c8971
--- /dev/null
+++ b/boost/numeric/ublas/opencl/transpose.hpp
@@ -0,0 +1,142 @@
+// Boost.uBLAS
+//
+// Copyright (c) 2018 Fady Essam
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef boost_numeric_ublas_opencl_transpose_hpp_
+#define boost_numeric_ublas_opencl_transpose_hpp_
+
+#include <boost/numeric/ublas/opencl/library.hpp>
+#include <boost/numeric/ublas/opencl/vector.hpp>
+#include <boost/numeric/ublas/opencl/matrix.hpp>
+
+// Kernel for transposition of various data types
+#define OPENCL_TRANSPOSITION_KERNEL(DATA_TYPE) \
+"__kernel void transpose(__global " #DATA_TYPE "* in, __global " #DATA_TYPE "* result, unsigned int width, unsigned int height) \n" \
+"{ \n" \
+" unsigned int column_index = get_global_id(0); \n" \
+" unsigned int row_index = get_global_id(1); \n" \
+" if (column_index < width && row_index < height) \n" \
+" { \n" \
+" unsigned int index_in = column_index + width * row_index; \n" \
+" unsigned int index_result = row_index + height * column_index; \n" \
+" result[index_result] = in[index_in]; \n" \
+" } \n" \
+"} \n"
+
+
+namespace boost { namespace numeric { namespace ublas { namespace opencl {
+
+template<class T, class L1, class L2>
+typename std::enable_if<is_numeric<T>::value>::type
+change_layout(ublas::matrix<T, L1, opencl::storage> const &m,
+ ublas::matrix<T, L2, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ assert(m.size1() == result.size1() && m.size2() == result.size2());
+ assert(m.device() == result.device() && m.device() == queue.get_device());
+ assert(!(std::is_same<L1, L2>::value));
+ char const *kernel;
+ if (std::is_same<T, float>::value)
+ kernel = OPENCL_TRANSPOSITION_KERNEL(float);
+ else if (std::is_same<T, double>::value)
+ kernel = OPENCL_TRANSPOSITION_KERNEL(double);
+ else if (std::is_same<T, std::complex<float>>::value)
+ kernel = OPENCL_TRANSPOSITION_KERNEL(float2);
+ else if (std::is_same<T, std::complex<double>>::value)
+ kernel = OPENCL_TRANSPOSITION_KERNEL(double2);
+ size_t len = strlen(kernel);
+ cl_int err;
+ cl_context c_context = queue.get_context().get();
+ cl_program program = clCreateProgramWithSource(c_context, 1, &kernel, &len, &err);
+ clBuildProgram(program, 1, &queue.get_device().get(), NULL, NULL, NULL);
+ cl_kernel c_kernel = clCreateKernel(program, "transpose", &err);
+ size_t width = std::is_same < L1, ublas::basic_row_major<>>::value ? m.size2() : m.size1();
+ size_t height = std::is_same < L1, ublas::basic_row_major<>>::value ? m.size1() : m.size2();
+ size_t global_size[2] = { width , height };
+ clSetKernelArg(c_kernel, 0, sizeof(T*), &m.begin().get_buffer().get());
+ clSetKernelArg(c_kernel, 1, sizeof(T*), &result.begin().get_buffer().get());
+ clSetKernelArg(c_kernel, 2, sizeof(unsigned int), &width);
+ clSetKernelArg(c_kernel, 3, sizeof(unsigned int), &height);
+ cl_command_queue c_queue = queue.get();
+ cl_event event = NULL;
+ clEnqueueNDRangeKernel(c_queue, c_kernel, 2, NULL, global_size, NULL, 0, NULL, &event);
+ clWaitForEvents(1, &event);
+}
+
+template<class T, class L1, class L2, class A>
+typename std::enable_if<is_numeric<T>::value>::type
+change_layout(ublas::matrix<T, L1, A> const &m,
+ ublas::matrix<T, L2, A> &result,
+ compute::command_queue& queue)
+{
+ ublas::matrix<T, L1, opencl::storage> mdev(m, queue);
+ ublas::matrix<T, L2, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context());
+ change_layout(mdev, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template<class T, class L>
+typename std::enable_if<is_numeric<T>::value>::type
+trans(ublas::matrix<T, L, opencl::storage> const &m,
+ ublas::matrix<T, L, opencl::storage> &result,
+ compute::command_queue& queue)
+{
+ assert(m.size1() == result.size2() && m.size2() == result.size1());
+ assert(m.device() == result.device() && m.device() == queue.get_device());
+ char const *kernel;
+ if (std::is_same<T, float>::value)
+ kernel = OPENCL_TRANSPOSITION_KERNEL(float);
+ else if (std::is_same<T, double>::value)
+ kernel = OPENCL_TRANSPOSITION_KERNEL(double);
+ else if (std::is_same<T, std::complex<float>>::value)
+ kernel = OPENCL_TRANSPOSITION_KERNEL(float2);
+ else if (std::is_same<T, std::complex<double>>::value)
+ kernel = OPENCL_TRANSPOSITION_KERNEL(double2);
+ size_t len = strlen(kernel);
+ cl_int err;
+ cl_context c_context = queue.get_context().get();
+ cl_program program = clCreateProgramWithSource(c_context, 1, &kernel, &len, &err);
+ clBuildProgram(program, 1, &queue.get_device().get(), NULL, NULL, NULL);
+ cl_kernel c_kernel = clCreateKernel(program, "transpose", &err);
+ size_t width = std::is_same <L, ublas::basic_row_major<>>::value ? m.size2() : m.size1();
+ size_t height = std::is_same <L, ublas::basic_row_major<>>::value ? m.size1() : m.size2();
+ size_t global_size[2] = { width , height };
+ clSetKernelArg(c_kernel, 0, sizeof(T*), &m.begin().get_buffer().get());
+ clSetKernelArg(c_kernel, 1, sizeof(T*), &result.begin().get_buffer().get());
+ clSetKernelArg(c_kernel, 2, sizeof(unsigned int), &width);
+ clSetKernelArg(c_kernel, 3, sizeof(unsigned int), &height);
+ cl_command_queue c_queue = queue.get();
+ cl_event event = NULL;
+ clEnqueueNDRangeKernel(c_queue, c_kernel, 2, NULL, global_size, NULL, 0, NULL, &event);
+ clWaitForEvents(1, &event);
+}
+
+template<class T, class L, class A>
+typename std::enable_if<is_numeric<T>::value>::type
+trans(ublas::matrix<T, L, A> const &m,
+ ublas::matrix<T, L, A> &result,
+ compute::command_queue& queue)
+{
+ ublas::matrix<T, L, opencl::storage> mdev(m, queue);
+ ublas::matrix<T, L, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context());
+ trans(mdev, rdev, queue);
+ rdev.to_host(result, queue);
+}
+
+template<class T, class L, class A>
+typename std::enable_if<is_numeric<T>::value, ublas::matrix<T, L, A>>::type
+trans(ublas::matrix<T, L, A>& m, compute::command_queue& queue)
+{
+ ublas::matrix<T, L, A> result(m.size2(), m.size1());
+ trans(m, result, queue);
+ return result;
+}
+
+}}}}
+
+#endif
diff --git a/boost/numeric/ublas/opencl/vector.hpp b/boost/numeric/ublas/opencl/vector.hpp
new file mode 100644
index 0000000000..1defa80461
--- /dev/null
+++ b/boost/numeric/ublas/opencl/vector.hpp
@@ -0,0 +1,90 @@
+// Boost.uBLAS
+//
+// Copyright (c) 2018 Fady Essam
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef boost_numeric_ublas_opencl_vector_hpp_
+#define boost_numeric_ublas_opencl_vector_hpp_
+
+#include <boost/numeric/ublas/opencl/library.hpp>
+#include <boost/numeric/ublas/functional.hpp>
+#include <boost/compute/core.hpp>
+#include <boost/compute/algorithm.hpp>
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace boost { namespace numeric { namespace ublas { namespace opencl {
+
+class storage;
+
+namespace compute = boost::compute;
+
+} // namespace opencl
+
+template <class T>
+class vector<T, opencl::storage> : public boost::compute::vector<T>
+{
+ typedef std::size_t size_type;
+public:
+ vector() : compute::vector<T>() {}
+ vector(size_type size, compute::context context)
+ : compute::vector<T>(size, context)
+ { device_ = context.get_device();}
+ vector(size_type size, T value, compute::command_queue queue)
+ : compute::vector<T>(size, value, queue.get_context())
+ {
+ queue.finish();
+ device_ = queue.get_device();
+ }
+
+ template <typename A>
+ vector(vector<T, A> const &v, compute::command_queue &queue)
+ : vector(v.size(), queue.get_context())
+ {
+ this->from_host(v, queue);
+ }
+
+
+ const compute::device device() const { return device_;}
+ compute::device device() { return device_;}
+
+ template<class A>
+ void from_host(ublas::vector<T, A> const &v, compute::command_queue & queue)
+ {
+ assert(this->device() == queue.get_device());
+ compute::copy(v.begin(),
+ v.end(),
+ this->begin(),
+ queue);
+ queue.finish();
+ }
+
+ template<class A>
+ void to_host(ublas::vector<T, A>& v, compute::command_queue& queue) const
+ {
+ assert(this->device() == queue.get_device());
+ compute::copy(this->begin(),
+ this->end(),
+ v.begin(),
+ queue);
+ queue.finish();
+ }
+
+ void fill(T value, compute::command_queue & queue)
+ {
+ assert(this->device() == queue.get_device());
+ compute::fill(this->begin(), this->end(), value, queue);
+ queue.finish();
+ }
+
+private:
+ compute::device device_;
+};
+
+}}}
+
+#endif
diff --git a/boost/numeric/ublas/operation/begin.hpp b/boost/numeric/ublas/operation/begin.hpp
index d14bb35cac..ea71349d64 100644
--- a/boost/numeric/ublas/operation/begin.hpp
+++ b/boost/numeric/ublas/operation/begin.hpp
@@ -28,289 +28,289 @@ namespace boost { namespace numeric { namespace ublas {
namespace detail {
- /**
- * \brief Auxiliary class for implementing the \c begin operation.
- * \tparam CategoryT The expression category type (e.g., vector_tag).
- * \tparam TagT The dimension type tag (e.g., tag::major).
- * \tparam OrientationT The orientation category type (e.g., row_major_tag).
- */
- template <typename CategoryT, typename TagT=void, typename OrientationT=void>
- struct begin_impl;
-
-
- /// \brief Specialization of \c begin_impl for iterating vector expressions.
- template <>
- struct begin_impl<vector_tag,void,void>
- {
- /**
- * \brief Return an iterator to the first element of the given vector
- * expression.
- * \tparam ExprT A model of VectorExpression type.
- * \param e A vector expression.
- * \return An iterator over the given vector expression.
- */
- template <typename ExprT>
- static typename ExprT::iterator apply(ExprT& e)
- {
- return e.begin();
- }
-
-
- /**
- * \brief Return a const iterator to the first element of the given vector
- * expression.
- * \tparam ExprT A model of VectorExpression type.
- * \param e A vector expression.
- * \return A const iterator to the first element of the given vector
- * expression.
- */
- template <typename ExprT>
- static typename ExprT::const_iterator apply(ExprT const& e)
- {
- return e.begin();
- }
- };
-
-
- /// \brief Specialization of \c begin_impl for iterating matrix expressions with
- /// a row-major orientation over the major dimension.
- template <>
- struct begin_impl<matrix_tag,tag::major,row_major_tag>
- {
- /**
- * \brief Return an iterator to the first element of the given row-major
- * matrix expression over the major dimension.
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return An iterator over the major dimension of the given matrix
- * expression.
- */
- template <typename ExprT>
- static typename ExprT::iterator1 apply(ExprT& e)
- {
- return e.begin1();
- }
-
-
- /**
- * \brief Return a const iterator to the first element of the given
- * row-major matrix expression over the major dimension.
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return A const iterator over the major dimension of the given matrix
- * expression.
- */
- template <typename ExprT>
- static typename ExprT::const_iterator1 apply(ExprT const& e)
- {
- return e.begin1();
- }
- };
-
-
- /// \brief Specialization of \c begin_impl for iterating matrix expressions with
- /// a column-major orientation over the major dimension.
- template <>
- struct begin_impl<matrix_tag,tag::major,column_major_tag>
- {
- /**
- * \brief Return an iterator to the first element of the given column-major
- * matrix expression over the major dimension.
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return An iterator over the major dimension of the given matrix
- * expression.
- */
- template <typename ExprT>
- static typename ExprT::iterator2 apply(ExprT& e)
- {
- return e.begin2();
- }
-
-
- /**
- * \brief Return a const iterator to the first element of the given
- * column-major matrix expression over the major dimension.
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return A const iterator over the major dimension of the given matrix
- * expression.
- */
- template <typename ExprT>
- static typename ExprT::const_iterator2 apply(ExprT const& e)
- {
- return e.begin2();
- }
- };
-
-
- /// \brief Specialization of \c begin_impl for iterating matrix expressions with
- /// a row-major orientation over the minor dimension.
- template <>
- struct begin_impl<matrix_tag,tag::minor,row_major_tag>
- {
- /**
- * \brief Return an iterator to the first element of the given row-major
- * matrix expression over the minor dimension.
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return An iterator over the minor dimension of the given matrix
- * expression.
- */
- template <typename ExprT>
- static typename ExprT::iterator2 apply(ExprT& e)
- {
- return e.begin2();
- }
-
-
- /**
- * \brief Return a const iterator to the first element of the given
- * row-major matrix expression over the minor dimension.
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return A const iterator over the minor dimension of the given matrix
- * expression.
- */
- template <typename ExprT>
- static typename ExprT::const_iterator2 apply(ExprT const& e)
- {
- return e.begin2();
- }
- };
-
-
-
- /// \brief Specialization of \c begin_impl for iterating matrix expressions with
- /// a column-major orientation over the minor dimension.
- template <>
- struct begin_impl<matrix_tag,tag::minor,column_major_tag>
- {
- /**
- * \brief Return an iterator to the first element of the given column-major
- * matrix expression over the minor dimension.
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return An iterator over the minor dimension of the given matrix
- * expression.
- */
- template <typename ExprT>
- static typename ExprT::iterator1 apply(ExprT& e)
- {
- return e.begin1();
- }
-
-
- /**
- * \brief Return a const iterator to the first element of the given
- * column-major matrix expression over the minor dimension.
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return A const iterator over the minor dimension of the given matrix
- * expression.
- */
- template <typename ExprT>
- static typename ExprT::const_iterator1 apply(ExprT const& e)
- {
- return e.begin1();
- }
- };
-
- } // Namespace detail
-
-
- /**
- * \brief An iterator to the first element of the given vector expression.
- * \tparam ExprT A model of VectorExpression type.
- * \param e A vector expression.
- * \return An iterator to the first element of the given vector expression.
- */
- template <typename ExprT>
- BOOST_UBLAS_INLINE
- typename ExprT::iterator begin(vector_expression<ExprT>& e)
- {
- return detail::begin_impl<typename ExprT::type_category>::apply(e());
- }
-
-
- /**
- * \brief A const iterator to the first element of the given vector expression.
- * \tparam ExprT A model of VectorExpression type.
- * \param e A vector expression.
- * \return A const iterator to the first element of the given vector expression.
- */
- template <typename ExprT>
- BOOST_UBLAS_INLINE
- typename ExprT::const_iterator begin(vector_expression<ExprT> const& e)
- {
- return detail::begin_impl<typename ExprT::type_category>::apply(e());
- }
-
-
- /**
- * \brief An iterator to the first element of the given matrix expression
- * according to its orientation.
- * \tparam DimTagT A dimension tag type (e.g., tag::major).
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return An iterator to the first element of the given matrix expression
- * according to its orientation.
- */
- template <typename TagT, typename ExprT>
- BOOST_UBLAS_INLINE
- typename iterator_type<ExprT,TagT>::type begin(matrix_expression<ExprT>& e)
- {
- return detail::begin_impl<typename ExprT::type_category, TagT, typename ExprT::orientation_category>::apply(e());
- }
-
-
- /**
- * \brief A const iterator to the first element of the given matrix expression
- * according to its orientation.
- * \tparam TagT A dimension tag type (e.g., tag::major).
- * \tparam ExprT A model of MatrixExpression type.
- * \param e A matrix expression.
- * \return A const iterator to the first element of the given matrix expression
- * according to its orientation.
- */
- template <typename TagT, typename ExprT>
- BOOST_UBLAS_INLINE
- typename const_iterator_type<ExprT,TagT>::type begin(matrix_expression<ExprT> const& e)
- {
- return detail::begin_impl<typename ExprT::type_category, TagT, typename ExprT::orientation_category>::apply(e());
- }
-
-
- /**
- * \brief An iterator to the first element over the dual dimension of the given
- * iterator.
- * \tparam IteratorT A model of Iterator type.
- * \param it An iterator.
- * \return An iterator to the first element over the dual dimension of the given
- * iterator.
- */
- template <typename IteratorT>
- BOOST_UBLAS_INLINE
- typename IteratorT::dual_iterator_type begin(IteratorT& it)
- {
- return it.begin();
- }
-
-
- /**
- * \brief A const iterator to the first element over the dual dimension of the
- * given iterator.
- * \tparam IteratorT A model of Iterator type.
- * \param it An iterator.
- * \return A const iterator to the first element over the dual dimension of the
- * given iterator.
- */
- template <typename IteratorT>
- BOOST_UBLAS_INLINE
- typename IteratorT::dual_iterator_type begin(IteratorT const& it)
- {
- return it.begin();
- }
+ /**
+ * \brief Auxiliary class for implementing the \c begin operation.
+ * \tparam CategoryT The expression category type (e.g., vector_tag).
+ * \tparam TagT The dimension type tag (e.g., tag::major).
+ * \tparam OrientationT The orientation category type (e.g., row_major_tag).
+ */
+ template <typename CategoryT, typename TagT=void, typename OrientationT=void>
+ struct begin_impl;
+
+
+ /// \brief Specialization of \c begin_impl for iterating vector expressions.
+ template <>
+ struct begin_impl<vector_tag,void,void>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given vector
+ * expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return An iterator over the given vector expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator apply(ExprT& e)
+ {
+ return e.begin();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given vector
+ * expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return A const iterator to the first element of the given vector
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator apply(ExprT const& e)
+ {
+ return e.begin();
+ }
+ };
+
+
+ /// \brief Specialization of \c begin_impl for iterating matrix expressions with
+ /// a row-major orientation over the major dimension.
+ template <>
+ struct begin_impl<matrix_tag,tag::major,row_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given row-major
+ * matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator1 apply(ExprT& e)
+ {
+ return e.begin1();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given
+ * row-major matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator1 apply(ExprT const& e)
+ {
+ return e.begin1();
+ }
+ };
+
+
+ /// \brief Specialization of \c begin_impl for iterating matrix expressions with
+ /// a column-major orientation over the major dimension.
+ template <>
+ struct begin_impl<matrix_tag,tag::major,column_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given column-major
+ * matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator2 apply(ExprT& e)
+ {
+ return e.begin2();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given
+ * column-major matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator2 apply(ExprT const& e)
+ {
+ return e.begin2();
+ }
+ };
+
+
+ /// \brief Specialization of \c begin_impl for iterating matrix expressions with
+ /// a row-major orientation over the minor dimension.
+ template <>
+ struct begin_impl<matrix_tag,tag::minor,row_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given row-major
+ * matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator2 apply(ExprT& e)
+ {
+ return e.begin2();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given
+ * row-major matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator2 apply(ExprT const& e)
+ {
+ return e.begin2();
+ }
+ };
+
+
+
+ /// \brief Specialization of \c begin_impl for iterating matrix expressions with
+ /// a column-major orientation over the minor dimension.
+ template <>
+ struct begin_impl<matrix_tag,tag::minor,column_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given column-major
+ * matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator1 apply(ExprT& e)
+ {
+ return e.begin1();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given
+ * column-major matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator1 apply(ExprT const& e)
+ {
+ return e.begin1();
+ }
+ };
+
+ } // Namespace detail
+
+
+ /**
+ * \brief An iterator to the first element of the given vector expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return An iterator to the first element of the given vector expression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename ExprT::iterator begin(vector_expression<ExprT>& e)
+ {
+ return detail::begin_impl<typename ExprT::type_category>::apply(e());
+ }
+
+
+ /**
+ * \brief A const iterator to the first element of the given vector expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return A const iterator to the first element of the given vector expression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename ExprT::const_iterator begin(vector_expression<ExprT> const& e)
+ {
+ return detail::begin_impl<typename ExprT::type_category>::apply(e());
+ }
+
+
+ /**
+ * \brief An iterator to the first element of the given matrix expression
+ * according to its orientation.
+ * \tparam DimTagT A dimension tag type (e.g., tag::major).
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator to the first element of the given matrix expression
+ * according to its orientation.
+ */
+ template <typename TagT, typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename iterator_type<ExprT,TagT>::type begin(matrix_expression<ExprT>& e)
+ {
+ return detail::begin_impl<typename ExprT::type_category, TagT, typename ExprT::orientation_category>::apply(e());
+ }
+
+
+ /**
+ * \brief A const iterator to the first element of the given matrix expression
+ * according to its orientation.
+ * \tparam TagT A dimension tag type (e.g., tag::major).
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator to the first element of the given matrix expression
+ * according to its orientation.
+ */
+ template <typename TagT, typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename const_iterator_type<ExprT,TagT>::type begin(matrix_expression<ExprT> const& e)
+ {
+ return detail::begin_impl<typename ExprT::type_category, TagT, typename ExprT::orientation_category>::apply(e());
+ }
+
+
+ /**
+ * \brief An iterator to the first element over the dual dimension of the given
+ * iterator.
+ * \tparam IteratorT A model of Iterator type.
+ * \param it An iterator.
+ * \return An iterator to the first element over the dual dimension of the given
+ * iterator.
+ */
+ template <typename IteratorT>
+ BOOST_UBLAS_INLINE
+ typename IteratorT::dual_iterator_type begin(IteratorT& it)
+ {
+ return it.begin();
+ }
+
+
+ /**
+ * \brief A const iterator to the first element over the dual dimension of the
+ * given iterator.
+ * \tparam IteratorT A model of Iterator type.
+ * \param it An iterator.
+ * \return A const iterator to the first element over the dual dimension of the
+ * given iterator.
+ */
+ template <typename IteratorT>
+ BOOST_UBLAS_INLINE
+ typename IteratorT::dual_iterator_type begin(IteratorT const& it)
+ {
+ return it.begin();
+ }
}}} // Namespace boost::numeric::ublas
diff --git a/boost/numeric/ublas/storage.hpp b/boost/numeric/ublas/storage.hpp
index bd648925a9..e28ac7c1b4 100644
--- a/boost/numeric/ublas/storage.hpp
+++ b/boost/numeric/ublas/storage.hpp
@@ -66,7 +66,15 @@ namespace boost { namespace numeric { namespace ublas {
alloc_(a), size_ (size) {
if (size_) {
data_ = alloc_.allocate (size_);
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (! detail::has_trivial_constructor<T>::value) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
for (pointer d = data_; d != data_ + size_; ++d)
alloc_.construct(d, value_type());
}
@@ -96,10 +104,28 @@ namespace boost { namespace numeric { namespace ublas {
else
data_ = 0;
}
+#ifdef BOOST_UBLAS_CPP_GE_2011
+ BOOST_UBLAS_INLINE
+ unbounded_array (unbounded_array &&c) :
+ storage_array<unbounded_array<T, ALLOC> >(),
+ alloc_ (std::move(c.alloc_)), size_ (c.size_), data_(c.data_)
+ {
+ c.size_ = 0;
+ c.data_ = nullptr;
+ }
+#endif
BOOST_UBLAS_INLINE
~unbounded_array () {
if (size_) {
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (! detail::has_trivial_destructor<T>::value) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
// std::_Destroy (begin(), end(), alloc_);
const iterator i_end = end();
for (iterator i = begin (); i != i_end; ++i) {
@@ -138,7 +164,15 @@ namespace boost { namespace numeric { namespace ublas {
}
}
else {
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (! detail::has_trivial_constructor<T>::value) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
for (pointer di = data_; di != data_ + size; ++di)
alloc_.construct (di, value_type());
}
@@ -146,7 +180,15 @@ namespace boost { namespace numeric { namespace ublas {
}
if (size_) {
+//Disabled warning C4127 because the conditional expression is constant
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
if (! detail::has_trivial_destructor<T>::value) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
for (pointer si = p_data; si != p_data + size_; ++si)
alloc_.destroy (si);
}
@@ -303,6 +345,7 @@ namespace boost { namespace numeric { namespace ublas {
// Handle explict destroy on a (possibly indexed) iterator
BOOST_UBLAS_INLINE
static void iterator_destroy (iterator &i) {
+ (void)(i);
(&(*i)) -> ~value_type ();
}
ALLOC alloc_;
diff --git a/boost/numeric/ublas/storage_sparse.hpp b/boost/numeric/ublas/storage_sparse.hpp
index c8a64a9d55..f87685c796 100644
--- a/boost/numeric/ublas/storage_sparse.hpp
+++ b/boost/numeric/ublas/storage_sparse.hpp
@@ -195,14 +195,13 @@ namespace boost { namespace numeric { namespace ublas {
// Default map type is simply forwarded to std::map
- // FIXME should use ALLOC for map but std::allocator of std::pair<const I, T> and std::pair<I,T> fail to compile
template<class I, class T, class ALLOC>
- class map_std : public std::map<I, T /*, ALLOC */> {
+ class map_std : public std::map<I, T, std::less<I>, ALLOC> {
public:
// Serialization
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */){
- ar & serialization::make_nvp("base", boost::serialization::base_object< std::map<I, T /*, ALLOC */> >(*this));
+ ar & serialization::make_nvp("base", boost::serialization::base_object< std::map<I, T, std::less<I>, ALLOC> >(*this));
}
};
@@ -398,7 +397,7 @@ namespace boost { namespace numeric { namespace ublas {
}
// Form Sorted Associative Container concept
// BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
- iterator insert (iterator hint, const value_type &p) {
+ iterator insert (iterator /*hint*/, const value_type &p) {
return insert (p).first;
}
// BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
diff --git a/boost/numeric/ublas/tensor.hpp b/boost/numeric/ublas/tensor.hpp
new file mode 100644
index 0000000000..5a72d43bbc
--- /dev/null
+++ b/boost/numeric/ublas/tensor.hpp
@@ -0,0 +1,26 @@
+// Copyright (c) 2018-2019
+// Cem Bassoy
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer and Google in producing this work
+// which started as a Google Summer of Code project.
+//
+
+/// \file tensor.hpp Definition for the class vector and its derivative
+
+#ifndef BOOST_NUMERIC_UBLAS_TENSOR_HPP
+#define BOOST_NUMERIC_UBLAS_TENSOR_HPP
+
+#include "tensor/functions.hpp"
+#include "tensor/operators_arithmetic.hpp"
+#include "tensor/operators_comparison.hpp"
+#include "tensor/extents.hpp"
+#include "tensor/strides.hpp"
+#include "tensor/ostream.hpp"
+#include "tensor/tensor.hpp"
+
+#endif // BOOST_NUMERIC_UBLAS_TENSOR_HPP
diff --git a/boost/numeric/ublas/tensor/algorithms.hpp b/boost/numeric/ublas/tensor/algorithms.hpp
new file mode 100644
index 0000000000..c6b9dba482
--- /dev/null
+++ b/boost/numeric/ublas/tensor/algorithms.hpp
@@ -0,0 +1,345 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+
+#ifndef _BOOST_UBLAS_TENSOR_ALGORITHMS_HPP
+#define _BOOST_UBLAS_TENSOR_ALGORITHMS_HPP
+
+
+#include <stdexcept>
+#include <complex>
+#include <functional>
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+
+
+
+/** @brief Copies a tensor to another tensor with different layouts
+ *
+ * Implements C[i1,i2,...,ip] = A[i1,i2,...,ip]
+ *
+ * @param[in] p rank of input and output tensor
+ * @param[in] n pointer to the extents of input or output tensor of length p
+ * @param[in] pi pointer to a one-based permutation tuple of length p
+ * @param[out] c pointer to the output tensor
+ * @param[in] wc pointer to the strides of output tensor c
+ * @param[in] a pointer to the input tensor
+ * @param[in] wa pointer to the strides of input tensor a
+*/
+template <class PointerOut, class PointerIn, class SizeType>
+void copy(const SizeType p, SizeType const*const n,
+ PointerOut c, SizeType const*const wc,
+ PointerIn a, SizeType const*const wa)
+{
+ static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn>::value,
+ "Static error in boost::numeric::ublas::copy: Argument types for pointers are not pointer types.");
+ if( p == 0 )
+ return;
+
+ if(c == nullptr || a == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers.");
+
+ if(wc == nullptr || wa == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers.");
+
+ if(n == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers.");
+
+
+ std::function<void(SizeType r, PointerOut c, PointerIn a)> lambda;
+
+ lambda = [&lambda, n, wc, wa](SizeType r, PointerOut c, PointerIn a)
+ {
+ if(r > 0)
+ for(auto d = 0u; d < n[r]; c += wc[r], a += wa[r], ++d)
+ lambda(r-1, c, a );
+ else
+ for(auto d = 0u; d < n[0]; c += wc[0], a += wa[0], ++d)
+ *c = *a;
+ };
+
+ lambda( p-1, c, a );
+}
+
+
+
+/** @brief Copies a tensor to another tensor with different layouts applying a unary operation
+ *
+ * Implements C[i1,i2,...,ip] = op ( A[i1,i2,...,ip] )
+ *
+ * @param[in] p rank of input and output tensor
+ * @param[in] n pointer to the extents of input or output tensor of length p
+ * @param[in] pi pointer to a one-based permutation tuple of length p
+ * @param[out] c pointer to the output tensor
+ * @param[in] wc pointer to the strides of output tensor c
+ * @param[in] a pointer to the input tensor
+ * @param[in] wa pointer to the strides of input tensor a
+ * @param[in] op unary operation
+*/
+template <class PointerOut, class PointerIn, class SizeType, class UnaryOp>
+void transform(const SizeType p,
+ SizeType const*const n,
+ PointerOut c, SizeType const*const wc,
+ PointerIn a, SizeType const*const wa,
+ UnaryOp op)
+{
+ static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn>::value,
+ "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types.");
+ if( p == 0 )
+ return;
+
+ if(c == nullptr || a == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers.");
+
+ if(wc == nullptr || wa == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers.");
+
+ if(n == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers.");
+
+
+ std::function<void(SizeType r, PointerOut c, PointerIn a)> lambda;
+
+ lambda = [&lambda, n, wc, wa, op](SizeType r, PointerOut c, PointerIn a)
+ {
+ if(r > 0)
+ for(auto d = 0u; d < n[r]; c += wc[r], a += wa[r], ++d)
+ lambda(r-1, c, a);
+ else
+ for(auto d = 0u; d < n[0]; c += wc[0], a += wa[0], ++d)
+ *c = op(*a);
+ };
+
+ lambda( p-1, c, a );
+
+}
+
+
+/** @brief Performs a reduce operation with all elements of the tensor and an initial value
+ *
+ * Implements k = sum_{i1,..,ip} A[i1,i2,...,ip]
+ *
+ * @param[in] r zero-based recursion level starting with r=p-1
+ * @param[in] n pointer to the extents of input or output tensor
+ * @param[in] a pointer to the first input tensor
+ * @param[in] w pointer to the strides of input tensor a
+ * @param[in] k accumulated value
+*/
+template <class PointerIn, class ValueType, class SizeType>
+ValueType accumulate(SizeType const p, SizeType const*const n,
+ PointerIn a, SizeType const*const w,
+ ValueType k)
+{
+ static_assert(std::is_pointer<PointerIn>::value,
+ "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types.");
+
+ if( p == 0 )
+ return k;
+
+ if(a == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers.");
+
+ if(w == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers.");
+
+ if(n == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers.");
+
+
+ std::function<ValueType(SizeType r, PointerIn a, ValueType k)> lambda;
+
+ lambda = [&lambda, n, w](SizeType r, PointerIn a, ValueType k)
+ {
+ if(r > 0u)
+ for(auto d = 0u; d < n[r]; a += w[r], ++d)
+ k = lambda(r-1, a, k);
+ else
+ for(auto d = 0u; d < n[0]; a += w[0], ++d)
+ k += *a;
+ return k;
+ };
+
+ return lambda( p-1, a, k );
+}
+
+/** @brief Performs a reduce operation with all elements of the tensor and an initial value
+ *
+ * Implements k = op ( k , A[i1,i2,...,ip] ), for all ir
+ *
+ * @param[in] r zero-based recursion level starting with r=p-1
+ * @param[in] n pointer to the extents of input or output tensor
+ * @param[in] a pointer to the first input tensor
+ * @param[in] w pointer to the strides of input tensor a
+ * @param[in] k accumulated value
+ * @param[in] op binary operation
+*/
+
+template <class PointerIn, class ValueType, class SizeType, class BinaryOp>
+ValueType accumulate(SizeType const p, SizeType const*const n,
+ PointerIn a, SizeType const*const w,
+ ValueType k, BinaryOp op)
+{
+ static_assert(std::is_pointer<PointerIn>::value,
+ "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types.");
+
+
+ if( p == 0 )
+ return k;
+
+ if(a == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers.");
+
+ if(w == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers.");
+
+ if(n == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers.");
+
+
+ std::function<ValueType(SizeType r, PointerIn a, ValueType k)> lambda;
+
+ lambda = [&lambda, n, w, op](SizeType r, PointerIn a, ValueType k)
+ {
+ if(r > 0u)
+ for(auto d = 0u; d < n[r]; a += w[r], ++d)
+ k = lambda(r-1, a, k);
+ else
+ for(auto d = 0u; d < n[0]; a += w[0], ++d)
+ k = op ( k, *a );
+ return k;
+ };
+
+ return lambda( p-1, a, k );
+}
+
+/** @brief Transposes a tensor
+ *
+ * Implements C[tau[i1],tau[i2],...,tau[ip]] = A[i1,i2,...,ip]
+ *
+ * @note is used in function trans
+ *
+ * @param[in] p rank of input and output tensor
+ * @param[in] na pointer to the extents of the input tensor a of length p
+ * @param[in] pi pointer to a one-based permutation tuple of length p
+ * @param[out] c pointer to the output tensor
+ * @param[in] wc pointer to the strides of output tensor c
+ * @param[in] a pointer to the input tensor
+ * @param[in] wa pointer to the strides of input tensor a
+*/
+
+template <class PointerOut, class PointerIn, class SizeType>
+void trans( SizeType const p, SizeType const*const na, SizeType const*const pi,
+ PointerOut c, SizeType const*const wc,
+ PointerIn a, SizeType const*const wa)
+{
+
+ static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn>::value,
+ "Static error in boost::numeric::ublas::trans: Argument types for pointers are not pointer types.");
+
+ if( p < 2)
+ return;
+
+ if(c == nullptr || a == nullptr)
+ throw std::runtime_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers.");
+
+ if(na == nullptr)
+ throw std::runtime_error("Error in boost::numeric::ublas::trans: Pointers shall not be null.");
+
+ if(wc == nullptr || wa == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers.");
+
+ if(na == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers.");
+
+ if(pi == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers.");
+
+
+ std::function<void(SizeType r, PointerOut c, PointerIn a)> lambda;
+
+ lambda = [&lambda, na, wc, wa, pi](SizeType r, PointerOut c, PointerIn a)
+ {
+ if(r > 0)
+ for(auto d = 0u; d < na[r]; c += wc[pi[r]-1], a += wa[r], ++d)
+ lambda(r-1, c, a);
+ else
+ for(auto d = 0u; d < na[0]; c += wc[pi[0]-1], a += wa[0], ++d)
+ *c = *a;
+ };
+
+ lambda( p-1, c, a );
+}
+
+
+/** @brief Transposes a tensor
+ *
+ * Implements C[tau[i1],tau[i2],...,tau[ip]] = A[i1,i2,...,ip]
+ *
+ * @note is used in function trans
+ *
+ * @param[in] p rank of input and output tensor
+ * @param[in] na pointer to the extents of the input tensor a of length p
+ * @param[in] pi pointer to a one-based permutation tuple of length p
+ * @param[out] c pointer to the output tensor
+ * @param[in] wc pointer to the strides of output tensor c
+ * @param[in] a pointer to the input tensor
+ * @param[in] wa pointer to the strides of input tensor a
+*/
+
+template <class ValueType, class SizeType>
+void trans( SizeType const p,
+ SizeType const*const na,
+ SizeType const*const pi,
+ std::complex<ValueType>* c, SizeType const*const wc,
+ std::complex<ValueType>* a, SizeType const*const wa)
+{
+ if( p < 2)
+ return;
+
+ if(c == nullptr || a == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers.");
+
+ if(wc == nullptr || wa == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers.");
+
+ if(na == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers.");
+
+ if(pi == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers.");
+
+
+ std::function<void(SizeType r, std::complex<ValueType>* c, std::complex<ValueType>* a)> lambda;
+
+ lambda = [&lambda, na, wc, wa, pi](SizeType r, std::complex<ValueType>* c, std::complex<ValueType>* a)
+ {
+ if(r > 0)
+ for(auto d = 0u; d < na[r]; c += wc[pi[r]-1], a += wa[r], ++d)
+ lambda(r-1, c, a);
+ else
+ for(auto d = 0u; d < na[0]; c += wc[pi[0]-1], a += wa[0], ++d)
+ *c = std::conj(*a);
+ };
+
+ lambda( p-1, c, a );
+
+}
+
+
+
+
+}
+}
+}
+
+#endif
diff --git a/boost/numeric/ublas/tensor/expression.hpp b/boost/numeric/ublas/tensor/expression.hpp
new file mode 100644
index 0000000000..2677a0e6f1
--- /dev/null
+++ b/boost/numeric/ublas/tensor/expression.hpp
@@ -0,0 +1,181 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+#ifndef BOOST_UBLAS_TENSOR_EXPRESSIONS_HPP
+#define BOOST_UBLAS_TENSOR_EXPRESSIONS_HPP
+
+#include <cstddef>
+#include <boost/numeric/ublas/expression_types.hpp>
+
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+
+
+template<class element_type, class storage_format, class storage_type>
+class tensor;
+
+template<class size_type>
+class basic_extents;
+
+
+//TODO: put in fwd.hpp
+struct tensor_tag {};
+
+}
+}
+}
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace detail {
+
+/** @\brief base class for tensor expressions
+ *
+ * \note implements crtp - no use of virtual function calls
+ *
+ * \tparam T type of the tensor
+ * \tparam E type of the derived expression (crtp)
+ *
+ **/
+template<class T, class E>
+struct tensor_expression
+ : public ublas_expression<E>
+{
+ // static const unsigned complexity = 0;
+ using expression_type = E;
+ using type_category = tensor_tag;
+ using tensor_type = T;
+
+ BOOST_UBLAS_INLINE
+ auto const& operator()() const { return *static_cast<const expression_type*> (this); }
+
+protected :
+ explicit tensor_expression() = default;
+ tensor_expression(const tensor_expression&) = delete;
+ tensor_expression& operator=(const tensor_expression&) = delete;
+};
+
+
+template<class T, class EL, class ER, class OP>
+struct binary_tensor_expression
+ : public tensor_expression <T, binary_tensor_expression<T,EL,ER,OP>>
+{
+ using self_type = binary_tensor_expression<T,EL,ER,OP>;
+ using tensor_type = T;
+ using binary_operation = OP;
+ using expression_type_left = EL;
+ using expression_type_right = ER;
+ using derived_type = tensor_expression <tensor_type,self_type>;
+
+ using size_type = typename tensor_type::size_type;
+
+ explicit binary_tensor_expression(expression_type_left const& l, expression_type_right const& r, binary_operation o)
+ : el(l) , er(r) , op(o) {}
+ binary_tensor_expression() = delete;
+ binary_tensor_expression(const binary_tensor_expression& l) = delete;
+ binary_tensor_expression(binary_tensor_expression&& l)
+ : el(l.el), er(l.er), op(l.op) {}
+
+ BOOST_UBLAS_INLINE
+ decltype(auto) operator()(size_type i) const { return op(el(i), er(i)); }
+
+ expression_type_left const& el;
+ expression_type_right const& er;
+ binary_operation op;
+};
+
+/// @brief helper function to simply instantiation of lambda proxy class
+template<class T, class EL, class ER, class OP>
+auto make_binary_tensor_expression( tensor_expression<T,EL> const& el, tensor_expression<T,ER> const& er, OP op)
+{
+ return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
+}
+
+template<class T, class EL, class ER, class OP>
+auto make_binary_tensor_expression( matrix_expression<EL> const& el, tensor_expression<T,ER> const& er, OP op)
+{
+ return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
+}
+
+template<class T, class EL, class ER, class OP>
+auto make_binary_tensor_expression( tensor_expression<T,EL> const& el, matrix_expression<ER> const& er, OP op)
+{
+ return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
+}
+
+template<class T, class EL, class ER, class OP>
+auto make_binary_tensor_expression( vector_expression<EL> const& el, tensor_expression<T,ER> const& er, OP op)
+{
+ return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
+}
+
+template<class T, class EL, class ER, class OP>
+auto make_binary_tensor_expression( tensor_expression<T,EL> const& el, vector_expression<ER> const& er, OP op)
+{
+ return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ;
+}
+
+
+
+template<class T, class E, class OP>
+struct unary_tensor_expression
+ : public tensor_expression <T, unary_tensor_expression<T,E,OP>>
+{
+
+ using self_type = unary_tensor_expression<T,E,OP>;
+ using tensor_type = T;
+ using expression_type = E;
+
+ using derived_type = tensor_expression <T, unary_tensor_expression<T,E,OP>>;
+
+ using size_type = typename tensor_type::size_type;
+
+ explicit unary_tensor_expression(E const& ee, OP o) : e(ee) , op(o) {}
+ unary_tensor_expression() = delete;
+ unary_tensor_expression(const unary_tensor_expression& l) = delete;
+ unary_tensor_expression(unary_tensor_expression&& l)
+ : e(l.e), op(op.l) {}
+
+ BOOST_UBLAS_INLINE
+ decltype(auto) operator()(size_type i) const { return op(e(i)); }
+
+ E const& e;
+ OP op;
+};
+
+// \brief helper function to simply instantiation of lambda proxy class
+template<class T, class E, class OP>
+auto make_unary_tensor_expression( tensor_expression<T,E> const& e, OP op)
+{
+ return unary_tensor_expression<T,E,OP>( e() , op);
+}
+
+template<class T, class E, class OP>
+auto make_unary_tensor_expression( matrix_expression<E> const& e, OP op)
+{
+ return unary_tensor_expression<T,E,OP>( e() , op);
+}
+
+template<class T, class E, class OP>
+auto make_unary_tensor_expression( vector_expression<E> const& e, OP op)
+{
+ return unary_tensor_expression<T,E,OP>( e() , op);
+}
+
+
+}
+}
+}
+}
+#endif
diff --git a/boost/numeric/ublas/tensor/expression_evaluation.hpp b/boost/numeric/ublas/tensor/expression_evaluation.hpp
new file mode 100644
index 0000000000..a7948639a9
--- /dev/null
+++ b/boost/numeric/ublas/tensor/expression_evaluation.hpp
@@ -0,0 +1,288 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+#ifndef _BOOST_UBLAS_TENSOR_EXPRESSIONS_EVALUATION_HPP_
+#define _BOOST_UBLAS_TENSOR_EXPRESSIONS_EVALUATION_HPP_
+
+#include <type_traits>
+#include <stdexcept>
+
+
+namespace boost::numeric::ublas {
+
+template<class element_type, class storage_format, class storage_type>
+class tensor;
+
+template<class size_type>
+class basic_extents;
+
+}
+
+namespace boost::numeric::ublas::detail {
+
+template<class T, class D>
+struct tensor_expression;
+
+template<class T, class EL, class ER, class OP>
+struct binary_tensor_expression;
+
+template<class T, class E, class OP>
+struct unary_tensor_expression;
+
+}
+
+namespace boost::numeric::ublas::detail {
+
+template<class T, class E>
+struct has_tensor_types
+{ static constexpr bool value = false; };
+
+template<class T>
+struct has_tensor_types<T,T>
+{ static constexpr bool value = true; };
+
+template<class T, class D>
+struct has_tensor_types<T, tensor_expression<T,D>>
+{ static constexpr bool value = std::is_same<T,D>::value || has_tensor_types<T,D>::value; };
+
+
+template<class T, class EL, class ER, class OP>
+struct has_tensor_types<T, binary_tensor_expression<T,EL,ER,OP>>
+{ static constexpr bool value = std::is_same<T,EL>::value || std::is_same<T,ER>::value || has_tensor_types<T,EL>::value || has_tensor_types<T,ER>::value; };
+
+template<class T, class E, class OP>
+struct has_tensor_types<T, unary_tensor_expression<T,E,OP>>
+{ static constexpr bool value = std::is_same<T,E>::value || has_tensor_types<T,E>::value; };
+
+} // namespace boost::numeric::ublas::detail
+
+
+namespace boost::numeric::ublas::detail {
+
+
+
+
+
+/** @brief Retrieves extents of the tensor
+ *
+*/
+template<class T, class F, class A>
+auto retrieve_extents(tensor<T,F,A> const& t)
+{
+ return t.extents();
+}
+
+/** @brief Retrieves extents of the tensor expression
+ *
+ * @note tensor expression must be a binary tree with at least one tensor type
+ *
+ * @returns extents of the child expression if it is a tensor or extents of one child of its child.
+*/
+template<class T, class D>
+auto retrieve_extents(tensor_expression<T,D> const& expr)
+{
+ static_assert(detail::has_tensor_types<T,tensor_expression<T,D>>::value,
+ "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors.");
+
+ auto const& cast_expr = static_cast<D const&>(expr);
+
+ if constexpr ( std::is_same<T,D>::value )
+ return cast_expr.extents();
+ else
+ return retrieve_extents(cast_expr);
+}
+
+/** @brief Retrieves extents of the binary tensor expression
+ *
+ * @note tensor expression must be a binary tree with at least one tensor type
+ *
+ * @returns extents of the (left and if necessary then right) child expression if it is a tensor or extents of a child of its (left and if necessary then right) child.
+*/
+template<class T, class EL, class ER, class OP>
+auto retrieve_extents(binary_tensor_expression<T,EL,ER,OP> const& expr)
+{
+ static_assert(detail::has_tensor_types<T,binary_tensor_expression<T,EL,ER,OP>>::value,
+ "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors.");
+
+ if constexpr ( std::is_same<T,EL>::value )
+ return expr.el.extents();
+
+ if constexpr ( std::is_same<T,ER>::value )
+ return expr.er.extents();
+
+ else if constexpr ( detail::has_tensor_types<T,EL>::value )
+ return retrieve_extents(expr.el);
+
+ else if constexpr ( detail::has_tensor_types<T,ER>::value )
+ return retrieve_extents(expr.er);
+}
+
+/** @brief Retrieves extents of the binary tensor expression
+ *
+ * @note tensor expression must be a binary tree with at least one tensor type
+ *
+ * @returns extents of the child expression if it is a tensor or extents of a child of its child.
+*/
+template<class T, class E, class OP>
+auto retrieve_extents(unary_tensor_expression<T,E,OP> const& expr)
+{
+
+ static_assert(detail::has_tensor_types<T,unary_tensor_expression<T,E,OP>>::value,
+ "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors.");
+
+ if constexpr ( std::is_same<T,E>::value )
+ return expr.e.extents();
+
+ else if constexpr ( detail::has_tensor_types<T,E>::value )
+ return retrieve_extents(expr.e);
+}
+
+} // namespace boost::numeric::ublas::detail
+
+
+///////////////
+
+namespace boost::numeric::ublas::detail {
+
+template<class T, class F, class A, class S>
+auto all_extents_equal(tensor<T,F,A> const& t, basic_extents<S> const& extents)
+{
+ return extents == t.extents();
+}
+
+template<class T, class D, class S>
+auto all_extents_equal(tensor_expression<T,D> const& expr, basic_extents<S> const& extents)
+{
+ static_assert(detail::has_tensor_types<T,tensor_expression<T,D>>::value,
+ "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors.");
+ auto const& cast_expr = static_cast<D const&>(expr);
+
+
+ if constexpr ( std::is_same<T,D>::value )
+ if( extents != cast_expr.extents() )
+ return false;
+
+ if constexpr ( detail::has_tensor_types<T,D>::value )
+ if ( !all_extents_equal(cast_expr, extents))
+ return false;
+
+ return true;
+
+}
+
+template<class T, class EL, class ER, class OP, class S>
+auto all_extents_equal(binary_tensor_expression<T,EL,ER,OP> const& expr, basic_extents<S> const& extents)
+{
+ static_assert(detail::has_tensor_types<T,binary_tensor_expression<T,EL,ER,OP>>::value,
+ "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors.");
+
+ if constexpr ( std::is_same<T,EL>::value )
+ if(extents != expr.el.extents())
+ return false;
+
+ if constexpr ( std::is_same<T,ER>::value )
+ if(extents != expr.er.extents())
+ return false;
+
+ if constexpr ( detail::has_tensor_types<T,EL>::value )
+ if(!all_extents_equal(expr.el, extents))
+ return false;
+
+ if constexpr ( detail::has_tensor_types<T,ER>::value )
+ if(!all_extents_equal(expr.er, extents))
+ return false;
+
+ return true;
+}
+
+
+template<class T, class E, class OP, class S>
+auto all_extents_equal(unary_tensor_expression<T,E,OP> const& expr, basic_extents<S> const& extents)
+{
+
+ static_assert(detail::has_tensor_types<T,unary_tensor_expression<T,E,OP>>::value,
+ "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors.");
+
+ if constexpr ( std::is_same<T,E>::value )
+ if(extents != expr.e.extents())
+ return false;
+
+ if constexpr ( detail::has_tensor_types<T,E>::value )
+ if(!all_extents_equal(expr.e, extents))
+ return false;
+
+ return true;
+}
+
+} // namespace boost::numeric::ublas::detail
+
+
+namespace boost::numeric::ublas::detail {
+
+
+/** @brief Evaluates expression for a tensor
+ *
+ * Assigns the results of the expression to the tensor.
+ *
+ * \note Checks if shape of the tensor matches those of all tensors within the expression.
+*/
+template<class tensor_type, class derived_type>
+void eval(tensor_type& lhs, tensor_expression<tensor_type, derived_type> const& expr)
+{
+ if constexpr (detail::has_tensor_types<tensor_type, tensor_expression<tensor_type,derived_type> >::value )
+ if(!detail::all_extents_equal(expr, lhs.extents() ))
+ throw std::runtime_error("Error in boost::numeric::ublas::tensor: expression contains tensors with different shapes.");
+
+#pragma omp parallel for
+ for(auto i = 0u; i < lhs.size(); ++i)
+ lhs(i) = expr()(i);
+}
+
+/** @brief Evaluates expression for a tensor
+ *
+ * Applies a unary function to the results of the expressions before the assignment.
+ * Usually applied needed for unary operators such as A += C;
+ *
+ * \note Checks if shape of the tensor matches those of all tensors within the expression.
+*/
+template<class tensor_type, class derived_type, class unary_fn>
+void eval(tensor_type& lhs, tensor_expression<tensor_type, derived_type> const& expr, unary_fn const fn)
+{
+
+ if constexpr (detail::has_tensor_types< tensor_type, tensor_expression<tensor_type,derived_type> >::value )
+ if(!detail::all_extents_equal( expr, lhs.extents() ))
+ throw std::runtime_error("Error in boost::numeric::ublas::tensor: expression contains tensors with different shapes.");
+
+#pragma omp parallel for
+ for(auto i = 0u; i < lhs.size(); ++i)
+ fn(lhs(i), expr()(i));
+}
+
+
+
+/** @brief Evaluates expression for a tensor
+ *
+ * Applies a unary function to the results of the expressions before the assignment.
+ * Usually applied needed for unary operators such as A += C;
+ *
+ * \note Checks if shape of the tensor matches those of all tensors within the expression.
+*/
+template<class tensor_type, class unary_fn>
+void eval(tensor_type& lhs, unary_fn const fn)
+{
+#pragma omp parallel for
+ for(auto i = 0u; i < lhs.size(); ++i)
+ fn(lhs(i));
+}
+
+
+}
+#endif
diff --git a/boost/numeric/ublas/tensor/extents.hpp b/boost/numeric/ublas/tensor/extents.hpp
new file mode 100644
index 0000000000..5d4bf8e5cf
--- /dev/null
+++ b/boost/numeric/ublas/tensor/extents.hpp
@@ -0,0 +1,335 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+
+#ifndef BOOST_NUMERIC_UBLAS_TENSOR_EXTENTS_HPP
+#define BOOST_NUMERIC_UBLAS_TENSOR_EXTENTS_HPP
+
+#include <algorithm>
+#include <initializer_list>
+#include <limits>
+#include <numeric>
+#include <stdexcept>
+#include <vector>
+
+#include <cassert>
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+
+
+/** @brief Template class for storing tensor extents with runtime variable size.
+ *
+ * Proxy template class of std::vector<int_type>.
+ *
+ */
+template<class int_type>
+class basic_extents
+{
+ static_assert( std::numeric_limits<typename std::vector<int_type>::value_type>::is_integer, "Static error in basic_layout: type must be of type integer.");
+ static_assert(!std::numeric_limits<typename std::vector<int_type>::value_type>::is_signed, "Static error in basic_layout: type must be of type unsigned integer.");
+
+public:
+ using base_type = std::vector<int_type>;
+ using value_type = typename base_type::value_type;
+ using const_reference = typename base_type::const_reference;
+ using reference = typename base_type::reference;
+ using size_type = typename base_type::size_type;
+ using const_pointer = typename base_type::const_pointer;
+ using const_iterator = typename base_type::const_iterator;
+
+
+ /** @brief Default constructs basic_extents
+ *
+ * @code auto ex = basic_extents<unsigned>{};
+ */
+ constexpr explicit basic_extents()
+ : _base{}
+ {
+ }
+
+ /** @brief Copy constructs basic_extents from a one-dimensional container
+ *
+ * @code auto ex = basic_extents<unsigned>( std::vector<unsigned>(3u,3u) );
+ *
+ * @note checks if size > 1 and all elements > 0
+ *
+ * @param b one-dimensional std::vector<int_type> container
+ */
+ explicit basic_extents(base_type const& b)
+ : _base(b)
+ {
+ if (!this->valid()){
+ throw std::length_error("Error in basic_extents::basic_extents() : shape tuple is not a valid permutation: has zero elements.");
+ }
+ }
+
+ /** @brief Move constructs basic_extents from a one-dimensional container
+ *
+ * @code auto ex = basic_extents<unsigned>( std::vector<unsigned>(3u,3u) );
+ *
+ * @note checks if size > 1 and all elements > 0
+ *
+ * @param b one-dimensional container of type std::vector<int_type>
+ */
+ explicit basic_extents(base_type && b)
+ : _base(std::move(b))
+ {
+ if (!this->valid()){
+ throw std::length_error("Error in basic_extents::basic_extents() : shape tuple is not a valid permutation: has zero elements.");
+ }
+ }
+
+ /** @brief Constructs basic_extents from an initializer list
+ *
+ * @code auto ex = basic_extents<unsigned>{3,2,4};
+ *
+ * @note checks if size > 1 and all elements > 0
+ *
+ * @param l one-dimensional list of type std::initializer<int_type>
+ */
+ basic_extents(std::initializer_list<value_type> l)
+ : basic_extents( base_type(std::move(l)) )
+ {
+ }
+
+ /** @brief Constructs basic_extents from a range specified by two iterators
+ *
+ * @code auto ex = basic_extents<unsigned>(a.begin(), a.end());
+ *
+ * @note checks if size > 1 and all elements > 0
+ *
+ * @param first iterator pointing to the first element
+ * @param last iterator pointing to the next position after the last element
+ */
+ basic_extents(const_iterator first, const_iterator last)
+ : basic_extents ( base_type( first,last ) )
+ {
+ }
+
+ /** @brief Copy constructs basic_extents */
+ basic_extents(basic_extents const& l )
+ : _base(l._base)
+ {
+ }
+
+ /** @brief Move constructs basic_extents */
+ basic_extents(basic_extents && l ) noexcept
+ : _base(std::move(l._base))
+ {
+ }
+
+ ~basic_extents() = default;
+
+ basic_extents& operator=(basic_extents other) noexcept
+ {
+ swap (*this, other);
+ return *this;
+ }
+
+ friend void swap(basic_extents& lhs, basic_extents& rhs) {
+ std::swap(lhs._base , rhs._base );
+ }
+
+
+
+ /** @brief Returns true if this has a scalar shape
+ *
+ * @returns true if (1,1,[1,...,1])
+ */
+ bool is_scalar() const
+ {
+ return
+ _base.size() != 0 &&
+ std::all_of(_base.begin(), _base.end(),
+ [](const_reference a){ return a == 1;});
+ }
+
+ /** @brief Returns true if this has a vector shape
+ *
+ * @returns true if (1,n,[1,...,1]) or (n,1,[1,...,1]) with n > 1
+ */
+ bool is_vector() const
+ {
+ if(_base.size() == 0){
+ return false;
+ }
+
+ if(_base.size() == 1){
+ return _base.at(0) > 1;
+ }
+
+ auto greater_one = [](const_reference a){ return a > 1;};
+ auto equal_one = [](const_reference a){ return a == 1;};
+
+ return
+ std::any_of(_base.begin(), _base.begin()+2, greater_one) &&
+ std::any_of(_base.begin(), _base.begin()+2, equal_one ) &&
+ std::all_of(_base.begin()+2, _base.end(), equal_one);
+ }
+
+ /** @brief Returns true if this has a matrix shape
+ *
+ * @returns true if (m,n,[1,...,1]) with m > 1 and n > 1
+ */
+ bool is_matrix() const
+ {
+ if(_base.size() < 2){
+ return false;
+ }
+
+ auto greater_one = [](const_reference a){ return a > 1;};
+ auto equal_one = [](const_reference a){ return a == 1;};
+
+ return
+ std::all_of(_base.begin(), _base.begin()+2, greater_one) &&
+ std::all_of(_base.begin()+2, _base.end(), equal_one );
+ }
+
+ /** @brief Returns true if this is has a tensor shape
+ *
+ * @returns true if !empty() && !is_scalar() && !is_vector() && !is_matrix()
+ */
+ bool is_tensor() const
+ {
+ if(_base.size() < 3){
+ return false;
+ }
+
+ auto greater_one = [](const_reference a){ return a > 1;};
+
+ return std::any_of(_base.begin()+2, _base.end(), greater_one);
+ }
+
+ const_pointer data() const
+ {
+ return this->_base.data();
+ }
+
+ const_reference operator[] (size_type p) const
+ {
+ return this->_base[p];
+ }
+
+ const_reference at (size_type p) const
+ {
+ return this->_base.at(p);
+ }
+
+ reference operator[] (size_type p)
+ {
+ return this->_base[p];
+ }
+
+ reference at (size_type p)
+ {
+ return this->_base.at(p);
+ }
+
+
+ bool empty() const
+ {
+ return this->_base.empty();
+ }
+
+ size_type size() const
+ {
+ return this->_base.size();
+ }
+
+ /** @brief Returns true if size > 1 and all elements > 0 */
+ bool valid() const
+ {
+ return
+ this->size() > 1 &&
+ std::none_of(_base.begin(), _base.end(),
+ [](const_reference a){ return a == value_type(0); });
+ }
+
+ /** @brief Returns the number of elements a tensor holds with this */
+ size_type product() const
+ {
+ if(_base.empty()){
+ return 0;
+ }
+
+ return std::accumulate(_base.begin(), _base.end(), 1ul, std::multiplies<>());
+
+ }
+
+
+ /** @brief Eliminates singleton dimensions when size > 2
+ *
+ * squeeze { 1,1} -> { 1,1}
+ * squeeze { 2,1} -> { 2,1}
+ * squeeze { 1,2} -> { 1,2}
+ *
+ * squeeze {1,2,3} -> { 2,3}
+ * squeeze {2,1,3} -> { 2,3}
+ * squeeze {1,3,1} -> { 3,1}
+ *
+ */
+ basic_extents squeeze() const
+ {
+ if(this->size() <= 2){
+ return *this;
+ }
+
+ auto new_extent = basic_extents{};
+ auto insert_iter = std::back_insert_iterator<typename basic_extents::base_type>(new_extent._base);
+ std::remove_copy(this->_base.begin(), this->_base.end(), insert_iter ,value_type{1});
+ return new_extent;
+
+ }
+
+ void clear()
+ {
+ this->_base.clear();
+ }
+
+ bool operator == (basic_extents const& b) const
+ {
+ return _base == b._base;
+ }
+
+ bool operator != (basic_extents const& b) const
+ {
+ return !( _base == b._base );
+ }
+
+ const_iterator
+ begin() const
+ {
+ return _base.begin();
+ }
+
+ const_iterator
+ end() const
+ {
+ return _base.end();
+ }
+
+ base_type const& base() const { return _base; }
+
+private:
+
+ base_type _base;
+
+};
+
+using shape = basic_extents<std::size_t>;
+
+} // namespace ublas
+} // namespace numeric
+} // namespace boost
+
+#endif
diff --git a/boost/numeric/ublas/tensor/functions.hpp b/boost/numeric/ublas/tensor/functions.hpp
new file mode 100644
index 0000000000..e2043ceb11
--- /dev/null
+++ b/boost/numeric/ublas/tensor/functions.hpp
@@ -0,0 +1,558 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+
+#ifndef BOOST_UBLAS_TENSOR_FUNCTIONS_HPP
+#define BOOST_UBLAS_TENSOR_FUNCTIONS_HPP
+
+
+#include <stdexcept>
+#include <vector>
+#include <algorithm>
+#include <numeric>
+
+
+#include "multiplication.hpp"
+#include "algorithms.hpp"
+#include "expression.hpp"
+#include "expression_evaluation.hpp"
+#include "storage_traits.hpp"
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+
+template<class Value, class Format, class Allocator>
+class tensor;
+
+template<class Value, class Format, class Allocator>
+class matrix;
+
+template<class Value, class Allocator>
+class vector;
+
+
+
+
+/** @brief Computes the m-mode tensor-times-vector product
+ *
+ * Implements C[i1,...,im-1,im+1,...,ip] = A[i1,i2,...,ip] * b[im]
+ *
+ * @note calls ublas::ttv
+ *
+ * @param[in] m contraction dimension with 1 <= m <= p
+ * @param[in] a tensor object A with order p
+ * @param[in] b vector object B
+ *
+ * @returns tensor object C with order p-1, the same storage format and allocator type as A
+*/
+template<class V, class F, class A1, class A2>
+auto prod(tensor<V,F,A1> const& a, vector<V,A2> const& b, const std::size_t m)
+{
+
+ using tensor_type = tensor<V,F,A1>;
+ using extents_type = typename tensor_type::extents_type;
+ using ebase_type = typename extents_type::base_type;
+ using value_type = typename tensor_type::value_type;
+ using size_type = typename extents_type::value_type;
+
+ auto const p = std::size_t(a.rank());
+
+ if( m == 0)
+ throw std::length_error("error in boost::numeric::ublas::prod(ttv): contraction mode must be greater than zero.");
+
+ if( p < m )
+ throw std::length_error("error in boost::numeric::ublas::prod(ttv): rank of tensor must be greater than or equal to the modus.");
+
+ if( p == 0)
+ throw std::length_error("error in boost::numeric::ublas::prod(ttv): rank of tensor must be greater than zero.");
+
+ if( a.empty() )
+ throw std::length_error("error in boost::numeric::ublas::prod(ttv): first argument tensor should not be empty.");
+
+ if( b.size() == 0)
+ throw std::length_error("error in boost::numeric::ublas::prod(ttv): second argument vector should not be empty.");
+
+
+ auto nc = ebase_type(std::max(p-1, size_type(2)) , size_type(1));
+ auto nb = ebase_type{b.size(),1};
+
+
+ for(auto i = 0u, j = 0u; i < p; ++i)
+ if(i != m-1)
+ nc[j++] = a.extents().at(i);
+
+ auto c = tensor_type(extents_type(nc),value_type{});
+
+ auto bb = &(b(0));
+
+ ttv(m, p,
+ c.data(), c.extents().data(), c.strides().data(),
+ a.data(), a.extents().data(), a.strides().data(),
+ bb, nb.data(), nb.data());
+
+
+ return c;
+}
+
+
+
+/** @brief Computes the m-mode tensor-times-matrix product
+ *
+ * Implements C[i1,...,im-1,j,im+1,...,ip] = A[i1,i2,...,ip] * B[j,im]
+ *
+ * @note calls ublas::ttm
+ *
+ * @param[in] a tensor object A with order p
+ * @param[in] b vector object B
+ * @param[in] m contraction dimension with 1 <= m <= p
+ *
+ * @returns tensor object C with order p, the same storage format and allocator type as A
+*/
+template<class V, class F, class A1, class A2>
+auto prod(tensor<V,F,A1> const& a, matrix<V,F,A2> const& b, const std::size_t m)
+{
+
+ using tensor_type = tensor<V,F,A1>;
+ using extents_type = typename tensor_type::extents_type;
+ using strides_type = typename tensor_type::strides_type;
+ using value_type = typename tensor_type::value_type;
+
+
+ auto const p = a.rank();
+
+ if( m == 0)
+ throw std::length_error("error in boost::numeric::ublas::prod(ttm): contraction mode must be greater than zero.");
+
+ if( p < m || m > a.extents().size())
+ throw std::length_error("error in boost::numeric::ublas::prod(ttm): rank of the tensor must be greater equal the modus.");
+
+ if( p == 0)
+ throw std::length_error("error in boost::numeric::ublas::prod(ttm): rank of the tensor must be greater than zero.");
+
+ if( a.empty() )
+ throw std::length_error("error in boost::numeric::ublas::prod(ttm): first argument tensor should not be empty.");
+
+ if( b.size1()*b.size2() == 0)
+ throw std::length_error("error in boost::numeric::ublas::prod(ttm): second argument matrix should not be empty.");
+
+
+ auto nc = a.extents().base();
+ auto nb = extents_type {b.size1(),b.size2()};
+ auto wb = strides_type (nb);
+
+ nc[m-1] = nb[0];
+
+ auto c = tensor_type(extents_type(nc),value_type{});
+
+ auto bb = &(b(0,0));
+
+ ttm(m, p,
+ c.data(), c.extents().data(), c.strides().data(),
+ a.data(), a.extents().data(), a.strides().data(),
+ bb, nb.data(), wb.data());
+
+
+ return c;
+}
+
+
+
+
+/** @brief Computes the q-mode tensor-times-tensor product
+ *
+ * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] )
+ *
+ * @note calls ublas::ttt
+ *
+ * na[phia[x]] = nb[phib[x]] for 1 <= x <= q
+ *
+ * @param[in] phia one-based permutation tuple of length q for the first input tensor a
+ * @param[in] phib one-based permutation tuple of length q for the second input tensor b
+ * @param[in] a left-hand side tensor with order r+q
+ * @param[in] b right-hand side tensor with order s+q
+ * @result tensor with order r+s
+*/
+template<class V, class F, class A1, class A2>
+auto prod(tensor<V,F,A1> const& a, tensor<V,F,A2> const& b,
+ std::vector<std::size_t> const& phia, std::vector<std::size_t> const& phib)
+{
+
+ using tensor_type = tensor<V,F,A1>;
+ using extents_type = typename tensor_type::extents_type;
+ using value_type = typename tensor_type::value_type;
+ using size_type = typename extents_type::value_type;
+
+ auto const pa = a.rank();
+ auto const pb = b.rank();
+
+ auto const q = size_type(phia.size());
+
+ if(pa == 0ul)
+ throw std::runtime_error("error in ublas::prod: order of left-hand side tensor must be greater than 0.");
+ if(pb == 0ul)
+ throw std::runtime_error("error in ublas::prod: order of right-hand side tensor must be greater than 0.");
+ if(pa < q)
+ throw std::runtime_error("error in ublas::prod: number of contraction dimensions cannot be greater than the order of the left-hand side tensor.");
+ if(pb < q)
+ throw std::runtime_error("error in ublas::prod: number of contraction dimensions cannot be greater than the order of the right-hand side tensor.");
+
+ if(q != phib.size())
+ throw std::runtime_error("error in ublas::prod: permutation tuples must have the same length.");
+
+ if(pa < phia.size())
+ throw std::runtime_error("error in ublas::prod: permutation tuple for the left-hand side tensor cannot be greater than the corresponding order.");
+ if(pb < phib.size())
+ throw std::runtime_error("error in ublas::prod: permutation tuple for the right-hand side tensor cannot be greater than the corresponding order.");
+
+
+ auto const& na = a.extents();
+ auto const& nb = b.extents();
+
+ for(auto i = 0ul; i < q; ++i)
+ if( na.at(phia.at(i)-1) != nb.at(phib.at(i)-1))
+ throw std::runtime_error("error in ublas::prod: permutations of the extents are not correct.");
+
+ auto const r = pa - q;
+ auto const s = pb - q;
+
+
+ std::vector<std::size_t> phia1(pa), phib1(pb);
+ std::iota(phia1.begin(), phia1.end(), 1ul);
+ std::iota(phib1.begin(), phib1.end(), 1ul);
+
+ std::vector<std::size_t> nc( std::max ( r+s , size_type(2) ), size_type(1) );
+
+ for(auto i = 0ul; i < phia.size(); ++i)
+ * std::remove(phia1.begin(), phia1.end(), phia.at(i)) = phia.at(i);
+
+ //phia1.erase( std::remove(phia1.begin(), phia1.end(), phia.at(i)), phia1.end() ) ;
+
+ assert(phia1.size() == pa);
+
+ for(auto i = 0ul; i < r; ++i)
+ nc[ i ] = na[ phia1[ i ] - 1 ];
+
+ for(auto i = 0ul; i < phib.size(); ++i)
+ * std::remove(phib1.begin(), phib1.end(), phib.at(i)) = phib.at(i) ;
+ //phib1.erase( std::remove(phib1.begin(), phib1.end(), phia.at(i)), phib1.end() ) ;
+
+ assert(phib1.size() == pb);
+
+ for(auto i = 0ul; i < s; ++i)
+ nc[ r + i ] = nb[ phib1[ i ] - 1 ];
+
+ // std::copy( phib.begin(), phib.end(), phib1.end() );
+
+ assert( phia1.size() == pa );
+ assert( phib1.size() == pb );
+
+ auto c = tensor_type(extents_type(nc), value_type{});
+
+ ttt(pa, pb, q,
+ phia1.data(), phib1.data(),
+ c.data(), c.extents().data(), c.strides().data(),
+ a.data(), a.extents().data(), a.strides().data(),
+ b.data(), b.extents().data(), b.strides().data());
+
+ return c;
+}
+
+//template<class V, class F, class A1, class A2, std::size_t N, std::size_t M>
+//auto operator*( tensor_index<V,F,A1,N> const& lhs, tensor_index<V,F,A2,M> const& rhs)
+
+
+
+
+/** @brief Computes the q-mode tensor-times-tensor product
+ *
+ * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] )
+ *
+ * @note calls ublas::ttt
+ *
+ * na[phi[x]] = nb[phi[x]] for 1 <= x <= q
+ *
+ * @param[in] phi one-based permutation tuple of length q for bot input tensors
+ * @param[in] a left-hand side tensor with order r+q
+ * @param[in] b right-hand side tensor with order s+q
+ * @result tensor with order r+s
+*/
+template<class V, class F, class A1, class A2>
+auto prod(tensor<V,F,A1> const& a, tensor<V,F,A2> const& b,
+ std::vector<std::size_t> const& phi)
+{
+ return prod(a, b, phi, phi);
+}
+
+
+/** @brief Computes the inner product of two tensors
+ *
+ * Implements c = sum(A[i1,i2,...,ip] * B[i1,i2,...,jp])
+ *
+ * @note calls inner function
+ *
+ * @param[in] a tensor object A
+ * @param[in] b tensor object B
+ *
+ * @returns a value type.
+*/
+template<class V, class F, class A1, class A2>
+auto inner_prod(tensor<V,F,A1> const& a, tensor<V,F,A2> const& b)
+{
+ using value_type = typename tensor<V,F,A1>::value_type;
+
+ if( a.rank() != b.rank() )
+ throw std::length_error("error in boost::numeric::ublas::inner_prod: Rank of both tensors must be the same.");
+
+ if( a.empty() || b.empty())
+ throw std::length_error("error in boost::numeric::ublas::inner_prod: Tensors should not be empty.");
+
+ if( a.extents() != b.extents())
+ throw std::length_error("error in boost::numeric::ublas::inner_prod: Tensor extents should be the same.");
+
+ return inner(a.rank(), a.extents().data(),
+ a.data(), a.strides().data(),
+ b.data(), b.strides().data(), value_type{0});
+}
+
+/** @brief Computes the outer product of two tensors
+ *
+ * Implements C[i1,...,ip,j1,...,jq] = A[i1,i2,...,ip] * B[j1,j2,...,jq]
+ *
+ * @note calls outer function
+ *
+ * @param[in] a tensor object A
+ * @param[in] b tensor object B
+ *
+ * @returns tensor object C with the same storage format F and allocator type A1
+*/
+template<class V, class F, class A1, class A2>
+auto outer_prod(tensor<V,F,A1> const& a, tensor<V,F,A2> const& b)
+{
+ using tensor_type = tensor<V,F,A1>;
+ using extents_type = typename tensor_type::extents_type;
+
+ if( a.empty() || b.empty() )
+ throw std::runtime_error("error in boost::numeric::ublas::outer_prod: tensors should not be empty.");
+
+ auto nc = typename extents_type::base_type(a.rank() + b.rank());
+ for(auto i = 0u; i < a.rank(); ++i)
+ nc.at(i) = a.extents().at(i);
+
+ for(auto i = 0u; i < b.rank(); ++i)
+ nc.at(a.rank()+i) = b.extents().at(i);
+
+ auto c = tensor_type(extents_type(nc));
+
+ outer(c.data(), c.rank(), c.extents().data(), c.strides().data(),
+ a.data(), a.rank(), a.extents().data(), a.strides().data(),
+ b.data(), b.rank(), b.extents().data(), b.strides().data());
+
+ return c;
+}
+
+
+
+/** @brief Transposes a tensor according to a permutation tuple
+ *
+ * Implements C[tau[i1],tau[i2]...,tau[ip]] = A[i1,i2,...,ip]
+ *
+ * @note calls trans function
+ *
+ * @param[in] a tensor object of rank p
+ * @param[in] tau one-based permutation tuple of length p
+ * @returns a transposed tensor object with the same storage format F and allocator type A
+*/
+template<class V, class F, class A>
+auto trans(tensor<V,F,A> const& a, std::vector<std::size_t> const& tau)
+{
+ using tensor_type = tensor<V,F,A>;
+ using extents_type = typename tensor_type::extents_type;
+ // using strides_type = typename tensor_type::strides_type;
+
+ if( a.empty() )
+ return tensor<V,F,A>{};
+
+ auto const p = a.rank();
+ auto const& na = a.extents();
+
+ auto nc = typename extents_type::base_type (p);
+ for(auto i = 0u; i < p; ++i)
+ nc.at(tau.at(i)-1) = na.at(i);
+
+ // auto wc = strides_type(extents_type(nc));
+
+ auto c = tensor_type(extents_type(nc));
+
+
+ trans( a.rank(), a.extents().data(), tau.data(),
+ c.data(), c.strides().data(),
+ a.data(), a.strides().data());
+
+ // auto wc_pi = typename strides_type::base_type (p);
+ // for(auto i = 0u; i < p; ++i)
+ // wc_pi.at(tau.at(i)-1) = c.strides().at(i);
+
+
+ //copy(a.rank(),
+ // a.extents().data(),
+ // c.data(), wc_pi.data(),
+ // a.data(), a.strides().data() );
+
+ return c;
+}
+
+/** @brief Computes the frobenius norm of a tensor expression
+ *
+ * @note evaluates the tensor expression and calls the accumulate function
+ *
+ *
+ * Implements the two-norm with
+ * k = sqrt( sum_(i1,...,ip) A(i1,...,ip)^2 )
+ *
+ * @param[in] a tensor object of rank p
+ * @returns the frobenius norm of the tensor
+*/
+//template<class V, class F, class A>
+//auto norm(tensor<V,F,A> const& a)
+template<class T, class D>
+auto norm(detail::tensor_expression<T,D> const& expr)
+{
+
+ using tensor_type = typename detail::tensor_expression<T,D>::tensor_type;
+ using value_type = typename tensor_type::value_type;
+
+ auto a = tensor_type( expr );
+
+ if( a.empty() )
+ throw std::runtime_error("error in boost::numeric::ublas::norm: tensors should not be empty.");
+
+ return std::sqrt( accumulate( a.order(), a.extents().data(), a.data(), a.strides().data(), value_type{},
+ [](auto const& l, auto const& r){ return l + r*r; } ) ) ;
+}
+
+
+
+/** @brief Extract the real component of tensor elements within a tensor expression
+ *
+ * @param[in] lhs tensor expression
+ * @returns unary tensor expression
+*/
+template<class T, class D>
+auto real(detail::tensor_expression<T,D> const& expr) {
+ return detail::make_unary_tensor_expression<T> (expr(), [] (auto const& l) { return std::real( l ); } );
+}
+
+/** @brief Extract the real component of tensor elements within a tensor expression
+ *
+ * @param[in] lhs tensor expression
+ * @returns unary tensor expression
+*/
+template<class V, class F, class A, class D>
+auto real(detail::tensor_expression<tensor<std::complex<V>,F,A>,D> const& expr)
+{
+ using tensor_complex_type = tensor<std::complex<V>,F,A>;
+ using tensor_type = tensor<V,F,typename storage_traits<A>::template rebind<V>>;
+
+ if( detail::retrieve_extents( expr ).empty() )
+ throw std::runtime_error("error in boost::numeric::ublas::real: tensors should not be empty.");
+
+ auto a = tensor_complex_type( expr );
+ auto c = tensor_type( a.extents() );
+
+ std::transform( a.begin(), a.end(), c.begin(), [](auto const& l){ return std::real(l) ; } );
+
+ return c;
+}
+
+
+/** @brief Extract the imaginary component of tensor elements within a tensor expression
+ *
+ * @param[in] lhs tensor expression
+ * @returns unary tensor expression
+*/
+template<class T, class D>
+auto imag(detail::tensor_expression<T,D> const& lhs) {
+ return detail::make_unary_tensor_expression<T> (lhs(), [] (auto const& l) { return std::imag( l ); } );
+}
+
+
+/** @brief Extract the imag component of tensor elements within a tensor expression
+ *
+ * @param[in] lhs tensor expression
+ * @returns unary tensor expression
+*/
+template<class V, class A, class F, class D>
+auto imag(detail::tensor_expression<tensor<std::complex<V>,F,A>,D> const& expr)
+{
+ using tensor_complex_type = tensor<std::complex<V>,F,A>;
+ using tensor_type = tensor<V,F,typename storage_traits<A>::template rebind<V>>;
+
+ if( detail::retrieve_extents( expr ).empty() )
+ throw std::runtime_error("error in boost::numeric::ublas::real: tensors should not be empty.");
+
+ auto a = tensor_complex_type( expr );
+ auto c = tensor_type( a.extents() );
+
+ std::transform( a.begin(), a.end(), c.begin(), [](auto const& l){ return std::imag(l) ; } );
+
+ return c;
+}
+
+/** @brief Computes the complex conjugate component of tensor elements within a tensor expression
+ *
+ * @param[in] expr tensor expression
+ * @returns complex tensor
+*/
+template<class T, class D>
+auto conj(detail::tensor_expression<T,D> const& expr)
+{
+ using tensor_type = T;
+ using value_type = typename tensor_type::value_type;
+ using layout_type = typename tensor_type::layout_type;
+ using array_type = typename tensor_type::array_type;
+
+ using new_value_type = std::complex<value_type>;
+ using new_array_type = typename storage_traits<array_type>::template rebind<new_value_type>;
+
+ using tensor_complex_type = tensor<new_value_type,layout_type, new_array_type>;
+
+ if( detail::retrieve_extents( expr ).empty() )
+ throw std::runtime_error("error in boost::numeric::ublas::conj: tensors should not be empty.");
+
+ auto a = tensor_type( expr );
+ auto c = tensor_complex_type( a.extents() );
+
+ std::transform( a.begin(), a.end(), c.begin(), [](auto const& l){ return std::conj(l) ; } );
+
+ return c;
+}
+
+
+/** @brief Computes the complex conjugate component of tensor elements within a tensor expression
+ *
+ * @param[in] lhs tensor expression
+ * @returns unary tensor expression
+*/
+template<class V, class A, class F, class D>
+auto conj(detail::tensor_expression<tensor<std::complex<V>,F,A>,D> const& expr)
+{
+ return detail::make_unary_tensor_expression<tensor<std::complex<V>,F,A>> (expr(), [] (auto const& l) { return std::conj( l ); } );
+}
+
+
+
+}
+}
+}
+
+
+#endif
diff --git a/boost/numeric/ublas/tensor/index.hpp b/boost/numeric/ublas/tensor/index.hpp
new file mode 100644
index 0000000000..a8a40deb85
--- /dev/null
+++ b/boost/numeric/ublas/tensor/index.hpp
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+#ifndef BOOST_UBLAS_TENSOR_INDEX_HPP
+#define BOOST_UBLAS_TENSOR_INDEX_HPP
+
+
+#include <cstddef>
+#include <array>
+#include <vector>
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace index {
+
+/** @brief Proxy template class for the einstein summation notation
+ *
+ * @note index::index_type<K> for 0<=K<=16 is used in tensor::operator()
+ *
+ * @tparam I wrapped integer
+*/
+template<std::size_t I>
+struct index_type
+{
+ static constexpr std::size_t value = I;
+
+ constexpr bool operator == (std::size_t other) const { return value == other; }
+ constexpr bool operator != (std::size_t other) const { return value != other; }
+
+ template <std::size_t K>
+ constexpr bool operator == (index_type<K> /*other*/) const { return I==K; }
+ template <std::size_t K>
+ constexpr bool operator != (index_type<K> /*other*/) const { return I!=K; }
+
+ constexpr bool operator == (index_type /*other*/) const { return true; }
+ constexpr bool operator != (index_type /*other*/) const { return false; }
+
+ constexpr std::size_t operator()() const { return I; }
+};
+
+/** @brief Proxy classes for the einstein summation notation
+ *
+ * @note index::_a ... index::_z is used in tensor::operator()
+*/
+
+static constexpr index_type< 0> _;
+static constexpr index_type< 1> _a;
+static constexpr index_type< 2> _b;
+static constexpr index_type< 3> _c;
+static constexpr index_type< 4> _d;
+static constexpr index_type< 5> _e;
+static constexpr index_type< 6> _f;
+static constexpr index_type< 7> _g;
+static constexpr index_type< 8> _h;
+static constexpr index_type< 9> _i;
+static constexpr index_type<10> _j;
+static constexpr index_type<11> _k;
+static constexpr index_type<12> _l;
+static constexpr index_type<13> _m;
+static constexpr index_type<14> _n;
+static constexpr index_type<15> _o;
+static constexpr index_type<16> _p;
+static constexpr index_type<17> _q;
+static constexpr index_type<18> _r;
+static constexpr index_type<19> _s;
+static constexpr index_type<20> _t;
+static constexpr index_type<21> _u;
+static constexpr index_type<22> _v;
+static constexpr index_type<23> _w;
+static constexpr index_type<24> _x;
+static constexpr index_type<25> _y;
+static constexpr index_type<26> _z;
+
+} // namespace indices
+
+}
+}
+}
+
+#endif // _BOOST_UBLAS_TENSOR_INDEX_HPP_
diff --git a/boost/numeric/ublas/tensor/multi_index.hpp b/boost/numeric/ublas/tensor/multi_index.hpp
new file mode 100644
index 0000000000..3cc86e2fdf
--- /dev/null
+++ b/boost/numeric/ublas/tensor/multi_index.hpp
@@ -0,0 +1,110 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+#ifndef BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP
+#define BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP
+
+
+#include <cstddef>
+#include <array>
+#include <vector>
+
+#include "multi_index_utility.hpp"
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace index {
+
+template<std::size_t I>
+struct index_type;
+
+} // namespace indices
+}
+}
+}
+
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+
+/** @brief Proxy class for the einstein summation notation
+ *
+ * Denotes an array of index_type types ::_a for 0<=K<=16 is used in tensor::operator()
+*/
+template<std::size_t N>
+class multi_index
+{
+public:
+ multi_index() = delete;
+
+ template<std::size_t I, class ... indexes>
+ constexpr multi_index(index::index_type<I> const& i, indexes ... is )
+ : _base{i(), is()... }
+ {
+ static_assert( sizeof...(is)+1 == N,
+ "Static assert in boost::numeric::ublas::multi_index: number of constructor arguments is not equal to the template parameter." );
+
+ static_assert( valid_multi_index<std::tuple<index::index_type<I>, indexes ...> >::value,
+ "Static assert in boost::numeric::ublas::multi_index: indexes occur twice in multi-index." );
+ }
+
+ multi_index(multi_index const& other)
+ : _base(other._base)
+ {
+ }
+
+ multi_index& operator=(multi_index const& other)
+ {
+ this->_base = other._base;
+ return *this;
+ }
+
+ ~multi_index() = default;
+
+ auto const& base() const { return _base; }
+ constexpr auto size() const { return _base.size(); }
+ constexpr auto at(std::size_t i) const { return _base.at(i); }
+ constexpr auto operator[](std::size_t i) const { return _base.at(i); }
+
+private:
+ std::array<std::size_t, N> _base;
+};
+
+template<std::size_t K, std::size_t N>
+constexpr auto get(multi_index<N> const& m) { return std::get<K>(m.base()); }
+
+template<std::size_t M, std::size_t N>
+auto array_to_vector(multi_index<M> const& lhs, multi_index<N> const& rhs)
+{
+ using vtype = std::vector<std::size_t>;
+
+ auto pair_of_vector = std::make_pair( vtype {}, vtype{} );
+
+ for(auto i = 0u; i < N; ++i)
+ for(auto j = 0u; j < M; ++j)
+ if ( lhs.at(i) == rhs.at(j) && lhs.at(i) != boost::numeric::ublas::index::_())
+ pair_of_vector.first .push_back( i+1 ),
+ pair_of_vector.second.push_back( j+1 );
+
+ return pair_of_vector;
+}
+
+
+
+
+
+} // namespace ublas
+} // namespace numeric
+} // namespace boost
+
+#endif // MULTI_INDEX_HPP
diff --git a/boost/numeric/ublas/tensor/multi_index_utility.hpp b/boost/numeric/ublas/tensor/multi_index_utility.hpp
new file mode 100644
index 0000000000..f04c0e8672
--- /dev/null
+++ b/boost/numeric/ublas/tensor/multi_index_utility.hpp
@@ -0,0 +1,364 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+#ifndef BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP
+#define BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP
+
+
+#include <tuple>
+#include <type_traits>
+
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace detail {
+
+
+template<class ... index_types>
+struct has_index_impl;
+
+template<class itype_left, class itype_right>
+struct has_index_impl<itype_left, itype_right>
+{
+ static constexpr bool value = itype_left::value == itype_right::value;
+};
+
+template<class itype_left>
+struct has_index_impl <itype_left, std::tuple<> >
+{
+ static constexpr bool value = false;
+};
+
+template<class itype_left, class itype_right>
+struct has_index_impl <itype_left, std::tuple<itype_right> >
+{
+ static constexpr bool value = has_index_impl<itype_left,itype_right>::value;
+};
+
+template<class itype_left, class itype_right, class ... index_types>
+struct has_index_impl <itype_left, std::tuple<itype_right, index_types...> >
+{
+ using next_type = has_index_impl<itype_left, std::tuple<index_types...>>;
+ static constexpr bool value = has_index_impl<itype_left,itype_right>::value || next_type::value;
+};
+} // namespace detail
+
+
+
+/** @brief has_index is true if index occurs once or more in a multi-index
+ *
+ * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
+ *
+ * @code auto has_index_value = has_index<index_type<1>, std::tuple<index_type<2>,index_type<1>> >::value; @endcode
+ *
+ * @tparam index_type type of index
+ * @tparam tuple_type type of std::tuple representing a multi-index
+*/
+template<class index_type, class tuple_type>
+struct has_index
+{
+ static constexpr bool value = detail::has_index_impl<std::decay_t<index_type>,std::decay_t<tuple_type>>::value;
+};
+
+} // namespace ublas
+} // namespace numeric
+} // namespace boost
+
+////////////////////////////////////////////////
+////////////////////////////////////////////////
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace detail {
+
+
+template<class ... index_types>
+struct valid_multi_index_impl;
+
+template<>
+struct valid_multi_index_impl<std::tuple<>>
+{
+ static constexpr bool value = true;
+};
+
+template<class itype>
+struct valid_multi_index_impl<std::tuple<itype>>
+{
+ static constexpr bool value = true;
+};
+
+
+template<class itype, class ... index_types>
+struct valid_multi_index_impl<std::tuple<itype,index_types...>>
+{
+ using ttype = std::tuple<index_types...>;
+ using has_index_type = has_index<itype, ttype>;
+
+ static constexpr bool is_index_zero = itype::value==0ul;
+ static constexpr bool has_index_value = has_index_type::value && !is_index_zero;
+ static constexpr bool value = !has_index_value && valid_multi_index_impl<ttype>::value;
+};
+} // namespace detail
+
+/** @brief valid_multi_index is true if indexes occur only once in a multi-index
+ *
+ * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
+ *
+ * @code auto valid = valid_multi_index< std::tuple<index_type<2>,index_type<1>> >::value;
+ * @endcode
+ *
+ * @tparam tuple_type type of std::tuple representing a multi-index
+*/
+template<class tupe_type>
+struct valid_multi_index
+{
+ static constexpr bool value = detail::valid_multi_index_impl<std::decay_t<tupe_type>>::value;
+};
+
+} // namespace ublas
+} // namespace numeric
+} // namespace boost
+
+////////////////////////////////////////////////
+////////////////////////////////////////////////
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace detail {
+
+template<class ... index_types >
+struct number_equal_indexes_impl;
+
+template<class ... itypes_right >
+struct number_equal_indexes_impl < std::tuple<>, std::tuple<itypes_right...>>
+{
+ static constexpr unsigned value = 0;
+};
+
+template<class itype, class ... itypes_left, class ... itypes_right>
+struct number_equal_indexes_impl < std::tuple<itype,itypes_left...>, std::tuple<itypes_right...>>
+{
+ using tuple_right = std::tuple<itypes_right...>;
+ using has_index_type = has_index<itype, tuple_right>;
+
+ static constexpr bool is_index_zero = itype::value==0ul;
+ static constexpr bool has_index_value = has_index_type::value && !is_index_zero;
+
+ using next_type = number_equal_indexes_impl< std::tuple<itypes_left...>, tuple_right >;
+ static constexpr unsigned v = has_index_value ? 1 : 0;
+ static constexpr unsigned value = v + next_type::value;
+};
+} // namespace detail
+
+
+/** @brief number_equal_indexes contains the number of equal indexes of two multi-indexes
+ *
+ * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
+ *
+ *
+ * @code auto num = number_equal_indexes<
+ * std::tuple<index_type<2>,index_type<1>>,
+ * std::tuple<index_type<1>,index_type<3>> >::value;
+ * @endcode
+ *
+ * @tparam tuple_type_left type of left std::tuple representing a multi-index
+ * @tparam tuple_type_right type of right std::tuple representing a multi-index
+*/
+template<class tuple_left, class tuple_right>
+struct number_equal_indexes
+{
+ static constexpr unsigned value =
+ detail::number_equal_indexes_impl< std::decay_t<tuple_left>, std::decay_t<tuple_right>>::value;
+};
+
+} // namespace ublas
+} // namespace numeric
+} // namespace boost
+
+
+////////////////////////////////////////////////
+////////////////////////////////////////////////
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace detail {
+
+
+template<std::size_t r, std::size_t m, class itype, class ttype>
+struct index_position_impl
+{
+ static constexpr auto is_same = std::is_same< std::decay_t<itype>, std::decay_t<std::tuple_element_t<r,ttype>> >::value;
+ static constexpr auto value = is_same ? r : index_position_impl<r+1,m,itype,ttype>::value;
+};
+
+
+
+template<std::size_t m, class itype, class ttype>
+struct index_position_impl < m, m, itype, ttype>
+{
+ static constexpr auto value = std::tuple_size<ttype>::value;
+};
+
+} // namespace detail
+
+
+
+/** @brief index_position contains the zero-based index position of an index type within a multi-index
+ *
+ * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
+ *
+ * @code auto num = index_position<
+ * index_type<1>,
+ * std::tuple<index_type<2>,index_type<1>> >::value;
+ * @endcode
+ *
+ * @returns value returns 0 and N-1 if index_type is found, N otherwise where N is tuple_size_v<tuple_type>.
+ *
+ * @tparam index_type type of index
+ * @tparam tuple_type type of std::tuple that is searched for index
+*/
+template<class index_type, class tuple_type>
+struct index_position
+{
+ static constexpr auto value = detail::index_position_impl<0ul,std::tuple_size<tuple_type>::value,std::decay_t<index_type>,std::decay_t<tuple_type>>::value;
+};
+
+} // namespace ublas
+} // namespace numeric
+} // namespace boost
+
+////////////////////////////////////////////////
+////////////////////////////////////////////////
+
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace detail {
+
+template<std::size_t r, std::size_t m>
+struct index_position_pairs_impl
+{
+ template<class array_type, class tuple_left, class tuple_right>
+ static constexpr void run(array_type& out, tuple_left const& lhs, tuple_right const& rhs, std::size_t p)
+ {
+ using index_type = std::tuple_element_t<r-1,tuple_left>;
+ using has_index_type = has_index<index_type, tuple_right>;
+ using get_index_type = index_position<index_type,tuple_right>;
+ using next_type = index_position_pairs_impl<r+1,m>;
+ if constexpr ( has_index_type::value && index_type::value != 0)
+ out[p++] = std::make_pair(r-1,get_index_type::value);
+ next_type::run( out, lhs, rhs, p );
+ }
+};
+
+template<std::size_t m>
+struct index_position_pairs_impl<m,m>
+{
+ template<class array_type, class tuple_left, class tuple_right>
+ static constexpr void run(array_type& out, tuple_left const& , tuple_right const& , std::size_t p)
+ {
+ using index_type = std::tuple_element_t<m-1,tuple_left>;
+ using has_index_type = has_index<index_type, tuple_right>;
+ using get_index_type = index_position<index_type, tuple_right>;
+ if constexpr ( has_index_type::value && index_type::value != 0 )
+ out[p] = std::make_pair(m-1,get_index_type::value);
+ }
+};
+
+template<std::size_t r>
+struct index_position_pairs_impl<r,0>
+{
+ template<class array_type, class tuple_left, class tuple_right>
+ static constexpr void run(array_type&, tuple_left const& , tuple_right const& , std::size_t)
+ {}
+};
+
+
+} // namespace detail
+
+
+/** @brief index_position_pairs returns zero-based index positions of matching indexes of two multi-indexes
+ *
+ * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
+ *
+ * @code auto pairs = index_position_pairs(std::make_tuple(_a,_b), std::make_tuple(_b,_c));
+ * @endcode
+ *
+ * @returns a std::array instance containing index position pairs of type std::pair<std::size_t, std::size_t>.
+ *
+ * @param lhs left std::tuple instance representing a multi-index
+ * @param rhs right std::tuple instance representing a multi-index
+*/
+template<class tuple_left, class tuple_right>
+auto index_position_pairs(tuple_left const& lhs, tuple_right const& rhs)
+{
+ using pair_type = std::pair<std::size_t,std::size_t>;
+ constexpr auto m = std::tuple_size<tuple_left >::value;
+ constexpr auto p = number_equal_indexes<tuple_left, tuple_right>::value;
+ auto array = std::array<pair_type,p>{};
+ detail::index_position_pairs_impl<1,m>::run(array, lhs, rhs,0);
+ return array;
+}
+
+} // namespace ublas
+} // namespace numeric
+} // namespace boost
+
+////////////////////////////
+////////////////////////////
+////////////////////////////
+////////////////////////////
+
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace detail {
+
+template<class array_type, std::size_t ... R>
+constexpr auto array_to_vector_impl( array_type const& array, std::index_sequence<R...> )
+{
+ return std::make_pair(
+ std::vector<std::size_t>{std::get<0>( std::get<R>(array) )+1 ...} ,
+ std::vector<std::size_t>{std::get<1>( std::get<R>(array) )+1 ...} );
+}
+
+} // namespace detail
+
+
+/** @brief array_to_vector converts a std::array of zero-based index position pairs into two std::vector of one-based index positions
+ *
+ * @code auto two_vectors = array_to_vector(std::make_array ( std::make_pair(1,2), std::make_pair(3,4) ) ) ;
+ * @endcode
+ *
+ * @returns two std::vector of one-based index positions
+ *
+ * @param array std::array of zero-based index position pairs
+*/
+template<class pair_type, std::size_t N>
+constexpr auto array_to_vector( std::array<pair_type,N> const& array)
+{
+ constexpr auto sequence = std::make_index_sequence<N>{};
+ return detail::array_to_vector_impl( array, sequence );
+}
+
+
+} // namespace ublas
+} // namespace numeric
+} // namespace boost
+
+
+#endif // _BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP_
diff --git a/boost/numeric/ublas/tensor/multiplication.hpp b/boost/numeric/ublas/tensor/multiplication.hpp
new file mode 100644
index 0000000000..f415a3e2fa
--- /dev/null
+++ b/boost/numeric/ublas/tensor/multiplication.hpp
@@ -0,0 +1,945 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+
+#ifndef BOOST_UBLAS_TENSOR_MULTIPLICATION
+#define BOOST_UBLAS_TENSOR_MULTIPLICATION
+
+#include <cassert>
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace detail {
+namespace recursive {
+
+
+/** @brief Computes the tensor-times-tensor product for q contraction modes
+ *
+ * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] )
+ *
+ * nc[x] = na[phia[x] ] for 1 <= x <= r
+ * nc[r+x] = nb[phib[x] ] for 1 <= x <= s
+ * na[phia[r+x]] = nb[phib[s+x]] for 1 <= x <= q
+ *
+ * @note is used in function ttt
+ *
+ * @param k zero-based recursion level starting with 0
+ * @param r number of non-contraction indices of A
+ * @param s number of non-contraction indices of B
+ * @param q number of contraction indices with q > 0
+ * @param phia pointer to the permutation tuple of length q+r for A
+ * @param phib pointer to the permutation tuple of length q+s for B
+ * @param c pointer to the output tensor C with rank(A)=r+s
+ * @param nc pointer to the extents of tensor C
+ * @param wc pointer to the strides of tensor C
+ * @param a pointer to the first input tensor with rank(A)=r+q
+ * @param na pointer to the extents of the first input tensor A
+ * @param wa pointer to the strides of the first input tensor A
+ * @param b pointer to the second input tensor B with rank(B)=s+q
+ * @param nb pointer to the extents of the second input tensor B
+ * @param wb pointer to the strides of the second input tensor B
+*/
+
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void ttt(SizeType const k,
+ SizeType const r, SizeType const s, SizeType const q,
+ SizeType const*const phia, SizeType const*const phib,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+ if(k < r)
+ {
+ assert(nc[k] == na[phia[k]-1]);
+ for(size_t ic = 0u; ic < nc[k]; a += wa[phia[k]-1], c += wc[k], ++ic)
+ ttt(k+1, r, s, q, phia,phib, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else if(k < r+s)
+ {
+ assert(nc[k] == nb[phib[k-r]-1]);
+ for(size_t ic = 0u; ic < nc[k]; b += wb[phib[k-r]-1], c += wc[k], ++ic)
+ ttt(k+1, r, s, q, phia, phib, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else if(k < r+s+q-1)
+ {
+ assert(na[phia[k-s]-1] == nb[phib[k-r]-1]);
+ for(size_t ia = 0u; ia < na[phia[k-s]-1]; a += wa[phia[k-s]-1], b += wb[phib[k-r]-1], ++ia)
+ ttt(k+1, r, s, q, phia, phib, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else
+ {
+ assert(na[phia[k-s]-1] == nb[phib[k-r]-1]);
+ for(size_t ia = 0u; ia < na[phia[k-s]-1]; a += wa[phia[k-s]-1], b += wb[phib[k-r]-1], ++ia)
+ *c += *a * *b;
+ }
+}
+
+
+
+
+/** @brief Computes the tensor-times-tensor product for q contraction modes
+ *
+ * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] )
+ *
+ * @note no permutation tuple is used
+ *
+ * nc[x] = na[x ] for 1 <= x <= r
+ * nc[r+x] = nb[x ] for 1 <= x <= s
+ * na[r+x] = nb[s+x] for 1 <= x <= q
+ *
+ * @note is used in function ttt
+ *
+ * @param k zero-based recursion level starting with 0
+ * @param r number of non-contraction indices of A
+ * @param s number of non-contraction indices of B
+ * @param q number of contraction indices with q > 0
+ * @param c pointer to the output tensor C with rank(A)=r+s
+ * @param nc pointer to the extents of tensor C
+ * @param wc pointer to the strides of tensor C
+ * @param a pointer to the first input tensor with rank(A)=r+q
+ * @param na pointer to the extents of the first input tensor A
+ * @param wa pointer to the strides of the first input tensor A
+ * @param b pointer to the second input tensor B with rank(B)=s+q
+ * @param nb pointer to the extents of the second input tensor B
+ * @param wb pointer to the strides of the second input tensor B
+*/
+
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void ttt(SizeType const k,
+ SizeType const r, SizeType const s, SizeType const q,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+ if(k < r)
+ {
+ assert(nc[k] == na[k]);
+ for(size_t ic = 0u; ic < nc[k]; a += wa[k], c += wc[k], ++ic)
+ ttt(k+1, r, s, q, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else if(k < r+s)
+ {
+ assert(nc[k] == nb[k-r]);
+ for(size_t ic = 0u; ic < nc[k]; b += wb[k-r], c += wc[k], ++ic)
+ ttt(k+1, r, s, q, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else if(k < r+s+q-1)
+ {
+ assert(na[k-s] == nb[k-r]);
+ for(size_t ia = 0u; ia < na[k-s]; a += wa[k-s], b += wb[k-r], ++ia)
+ ttt(k+1, r, s, q, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else
+ {
+ assert(na[k-s] == nb[k-r]);
+ for(size_t ia = 0u; ia < na[k-s]; a += wa[k-s], b += wb[k-r], ++ia)
+ *c += *a * *b;
+ }
+}
+
+
+/** @brief Computes the tensor-times-matrix product for the contraction mode m > 0
+ *
+ * Implements C[i1,i2,...,im-1,j,im+1,...,ip] = sum(A[i1,i2,...,im,...,ip] * B[j,im])
+ *
+ * @note is used in function ttm
+ *
+ * @param m zero-based contraction mode with 0<m<p
+ * @param r zero-based recursion level starting with p-1
+ * @param c pointer to the output tensor
+ * @param nc pointer to the extents of tensor c
+ * @param wc pointer to the strides of tensor c
+ * @param a pointer to the first input tensor
+ * @param na pointer to the extents of input tensor a
+ * @param wa pointer to the strides of input tensor a
+ * @param b pointer to the second input tensor
+ * @param nb pointer to the extents of input tensor b
+ * @param wb pointer to the strides of input tensor b
+*/
+
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void ttm(SizeType const m, SizeType const r,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+
+ if(r == m) {
+ ttm(m, r-1, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else if(r == 0){
+ for(auto i0 = 0ul; i0 < nc[0]; c += wc[0], a += wa[0], ++i0) {
+ auto cm = c;
+ auto b0 = b;
+ for(auto i0 = 0ul; i0 < nc[m]; cm += wc[m], b0 += wb[0], ++i0){
+ auto am = a;
+ auto b1 = b0;
+ for(auto i1 = 0ul; i1 < nb[1]; am += wa[m], b1 += wb[1], ++i1)
+ *cm += *am * *b1;
+ }
+ }
+ }
+
+ else{
+ for(auto i = 0ul; i < na[r]; c += wc[r], a += wa[r], ++i)
+ ttm(m, r-1, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+}
+
+/** @brief Computes the tensor-times-matrix product for the contraction mode m = 0
+ *
+ * Implements C[j,i2,...,ip] = sum(A[i1,i2,...,ip] * B[j,i1])
+ *
+ * @note is used in function ttm
+ *
+ * @param m zero-based contraction mode with 0<m<p
+ * @param r zero-based recursion level starting with p-1
+ * @param c pointer to the output tensor
+ * @param nc pointer to the extents of tensor c
+ * @param wc pointer to the strides of tensor c
+ * @param a pointer to the first input tensor
+ * @param na pointer to the extents of input tensor a
+ * @param wa pointer to the strides of input tensor a
+ * @param b pointer to the second input tensor
+ * @param nb pointer to the extents of input tensor b
+ * @param wb pointer to the strides of input tensor b
+*/
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void ttm0( SizeType const r,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+
+ if(r > 1){
+ for(auto i = 0ul; i < na[r]; c += wc[r], a += wa[r], ++i)
+ ttm0(r-1, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else{
+ for(auto i1 = 0ul; i1 < nc[1]; c += wc[1], a += wa[1], ++i1) {
+ auto cm = c;
+ auto b0 = b;
+ // r == m == 0
+ for(auto i0 = 0ul; i0 < nc[0]; cm += wc[0], b0 += wb[0], ++i0){
+
+ auto am = a;
+ auto b1 = b0;
+ for(auto i1 = 0u; i1 < nb[1]; am += wa[0], b1 += wb[1], ++i1){
+
+ *cm += *am * *b1;
+ }
+ }
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+/** @brief Computes the tensor-times-vector product for the contraction mode m > 0
+ *
+ * Implements C[i1,i2,...,im-1,im+1,...,ip] = sum(A[i1,i2,...,im,...,ip] * b[im])
+ *
+ * @note is used in function ttv
+ *
+ * @param m zero-based contraction mode with 0<m<p
+ * @param r zero-based recursion level starting with p-1 for tensor A
+ * @param q zero-based recursion level starting with p-1 for tensor C
+ * @param c pointer to the output tensor
+ * @param nc pointer to the extents of tensor c
+ * @param wc pointer to the strides of tensor c
+ * @param a pointer to the first input tensor
+ * @param na pointer to the extents of input tensor a
+ * @param wa pointer to the strides of input tensor a
+ * @param b pointer to the second input tensor
+*/
+
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void ttv( SizeType const m, SizeType const r, SizeType const q,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b)
+{
+
+ if(r == m) {
+ ttv(m, r-1, q, c, nc, wc, a, na, wa, b);
+ }
+ else if(r == 0){
+ for(auto i0 = 0u; i0 < na[0]; c += wc[0], a += wa[0], ++i0) {
+ auto c1 = c; auto a1 = a; auto b1 = b;
+ for(auto im = 0u; im < na[m]; a1 += wa[m], ++b1, ++im)
+ *c1 += *a1 * *b1;
+ }
+ }
+ else{
+ for(auto i = 0u; i < na[r]; c += wc[q], a += wa[r], ++i)
+ ttv(m, r-1, q-1, c, nc, wc, a, na, wa, b);
+ }
+}
+
+
+/** @brief Computes the tensor-times-vector product for the contraction mode m = 0
+ *
+ * Implements C[i2,...,ip] = sum(A[i1,...,ip] * b[i1])
+ *
+ * @note is used in function ttv
+ *
+ * @param m zero-based contraction mode with m=0
+ * @param r zero-based recursion level starting with p-1
+ * @param c pointer to the output tensor
+ * @param nc pointer to the extents of tensor c
+ * @param wc pointer to the strides of tensor c
+ * @param a pointer to the first input tensor
+ * @param na pointer to the extents of input tensor a
+ * @param wa pointer to the strides of input tensor a
+ * @param b pointer to the second input tensor
+*/
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void ttv0(SizeType const r,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b)
+{
+
+ if(r > 1){
+ for(auto i = 0u; i < na[r]; c += wc[r-1], a += wa[r], ++i)
+ ttv0(r-1, c, nc, wc, a, na, wa, b);
+ }
+ else{
+ for(auto i1 = 0u; i1 < na[1]; c += wc[0], a += wa[1], ++i1)
+ {
+ auto c1 = c; auto a1 = a; auto b1 = b;
+ for(auto i0 = 0u; i0 < na[0]; a1 += wa[0], ++b1, ++i0)
+ *c1 += *a1 * *b1;
+ }
+ }
+}
+
+
+/** @brief Computes the matrix-times-vector product
+ *
+ * Implements C[i1] = sum(A[i1,i2] * b[i2]) or C[i2] = sum(A[i1,i2] * b[i1])
+ *
+ * @note is used in function ttv
+ *
+ * @param[in] m zero-based contraction mode with m=0 or m=1
+ * @param[out] c pointer to the output tensor C
+ * @param[in] nc pointer to the extents of tensor C
+ * @param[in] wc pointer to the strides of tensor C
+ * @param[in] a pointer to the first input tensor A
+ * @param[in] na pointer to the extents of input tensor A
+ * @param[in] wa pointer to the strides of input tensor A
+ * @param[in] b pointer to the second input tensor B
+*/
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void mtv(SizeType const m,
+ PointerOut c, SizeType const*const , SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b)
+{
+ // decides whether matrix multiplied with vector or vector multiplied with matrix
+ const auto o = (m == 0) ? 1 : 0;
+
+ for(auto io = 0u; io < na[o]; c += wc[o], a += wa[o], ++io) {
+ auto c1 = c; auto a1 = a; auto b1 = b;
+ for(auto im = 0u; im < na[m]; a1 += wa[m], ++b1, ++im)
+ *c1 += *a1 * *b1;
+ }
+}
+
+
+/** @brief Computes the matrix-times-matrix product
+ *
+ * Implements C[i1,i3] = sum(A[i1,i2] * B[i2,i3])
+ *
+ * @note is used in function ttm
+ *
+ * @param[out] c pointer to the output tensor C
+ * @param[in] nc pointer to the extents of tensor C
+ * @param[in] wc pointer to the strides of tensor C
+ * @param[in] a pointer to the first input tensor A
+ * @param[in] na pointer to the extents of input tensor A
+ * @param[in] wa pointer to the strides of input tensor A
+ * @param[in] b pointer to the second input tensor B
+ * @param[in] nb pointer to the extents of input tensor B
+ * @param[in] wb pointer to the strides of input tensor B
+*/
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void mtm(PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+
+ // C(i,j) = A(i,k) * B(k,j)
+
+ assert(nc[0] == na[0]);
+ assert(nc[1] == nb[1]);
+ assert(na[1] == nb[0]);
+
+ auto cj = c; auto bj = b;
+ for(auto j = 0u; j < nc[1]; cj += wc[1], bj += wb[1], ++j) {
+
+ auto bk = bj; auto ak = a;
+ for(auto k = 0u; k < na[1]; ak += wa[1], bk += wb[0], ++k) {
+
+ auto ci = cj; auto ai = ak;
+ for(auto i = 0u; i < na[0]; ai += wa[0], ci += wc[0], ++i){
+ *ci += *ai * *bk;
+ }
+
+ }
+
+ }
+}
+
+
+
+/** @brief Computes the inner product of two tensors
+ *
+ * Implements c = sum(A[i1,i2,...,ip] * B[i1,i2,...,ip])
+ *
+ * @note is used in function inner
+ *
+ * @param r zero-based recursion level starting with p-1
+ * @param n pointer to the extents of input or output tensor
+ * @param a pointer to the first input tensor
+ * @param wa pointer to the strides of input tensor a
+ * @param b pointer to the second input tensor
+ * @param wb pointer to the strides of tensor b
+ * @param v previously computed value (start with v = 0).
+ * @return inner product of two tensors.
+*/
+template <class PointerIn1, class PointerIn2, class value_t, class SizeType>
+value_t inner(SizeType const r, SizeType const*const n,
+ PointerIn1 a, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const wb,
+ value_t v)
+{
+ if(r == 0)
+ for(auto i0 = 0u; i0 < n[0]; a += wa[0], b += wb[0], ++i0)
+ v += *a * *b;
+ else
+ for(auto ir = 0u; ir < n[r]; a += wa[r], b += wb[r], ++ir)
+ v = inner(r-1, n, a, wa, b, wb, v);
+ return v;
+}
+
+
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void outer_2x2(SizeType const pa,
+ PointerOut c, SizeType const*const , SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+ // assert(rc == 3);
+ // assert(ra == 1);
+ // assert(rb == 1);
+
+ for(auto ib1 = 0u; ib1 < nb[1]; b += wb[1], c += wc[pa+1], ++ib1) {
+ auto c2 = c;
+ auto b0 = b;
+ for(auto ib0 = 0u; ib0 < nb[0]; b0 += wb[0], c2 += wc[pa], ++ib0) {
+ const auto b = *b0;
+ auto c1 = c2;
+ auto a1 = a;
+ for(auto ia1 = 0u; ia1 < na[1]; a1 += wa[1], c1 += wc[1], ++ia1) {
+ auto a0 = a1;
+ auto c0 = c1;
+ for(SizeType ia0 = 0u; ia0 < na[0]; a0 += wa[0], c0 += wc[0], ++ia0)
+ *c0 = *a0 * b;
+ }
+ }
+ }
+}
+
+/** @brief Computes the outer product of two tensors
+ *
+ * Implements C[i1,...,ip,j1,...,jq] = A[i1,i2,...,ip] * B[j1,j2,...,jq]
+ *
+ * @note called by outer
+ *
+ *
+ * @param[in] pa number of dimensions (rank) of the first input tensor A with pa > 0
+ *
+ * @param[in] rc recursion level for C that starts with pc-1
+ * @param[out] c pointer to the output tensor
+ * @param[in] nc pointer to the extents of output tensor c
+ * @param[in] wc pointer to the strides of output tensor c
+ *
+ * @param[in] ra recursion level for A that starts with pa-1
+ * @param[in] a pointer to the first input tensor
+ * @param[in] na pointer to the extents of the first input tensor a
+ * @param[in] wa pointer to the strides of the first input tensor a
+ *
+ * @param[in] rb recursion level for B that starts with pb-1
+ * @param[in] b pointer to the second input tensor
+ * @param[in] nb pointer to the extents of the second input tensor b
+ * @param[in] wb pointer to the strides of the second input tensor b
+*/
+template<class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void outer(SizeType const pa,
+ SizeType const rc, PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ SizeType const ra, PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ SizeType const rb, PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+ if(rb > 1)
+ for(auto ib = 0u; ib < nb[rb]; b += wb[rb], c += wc[rc], ++ib)
+ outer(pa, rc-1, c, nc, wc, ra, a, na, wa, rb-1, b, nb, wb);
+ else if(ra > 1)
+ for(auto ia = 0u; ia < na[ra]; a += wa[ra], c += wc[ra], ++ia)
+ outer(pa, rc-1, c, nc, wc, ra-1, a, na, wa, rb, b, nb, wb);
+ else
+ outer_2x2(pa, c, nc, wc, a, na, wa, b, nb, wb); //assert(ra==1 && rb==1 && rc==3);
+}
+
+
+
+
+/** @brief Computes the outer product with permutation tuples
+ *
+ * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir] * B[j1,...,js] )
+ *
+ * nc[x] = na[phia[x]] for 1 <= x <= r
+ * nc[r+x] = nb[phib[x]] for 1 <= x <= s
+ *
+ * @note maybe called by ttt function
+ *
+ * @param k zero-based recursion level starting with 0
+ * @param r number of non-contraction indices of A
+ * @param s number of non-contraction indices of B
+ * @param phia pointer to the permutation tuple of length r for A
+ * @param phib pointer to the permutation tuple of length s for B
+ * @param c pointer to the output tensor C with rank(A)=r+s
+ * @param nc pointer to the extents of tensor C
+ * @param wc pointer to the strides of tensor C
+ * @param a pointer to the first input tensor with rank(A)=r
+ * @param na pointer to the extents of the first input tensor A
+ * @param wa pointer to the strides of the first input tensor A
+ * @param b pointer to the second input tensor B with rank(B)=s
+ * @param nb pointer to the extents of the second input tensor B
+ * @param wb pointer to the strides of the second input tensor B
+*/
+
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void outer(SizeType const k,
+ SizeType const r, SizeType const s,
+ SizeType const*const phia, SizeType const*const phib,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+ if(k < r)
+ {
+ assert(nc[k] == na[phia[k]-1]);
+ for(size_t ic = 0u; ic < nc[k]; a += wa[phia[k]-1], c += wc[k], ++ic)
+ outer(k+1, r, s, phia,phib, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else if(k < r+s-1)
+ {
+ assert(nc[k] == nb[phib[k-r]-1]);
+ for(size_t ic = 0u; ic < nc[k]; b += wb[phib[k-r]-1], c += wc[k], ++ic)
+ outer(k+1, r, s, phia, phib, c, nc, wc, a, na, wa, b, nb, wb);
+ }
+ else
+ {
+ assert(nc[k] == nb[phib[k-r]-1]);
+ for(size_t ic = 0u; ic < nc[k]; b += wb[phib[k-r]-1], c += wc[k], ++ic)
+ *c = *a * *b;
+ }
+}
+
+
+} // namespace recursive
+} // namespace detail
+} // namespace ublas
+} // namespace numeric
+} // namespace boost
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+#include <stdexcept>
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+
+/** @brief Computes the tensor-times-vector product
+ *
+ * Implements
+ * C[i1,i2,...,im-1,im+1,...,ip] = sum(A[i1,i2,...,im,...,ip] * b[im]) for m>1 and
+ * C[i2,...,ip] = sum(A[i1,...,ip] * b[i1]) for m=1
+ *
+ * @note calls detail::ttv, detail::ttv0 or detail::mtv
+ *
+ * @param[in] m contraction mode with 0 < m <= p
+ * @param[in] p number of dimensions (rank) of the first input tensor with p > 0
+ * @param[out] c pointer to the output tensor with rank p-1
+ * @param[in] nc pointer to the extents of tensor c
+ * @param[in] wc pointer to the strides of tensor c
+ * @param[in] a pointer to the first input tensor
+ * @param[in] na pointer to the extents of input tensor a
+ * @param[in] wa pointer to the strides of input tensor a
+ * @param[in] b pointer to the second input tensor
+ * @param[in] nb pointer to the extents of input tensor b
+ * @param[in] wb pointer to the strides of input tensor b
+*/
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void ttv(SizeType const m, SizeType const p,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ const PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ const PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+ static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value,
+ "Static error in boost::numeric::ublas::ttv: Argument types for pointers are not pointer types.");
+
+ if( m == 0)
+ throw std::length_error("Error in boost::numeric::ublas::ttv: Contraction mode must be greater than zero.");
+
+ if( p < m )
+ throw std::length_error("Error in boost::numeric::ublas::ttv: Rank must be greater equal the modus.");
+
+ if( p == 0)
+ throw std::length_error("Error in boost::numeric::ublas::ttv: Rank must be greater than zero.");
+
+ if(c == nullptr || a == nullptr || b == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::ttv: Pointers shall not be null pointers.");
+
+ for(auto i = 0u; i < m-1; ++i)
+ if(na[i] != nc[i])
+ throw std::length_error("Error in boost::numeric::ublas::ttv: Extents (except of dimension mode) of A and C must be equal.");
+
+ for(auto i = m; i < p; ++i)
+ if(na[i] != nc[i-1])
+ throw std::length_error("Error in boost::numeric::ublas::ttv: Extents (except of dimension mode) of A and C must be equal.");
+
+ const auto max = std::max(nb[0], nb[1]);
+ if( na[m-1] != max)
+ throw std::length_error("Error in boost::numeric::ublas::ttv: Extent of dimension mode of A and b must be equal.");
+
+
+ if((m != 1) && (p > 2))
+ detail::recursive::ttv(m-1, p-1, p-2, c, nc, wc, a, na, wa, b);
+ else if ((m == 1) && (p > 2))
+ detail::recursive::ttv0(p-1, c, nc, wc, a, na, wa, b);
+ else if( p == 2 )
+ detail::recursive::mtv(m-1, c, nc, wc, a, na, wa, b);
+ else /*if( p == 1 )*/{
+ auto v = std::remove_pointer_t<std::remove_cv_t<PointerOut>>{};
+ *c = detail::recursive::inner(SizeType(0), na, a, wa, b, wb, v);
+ }
+
+}
+
+
+
+/** @brief Computes the tensor-times-matrix product
+ *
+ * Implements
+ * C[i1,i2,...,im-1,j,im+1,...,ip] = sum(A[i1,i2,...,im,...,ip] * B[j,im]) for m>1 and
+ * C[j,i2,...,ip] = sum(A[i1,i2,...,ip] * B[j,i1]) for m=1
+ *
+ * @note calls detail::ttm or detail::ttm0
+ *
+ * @param[in] m contraction mode with 0 < m <= p
+ * @param[in] p number of dimensions (rank) of the first input tensor with p > 0
+ * @param[out] c pointer to the output tensor with rank p-1
+ * @param[in] nc pointer to the extents of tensor c
+ * @param[in] wc pointer to the strides of tensor c
+ * @param[in] a pointer to the first input tensor
+ * @param[in] na pointer to the extents of input tensor a
+ * @param[in] wa pointer to the strides of input tensor a
+ * @param[in] b pointer to the second input tensor
+ * @param[in] nb pointer to the extents of input tensor b
+ * @param[in] wb pointer to the strides of input tensor b
+*/
+
+template <class PointerIn1, class PointerIn2, class PointerOut, class SizeType>
+void ttm(SizeType const m, SizeType const p,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ const PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ const PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+
+ static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value,
+ "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types.");
+
+ if( m == 0 )
+ throw std::length_error("Error in boost::numeric::ublas::ttm: Contraction mode must be greater than zero.");
+
+ if( p < m )
+ throw std::length_error("Error in boost::numeric::ublas::ttm: Rank must be greater equal than the specified mode.");
+
+ if( p == 0)
+ throw std::length_error("Error in boost::numeric::ublas::ttm:Rank must be greater than zero.");
+
+ if(c == nullptr || a == nullptr || b == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::ttm: Pointers shall not be null pointers.");
+
+ for(auto i = 0u; i < m-1; ++i)
+ if(na[i] != nc[i])
+ throw std::length_error("Error in boost::numeric::ublas::ttm: Extents (except of dimension mode) of A and C must be equal.");
+
+ for(auto i = m; i < p; ++i)
+ if(na[i] != nc[i])
+ throw std::length_error("Error in boost::numeric::ublas::ttm: Extents (except of dimension mode) of A and C must be equal.");
+
+ if(na[m-1] != nb[1])
+ throw std::length_error("Error in boost::numeric::ublas::ttm: 2nd Extent of B and M-th Extent of A must be the equal.");
+
+ if(nc[m-1] != nb[0])
+ throw std::length_error("Error in boost::numeric::ublas::ttm: 1nd Extent of B and M-th Extent of C must be the equal.");
+
+ if ( m != 1 )
+ detail::recursive::ttm (m-1, p-1, c, nc, wc, a, na, wa, b, nb, wb);
+ else /*if (m == 1 && p > 2)*/
+ detail::recursive::ttm0( p-1, c, nc, wc, a, na, wa, b, nb, wb);
+
+}
+
+
+/** @brief Computes the tensor-times-tensor product
+ *
+ * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] )
+ *
+ * @note calls detail::recursive::ttt or ttm or ttv or inner or outer
+ *
+ * nc[x] = na[phia[x] ] for 1 <= x <= r
+ * nc[r+x] = nb[phib[x] ] for 1 <= x <= s
+ * na[phia[r+x]] = nb[phib[s+x]] for 1 <= x <= q
+ *
+ * @param[in] pa number of dimensions (rank) of the first input tensor a with pa > 0
+ * @param[in] pb number of dimensions (rank) of the second input tensor b with pb > 0
+ * @param[in] q number of contraction dimensions with pa >= q and pb >= q and q >= 0
+ * @param[in] phia pointer to a permutation tuple for the first input tensor a
+ * @param[in] phib pointer to a permutation tuple for the second input tensor b
+ * @param[out] c pointer to the output tensor with rank p-1
+ * @param[in] nc pointer to the extents of tensor c
+ * @param[in] wc pointer to the strides of tensor c
+ * @param[in] a pointer to the first input tensor
+ * @param[in] na pointer to the extents of input tensor a
+ * @param[in] wa pointer to the strides of input tensor a
+ * @param[in] b pointer to the second input tensor
+ * @param[in] nb pointer to the extents of input tensor b
+ * @param[in] wb pointer to the strides of input tensor b
+*/
+
+template <class PointerIn1, class PointerIn2, class PointerOut, class SizeType>
+void ttt(SizeType const pa, SizeType const pb, SizeType const q,
+ SizeType const*const phia, SizeType const*const phib,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+ static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value,
+ "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types.");
+
+ if( pa == 0 || pb == 0)
+ throw std::length_error("Error in boost::numeric::ublas::ttt: tensor order must be greater zero.");
+
+ if( q > pa && q > pb)
+ throw std::length_error("Error in boost::numeric::ublas::ttt: number of contraction must be smaller than or equal to the tensor order.");
+
+
+ SizeType const r = pa - q;
+ SizeType const s = pb - q;
+
+ if(c == nullptr || a == nullptr || b == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::ttm: Pointers shall not be null pointers.");
+
+ for(auto i = 0ul; i < r; ++i)
+ if( na[phia[i]-1] != nc[i] )
+ throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of lhs and res tensor not correct.");
+
+ for(auto i = 0ul; i < s; ++i)
+ if( nb[phib[i]-1] != nc[r+i] )
+ throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of rhs and res not correct.");
+
+ for(auto i = 0ul; i < q; ++i)
+ if( nb[phib[s+i]-1] != na[phia[r+i]-1] )
+ throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of lhs and rhs not correct.");
+
+
+ if(q == 0ul)
+ detail::recursive::outer(SizeType{0},r,s, phia,phib, c,nc,wc, a,na,wa, b,nb,wb);
+ else
+ detail::recursive::ttt(SizeType{0},r,s,q, phia,phib, c,nc,wc, a,na,wa, b,nb,wb);
+}
+
+
+
+/** @brief Computes the tensor-times-tensor product
+ *
+ * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] )
+ *
+ * @note calls detail::recursive::ttt or ttm or ttv or inner or outer
+ *
+ * nc[x] = na[x ] for 1 <= x <= r
+ * nc[r+x] = nb[x ] for 1 <= x <= s
+ * na[r+x] = nb[s+x] for 1 <= x <= q
+ *
+ * @param[in] pa number of dimensions (rank) of the first input tensor a with pa > 0
+ * @param[in] pb number of dimensions (rank) of the second input tensor b with pb > 0
+ * @param[in] q number of contraction dimensions with pa >= q and pb >= q and q >= 0
+ * @param[out] c pointer to the output tensor with rank p-1
+ * @param[in] nc pointer to the extents of tensor c
+ * @param[in] wc pointer to the strides of tensor c
+ * @param[in] a pointer to the first input tensor
+ * @param[in] na pointer to the extents of input tensor a
+ * @param[in] wa pointer to the strides of input tensor a
+ * @param[in] b pointer to the second input tensor
+ * @param[in] nb pointer to the extents of input tensor b
+ * @param[in] wb pointer to the strides of input tensor b
+*/
+
+template <class PointerIn1, class PointerIn2, class PointerOut, class SizeType>
+void ttt(SizeType const pa, SizeType const pb, SizeType const q,
+ PointerOut c, SizeType const*const nc, SizeType const*const wc,
+ PointerIn1 a, SizeType const*const na, SizeType const*const wa,
+ PointerIn2 b, SizeType const*const nb, SizeType const*const wb)
+{
+ static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value,
+ "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types.");
+
+ if( pa == 0 || pb == 0)
+ throw std::length_error("Error in boost::numeric::ublas::ttt: tensor order must be greater zero.");
+
+ if( q > pa && q > pb)
+ throw std::length_error("Error in boost::numeric::ublas::ttt: number of contraction must be smaller than or equal to the tensor order.");
+
+
+ SizeType const r = pa - q;
+ SizeType const s = pb - q;
+ SizeType const pc = r+s;
+
+ if(c == nullptr || a == nullptr || b == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::ttm: Pointers shall not be null pointers.");
+
+ for(auto i = 0ul; i < r; ++i)
+ if( na[i] != nc[i] )
+ throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of lhs and res tensor not correct.");
+
+ for(auto i = 0ul; i < s; ++i)
+ if( nb[i] != nc[r+i] )
+ throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of rhs and res not correct.");
+
+ for(auto i = 0ul; i < q; ++i)
+ if( nb[s+i] != na[r+i] )
+ throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of lhs and rhs not correct.");
+
+ using value_type = std::decay_t<decltype(*c)>;
+
+
+
+ if(q == 0ul)
+ detail::recursive::outer(pa, pc-1, c,nc,wc, pa-1, a,na,wa, pb-1, b,nb,wb);
+ else if(r == 0ul && s == 0ul)
+ *c = detail::recursive::inner(q-1, na, a,wa, b,wb, value_type(0) );
+ else
+ detail::recursive::ttt(SizeType{0},r,s,q, c,nc,wc, a,na,wa, b,nb,wb);
+}
+
+
+/** @brief Computes the inner product of two tensors
+ *
+ * Implements c = sum(A[i1,i2,...,ip] * B[i1,i2,...,ip])
+ *
+ * @note calls detail::inner
+ *
+ * @param[in] p number of dimensions (rank) of the first input tensor with p > 0
+ * @param[in] n pointer to the extents of input or output tensor
+ * @param[in] a pointer to the first input tensor
+ * @param[in] wa pointer to the strides of input tensor a
+ * @param[in] b pointer to the second input tensor
+ * @param[in] wb pointer to the strides of input tensor b
+ * @param[in] v inital value
+ *
+ * @return inner product of two tensors.
+*/
+template <class PointerIn1, class PointerIn2, class value_t, class SizeType>
+auto inner(const SizeType p, SizeType const*const n,
+ const PointerIn1 a, SizeType const*const wa,
+ const PointerIn2 b, SizeType const*const wb,
+ value_t v)
+{
+ static_assert( std::is_pointer<PointerIn1>::value && std::is_pointer<PointerIn2>::value,
+ "Static error in boost::numeric::ublas::inner: Argument types for pointers must be pointer types.");
+ if(p<2)
+ throw std::length_error("Error in boost::numeric::ublas::inner: Rank must be greater than zero.");
+ if(a == nullptr || b == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::inner: Pointers shall not be null pointers.");
+
+ return detail::recursive::inner(p-1, n, a, wa, b, wb, v);
+
+}
+
+
+/** @brief Computes the outer product of two tensors
+ *
+ * Implements C[i1,...,ip,j1,...,jq] = A[i1,i2,...,ip] * B[j1,j2,...,jq]
+ *
+ * @note calls detail::outer
+ *
+ * @param[out] c pointer to the output tensor
+ * @param[in] pc number of dimensions (rank) of the output tensor c with pc > 0
+ * @param[in] nc pointer to the extents of output tensor c
+ * @param[in] wc pointer to the strides of output tensor c
+ * @param[in] a pointer to the first input tensor
+ * @param[in] pa number of dimensions (rank) of the first input tensor a with pa > 0
+ * @param[in] na pointer to the extents of the first input tensor a
+ * @param[in] wa pointer to the strides of the first input tensor a
+ * @param[in] b pointer to the second input tensor
+ * @param[in] pb number of dimensions (rank) of the second input tensor b with pb > 0
+ * @param[in] nb pointer to the extents of the second input tensor b
+ * @param[in] wb pointer to the strides of the second input tensor b
+*/
+template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType>
+void outer(PointerOut c, SizeType const pc, SizeType const*const nc, SizeType const*const wc,
+ const PointerIn1 a, SizeType const pa, SizeType const*const na, SizeType const*const wa,
+ const PointerIn2 b, SizeType const pb, SizeType const*const nb, SizeType const*const wb)
+{
+ static_assert( std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value & std::is_pointer<PointerOut>::value,
+ "Static error in boost::numeric::ublas::outer: argument types for pointers must be pointer types.");
+ if(pa < 2u || pb < 2u)
+ throw std::length_error("Error in boost::numeric::ublas::outer: number of extents of lhs and rhs tensor must be equal or greater than two.");
+ if((pa + pb) != pc)
+ throw std::length_error("Error in boost::numeric::ublas::outer: number of extents of lhs plus rhs tensor must be equal to the number of extents of C.");
+ if(a == nullptr || b == nullptr || c == nullptr)
+ throw std::length_error("Error in boost::numeric::ublas::outer: pointers shall not be null pointers.");
+
+ detail::recursive::outer(pa, pc-1, c, nc, wc, pa-1, a, na, wa, pb-1, b, nb, wb);
+
+}
+
+
+
+
+}
+}
+}
+
+#endif
diff --git a/boost/numeric/ublas/tensor/operators_arithmetic.hpp b/boost/numeric/ublas/tensor/operators_arithmetic.hpp
new file mode 100644
index 0000000000..c9de6d30c6
--- /dev/null
+++ b/boost/numeric/ublas/tensor/operators_arithmetic.hpp
@@ -0,0 +1,244 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+#ifndef BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_HPP
+#define BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_HPP
+
+#include "expression.hpp"
+#include "expression_evaluation.hpp"
+#include "multi_index_utility.hpp"
+#include "functions.hpp"
+
+#include <type_traits>
+#include <functional>
+#include <algorithm>
+
+namespace boost{
+namespace numeric{
+namespace ublas {
+
+
+template<class element_type, class storage_format, class storage_type>
+class tensor;
+
+template<class E>
+class matrix_expression;
+
+
+template<class E>
+class vector_expression;
+
+}
+}
+}
+
+#define FIRST_ORDER_OPERATOR_RIGHT(OP, EXPR_TYPE_L, EXPR_TYPE_R) \
+template<class T, class L, class R> \
+auto operator OP ( boost::numeric::ublas:: EXPR_TYPE_L <T,L> const& lhs, boost::numeric::ublas:: EXPR_TYPE_R <R> const& rhs) { \
+ return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), \
+ [](auto const& l, auto const& r){ return l OP r; }); \
+} \
+
+FIRST_ORDER_OPERATOR_RIGHT (*, detail:: tensor_expression , vector_expression)
+FIRST_ORDER_OPERATOR_RIGHT (+, detail:: tensor_expression , vector_expression)
+FIRST_ORDER_OPERATOR_RIGHT (-, detail:: tensor_expression , vector_expression)
+FIRST_ORDER_OPERATOR_RIGHT (/, detail:: tensor_expression , vector_expression)
+
+FIRST_ORDER_OPERATOR_RIGHT (*, detail:: tensor_expression , matrix_expression)
+FIRST_ORDER_OPERATOR_RIGHT (+, detail:: tensor_expression , matrix_expression)
+FIRST_ORDER_OPERATOR_RIGHT (-, detail:: tensor_expression , matrix_expression)
+FIRST_ORDER_OPERATOR_RIGHT (/, detail:: tensor_expression , matrix_expression)
+
+
+#define FIRST_ORDER_OPERATOR_LEFT(OP, EXPR_TYPE_L, EXPR_TYPE_R) \
+template<class T, class L, class R> \
+auto operator OP ( boost::numeric::ublas:: EXPR_TYPE_L <L> const& lhs, boost::numeric::ublas:: EXPR_TYPE_R <T,R> const& rhs) { \
+ return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), \
+ [](auto const& l, auto const& r){ return l OP r; }); \
+} \
+
+FIRST_ORDER_OPERATOR_LEFT (*, vector_expression, detail:: tensor_expression)
+FIRST_ORDER_OPERATOR_LEFT (+, vector_expression, detail:: tensor_expression)
+FIRST_ORDER_OPERATOR_LEFT (-, vector_expression, detail:: tensor_expression)
+FIRST_ORDER_OPERATOR_LEFT (/, vector_expression, detail:: tensor_expression)
+
+FIRST_ORDER_OPERATOR_LEFT (*, matrix_expression, detail:: tensor_expression)
+FIRST_ORDER_OPERATOR_LEFT (+, matrix_expression, detail:: tensor_expression)
+FIRST_ORDER_OPERATOR_LEFT (-, matrix_expression, detail:: tensor_expression)
+FIRST_ORDER_OPERATOR_LEFT (/, matrix_expression, detail:: tensor_expression)
+
+
+
+
+template<class T, class L, class R>
+auto operator+( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l + r; });
+}
+template<class T, class L, class R>
+auto operator-( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l - r; });
+// return boost::numeric::ublas::detail::make_lambda<T>([&lhs,&rhs](std::size_t i){ return lhs(i) - rhs(i);});
+}
+template<class T, class L, class R>
+auto operator*( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l * r; });
+}
+template<class T, class L, class R>
+auto operator/( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l / r; });
+}
+
+
+// Overloaded Arithmetic Operators with Scalars
+template<class T, class R>
+auto operator+(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs + r; });
+ //return boost::numeric::ublas::detail::make_lambda<T>( [&lhs,&rhs](std::size_t i) {return lhs + rhs(i); } );
+}
+template<class T, class R>
+auto operator-(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs - r; });
+}
+template<class T, class R>
+auto operator*(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs * r; });
+}
+template<class T, class R>
+auto operator/(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs / r; });
+}
+
+
+template<class T, class L>
+auto operator+(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l + rhs; } );
+}
+template<class T, class L>
+auto operator-(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l - rhs; } );
+}
+template<class T, class L>
+auto operator*(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l * rhs; } );
+}
+template<class T, class L>
+auto operator/(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l / rhs; } );
+}
+
+
+
+template<class T, class D>
+auto& operator += (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) {
+ boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l+=r; } );
+ return lhs;
+}
+
+template<class T, class D>
+auto& operator -= (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) {
+ boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l-=r; } );
+ return lhs;
+}
+
+template<class T, class D>
+auto& operator *= (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) {
+ boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l*=r; } );
+ return lhs;
+}
+
+template<class T, class D>
+auto& operator /= (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) {
+ boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l/=r; } );
+ return lhs;
+}
+
+
+
+
+template<class E, class F, class A>
+auto& operator += (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) {
+ boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l+=r; } );
+ return lhs;
+}
+
+template<class E, class F, class A>
+auto& operator -= (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) {
+ boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l-=r; } );
+ return lhs;
+}
+
+template<class E, class F, class A>
+auto& operator *= (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) {
+ boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l*=r; } );
+ return lhs;
+}
+
+template<class E, class F, class A>
+auto& operator /= (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) {
+ boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l/=r; } );
+ return lhs;
+}
+
+
+
+
+
+
+template<class T, class D>
+auto const& operator +(const boost::numeric::ublas::detail::tensor_expression<T,D>& lhs) {
+ return lhs;
+}
+
+template<class T, class D>
+auto operator -(boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs) {
+ return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [] (auto const& l) { return -l; } );
+}
+
+
+
+
+
+/** @brief Performs a tensor contraction, not an elementwise multiplication
+ *
+*/
+
+template<class tensor_type_left, class tuple_type_left, class tensor_type_right, class tuple_type_right>
+auto operator*(
+ std::pair< tensor_type_left const&, tuple_type_left > lhs,
+ std::pair< tensor_type_right const&, tuple_type_right > rhs)
+{
+
+ using namespace boost::numeric::ublas;
+
+ auto const& tensor_left = lhs.first;
+ auto const& tensor_right = rhs.first;
+
+ auto multi_index_left = lhs.second;
+ auto multi_index_right = rhs.second;
+
+ static constexpr auto num_equal_ind = number_equal_indexes<tuple_type_left, tuple_type_right>::value;
+
+ if constexpr ( num_equal_ind == 0 ){
+ return tensor_left * tensor_right;
+ }
+ else if constexpr ( num_equal_ind==std::tuple_size<tuple_type_left>::value && std::is_same<tuple_type_left, tuple_type_right>::value ){
+
+ return boost::numeric::ublas::inner_prod( tensor_left, tensor_right );
+ }
+ else {
+ auto array_index_pairs = index_position_pairs(multi_index_left,multi_index_right);
+ auto index_pairs = array_to_vector( array_index_pairs );
+ return boost::numeric::ublas::prod( tensor_left, tensor_right, index_pairs.first, index_pairs.second );
+ }
+
+}
+
+#endif
diff --git a/boost/numeric/ublas/tensor/operators_comparison.hpp b/boost/numeric/ublas/tensor/operators_comparison.hpp
new file mode 100644
index 0000000000..e54b47af49
--- /dev/null
+++ b/boost/numeric/ublas/tensor/operators_comparison.hpp
@@ -0,0 +1,175 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+#ifndef BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_HPP
+#define BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_HPP
+
+#include <boost/numeric/ublas/tensor/expression.hpp>
+#include <boost/numeric/ublas/tensor/expression_evaluation.hpp>
+#include <type_traits>
+#include <functional>
+
+namespace boost::numeric::ublas {
+template<class element_type, class storage_format, class storage_type>
+class tensor;
+}
+
+namespace boost::numeric::ublas::detail {
+
+template<class T, class F, class A, class BinaryPred>
+bool compare(tensor<T,F,A> const& lhs, tensor<T,F,A> const& rhs, BinaryPred pred)
+{
+
+ if(lhs.extents() != rhs.extents()){
+ if constexpr(!std::is_same<BinaryPred,std::equal_to<>>::value && !std::is_same<BinaryPred,std::not_equal_to<>>::value)
+ throw std::runtime_error("Error in boost::numeric::ublas::detail::compare: cannot compare tensors with different shapes.");
+ else
+ return false;
+ }
+
+ if constexpr(std::is_same<BinaryPred,std::greater<>>::value || std::is_same<BinaryPred,std::less<>>::value)
+ if(lhs.empty())
+ return false;
+
+ for(auto i = 0u; i < lhs.size(); ++i)
+ if(!pred(lhs(i), rhs(i)))
+ return false;
+ return true;
+}
+
+template<class T, class F, class A, class UnaryPred>
+bool compare(tensor<T,F,A> const& rhs, UnaryPred pred)
+{
+ for(auto i = 0u; i < rhs.size(); ++i)
+ if(!pred(rhs(i)))
+ return false;
+ return true;
+}
+
+
+template<class T, class L, class R, class BinaryPred>
+bool compare(tensor_expression<T,L> const& lhs, tensor_expression<T,R> const& rhs, BinaryPred pred)
+{
+ constexpr bool lhs_is_tensor = std::is_same<T,L>::value;
+ constexpr bool rhs_is_tensor = std::is_same<T,R>::value;
+
+ if constexpr (lhs_is_tensor && rhs_is_tensor)
+ return compare(static_cast<T const&>( lhs ), static_cast<T const&>( rhs ), pred);
+ else if constexpr (lhs_is_tensor && !rhs_is_tensor)
+ return compare(static_cast<T const&>( lhs ), T( rhs ), pred);
+ else if constexpr (!lhs_is_tensor && rhs_is_tensor)
+ return compare(T( lhs ), static_cast<T const&>( rhs ), pred);
+ else
+ return compare(T( lhs ), T( rhs ), pred);
+
+}
+
+template<class T, class D, class UnaryPred>
+bool compare(tensor_expression<T,D> const& expr, UnaryPred pred)
+{
+ if constexpr (std::is_same<T,D>::value)
+ return compare(static_cast<T const&>( expr ), pred);
+ else
+ return compare(T( expr ), pred);
+}
+
+}
+
+
+template<class T, class L, class R>
+bool operator==( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
+ boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, rhs, std::equal_to<>{} );
+}
+template<class T, class L, class R>
+auto operator!=(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
+ boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, rhs, std::not_equal_to<>{} );
+}
+template<class T, class L, class R>
+auto operator< ( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
+ boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, rhs, std::less<>{} );
+}
+template<class T, class L, class R>
+auto operator<=( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
+ boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, rhs, std::less_equal<>{} );
+}
+template<class T, class L, class R>
+auto operator> ( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
+ boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, rhs, std::greater<>{} );
+}
+template<class T, class L, class R>
+auto operator>=( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
+ boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, rhs, std::greater_equal<>{} );
+}
+
+
+
+
+
+template<class T, class D>
+bool operator==( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
+ return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs == r; } );
+}
+template<class T, class D>
+auto operator!=( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
+ return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs != r; } );
+}
+template<class T, class D>
+auto operator< ( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
+ return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs < r; } );
+}
+template<class T, class D>
+auto operator<=( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
+ return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs <= r; } );
+}
+template<class T, class D>
+auto operator> ( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
+ return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs > r; } );
+}
+template<class T, class D>
+auto operator>=( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
+ return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs >= r; } );
+}
+
+
+
+template<class T, class D>
+bool operator==( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l == rhs; } );
+}
+template<class T, class D>
+auto operator!=( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l != rhs; } );
+}
+template<class T, class D>
+auto operator< ( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l < rhs; } );
+}
+template<class T, class D>
+auto operator<=( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l <= rhs; } );
+}
+template<class T, class D>
+auto operator> ( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l > rhs; } );
+}
+template<class T, class D>
+auto operator>=( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
+ return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l >= rhs; } );
+}
+
+
+#endif
diff --git a/boost/numeric/ublas/tensor/ostream.hpp b/boost/numeric/ublas/tensor/ostream.hpp
new file mode 100644
index 0000000000..74ee77ea63
--- /dev/null
+++ b/boost/numeric/ublas/tensor/ostream.hpp
@@ -0,0 +1,122 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+
+#ifndef BOOST_UBLAS_TENSOR_OSTREAM_HPP
+#define BOOST_UBLAS_TENSOR_OSTREAM_HPP
+
+#include <ostream>
+#include <complex>
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+namespace detail {
+
+template <class value_type>
+void print(std::ostream& out, value_type const& p)
+{
+ out << p << " ";
+}
+
+template <class value_type>
+void print(std::ostream& out, const std::complex<value_type>& p)
+{
+ out << std::real(p) << "+" << std::imag(p) << "i ";
+}
+
+
+template <class size_type, class value_type>
+void print(std::ostream& out, size_type r, const value_type* p, const size_type* w, const size_type* n)
+{
+
+ if(r < 2)
+ {
+ out << "[ ... " << std::endl;
+
+ for(auto row = 0u; row < n[0]; p += w[0], ++row) // iterate over one column
+ {
+ auto p1 = p;
+ for(auto col = 0u; col < n[1]; p1 += w[1], ++col) // iterate over first row
+ {
+ print(out,*p1);
+ }
+ if(row < n[0]-1)
+ out << "; " << std::endl;
+ }
+ out << "]";
+ }
+ else
+ {
+ out << "cat("<< r+1 <<",..." << std::endl;
+ for(auto d = 0u; d < n[r]-1; p += w[r], ++d){
+ print(out, r-1, p, w, n);
+ out << ",..." << std::endl;
+ }
+ print(out, r-1, p, w, n);
+ }
+ if(r>1)
+ out << ")";
+}
+
+////////////////////////////
+
+
+}
+}
+}
+}
+
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+
+template<class T, class F, class A>
+class tensor;
+
+template<class T, class F, class A>
+class matrix;
+
+template<class T, class A>
+class vector;
+
+}
+}
+}
+
+
+template <class V, class F, class A>
+std::ostream& operator << (std::ostream& out, boost::numeric::ublas::tensor<V,F,A> const& t)
+{
+
+ if(t.extents().is_scalar()){
+ out << '[';
+ boost::numeric::ublas::detail::print(out,t[0]);
+ out << ']';
+ }
+ else if(t.extents().is_vector()) {
+ const auto& cat = t.extents().at(0) > t.extents().at(1) ? ';' : ',';
+ out << '[';
+ for(auto i = 0u; i < t.size()-1; ++i){
+ boost::numeric::ublas::detail::print(out,t[i]);
+ out << cat << ' ';
+ }
+ boost::numeric::ublas::detail::print(out,t[t.size()-1]);
+ out << ']';
+ }
+ else{
+ boost::numeric::ublas::detail::print(out, t.rank()-1, t.data(), t.strides().data(), t.extents().data());
+ }
+ return out;
+}
+
+
+#endif
diff --git a/boost/numeric/ublas/tensor/storage_traits.hpp b/boost/numeric/ublas/tensor/storage_traits.hpp
new file mode 100644
index 0000000000..52840e9684
--- /dev/null
+++ b/boost/numeric/ublas/tensor/storage_traits.hpp
@@ -0,0 +1,84 @@
+//
+// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen Germany
+//
+
+
+#ifndef _BOOST_STORAGE_TRAITS_HPP_
+#define _BOOST_STORAGE_TRAITS_HPP_
+
+#include <vector>
+#include <array>
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+
+
+template <class A>
+struct storage_traits;
+
+
+template <class V, class A>
+struct storage_traits<std::vector<V,A>>
+{
+ using array_type = std::vector<V,A>;
+
+ using size_type = typename array_type::size_type;
+ using difference_type = typename array_type::difference_type;
+ using value_type = typename array_type::value_type;
+
+ using reference = typename array_type::reference;
+ using const_reference = typename array_type::const_reference;
+
+ using pointer = typename array_type::pointer;
+ using const_pointer = typename array_type::const_pointer;
+
+ using iterator = typename array_type::iterator;
+ using const_iterator = typename array_type::const_iterator;
+
+ using reverse_iterator = typename array_type::reverse_iterator;
+ using const_reverse_iterator = typename array_type::const_reverse_iterator;
+
+ template<class U>
+ using rebind = std::vector<U, typename std::allocator_traits<A>::template rebind_alloc<U>>;
+};
+
+
+template <class V, std::size_t N>
+struct storage_traits<std::array<V,N>>
+{
+ using array_type = std::array<V,N>;
+
+ using size_type = typename array_type::size_type;
+ using difference_type = typename array_type::difference_type;
+ using value_type = typename array_type::value_type;
+
+ using reference = typename array_type::reference;
+ using const_reference = typename array_type::const_reference;
+
+ using pointer = typename array_type::pointer;
+ using const_pointer = typename array_type::const_pointer;
+
+ using iterator = typename array_type::iterator;
+ using const_iterator = typename array_type::const_iterator;
+
+ using reverse_iterator = typename array_type::reverse_iterator;
+ using const_reverse_iterator = typename array_type::const_reverse_iterator;
+
+ template<class U>
+ using rebind = std::array<U,N>;
+};
+
+} // ublas
+} // numeric
+} // boost
+
+
+#endif // _BOOST_STORAGE_TRAITS_HPP_
diff --git a/boost/numeric/ublas/tensor/strides.hpp b/boost/numeric/ublas/tensor/strides.hpp
new file mode 100644
index 0000000000..53de553bb7
--- /dev/null
+++ b/boost/numeric/ublas/tensor/strides.hpp
@@ -0,0 +1,251 @@
+//
+// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer IOSB, Ettlingen, Germany
+//
+/// \file strides.hpp Definition for the basic_strides template class
+
+
+#ifndef BOOST_UBLAS_TENSOR_STRIDES_HPP
+#define BOOST_UBLAS_TENSOR_STRIDES_HPP
+
+#include <vector>
+#include <limits>
+#include <numeric>
+#include <stdexcept>
+#include <initializer_list>
+#include <algorithm>
+#include <cassert>
+
+#include <boost/numeric/ublas/functional.hpp>
+
+namespace boost {
+namespace numeric {
+namespace ublas {
+
+using first_order = column_major;
+using last_order = row_major;
+
+template<class T>
+class basic_extents;
+
+
+/** @brief Template class for storing tensor strides for iteration with runtime variable size.
+ *
+ * Proxy template class of std::vector<int_type>.
+ *
+ */
+template<class __int_type, class __layout>
+class basic_strides
+{
+public:
+
+ using base_type = std::vector<__int_type>;
+
+ static_assert( std::numeric_limits<typename base_type::value_type>::is_integer,
+ "Static error in boost::numeric::ublas::basic_strides: type must be of type integer.");
+ static_assert(!std::numeric_limits<typename base_type::value_type>::is_signed,
+ "Static error in boost::numeric::ublas::basic_strides: type must be of type unsigned integer.");
+ static_assert(std::is_same<__layout,first_order>::value || std::is_same<__layout,last_order>::value,
+ "Static error in boost::numeric::ublas::basic_strides: layout type must either first or last order");
+
+
+ using layout_type = __layout;
+ using value_type = typename base_type::value_type;
+ using reference = typename base_type::reference;
+ using const_reference = typename base_type::const_reference;
+ using size_type = typename base_type::size_type;
+ using const_pointer = typename base_type::const_pointer;
+ using const_iterator = typename base_type::const_iterator;
+
+
+ /** @brief Default constructs basic_strides
+ *
+ * @code auto ex = basic_strides<unsigned>{};
+ */
+ constexpr explicit basic_strides()
+ : _base{}
+ {
+ }
+
+ /** @brief Constructs basic_strides from basic_extents for the first- and last-order storage formats
+ *
+ * @code auto strides = basic_strides<unsigned>( basic_extents<std::size_t>{2,3,4} );
+ *
+ */
+ template <class T>
+ basic_strides(basic_extents<T> const& s)
+ : _base(s.size(),1)
+ {
+ if(s.empty())
+ return;
+
+ if(!s.valid())
+ throw std::runtime_error("Error in boost::numeric::ublas::basic_strides() : shape is not valid.");
+
+ if(s.is_vector() || s.is_scalar())
+ return;
+
+ if(this->size() < 2)
+ throw std::runtime_error("Error in boost::numeric::ublas::basic_strides() : size of strides must be greater or equal 2.");
+
+
+ if constexpr (std::is_same<layout_type,first_order>::value){
+ size_type k = 1ul, kend = this->size();
+ for(; k < kend; ++k)
+ _base[k] = _base[k-1] * s[k-1];
+ }
+ else {
+ size_type k = this->size()-2, kend = 0ul;
+ for(; k > kend; --k)
+ _base[k] = _base[k+1] * s[k+1];
+ _base[0] = _base[1] * s[1];
+ }
+ }
+
+ basic_strides(basic_strides const& l)
+ : _base(l._base)
+ {}
+
+ basic_strides(basic_strides && l )
+ : _base(std::move(l._base))
+ {}
+
+ basic_strides(base_type const& l )
+ : _base(l)
+ {}
+
+ basic_strides(base_type && l )
+ : _base(std::move(l))
+ {}
+
+ ~basic_strides() = default;
+
+
+ basic_strides& operator=(basic_strides other)
+ {
+ swap (*this, other);
+ return *this;
+ }
+
+ friend void swap(basic_strides& lhs, basic_strides& rhs) {
+ std::swap(lhs._base , rhs._base);
+ }
+
+ const_reference operator[] (size_type p) const{
+ return _base[p];
+ }
+
+ const_pointer data() const{
+ return _base.data();
+ }
+
+ const_reference at (size_type p) const{
+ return _base.at(p);
+ }
+
+
+ bool empty() const{
+ return _base.empty();
+ }
+
+ size_type size() const{
+ return _base.size();
+ }
+
+ template<class other_layout>
+ bool operator == (basic_strides<value_type, other_layout> const& b) const{
+ return b.base() == this->base();
+ }
+
+ template<class other_layout>
+ bool operator != (basic_strides<value_type, other_layout> const& b) const{
+ return b.base() != this->base();
+ }
+
+ bool operator == (basic_strides const& b) const{
+ return b._base == _base;
+ }
+
+ bool operator != (basic_strides const& b) const{
+ return b._base != _base;
+ }
+
+ const_iterator begin() const{
+ return _base.begin();
+ }
+
+ const_iterator end() const{
+ return _base.end();
+ }
+
+ void clear() {
+ this->_base.clear();
+ }
+
+ base_type const& base() const{
+ return this->_base;
+ }
+
+
+protected:
+ base_type _base;
+};
+
+template<class layout_type>
+using strides = basic_strides<std::size_t, layout_type>;
+
+namespace detail {
+
+
+/** @brief Returns relative memory index with respect to a multi-index
+ *
+ * @code auto j = access(std::vector{3,4,5}, strides{shape{4,2,3},first_order}); @endcode
+ *
+ * @param[in] i multi-index of length p
+ * @param[in] w stride vector of length p
+ * @returns relative memory location depending on \c i and \c w
+*/
+BOOST_UBLAS_INLINE
+template<class size_type, class layout_type>
+auto access(std::vector<size_type> const& i, basic_strides<size_type,layout_type> const& w)
+{
+ const auto p = i.size();
+ size_type sum = 0u;
+ for(auto r = 0u; r < p; ++r)
+ sum += i[r]*w[r];
+ return sum;
+}
+
+/** @brief Returns relative memory index with respect to a multi-index
+ *
+ * @code auto j = access(0, strides{shape{4,2,3},first_order}, 2,3,4); @endcode
+ *
+ * @param[in] i first element of the partial multi-index
+ * @param[in] is the following elements of the partial multi-index
+ * @param[in] sum the current relative memory index
+ * @returns relative memory location depending on \c i and \c w
+*/
+BOOST_UBLAS_INLINE
+template<std::size_t r, class layout_type, class ... size_types>
+auto access(std::size_t sum, basic_strides<std::size_t, layout_type> const& w, std::size_t i, size_types ... is)
+{
+ sum+=i*w[r];
+ if constexpr (sizeof...(is) == 0)
+ return sum;
+ else
+ return detail::access<r+1>(sum,w,std::forward<size_types>(is)...);
+}
+
+}
+
+}
+}
+}
+
+#endif
diff --git a/boost/numeric/ublas/tensor/tensor.hpp b/boost/numeric/ublas/tensor/tensor.hpp
new file mode 100644
index 0000000000..ea4521c29e
--- /dev/null
+++ b/boost/numeric/ublas/tensor/tensor.hpp
@@ -0,0 +1,734 @@
+// Copyright (c) 2018-2019
+// Cem Bassoy
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The authors gratefully acknowledge the support of
+// Fraunhofer and Google in producing this work
+// which started as a Google Summer of Code project.
+//
+
+
+/// \file tensor.hpp Definition for the tensor template class
+
+#ifndef BOOST_UBLAS_TENSOR_IMPL_HPP
+#define BOOST_UBLAS_TENSOR_IMPL_HPP
+
+#include <boost/config.hpp>
+
+#include <initializer_list>
+
+#include "algorithms.hpp"
+#include "expression.hpp"
+#include "expression_evaluation.hpp"
+#include "extents.hpp"
+#include "strides.hpp"
+#include "index.hpp"
+
+namespace boost { namespace numeric { namespace ublas {
+
+template<class T, class F, class A>
+class tensor;
+
+template<class T, class F, class A>
+class matrix;
+
+template<class T, class A>
+class vector;
+
+///** \brief Base class for Tensor container models
+// *
+// * it does not model the Tensor concept but all derived types should.
+// * The class defines a common base type and some common interface for all
+// * statically derived Tensor classes
+// * We implement the casts to the statically derived type.
+// */
+//template<class C>
+//class tensor_container:
+// public detail::tensor_expression<C>
+//{
+//public:
+// static const unsigned complexity = 0;
+// typedef C container_type;
+// typedef tensor_tag type_category;
+
+// BOOST_UBLAS_INLINE
+// const container_type &operator () () const {
+// return *static_cast<const container_type *> (this);
+// }
+// BOOST_UBLAS_INLINE
+// container_type &operator () () {
+// return *static_cast<container_type *> (this);
+// }
+//};
+
+
+
+/** @brief A dense tensor of values of type \c T.
+ *
+ * For a \f$n\f$-dimensional tensor \f$v\f$ and \f$0\leq i < n\f$ every element \f$v_i\f$ is mapped
+ * to the \f$i\f$-th element of the container. A storage type \c A can be specified which defaults to \c unbounded_array.
+ * Elements are constructed by \c A, which need not initialise their value.
+ *
+ * @tparam T type of the objects stored in the tensor (like int, double, complex,...)
+ * @tparam A The type of the storage array of the tensor. Default is \c unbounded_array<T>. \c <bounded_array<T> and \c std::vector<T> can also be used
+ */
+template<class T, class F = first_order, class A = std::vector<T,std::allocator<T>> >
+class tensor:
+ public detail::tensor_expression<tensor<T, F, A>,tensor<T, F, A>>
+{
+
+ static_assert( std::is_same<F,first_order>::value ||
+ std::is_same<F,last_order >::value, "boost::numeric::tensor template class only supports first- or last-order storage formats.");
+
+ using self_type = tensor<T, F, A>;
+public:
+
+
+
+ template<class derived_type>
+ using tensor_expression_type = detail::tensor_expression<self_type,derived_type>;
+
+ template<class derived_type>
+ using matrix_expression_type = matrix_expression<derived_type>;
+
+ template<class derived_type>
+ using vector_expression_type = vector_expression<derived_type>;
+
+ using super_type = tensor_expression_type<self_type>;
+
+// static_assert(std::is_same_v<tensor_expression_type<self_type>, detail::tensor_expression<tensor<T,F,A>,tensor<T,F,A>>>, "tensor_expression_type<self_type>");
+
+ using array_type = A;
+ using layout_type = F;
+
+
+ using size_type = typename array_type::size_type;
+ using difference_type = typename array_type::difference_type;
+ using value_type = typename array_type::value_type;
+
+ using reference = typename array_type::reference;
+ using const_reference = typename array_type::const_reference;
+
+ using pointer = typename array_type::pointer;
+ using const_pointer = typename array_type::const_pointer;
+
+ using iterator = typename array_type::iterator;
+ using const_iterator = typename array_type::const_iterator;
+
+ using reverse_iterator = typename array_type::reverse_iterator;
+ using const_reverse_iterator = typename array_type::const_reverse_iterator;
+
+ using tensor_temporary_type = self_type;
+ using storage_category = dense_tag;
+
+ using strides_type = basic_strides<std::size_t,layout_type>;
+ using extents_type = shape;
+
+ using matrix_type = matrix<value_type,layout_type,array_type>;
+ using vector_type = vector<value_type,array_type>;
+
+
+ /** @brief Constructs a tensor.
+ *
+ * @note the tensor is empty.
+ * @note the tensor needs to reshaped for further use.
+ *
+ */
+ BOOST_UBLAS_INLINE
+ constexpr tensor ()
+ : tensor_expression_type<self_type>() // container_type
+ , extents_()
+ , strides_()
+ , data_()
+ {
+ }
+
+
+ /** @brief Constructs a tensor with an initializer list
+ *
+ * By default, its elements are initialized to 0.
+ *
+ * @code tensor<float> A{4,2,3}; @endcode
+ *
+ * @param l initializer list for setting the dimension extents of the tensor
+ */
+ explicit BOOST_UBLAS_INLINE
+ tensor (std::initializer_list<size_type> l)
+ : tensor_expression_type<self_type>()
+ , extents_ (std::move(l))
+ , strides_ (extents_)
+ , data_ (extents_.product())
+ {
+ }
+
+
+ /** @brief Constructs a tensor with a \c shape
+ *
+ * By default, its elements are initialized to 0.
+ *
+ * @code tensor<float> A{extents{4,2,3}}; @endcode
+ *
+ * @param s initial tensor dimension extents
+ */
+ explicit BOOST_UBLAS_INLINE
+ tensor (extents_type const& s)
+ : tensor_expression_type<self_type>() //tensor_container<self_type>()
+ , extents_ (s)
+ , strides_ (extents_)
+ , data_ (extents_.product())
+ {}
+
+
+ /** @brief Constructs a tensor with a \c shape and initiates it with one-dimensional data
+ *
+ * @code tensor<float> A{extents{4,2,3}, array }; @endcode
+ *
+ *
+ * @param s initial tensor dimension extents
+ * @param a container of \c array_type that is copied according to the storage layout
+ */
+ BOOST_UBLAS_INLINE
+ tensor (extents_type const& s, const array_type &a)
+ : tensor_expression_type<self_type>() //tensor_container<self_type>()
+ , extents_ (s)
+ , strides_ (extents_)
+ , data_ (a)
+ {
+ if(this->extents_.product() != this->data_.size())
+ throw std::runtime_error("Error in boost::numeric::ublas::tensor: size of provided data and specified extents do not match.");
+ }
+
+
+
+ /** @brief Constructs a tensor using a shape tuple and initiates it with a value.
+ *
+ * @code tensor<float> A{extents{4,2,3}, 1 }; @endcode
+ *
+ * @param e initial tensor dimension extents
+ * @param i initial value of all elements of type \c value_type
+ */
+ BOOST_UBLAS_INLINE
+ tensor (extents_type const& e, const value_type &i)
+ : tensor_expression_type<self_type>() //tensor_container<self_type> ()
+ , extents_ (e)
+ , strides_ (extents_)
+ , data_ (extents_.product(), i)
+ {}
+
+
+
+ /** @brief Constructs a tensor from another tensor
+ *
+ * @param v tensor to be copied.
+ */
+ BOOST_UBLAS_INLINE
+ tensor (const tensor &v)
+ : tensor_expression_type<self_type>()
+ , extents_ (v.extents_)
+ , strides_ (v.strides_)
+ , data_ (v.data_ )
+ {}
+
+
+
+ /** @brief Constructs a tensor from another tensor
+ *
+ * @param v tensor to be moved.
+ */
+ BOOST_UBLAS_INLINE
+ tensor (tensor &&v)
+ : tensor_expression_type<self_type>() //tensor_container<self_type> ()
+ , extents_ (std::move(v.extents_))
+ , strides_ (std::move(v.strides_))
+ , data_ (std::move(v.data_ ))
+ {}
+
+
+ /** @brief Constructs a tensor with a matrix
+ *
+ * \note Initially the tensor will be two-dimensional.
+ *
+ * @param v matrix to be copied.
+ */
+ BOOST_UBLAS_INLINE
+ tensor (const matrix_type &v)
+ : tensor_expression_type<self_type>()
+ , extents_ ()
+ , strides_ ()
+ , data_ (v.data())
+ {
+ if(!data_.empty()){
+ extents_ = extents_type{v.size1(),v.size2()};
+ strides_ = strides_type(extents_);
+ }
+ }
+
+ /** @brief Constructs a tensor with a matrix
+ *
+ * \note Initially the tensor will be two-dimensional.
+ *
+ * @param v matrix to be moved.
+ */
+ BOOST_UBLAS_INLINE
+ tensor (matrix_type &&v)
+ : tensor_expression_type<self_type>()
+ , extents_ {}
+ , strides_ {}
+ , data_ {}
+ {
+ if(v.size1()*v.size2() != 0){
+ extents_ = extents_type{v.size1(),v.size2()};
+ strides_ = strides_type(extents_);
+ data_ = std::move(v.data());
+ }
+ }
+
+ /** @brief Constructs a tensor using a \c vector
+ *
+ * @note It is assumed that vector is column vector
+ * @note Initially the tensor will be one-dimensional.
+ *
+ * @param v vector to be copied.
+ */
+ BOOST_UBLAS_INLINE
+ tensor (const vector_type &v)
+ : tensor_expression_type<self_type>()
+ , extents_ ()
+ , strides_ ()
+ , data_ (v.data())
+ {
+ if(!data_.empty()){
+ extents_ = extents_type{data_.size(),1};
+ strides_ = strides_type(extents_);
+ }
+ }
+
+ /** @brief Constructs a tensor using a \c vector
+ *
+ * @param v vector to be moved.
+ */
+ BOOST_UBLAS_INLINE
+ tensor (vector_type &&v)
+ : tensor_expression_type<self_type>()
+ , extents_ {}
+ , strides_ {}
+ , data_ {}
+ {
+ if(v.size() != 0){
+ extents_ = extents_type{v.size(),1};
+ strides_ = strides_type(extents_);
+ data_ = std::move(v.data());
+ }
+ }
+
+
+ /** @brief Constructs a tensor with another tensor with a different layout
+ *
+ * @param other tensor with a different layout to be copied.
+ */
+ BOOST_UBLAS_INLINE
+ template<class other_layout>
+ tensor (const tensor<value_type, other_layout> &other)
+ : tensor_expression_type<self_type> ()
+ , extents_ (other.extents())
+ , strides_ (other.extents())
+ , data_ (other.extents().product())
+ {
+ copy(this->rank(), this->extents().data(),
+ this->data(), this->strides().data(),
+ other.data(), other.strides().data());
+ }
+
+ /** @brief Constructs a tensor with an tensor expression
+ *
+ * @code tensor<float> A = B + 3 * C; @endcode
+ *
+ * @note type must be specified of tensor must be specified.
+ * @note dimension extents are extracted from tensors within the expression.
+ *
+ * @param expr tensor expression
+ */
+ BOOST_UBLAS_INLINE
+ template<class derived_type>
+ tensor (const tensor_expression_type<derived_type> &expr)
+ : tensor_expression_type<self_type> ()
+ , extents_ ( detail::retrieve_extents(expr) )
+ , strides_ ( extents_ )
+ , data_ ( extents_.product() )
+ {
+ static_assert( detail::has_tensor_types<self_type, tensor_expression_type<derived_type>>::value,
+ "Error in boost::numeric::ublas::tensor: expression does not contain a tensor. cannot retrieve shape.");
+ detail::eval( *this, expr );
+ }
+
+ /** @brief Constructs a tensor with a matrix expression
+ *
+ * @code tensor<float> A = B + 3 * C; @endcode
+ *
+ * @note matrix expression is evaluated and pushed into a temporary matrix before assignment.
+ * @note extents are automatically extracted from the temporary matrix
+ *
+ * @param expr matrix expression
+ */
+ BOOST_UBLAS_INLINE
+ template<class derived_type>
+ tensor (const matrix_expression_type<derived_type> &expr)
+ : tensor( matrix_type ( expr ) )
+ {
+ }
+
+ /** @brief Constructs a tensor with a vector expression
+ *
+ * @code tensor<float> A = b + 3 * b; @endcode
+ *
+ * @note matrix expression is evaluated and pushed into a temporary matrix before assignment.
+ * @note extents are automatically extracted from the temporary matrix
+ *
+ * @param expr vector expression
+ */
+ BOOST_UBLAS_INLINE
+ template<class derived_type>
+ tensor (const vector_expression_type<derived_type> &expr)
+ : tensor( vector_type ( expr ) )
+ {
+ }
+
+ /** @brief Evaluates the tensor_expression and assigns the results to the tensor
+ *
+ * @code A = B + C * 2; @endcode
+ *
+ * @note rank and dimension extents of the tensors in the expressions must conform with this tensor.
+ *
+ * @param expr expression that is evaluated.
+ */
+ BOOST_UBLAS_INLINE
+ template<class derived_type>
+ tensor &operator = (const tensor_expression_type<derived_type> &expr)
+ {
+ detail::eval(*this, expr);
+ return *this;
+ }
+
+ tensor& operator=(tensor other)
+ {
+ swap (*this, other);
+ return *this;
+ }
+
+ tensor& operator=(const_reference v)
+ {
+ std::fill(this->begin(), this->end(), v);
+ return *this;
+ }
+
+ /** @brief Returns true if the tensor is empty (\c size==0) */
+ BOOST_UBLAS_INLINE
+ bool empty () const {
+ return this->data_.empty();
+ }
+
+
+ /** @brief Returns the size of the tensor */
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return this->data_.size ();
+ }
+
+ /** @brief Returns the size of the tensor */
+ BOOST_UBLAS_INLINE
+ size_type size (size_type r) const {
+ return this->extents_.at(r);
+ }
+
+ /** @brief Returns the number of dimensions/modes of the tensor */
+ BOOST_UBLAS_INLINE
+ size_type rank () const {
+ return this->extents_.size();
+ }
+
+ /** @brief Returns the number of dimensions/modes of the tensor */
+ BOOST_UBLAS_INLINE
+ size_type order () const {
+ return this->extents_.size();
+ }
+
+ /** @brief Returns the strides of the tensor */
+ BOOST_UBLAS_INLINE
+ strides_type const& strides () const {
+ return this->strides_;
+ }
+
+ /** @brief Returns the extents of the tensor */
+ BOOST_UBLAS_INLINE
+ extents_type const& extents () const {
+ return this->extents_;
+ }
+
+
+ /** @brief Returns a \c const reference to the container. */
+ BOOST_UBLAS_INLINE
+ const_pointer data () const {
+ return this->data_.data();
+ }
+
+ /** @brief Returns a \c const reference to the container. */
+ BOOST_UBLAS_INLINE
+ pointer data () {
+ return this->data_.data();
+ }
+
+ /** @brief Element access using a single index.
+ *
+ * @code auto a = A[i]; @endcode
+ *
+ * @param i zero-based index where 0 <= i < this->size()
+ */
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return this->data_[i];
+ }
+
+ /** @brief Element access using a single index.
+ *
+ *
+ * @code A[i] = a; @endcode
+ *
+ * @param i zero-based index where 0 <= i < this->size()
+ */
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i)
+ {
+ return this->data_[i];
+ }
+
+
+ /** @brief Element access using a multi-index or single-index.
+ *
+ *
+ * @code auto a = A.at(i,j,k); @endcode or
+ * @code auto a = A.at(i); @endcode
+ *
+ * @param i zero-based index where 0 <= i < this->size() if sizeof...(is) == 0, else 0<= i < this->size(0)
+ * @param is zero-based indices where 0 <= is[r] < this->size(r) where 0 < r < this->rank()
+ */
+ template<class ... size_types>
+ BOOST_UBLAS_INLINE
+ const_reference at (size_type i, size_types ... is) const {
+ if constexpr (sizeof...(is) == 0)
+ return this->data_[i];
+ else
+ return this->data_[detail::access<0ul>(size_type(0),this->strides_,i,std::forward<size_types>(is)...)];
+ }
+
+ /** @brief Element access using a multi-index or single-index.
+ *
+ *
+ * @code A.at(i,j,k) = a; @endcode or
+ * @code A.at(i) = a; @endcode
+ *
+ * @param i zero-based index where 0 <= i < this->size() if sizeof...(is) == 0, else 0<= i < this->size(0)
+ * @param is zero-based indices where 0 <= is[r] < this->size(r) where 0 < r < this->rank()
+ */
+ BOOST_UBLAS_INLINE
+ template<class ... size_types>
+ reference at (size_type i, size_types ... is) {
+ if constexpr (sizeof...(is) == 0)
+ return this->data_[i];
+ else
+ return this->data_[detail::access<0ul>(size_type(0),this->strides_,i,std::forward<size_types>(is)...)];
+ }
+
+
+
+
+ /** @brief Element access using a single index.
+ *
+ *
+ * @code A(i) = a; @endcode
+ *
+ * @param i zero-based index where 0 <= i < this->size()
+ */
+ BOOST_UBLAS_INLINE
+ const_reference operator()(size_type i) const {
+ return this->data_[i];
+ }
+
+
+ /** @brief Element access using a single index.
+ *
+ * @code A(i) = a; @endcode
+ *
+ * @param i zero-based index where 0 <= i < this->size()
+ */
+ BOOST_UBLAS_INLINE
+ reference operator()(size_type i){
+ return this->data_[i];
+ }
+
+
+
+
+ /** @brief Generates a tensor index for tensor contraction
+ *
+ *
+ * @code auto Ai = A(_i,_j,k); @endcode
+ *
+ * @param i placeholder
+ * @param is zero-based indices where 0 <= is[r] < this->size(r) where 0 < r < this->rank()
+ */
+ BOOST_UBLAS_INLINE
+ template<std::size_t I, class ... index_types>
+ decltype(auto) operator() (index::index_type<I> p, index_types ... ps) const
+ {
+ constexpr auto N = sizeof...(ps)+1;
+ if( N != this->rank() )
+ throw std::runtime_error("Error in boost::numeric::ublas::operator(): size of provided index_types does not match with the rank.");
+
+ return std::make_pair( std::cref(*this), std::make_tuple( p, std::forward<index_types>(ps)... ) );
+ }
+
+
+
+
+
+ /** @brief Reshapes the tensor
+ *
+ *
+ * (1) @code A.reshape(extents{m,n,o}); @endcode or
+ * (2) @code A.reshape(extents{m,n,o},4); @endcode
+ *
+ * If the size of this smaller than the specified extents than
+ * default constructed (1) or specified (2) value is appended.
+ *
+ * @note rank of the tensor might also change.
+ *
+ * @param e extents with which the tensor is reshaped.
+ * @param v value which is appended if the tensor is enlarged.
+ */
+ BOOST_UBLAS_INLINE
+ void reshape (extents_type const& e, value_type v = value_type{})
+ {
+ this->extents_ = e;
+ this->strides_ = strides_type(this->extents_);
+
+ if(e.product() != this->size())
+ this->data_.resize (this->extents_.product(), v);
+ }
+
+
+
+
+
+ friend void swap(tensor& lhs, tensor& rhs) {
+ std::swap(lhs.data_ , rhs.data_ );
+ std::swap(lhs.extents_, rhs.extents_);
+ std::swap(lhs.strides_, rhs.strides_);
+ }
+
+
+ /// \brief return an iterator on the first element of the tensor
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return data_.begin ();
+ }
+
+ /// \brief return an iterator on the first element of the tensor
+ BOOST_UBLAS_INLINE
+ const_iterator cbegin () const {
+ return data_.cbegin ();
+ }
+
+ /// \brief return an iterator after the last element of the tensor
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return data_.end();
+ }
+
+ /// \brief return an iterator after the last element of the tensor
+ BOOST_UBLAS_INLINE
+ const_iterator cend () const {
+ return data_.cend ();
+ }
+
+ /// \brief Return an iterator on the first element of the tensor
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return data_.begin();
+ }
+
+ /// \brief Return an iterator at the end of the tensor
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return data_.end();
+ }
+
+ /// \brief Return a const reverse iterator before the first element of the reversed tensor (i.e. end() of normal tensor)
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return data_.rbegin();
+ }
+
+ /// \brief Return a const reverse iterator before the first element of the reversed tensor (i.e. end() of normal tensor)
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator crbegin () const {
+ return data_.crbegin();
+ }
+
+ /// \brief Return a const reverse iterator on the end of the reverse tensor (i.e. first element of the normal tensor)
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return data_.rend();
+ }
+
+ /// \brief Return a const reverse iterator on the end of the reverse tensor (i.e. first element of the normal tensor)
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator crend () const {
+ return data_.crend();
+ }
+
+ /// \brief Return a const reverse iterator before the first element of the reversed tensor (i.e. end() of normal tensor)
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return data_.rbegin();
+ }
+
+ /// \brief Return a const reverse iterator on the end of the reverse tensor (i.e. first element of the normal tensor)
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return data_.rend();
+ }
+
+
+#if 0
+ // -------------
+ // Serialization
+ // -------------
+
+ /// Serialize a tensor into and archive as defined in Boost
+ /// \param ar Archive object. Can be a flat file, an XML file or any other stream
+ /// \param file_version Optional file version (not yet used)
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ ar & serialization::make_nvp("data",data_);
+ }
+#endif
+
+
+
+private:
+
+ extents_type extents_;
+ strides_type strides_;
+ array_type data_;
+};
+
+}}} // namespaces
+
+
+
+
+
+#endif
diff --git a/boost/numeric/ublas/traits.hpp b/boost/numeric/ublas/traits.hpp
index ecd52cad8f..cc8a050424 100644
--- a/boost/numeric/ublas/traits.hpp
+++ b/boost/numeric/ublas/traits.hpp
@@ -32,10 +32,17 @@
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_unsigned.hpp>
#include <boost/mpl/and.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/typeof/typeof.hpp>
+
// anonymous namespace to avoid ADL issues
namespace {
- template<class T> T boost_numeric_ublas_sqrt (const T& t) {
+ template<class T>
+ typename boost::mpl::if_c<boost::is_integral<T>::value,
+ double,
+ T>::type
+ boost_numeric_ublas_sqrt (const T& t) {
using namespace std;
// we'll find either std::sqrt or else another version via ADL:
return sqrt (t);
@@ -46,7 +53,8 @@ inline typename boost::disable_if<
boost::is_unsigned<T>, T >::type
boost_numeric_ublas_abs (const T &t ) {
using namespace std;
- return abs( t );
+ // force a type conversion back to T for char and short types
+ return static_cast<T>(abs( t ));
}
template<typename T>
@@ -140,24 +148,10 @@ namespace boost { namespace numeric { namespace ublas {
return in1 / R (in2);
}
- // Use Joel de Guzman's return type deduction
// uBLAS assumes a common return type for all binary arithmetic operators
template<class X, class Y>
struct promote_traits {
- typedef type_deduction_detail::base_result_of<X, Y> base_type;
- static typename base_type::x_type x;
- static typename base_type::y_type y;
- static const std::size_t size = sizeof (
- type_deduction_detail::test<
- typename base_type::x_type
- , typename base_type::y_type
- >(x + y) // Use x+y to stand of all the arithmetic actions
- );
-
- static const std::size_t index = (size / sizeof (char)) - 1;
- typedef typename mpl::at_c<
- typename base_type::types, index>::type id;
- typedef typename id::type promote_type;
+ typedef BOOST_TYPEOF_TPL(X() + Y()) promote_type;
};
diff --git a/boost/numeric/ublas/vector.hpp b/boost/numeric/ublas/vector.hpp
index c1384c1455..73a387dcd3 100644
--- a/boost/numeric/ublas/vector.hpp
+++ b/boost/numeric/ublas/vector.hpp
@@ -903,21 +903,14 @@ namespace boost { namespace numeric { namespace ublas {
vector_assign<scalar_assign> (*this, ae);
}
- /// \brief Construct a fixed_vector from a list of values
- /// This constructor enables initialization by using any of:
- /// fixed_vector<double, 3> v = { 1, 2, 3 } or fixed_vector<double,3> v( {1, 2, 3} ) or fixed_vector<double,3> v( 1, 2, 3 )
-#if defined(BOOST_MSVC)
- // This may or may not work. Maybe use this for all instead only for MSVC
- template <typename... U>
- fixed_vector(U&&... values) :
- vector_container<self_type> (),
- data_{{ std::forward<U>(values)... }} {}
-#else
+ /// \brief Construct a fixed_vector from a list of values
+ /// This constructor enables initialization by using any of:
+ /// fixed_vector<double, 3> v = { 1, 2, 3 } or fixed_vector<double,3> v( {1, 2, 3} ) or fixed_vector<double,3> v( 1, 2, 3 )
template <typename... Types>
+ BOOST_UBLAS_INLINE
fixed_vector(value_type v0, Types... vrest) :
vector_container<self_type> (),
- data_{ { v0, vrest... } } {}
-#endif
+ data_( array_type{ v0, vrest... } ) {}
// -----------------------
// Random Access Container
diff --git a/boost/numeric/ublas/vector_expression.hpp b/boost/numeric/ublas/vector_expression.hpp
index aebb403b65..6f952a4646 100644
--- a/boost/numeric/ublas/vector_expression.hpp
+++ b/boost/numeric/ublas/vector_expression.hpp
@@ -739,11 +739,11 @@ namespace boost { namespace numeric { namespace ublas {
}
BOOST_UBLAS_INLINE
value_type dereference (packed_random_access_iterator_tag) const {
- value_type t1 = value_type/*zero*/();
+ typename E1::value_type t1 = typename E1::value_type/*zero*/();
if (it1_ != it1_end_)
if (it1_.index () == i_)
t1 = *it1_;
- value_type t2 = value_type/*zero*/();
+ typename E2::value_type t2 = typename E2::value_type/*zero*/();
if (it2_ != it2_end_)
if (it2_.index () == i_)
t2 = *it2_;
@@ -811,15 +811,15 @@ namespace boost { namespace numeric { namespace ublas {
}
BOOST_UBLAS_INLINE
value_type dereference (sparse_bidirectional_iterator_tag) const {
- value_type t1 = value_type/*zero*/();
+ typename E1::value_type t1 = typename E1::value_type/*zero*/();
if (it1_ != it1_end_)
if (it1_.index () == i_)
t1 = *it1_;
- value_type t2 = value_type/*zero*/();
+ typename E2::value_type t2 = typename E2::value_type/*zero*/();
if (it2_ != it2_end_)
if (it2_.index () == i_)
t2 = *it2_;
- return functor_type::apply (t1, t2);
+ return static_cast<value_type>(functor_type::apply (t1, t2));
}
public:
@@ -1235,7 +1235,7 @@ namespace boost { namespace numeric { namespace ublas {
// (t * v) [i] = t * v [i]
template<class T1, class E2>
BOOST_UBLAS_INLINE
- typename enable_if< is_convertible<T1, typename E2::value_type >,
+ typename boost::enable_if< is_convertible<T1, typename E2::value_type >,
typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
>::type
operator * (const T1 &e1,
@@ -1478,7 +1478,7 @@ namespace boost { namespace numeric { namespace ublas {
// (v * t) [i] = v [i] * t
template<class E1, class T2>
BOOST_UBLAS_INLINE
- typename enable_if< is_convertible<T2, typename E1::value_type >,
+ typename boost::enable_if< is_convertible<T2, typename E1::value_type >,
typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
>::type
operator * (const vector_expression<E1> &e1,
@@ -1490,7 +1490,7 @@ namespace boost { namespace numeric { namespace ublas {
// (v / t) [i] = v [i] / t
template<class E1, class T2>
BOOST_UBLAS_INLINE
- typename enable_if< is_convertible<T2, typename E1::value_type >,
+ typename boost::enable_if< is_convertible<T2, typename E1::value_type >,
typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
>::type
operator / (const vector_expression<E1> &e1,
@@ -1609,6 +1609,16 @@ namespace boost { namespace numeric { namespace ublas {
return expression_type (e ());
}
+ // real: norm_2_square v = sum(v [i] * v [i])
+ // complex: norm_2_square v = sum(v [i] * conj (v [i]))
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_scalar_unary_traits<E, vector_norm_2_square<E> >::result_type
+ norm_2_square (const vector_expression<E> &e) {
+ typedef typename vector_scalar_unary_traits<E, vector_norm_2_square<E> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
// real: norm_inf v = maximum (abs (v [i]))
// complex: norm_inf v = maximum (maximum (abs (real (v [i])), abs (imag (v [i]))))
template<class E>
diff --git a/boost/numeric/ublas/vector_of_vector.hpp b/boost/numeric/ublas/vector_of_vector.hpp
index de87a668ac..e18c9a908a 100644
--- a/boost/numeric/ublas/vector_of_vector.hpp
+++ b/boost/numeric/ublas/vector_of_vector.hpp
@@ -66,7 +66,7 @@ namespace boost { namespace numeric { namespace ublas {
storage_invariants ();
}
BOOST_UBLAS_INLINE
- generalized_vector_of_vector (size_type size1, size_type size2, size_type non_zeros = 0):
+ generalized_vector_of_vector (size_type size1, size_type size2, size_type /*non_zeros = 0*/):
matrix_container<self_type> (),
size1_ (size1), size2_ (size2), data_ (layout_type::size_M (size1_, size2_) + 1) {
const size_type sizeM = layout_type::size_M (size1_, size2_);
@@ -84,7 +84,7 @@ namespace boost { namespace numeric { namespace ublas {
}
template<class AE>
BOOST_UBLAS_INLINE
- generalized_vector_of_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0):
+ generalized_vector_of_vector (const matrix_expression<AE> &ae, size_type /*non_zeros = 0*/):
matrix_container<self_type> (),
size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) {
const size_type sizeM = layout_type::size_M (size1_, size2_);
diff --git a/boost/numeric/ublas/vector_sparse.hpp b/boost/numeric/ublas/vector_sparse.hpp
index 07c64cbf0e..0a021b063d 100644
--- a/boost/numeric/ublas/vector_sparse.hpp
+++ b/boost/numeric/ublas/vector_sparse.hpp
@@ -13,6 +13,31 @@
#ifndef _BOOST_UBLAS_VECTOR_SPARSE_
#define _BOOST_UBLAS_VECTOR_SPARSE_
+#include <boost/config.hpp>
+
+// In debug mode, MSCV enables iterator debugging, which additional checks are
+// executed for consistency. So, when two iterators are compared, it is tested
+// that they point to elements of the same container. If the check fails, then
+// the program is aborted.
+//
+// When matrices MVOV are traversed by column and then by row, the previous
+// check fails.
+//
+// MVOV::iterator2 iter2 = mvov.begin2();
+// for (; iter2 != mvov.end() ; iter2++) {
+// MVOV::iterator1 iter1 = iter2.begin();
+// .....
+// }
+//
+// These additional checks in iterators are disabled in this file, but their
+// status are restored at the end of file.
+// https://msdn.microsoft.com/en-us/library/hh697468.aspx
+#ifdef BOOST_MSVC
+#define _BACKUP_ITERATOR_DEBUG_LEVEL _ITERATOR_DEBUG_LEVEL
+#undef _ITERATOR_DEBUG_LEVEL
+#define _ITERATOR_DEBUG_LEVEL 0
+#endif
+
#include <boost/numeric/ublas/storage_sparse.hpp>
#include <boost/numeric/ublas/vector_expression.hpp>
#include <boost/numeric/ublas/detail/vector_assign.hpp>
@@ -372,7 +397,7 @@ namespace boost { namespace numeric { namespace ublas {
// Reserving
BOOST_UBLAS_INLINE
- void reserve (size_type non_zeros = 0, bool preserve = true) {
+ void reserve (size_type non_zeros, bool /*preserve*/ = true) {
detail::map_reserve (data (), restrict_capacity (non_zeros));
}
@@ -2212,4 +2237,10 @@ namespace boost { namespace numeric { namespace ublas {
}}}
+#ifdef BOOST_MSVC
+#undef _ITERATOR_DEBUG_LEVEL
+#define _ITERATOR_DEBUG_LEVEL _BACKUP_ITERATOR_DEBUG_LEVEL
+#undef _BACKUP_ITERATOR_DEBUG_LEVEL
+#endif
+
#endif