plll  1.0
matrix-ops.hpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2011-2014 University of Zurich
3 
4  Permission is hereby granted, free of charge, to any person obtaining a copy
5  of this software and associated documentation files (the "Software"), to deal
6  in the Software without restriction, including without limitation the rights
7  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  copies of the Software, and to permit persons to whom the Software is
9  furnished to do so, subject to the following conditions:
10 
11  The above copyright notice and this permission notice shall be included in
12  all copies or substantial portions of the Software.
13 
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  THE SOFTWARE.
21 */
22 
23 #ifndef PLLL_INCLUDE_GUARD__MATRIX_OPS_HPP
24 #define PLLL_INCLUDE_GUARD__MATRIX_OPS_HPP
25 
26 #include "arithmetic.hpp"
27 #include <memory>
28 
36 namespace plll
37 {
38  namespace linalg
39  {
43 
44  namespace implementation
45  {
46  namespace expressions
47  {
48  template<template<typename DataType> class Operator, typename Data>
49  class expr : private Operator<Data>
50  {
51  private:
52  Data d_data;
53 
54  public:
55  inline expr(const Data & data)
56  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Data(data)))
57  : d_data(data)
58  {
59  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::expr(" << getAddress(*this) << "; " << getAddress(data) << ")");
60  }
61 
62  inline expr(const Operator<Data> & op, const Data & data)
63  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Operator<Data>(op)) && noexcept(Data(data)))
64  : Operator<Data>(op), d_data(data)
65  {
66  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::expr(" << getAddress(*this) << "; " << getAddress(op) << "; " << getAddress(data) << ")");
67  }
68 
69  inline const expr<Operator, Data> & operator = (const expr<Operator, Data> & a) const
70  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(assign(helper::make_type_lvalue<expr<Operator, Data>>(), a)))
71  {
72  assign(*this, a);
73  return *this;
74  }
75 
76  enum { has_direct_access = Operator<Data>::has_direct_access };
77 
78  typedef typename Operator<Data>::CoeffType CoeffType;
79  typedef typename Operator<Data>::CoeffType_Get CoeffType_Get;
80  typedef typename Operator<Data>::GetCoeffSteps_Type GetCoeffSteps_Type;
81  typedef typename Operator<Data>::ValueType ValueType;
84  expr<Operator, Data> >::result LazyEvalType;
85  typedef typename Operator<Data>::data_pointer_type data_pointer_type;
86  typedef typename Operator<Data>::data_ref_type data_ref_type;
87 
88  template<typename ResultType>
89  inline void get_coeff(ResultType & result, size_type i, size_type j) const
90  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::get_coeff(result, i, j, d_data)))
91  {
92  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << ") const");
94  Operator<Data>::get_coeff(result, i, j, d_data);
95  }
96 
97  inline bool get_coeff_alwayszero() const
98  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::get_coeff_alwayszero(d_data)))
99  {
100  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::get_coeff_alwayszero(" << getAddress(*this) << ")");
102  return Operator<Data>::get_coeff_alwayszero(d_data);
103  }
104 
105  inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j) const
106  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::get_coeff_steps(i, j, d_data)))
107  {
108  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::get_coeff_steps(" << getAddress(*this) << ")");
110  return Operator<Data>::get_coeff_steps(i, j, d_data);
111  }
112 
113  inline CoeffType_Get operator () (size_type i, size_type j) const
114  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::operator()(i, j, d_data)))
115  {
116  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::operator () (" << getAddress(*this) << "; " << i << " " << j << ")");
118  return Operator<Data>::operator()(i, j, d_data);
119  }
120 
121  inline CoeffType_Get operator [] (size_type i) const
122  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL((MatrixInfo<ValueType>::cols == 1) ?
123  noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::operator()(i, 0, d_data)) :
124  noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::operator()(0, i, d_data)))
125  {
126  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::operator [] (" << getAddress(*this) << "; " << i << ")");
129  (MatrixInfo<ValueType>::rows == 1), OnlyDefinedForVectors);
130  return (MatrixInfo<ValueType>::cols == 1) ? Operator<Data>::operator()(i, 0, d_data) : Operator<Data>::operator()(0, i, d_data);
131  }
132 
133  inline data_pointer_type data() const
134  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::data(d_data)))
135  {
136  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::data(" << getAddress(*this) << ") const");
137  return Operator<Data>::data(d_data);
138  }
139 
140  inline data_ref_type data(size_type i) const
141  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::data(d_data, i)))
142  {
143  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::data(" << getAddress(*this) << "; " << i << ")");
144  return Operator<Data>::data(d_data, i);
145  }
146 
147  inline size_type rows() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
148  {
149  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::rows(" << getAddress(*this) << ")");
150  return Operator<Data>::rows(d_data);
151  }
152 
153  inline size_type cols() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
154  {
155  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::cols(" << getAddress(*this) << ")");
156  return Operator<Data>::cols(d_data);
157  }
158 
159  inline size_type size() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
160  {
161  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::size(" << getAddress(*this) << ")");
162  return Operator<Data>::size(d_data);
163  }
164 
165  template<unsigned SRows, unsigned SCols>
166  inline expr<sub<SRows, SCols>::template operation_generic, expr<Operator, Data> >
167  block(size_type r_ofs, size_type c_ofs) const
168  {
169  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::block<" << SRows << " " << SCols << ">(" << getAddress(*this) << "; " << r_ofs << " " << c_ofs << ") const");
170  return expr<sub<SRows, SCols>::template operation_generic, expr<Operator, Data> >
171  (typename sub<SRows, SCols>::template operation_generic<expr<Operator, Data> >(SRows, SCols, r_ofs, c_ofs, *this), *this);
172  }
173 
175  block(size_type r_ofs, size_type c_ofs, size_type rows, size_type cols) const
176  {
177  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::block(" << getAddress(*this) << "; " << r_ofs << " " << c_ofs << " " << rows << " " << cols << ")");
179  (typename sub<Flexible, Flexible>::template operation_generic<expr<Operator, Data> >(rows, cols, r_ofs, c_ofs, *this), *this);
180  }
181 
183  row(size_type row_index) const
184  {
185  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::row(" << getAddress(*this) << "; " << row_index << ") const");
187  (typename sub_1d<MatrixInfo<typename Operator<Data>::ValueType>::cols>::template operation_row<expr<Operator, Data> >(cols(), row_index, *this), *this);
188  }
189 
191  col(size_type col_index) const
192  {
193  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::col(" << getAddress(*this) << "; " << col_index << ") const");
195  (typename sub_1d<MatrixInfo<typename Operator<Data>::ValueType>::rows>::template operation_col<expr<Operator, Data> >(rows(), col_index, *this), *this);
196  }
197 
198  inline expr<expressions::transpose, expr<Operator, Data> > transpose() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
199  {
200  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::transpose(" << getAddress(*this) << ") const");
202  }
203 
204  inline ValueType evaluate() const
205  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ValueType(helper::make_type_lvalue<const expr<Operator, Data> >())))
206  {
207  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::evaluate(" << getAddress(*this) << ")");
208  return ValueType(*this);
209  }
210 
211  inline LazyEvalType lazy_evaluate() const
212  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(LazyEvalType(helper::make_type_lvalue<const expr<Operator, Data> >())))
213  {
214  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::lazy_evaluate(" << getAddress(*this) << ")");
215  return LazyEvalType(*this);
216  }
217 
218  template<typename MatrixType>
219  inline bool involves_this_matrix(const MatrixType & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
220  {
221  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(A) << ")");
222  return Operator<Data>::involves_this_matrix(A, d_data);
223  }
224 
225  template<typename MatrixType>
226  inline bool test_involvement(const MatrixType & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
227  {
228  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::test_involvement(" << getAddress(*this) << "; " << getAddress(A) << ")");
229  return Operator<Data>::test_involvement(A, d_data);
230  }
231 
232  template<typename T, int R, int C, typename ST, bool MO>
233  const expr<Operator, Data> & operator = (const base_matrix<T, R, C, ST, MO> & m) const
234  {
235  PLLL_DEBUG_OUTPUT_MESSAGE("base_matrix::operator = (" << getAddress(*this) << "; " << getAddress(m) << ")");
236  PLLL_INTERNAL_STATIC_CHECK((MatrixInfo<base_matrix<T, R, C, ST, MO> >::is_matrix), RequiresMatrixType);
237  assign(*this, m);
238  return *this;
239  }
240 
241  template<template<typename> class Op_, typename Data_>
242  const expr<Operator, Data> & operator = (const expr<Op_, Data_> & m) const
243  {
244  PLLL_DEBUG_OUTPUT_MESSAGE("base_matrix::operator = (" << getAddress(*this) << "; " << getAddress(m) << ")");
245  PLLL_INTERNAL_STATIC_CHECK((MatrixInfo<expr<Op_, Data_> >::is_matrix), RequiresMatrixType);
246  assign(*this, m);
247  return *this;
248  }
249 
250 #if __cplusplus >= 201103L
251  template<typename T, int R, int C, typename ST, bool MO>
252  const expr<Operator, Data> & operator = (base_matrix<T, R, C, ST, MO> && m) const
253  {
254  PLLL_DEBUG_OUTPUT_MESSAGE("base_matrix::operator = (" << getAddress(*this) << "; " << getAddress(m) << ") [&&]");
255  PLLL_INTERNAL_STATIC_CHECK((MatrixInfo<base_matrix<T, R, C, ST, MO> >::is_matrix), RequiresMatrixType);
256  assign(*this, std::move(m));
257  return *this;
258  }
259 
260  template<template<typename> class Op_, typename Data_>
261  const expr<Operator, Data> & operator = (expr<Op_, Data_> && m) const
262  {
263  PLLL_DEBUG_OUTPUT_MESSAGE("base_matrix::operator = (" << getAddress(*this) << "; " << getAddress(m) << ") [&&]");
264  PLLL_INTERNAL_STATIC_CHECK((MatrixInfo<expr<Op_, Data_> >::is_matrix), RequiresMatrixType);
265  assign(*this, std::move(m));
266  return *this;
267  }
268 #endif
269 
270  template<typename MatrixType>
271  void assign_resize(const MatrixType & mat) const
272  {
273  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::assign_resize(" << getAddress(*this) << "; " << getAddress(mat) << ")");
275  PLLL_INTERNAL_STATIC_CHECK(Operator<Data>::can_resize_rows || Operator<Data>::can_resize_cols, RequiresResizeableMatrixType);
276  PLLL_INTERNAL_STATIC_CHECK(Operator<Data>::can_assign_to, RequiresAssignableMatrixType);
277  Operator<Data>::assign_resize(mat, d_data);
278  }
279 
280 #if __cplusplus >= 201103L
281  template<typename MatrixType>
282  void move_resize(MatrixType && mat) const
283  {
284  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::move_resize(" << getAddress(*this) << "; " << getAddress(mat) << ")");
287  PLLL_INTERNAL_STATIC_CHECK(Operator<Data>::can_resize_rows || Operator<Data>::can_resize_cols, RequiresResizeableMatrixType);
288  PLLL_INTERNAL_STATIC_CHECK(Operator<Data>::can_assign_to, RequiresAssignableMatrixType);
289  Operator<Data>::move_resize(std::move(mat), d_data);
290  }
291 #else
292  template<typename MatrixType>
293  void move_resize(const MatrixType & mat) const
294  {
295  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::expr::move_resize(" << getAddress(*this) << "; " << getAddress(mat) << ")");
298  PLLL_INTERNAL_STATIC_CHECK(Operator<Data>::can_resize_rows || Operator<Data>::can_resize_cols, RequiresResizeableMatrixType);
299  PLLL_INTERNAL_STATIC_CHECK(Operator<Data>::can_assign_to, RequiresAssignableMatrixType);
300  Operator<Data>::move_resize(mat, d_data);
301  }
302 #endif
303 
304  typedef typename Operator<Data>::Enumerator Enumerator;
305  typedef typename Operator<Data>::RowEnumerator RowEnumerator;
306  typedef typename Operator<Data>::ColEnumerator ColEnumerator;
307  typedef typename Operator<Data>::ConstEnumerator ConstEnumerator;
308  typedef typename Operator<Data>::ConstRowEnumerator ConstRowEnumerator;
309  typedef typename Operator<Data>::ConstColEnumerator ConstColEnumerator;
310  typedef typename Operator<Data>::DefaultEnumerator DefaultEnumerator;
311  typedef typename Operator<Data>::DefaultRowEnumerator DefaultRowEnumerator;
312  typedef typename Operator<Data>::DefaultColEnumerator DefaultColEnumerator;
313 
314  inline DefaultEnumerator enumerate() const
315  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::enumerate(d_data)))
316  {
317  return Operator<Data>::enumerate(d_data);
318  }
319 
320  inline DefaultRowEnumerator enumerate_row(size_type row) const
321  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::enumerate_row(row, d_data)))
322  {
323  return Operator<Data>::enumerate_row(row, d_data);
324  }
325 
326  inline DefaultColEnumerator enumerate_col(size_type col) const
327  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::enumerate_col(col, d_data)))
328  {
329  return Operator<Data>::enumerate_col(col, d_data);
330  }
331 
332  typedef typename Operator<Data>::RowsEnumerator RowsEnumerator;
333  typedef typename Operator<Data>::ColsEnumerator ColsEnumerator;
334  typedef typename Operator<Data>::ConstRowsEnumerator ConstRowsEnumerator;
335  typedef typename Operator<Data>::ConstColsEnumerator ConstColsEnumerator;
336  typedef typename Operator<Data>::DefaultRowsEnumerator DefaultRowsEnumerator;
337  typedef typename Operator<Data>::DefaultColsEnumerator DefaultColsEnumerator;
338 
339  inline DefaultRowsEnumerator enumerate_rows() const
340  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::enumerate_rows(d_data)))
341  {
342  return Operator<Data>::enumerate_rows(d_data);
343  }
344 
345  inline DefaultColsEnumerator enumerate_cols() const
346  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(helper::make_type_lvalue<expr<Operator, Data> >().Operator<Data>::enumerate_cols(d_data)))
347  {
348  return Operator<Data>::enumerate_cols(d_data);
349  }
350  };
351 
352  template<typename Data>
354  {
355  public:
356  typedef typename Data::CoeffType CoeffType;
357  typedef typename Data::CoeffType_Get CoeffType_Get;
358  typedef typename Data::GetCoeffSteps_Type GetCoeffSteps_Type;
359  typedef typename Data::ValueType ValueType;
360  typedef typename Data::data_pointer_type data_pointer_type;
361  typedef typename Data::data_ref_type data_ref_type;
362 
363  enum { use_temporary_on_evaluate = MatrixInfo<Data>::use_temporary_on_evaluate,
364  coeffs_are_simple_expressions = MatrixInfo<Data>::coeffs_are_simple_expressions,
365  is_const = MatrixInfo<Data>::is_const,
366  can_assign_to = MatrixInfo<Data>::can_assign_to,
367  can_move_from = MatrixInfo<Data>::can_move_from,
368  can_resize_rows = MatrixInfo<Data>::can_resize_rows,
369  can_resize_cols = MatrixInfo<Data>::can_resize_cols,
370  has_direct_access = Data::has_direct_access };
371 
372  template<typename ResultType>
373  static inline void get_coeff(ResultType & result, size_type i, size_type j, const Data & D)
374  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(D.get_coeff(result, i, j)))
375  {
376  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << " " << getAddress(D) << ")");
377  D.get_coeff(result, i, j);
378  }
379 
380  static inline bool get_coeff_alwayszero(const Data & D)
381  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(D.get_coeff_alwayszero()))
382  {
383  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::get_coeff_alwayszero(" << getAddress(*this) << "; " << getAddress(D) << ")");
384  return D.get_coeff_alwayszero();
385  }
386 
387  static inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j, const Data & D)
388  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(D.get_coeff_steps(i, j)))
389  {
390  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::get_coeff_steps(" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(D) << ")");
391  return D.get_coeff_steps(i, j);
392  }
393 
394  inline CoeffType_Get operator () (size_type i, size_type j, const Data & D) const
395  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(D(i, j)))
396  {
397  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::operator () (" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(D) << ")");
398  return D(i, j);
399  }
400 
401  static inline data_pointer_type data(const Data & D)
402  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(D.data()))
403  {
404  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::data(" << getAddress(*this) << ";" << getAddress(D) << ") const");
405  return D.data();
406  }
407 
408  static inline data_ref_type data(const Data & D, size_type i)
409  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(D.data(i)))
410  {
411  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::data(" << getAddress(*this) << "; " << getAddress(D) << " " << i << ")");
412  return D.data(i);
413  }
414 
415  static inline size_type rows(const Data & D) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
416  {
417  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::rows(" << getAddress(*this) << "; " << getAddress(D) << ")");
418  return D.rows();
419  }
420 
421  static inline size_type cols(const Data & D) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
422  {
423  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::cols(" << getAddress(*this) << "; " << getAddress(D) << ")");
424  return D.cols();
425  }
426 
427  static inline size_type size(const Data & D) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
428  {
429  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::size(" << getAddress(*this) << "; " << getAddress(D) << ")");
430  return D.size();
431  }
432 
433  template<typename MatrixType>
434  static inline bool involves_this_matrix(const MatrixType & matrix, const Data & D) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
435  {
436  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(D) << ")");
437  return D.involves_this_matrix(matrix);
438  }
439 
440  template<typename MatrixType>
441  static inline bool test_involvement(const MatrixType & matrix, const Data & D) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
442  {
443  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::test_involvement(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(D) << ")");
444  return D.test_involvement(matrix);
445  }
446 
447  template<typename MatrixType>
448  static void assign_resize(const MatrixType & mat, const Data & D)
449  {
450  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::assign_resize(" << getAddress(*this) << "; " << getAddress(mat) << " " << getAddress(D) << ")");
451  D.assign_resize(mat);
452  }
453 
454 #if __cplusplus >= 201103L
455  template<typename MatrixType>
456  static void move_resize(MatrixType && mat, const Data & D)
457  {
458  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::move_resize(" << getAddress(*this) << "; " << getAddress(mat) << " " << getAddress(D) << ")");
459  D.move_resize(std::move(mat));
460  }
461 #else
462  template<typename MatrixType>
463  static void move_resize(const MatrixType & mat, const Data & D)
464  {
465  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::identity_operation::move_resize(" << getAddress(*this) << "; " << getAddress(mat) << " " << getAddress(D) << ")");
466  D.move_resize(mat);
467  }
468 #endif
469 
470  typedef typename Data::Enumerator Enumerator;
471  typedef typename Data::RowEnumerator RowEnumerator;
472  typedef typename Data::ColEnumerator ColEnumerator;
473  typedef typename Data::ConstEnumerator ConstEnumerator;
474  typedef typename Data::ConstRowEnumerator ConstRowEnumerator;
475  typedef typename Data::ConstColEnumerator ConstColEnumerator;
476  typedef typename Data::DefaultEnumerator DefaultEnumerator;
477  typedef typename Data::DefaultRowEnumerator DefaultRowEnumerator;
478  typedef typename Data::DefaultColEnumerator DefaultColEnumerator;
479 
480  static inline DefaultEnumerator enumerate(const Data & data)
481  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(data.enumerate()))
482  {
483  return data.enumerate();
484  }
485 
486  static inline DefaultRowEnumerator enumerate_row(size_type row, const Data & data)
487  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(data.enumerate_row(row)))
488  {
489  return data.enumerate_row(row);
490  }
491 
492  static inline DefaultColEnumerator enumerate_col(size_type col, const Data & data)
493  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(data.enumerate_col(col)))
494  {
495  return data.enumerate_col(col);
496  }
497 
498  typedef typename Data::RowsEnumerator RowsEnumerator;
499  typedef typename Data::ColsEnumerator ColsEnumerator;
500  typedef typename Data::ConstRowsEnumerator ConstRowsEnumerator;
501  typedef typename Data::ConstColsEnumerator ConstColsEnumerator;
502  typedef typename Data::DefaultRowsEnumerator DefaultRowsEnumerator;
503  typedef typename Data::DefaultColsEnumerator DefaultColsEnumerator;
504 
505  static inline DefaultRowsEnumerator enumerate_rows(const Data & data)
506  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(data.enumerate_rows()))
507  {
508  return data.enumerate_rows();
509  }
510 
511  static inline DefaultColsEnumerator enumerate_cols(const Data & data)
512  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(data.enumerate_cols()))
513  {
514  return data.enumerate_cols();
515  }
516  };
517 
518  template<typename MatrixType>
520  {
521  private:
522  MatrixType & d_matrix;
523 
524  public:
525  enum { has_direct_access = MatrixType::has_direct_access };
526 
527  typedef typename MatrixInfo<MatrixType>::Type CoeffType;
528  typedef typename MatrixInfo<MatrixType>::Type & CoeffType_Get;
529  typedef typename MatrixType::GetCoeffSteps_Type GetCoeffSteps_Type;
530  typedef MatrixType ValueType;
531  typedef MatrixType & LazyEvalType;
532  typedef typename MatrixInfo<MatrixType>::StorageTraits::pointer_type data_pointer_type;
533  typedef typename MatrixInfo<MatrixType>::StorageTraits::ref_type data_ref_type;
534 
535  template<typename ResultType>
536  inline void get_coeff(ResultType & result, size_type i, size_type j) const
537  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.get_coeff(result, i, j)))
538  {
539  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << ") const");
540  d_matrix.get_coeff(result, i, j);
541  }
542 
543  static inline bool get_coeff_alwayszero() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
544  {
545  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::get_coeff_alwayszero(" << getAddress(*this) << ")");
546  return false;
547  }
548 
549  inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j) const
550  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.get_coeff_steps(i, j)))
551  {
552  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::get_zero_steps(" << getAddress(*this) << "; " << i << " " << j << ")");
553  return d_matrix.get_coeff_steps(i, j);
554  }
555 
556  inline CoeffType_Get operator () (size_type i, size_type j) const
557  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix(i, j)))
558  {
559  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::operator () (" << getAddress(*this) << "; " << i << " " << j << ")");
560  return d_matrix(i, j);
561  }
562 
563  inline CoeffType_Get operator [] (size_type i) const
564  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix[i]))
565  {
566  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::operator [] (" << getAddress(*this) << "; " << i << ")");
567  return d_matrix[i];
568  }
569 
570  inline size_type rows() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
571  {
572  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::rows(" << getAddress(*this) << ")");
573  return d_matrix.rows();
574  }
575 
576  inline size_type cols() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
577  {
578  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::cols(" << getAddress(*this) << ")");
579  return d_matrix.cols();
580  }
581 
582  inline size_type size() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
583  {
584  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::size(" << getAddress(*this) << ")");
585  return d_matrix.size();
586  }
587 
588  inline data_pointer_type data() const
589  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.data()))
590  {
591  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::data(" << getAddress(*this) << ") const");
592  return d_matrix.data();
593  }
594 
595  inline data_ref_type data(size_type i) const
596  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.data(i)))
597  {
598  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::data(" << getAddress(*this) << "; " << i << ")");
599  return d_matrix.data(i);
600  }
601 
602  inline MatrixWrapper(MatrixType & matrix) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
603  : d_matrix(matrix)
604  {
605  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::MatrixWrapper(" << getAddress(*this) << "; " << getAddress(matrix) << ")");
606  }
607 
608  inline MatrixType & evaluate() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
609  {
610  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::evaluate(" << getAddress(*this) << ")");
611  return d_matrix;
612  }
613 
614  inline LazyEvalType lazy_evaluate() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
615  {
616  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::lazy_evaluate(" << getAddress(*this) << ")");
617  return d_matrix;
618  }
619 
620  template<typename QMatrixType>
621  inline bool involves_this_matrix(const QMatrixType & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
622  {
623  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(A) << ")");
624  return d_matrix.involves_this_matrix(A);
625  }
626 
627  template<typename MatrixType_>
628  inline bool test_involvement(const MatrixType_ & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
629  {
630  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::test_involvement(" << getAddress(*this) << "; " << getAddress(A) << ")");
631  return d_matrix.test_involvement(A);
632  }
633 
634  template<typename MatrixType_>
635  void assign_resize(const MatrixType_ & mat) const
636  {
637  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::assign_resize(" << getAddress(*this) << "; " << getAddress(mat) << ")");
638  d_matrix.assign_resize(mat);
639  }
640 
641 #if __cplusplus >= 201103L
642  template<typename MatrixType_>
643  void move_resize(MatrixType_ && mat) const
644  {
645  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::move_resize(" << getAddress(*this) << "; " << getAddress(mat) << ")");
646  d_matrix.move_resize(std::move(mat));
647  }
648 #else
649  template<typename MatrixType_>
650  void move_resize(const MatrixType_ & mat) const
651  {
652  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixWrapper::move_resize(" << getAddress(*this) << "; " << getAddress(mat) << ")");
653  d_matrix.move_resize(mat);
654  }
655 #endif
656 
657  typedef typename MatrixType::Enumerator Enumerator;
658  typedef typename MatrixType::Enumerator DefaultEnumerator;
659  typedef typename MatrixType::ConstEnumerator ConstEnumerator;
660  typedef typename MatrixType::RowEnumerator RowEnumerator;
661  typedef typename MatrixType::RowEnumerator DefaultRowEnumerator;
662  typedef typename MatrixType::ConstRowEnumerator ConstRowEnumerator;
663  typedef typename MatrixType::ColEnumerator ColEnumerator;
664  typedef typename MatrixType::ColEnumerator DefaultColEnumerator;
665  typedef typename MatrixType::ConstColEnumerator ConstColEnumerator;
666 
667  inline DefaultEnumerator enumerate() const
668  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate()))
669  {
670  return d_matrix.enumerate();
671  }
672 
673  inline DefaultRowEnumerator enumerate_row(size_type row) const
674  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate_row(row)))
675  {
676  return d_matrix.enumerate_row(row);
677  }
678 
679  inline DefaultColEnumerator enumerate_col(size_type col) const
680  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate_col(col)))
681  {
682  return d_matrix.enumerate_col(col);
683  }
684 
685  typedef typename MatrixType::RowsEnumerator RowsEnumerator;
686  typedef typename MatrixType::ColsEnumerator ColsEnumerator;
687  typedef typename MatrixType::RowsEnumerator DefaultRowsEnumerator;
688  typedef typename MatrixType::ColsEnumerator DefaultColsEnumerator;
689  typedef typename MatrixType::ConstRowsEnumerator ConstRowsEnumerator;
690  typedef typename MatrixType::ConstColsEnumerator ConstColsEnumerator;
691 
692  inline DefaultRowsEnumerator enumerate_rows() const
693  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate_rows()))
694  {
695  return d_matrix.enumerate_rows();
696  }
697 
698  inline DefaultColsEnumerator enumerate_cols() const
699  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate_cols()))
700  {
701  return d_matrix.enumerate_cols();
702  }
703  };
704 
705  template<typename MatrixType>
707  {
708  private:
709  const MatrixType & d_matrix;
710 
711  public:
712  enum { has_direct_access = MatrixType::has_direct_access };
713 
714  typedef typename MatrixInfo<MatrixType>::Type CoeffType;
715  typedef const typename MatrixInfo<MatrixType>::Type & CoeffType_Get;
716  typedef typename MatrixType::GetCoeffSteps_Type GetCoeffSteps_Type;
717  typedef MatrixType ValueType;
718  typedef MatrixType & LazyEvalType;
719  typedef typename MatrixInfo<MatrixType>::StorageTraits::constpointer_type data_pointer_type;
720  typedef typename MatrixInfo<MatrixType>::StorageTraits::constref_type data_ref_type;
721 
722  template<typename ResultType>
723  inline void get_coeff(ResultType & result, size_type i, size_type j) const
724  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.get_coeff(result, i, j)))
725  {
726  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << ") const");
727  d_matrix.get_coeff(result, i, j);
728  }
729 
730  static inline bool get_coeff_alwayszero() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
731  {
732  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::get_coeff_alwayszero(" << getAddress(*this) << ")");
733  return false;
734  }
735 
736  inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j) const
737  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.get_coeff_steps(i, j)))
738  {
739  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::get_zero_steps(" << getAddress(*this) << "; " << i << " " << j << ")");
740  return d_matrix.get_coeff_steps(i, j);
741  }
742 
743  inline CoeffType_Get operator () (size_type i, size_type j) const
744  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix(i, j)))
745  {
746  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::operator () (" << getAddress(*this) << "; " << i << " " << j << ")");
747  return d_matrix(i, j);
748  }
749 
750  inline CoeffType_Get operator [] (size_type i) const
751  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix[i]))
752  {
753  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::operator [] (" << getAddress(*this) << "; " << i << ")");
754  return d_matrix[i];
755  }
756 
757  inline size_type rows() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
758  {
759  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::rows(" << getAddress(*this) << ")");
760  return d_matrix.rows();
761  }
762 
763  inline size_type cols() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
764  {
765  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::cols(" << getAddress(*this) << ")");
766  return d_matrix.cols();
767  }
768 
769  inline size_type size() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
770  {
771  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::size(" << getAddress(*this) << ")");
772  return d_matrix.size();
773  }
774 
775  inline data_pointer_type data() const
776  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.data()))
777  {
778  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::data(" << getAddress(*this) << ") const");
779  return d_matrix.data();
780  }
781 
782  inline data_ref_type data(size_type i) const
783  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.data(i)))
784  {
785  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::data(" << getAddress(*this) << "; " << i << ") const");
786  return d_matrix.data(i);
787  }
788 
789  inline ConstMatrixWrapper(const MatrixType & matrix) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
790  : d_matrix(matrix)
791  {
792  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::ConstMatrixWrapper(" << getAddress(*this) << "; " << getAddress(matrix) << ")");
793  }
794 
795  inline const MatrixType & evaluate() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
796  {
797  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::evaluate(" << getAddress(*this) << ")");
798  return d_matrix;
799  }
800 
801  inline LazyEvalType lazy_evaluate() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
802  {
803  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::lazy_evaluate(" << getAddress(*this) << ")");
804  return d_matrix;
805  }
806 
807  template<typename QMatrixType>
808  inline bool involves_this_matrix(const QMatrixType & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
809  {
810  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(A) << ")");
811  return d_matrix.involves_this_matrix(A);
812  }
813 
814  template<typename MatrixType_>
815  inline bool test_involvement(const MatrixType_ & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
816  {
817  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ConstMatrixWrapper::test_involvement(" << getAddress(*this) << "; " << getAddress(A) << ")");
818  return d_matrix.test_involvement(A);
819  }
820 
821  typedef void Enumerator;
822  typedef void RowEnumerator;
823  typedef void ColEnumerator;
824  typedef typename MatrixType::ConstEnumerator ConstEnumerator;
825  typedef typename MatrixType::ConstRowEnumerator ConstRowEnumerator;
826  typedef typename MatrixType::ConstColEnumerator ConstColEnumerator;
827  typedef typename MatrixType::ConstEnumerator DefaultEnumerator;
828  typedef typename MatrixType::ConstRowEnumerator DefaultRowEnumerator;
829  typedef typename MatrixType::ConstColEnumerator DefaultColEnumerator;
830 
831  inline DefaultEnumerator enumerate() const
832  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate()))
833  {
834  return d_matrix.enumerate();
835  }
836 
837  inline DefaultRowEnumerator enumerate_row(size_type row) const
838  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate_row(row)))
839  {
840  return d_matrix.enumerate_row(row);
841  }
842 
843  inline DefaultColEnumerator enumerate_col(size_type col) const
844  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate_col(col)))
845  {
846  return d_matrix.enumerate_col(col);
847  }
848 
849  typedef void RowsEnumerator;
850  typedef void ColsEnumerator;
851  typedef typename MatrixType::ConstRowsEnumerator ConstRowsEnumerator;
852  typedef typename MatrixType::ConstColsEnumerator ConstColsEnumerator;
853  typedef typename MatrixType::ConstRowsEnumerator DefaultRowsEnumerator;
854  typedef typename MatrixType::ConstColsEnumerator DefaultColsEnumerator;
855 
856  inline DefaultRowsEnumerator enumerate_rows() const
857  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate_rows()))
858  {
859  return d_matrix.enumerate_rows();
860  }
861 
862  inline DefaultColsEnumerator enumerate_cols() const
863  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix.enumerate_cols()))
864  {
865  return d_matrix.enumerate_cols();
866  }
867  };
868 
869  template<typename MatrixType>
871  make_matrix_wrapper(MatrixType & matrix) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
872  {
873  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::make_matrix_wrapper(" << getAddress(matrix) << ") [1]");
874  return MatrixWrapper<MatrixType>(matrix);
875  }
876 
877  template<typename MatrixType>
878  inline ConstMatrixWrapper<MatrixType>
879  make_matrix_wrapper(const MatrixType & matrix) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
880  {
881  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::make_matrix_wrapper(" << getAddress(matrix) << ") [2]");
882  return ConstMatrixWrapper<MatrixType>(matrix);
883  }
884 
885  template<typename MatrixType>
886  inline expr<identity_operation, MatrixWrapper<MatrixType> >
887  make_matrix_expression(MatrixType & matrix) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
888  {
889  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::make_matrix_expression(" << getAddress(matrix) << ") [1]");
890  return expr<identity_operation, MatrixWrapper<MatrixType> >(MatrixWrapper<MatrixType>(matrix));
891  }
892 
893  template<typename MatrixType>
894  inline expr<identity_operation, ConstMatrixWrapper<MatrixType> >
895  make_matrix_expression(const MatrixType & matrix) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
896  {
897  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::make_matrix_expression(" << getAddress(matrix) << ") [2]");
898  return expr<identity_operation, ConstMatrixWrapper<MatrixType> >(ConstMatrixWrapper<MatrixType>(matrix));
899  }
900 
901  template<typename MatrixType>
903  {
904  private:
905 #if __cplusplus >= 201103L
906  mutable std::unique_ptr<MatrixType> d_matrix;
907 #else
908  mutable std::auto_ptr<MatrixType> d_matrix;
909 #endif
910 
911  public:
912  enum { has_direct_access = MatrixType::has_direct_access };
913 
914  typedef typename MatrixInfo<MatrixType>::Type CoeffType;
915 #if __cplusplus >= 201103L
916  typedef typename MatrixInfo<MatrixType>::Type && CoeffType_Get;
917 #else
918  // make them accessible to allow "move by swap"
919  typedef typename MatrixInfo<MatrixType>::Type & CoeffType_Get;
920 #endif
921  typedef typename MatrixType::GetCoeffSteps_Type GetCoeffSteps_Type;
922  typedef MatrixType ValueType;
923  typedef const MatrixType & LazyEvalType;
924  typedef typename MatrixInfo<MatrixType>::StorageTraits::pointer_type data_pointer_type;
925  typedef typename MatrixInfo<MatrixType>::StorageTraits::ref_type data_ref_type;
926 
927  template<typename ResultType>
928  inline void get_coeff(ResultType & result, size_type i, size_type j) const
929  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix->get_coeff(result, i, j)))
930  {
931  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << ") const");
932  d_matrix->get_coeff(result, i, j);
933  }
934 
935  static inline bool get_coeff_alwayszero() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
936  {
937  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::get_coeff_alwayszero(" << getAddress(*this) << ")");
938  return false;
939  }
940 
941  inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j) const
942  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix->get_coeff_steps(i, j)))
943  {
944  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::get_zero_steps(" << getAddress(*this) << "; " << i << " " << j << ")");
945  return d_matrix->get_coeff_steps(i, j);
946  }
947 
948  inline CoeffType_Get operator () (size_type i, size_type j) const
949  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept((*d_matrix)(i, j)))
950  {
951  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::operator () (" << getAddress(*this) << "; " << i << " " << j << ")");
952 #if __cplusplus >= 201103L
953  return std::move((*d_matrix)(i, j));
954 #else
955  return (*d_matrix)(i, j);
956 #endif
957  }
958 
959  inline CoeffType_Get operator [] (size_type i) const
960  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept((*d_matrix)[i]))
961  {
962  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::operator [] (" << getAddress(*this) << "; " << i << ")");
963 #if __cplusplus >= 201103L
964  return std::move((*d_matrix)[i]);
965 #else
966  return (*d_matrix)[i];
967 #endif
968  }
969 
970  inline size_type rows() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
971  {
972  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::rows(" << getAddress(*this) << ")");
973  return d_matrix->rows();
974  }
975 
976  inline size_type cols() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
977  {
978  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::cols(" << getAddress(*this) << ")");
979  return d_matrix->cols();
980  }
981 
982  inline size_type size() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
983  {
984  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::size(" << getAddress(*this) << ")");
985  return d_matrix->size();
986  }
987 
988  inline data_pointer_type data() const
989  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix->data()))
990  {
991  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::data(" << getAddress(*this) << ") const");
992  return d_matrix->data();
993  }
994 
995  inline data_ref_type data(size_type i) const
996  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix->data(i)))
997  {
998  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::data(" << getAddress(*this) << "; " << i << ") const");
999  return d_matrix->data(i);
1000  }
1001 
1002  template<typename MatrixType_>
1003  inline MatrixTemporaryWrapper(const MatrixType_ & matrix)
1004  : d_matrix(new MatrixType(matrix))
1005  {
1006  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::MatrixTemporaryWrapper(" << getAddress(*this) << "; " << getAddress(matrix) << ") [1]");
1007  }
1008 
1009 #if __cplusplus >= 201103L
1010  inline MatrixTemporaryWrapper(const MatrixTemporaryWrapper<MatrixType> & mtw) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1011  : d_matrix(std::move(mtw.d_matrix))
1012  {
1013  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::MatrixTemporaryWrapper(" << getAddress(*this) << "; " << getAddress(mtw) << ") [2]");
1014  }
1015 
1016  inline MatrixTemporaryWrapper(MatrixTemporaryWrapper<MatrixType> && mtw) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1017  : d_matrix(std::move(mtw.d_matrix))
1018  {
1019  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::MatrixTemporaryWrapper(" << getAddress(*this) << "; " << getAddress(mtw) << ") [3&&]");
1020  }
1021 
1022  template<typename MatrixType_>
1023  inline MatrixTemporaryWrapper(MatrixType_ && matrix)
1024  : d_matrix(new MatrixType(std::move(matrix)))
1025  {
1026  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::MatrixTemporaryWrapper(" << getAddress(*this) << "; " << getAddress(matrix) << ") [4&&]");
1027  }
1028 #else
1029  inline MatrixTemporaryWrapper(const MatrixTemporaryWrapper<MatrixType> & mtw) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1030  : d_matrix(mtw.d_matrix)
1031  {
1032  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::MatrixTemporaryWrapper(" << getAddress(*this) << "; " << getAddress(mtw) << ") [2]");
1033  }
1034 #endif
1035 
1036 #if __cplusplus >= 201103L
1037  inline MatrixType && evaluate() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1038  {
1039  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::evaluate(" << getAddress(*this) << ")");
1040  return std::move(*d_matrix);
1041  }
1042 #else
1043  inline const MatrixType & evaluate() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1044  {
1045  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::evaluate(" << getAddress(*this) << ")");
1046  return *d_matrix;
1047  }
1048 #endif
1049 
1050  inline LazyEvalType lazy_evaluate() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1051  {
1052  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::lazy_evaluate(" << getAddress(*this) << ")");
1053  return *d_matrix;
1054  }
1055 
1056  template<typename QMatrixType>
1057  static inline bool involves_this_matrix(const QMatrixType & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1058  {
1059  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(A) << ")");
1060  return false;
1061  }
1062 
1063  template<typename MatrixType_>
1064  static inline bool test_involvement(const MatrixType_ & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1065  {
1066  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::MatrixTemporaryWrapper::test_involvement(" << getAddress(*this) << "; " << getAddress(A) << ")");
1067  return false;
1068  }
1069 
1070  typedef void Enumerator;
1071  typedef void RowEnumerator;
1072  typedef void ColEnumerator;
1073  typedef typename MatrixType::ConstEnumerator ConstEnumerator;
1074  typedef typename MatrixType::ConstRowEnumerator ConstRowEnumerator;
1075  typedef typename MatrixType::ConstColEnumerator ConstColEnumerator;
1076  typedef typename MatrixType::ConstEnumerator DefaultEnumerator;
1077  typedef typename MatrixType::ConstRowEnumerator DefaultRowEnumerator;
1078  typedef typename MatrixType::ConstColEnumerator DefaultColEnumerator;
1079 
1080  inline DefaultEnumerator enumerate() const
1081  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix->enumerate()))
1082  {
1083  return d_matrix->enumerate();
1084  }
1085 
1086  inline DefaultRowEnumerator enumerate_row(size_type row) const
1087  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix->enumerate_row(row)))
1088  {
1089  return d_matrix->enumerate_row(row);
1090  }
1091 
1092  inline DefaultColEnumerator enumerate_col(size_type col) const
1093  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix->enumerate_col(col)))
1094  {
1095  return d_matrix->enumerate_col(col);
1096  }
1097 
1098  typedef void RowsEnumerator;
1099  typedef void ColsEnumerator;
1100  typedef typename MatrixType::ConstRowsEnumerator ConstRowsEnumerator;
1101  typedef typename MatrixType::ConstColsEnumerator ConstColsEnumerator;
1102  typedef typename MatrixType::ConstRowsEnumerator DefaultRowsEnumerator;
1103  typedef typename MatrixType::ConstColsEnumerator DefaultColsEnumerator;
1104 
1105  inline DefaultRowsEnumerator enumerate_rows() const
1106  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix->enumerate_rows()))
1107  {
1108  return d_matrix->enumerate_rows();
1109  }
1110 
1111  inline DefaultColsEnumerator enumerate_cols() const
1112  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_matrix->enumerate_cols()))
1113  {
1114  return d_matrix->enumerate_cols();
1115  }
1116  };
1117 
1118  template<template<typename> class Op, typename Data>
1120  make_matrix_temporary_expression(const expr<Op, Data> & matrix)
1121  {
1122  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::make_matrix_temporary_expression(" << getAddress(matrix) << ") [1]");
1125  }
1126 
1127  template<typename MatrixType>
1128  inline expr<identity_operation, MatrixTemporaryWrapper<MatrixType> >
1129  make_matrix_temporary_expression(MatrixType & matrix)
1130  {
1131  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::make_matrix_temporary_expression(" << getAddress(matrix) << ") [2]");
1132  return expr<identity_operation, MatrixTemporaryWrapper<MatrixType> >(MatrixTemporaryWrapper<MatrixType>(matrix));
1133  }
1134 
1135  template<typename ScalarType>
1137  {
1138  private:
1139  const ScalarType & d_scalar;
1140 
1141  public:
1142  typedef ScalarType ValueType;
1143  typedef const ScalarType & LazyEvalType;
1144 
1145  inline ScalarWrapper(const ScalarType & scalar) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1146  : d_scalar(scalar)
1147  {
1148  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ScalarWrapper::ScalarWrapper(" << getAddress(*this) << "; " << getAddress(scalar) << ")");
1149  }
1150 
1151  inline const ScalarType & evaluate() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1152  {
1153  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ScalarWrapper::evaluate(" << getAddress(*this) << ")");
1154  return d_scalar;
1155  }
1156 
1157  inline LazyEvalType lazy_evaluate() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1158  {
1159  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ScalarWrapper::lazy_evaluate(" << getAddress(*this) << ")");
1160  return d_scalar;
1161  }
1162 
1163  template<typename MatrixType>
1164  static inline bool involves_this_matrix(const MatrixType & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1165  {
1166  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ScalarWrapper::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(A) << ")");
1167  return false;
1168  }
1169 
1170  template<typename MatrixType>
1171  static inline bool test_involvement(const MatrixType & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1172  {
1173  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::ScalarWrapper::test_involvement(" << getAddress(*this) << "; " << getAddress(A) << ")");
1174  return false;
1175  }
1176  };
1177 
1178  template<typename ScalarType>
1179  inline ScalarWrapper<ScalarType> make_scalar_wrapper(const ScalarType & scalar) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1180  {
1181  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::make_scalar_wrapper(" << getAddress(scalar) << ")");
1182  return ScalarWrapper<ScalarType>(scalar);
1183  }
1184 
1185  template<typename PairMatrices>
1187  {
1188  private:
1189  typedef typename PairMatrices::first_type MTA;
1190  typedef typename PairMatrices::second_type MTB;
1191 
1192  public:
1193  typedef typename arithmetic::binary_operation<typename arithmetic::binary_operation<typename MTA::CoeffType_Get, typename MTB::CoeffType_Get,
1194  arithmetic::op::multiplication>::ResultType,
1195  typename arithmetic::binary_operation<typename MTA::CoeffType_Get, typename MTB::CoeffType_Get,
1196  arithmetic::op::multiplication>::ResultType,
1197  arithmetic::op::addition>::ResultType CoeffType;
1198  typedef CoeffType CoeffType_Get;
1199  typedef base_matrix<CoeffType,
1202  typename MatrixInfo<MTA>::StorageTraits,
1203  true> ValueType;
1204  typedef void data_pointer_type;
1205  typedef void data_ref_type;
1206 
1207  enum { use_temporary_on_evaluate = true/*MatrixInfo<MTA>::use_temporary_on_evaluate | MatrixInfo<MTB>::use_temporary_on_evaluate*/,
1208  coeffs_are_simple_expressions = false,
1209  is_const = true,
1210  can_assign_to = false,
1211  can_move_from = false,
1212  can_resize_rows = false,
1213  can_resize_cols = false,
1214  has_direct_access = false };
1215 
1216  matrix_matrix_multiplication() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1217  {
1219  (static_cast<size_type>(MatrixInfo<MTA>::cols) == static_cast<size_type>(MatrixInfo<MTB>::rows)), FormatsDoNotMatch);
1222  }
1223 
1224  template<typename ResultType>
1225  static inline void get_coeff(ResultType & result, size_type i, size_type j, const std::pair<MTA, MTB> & AB)
1226  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(setZero(result)) &&
1227  noexcept(CoeffType()) &&
1228  (((MatrixInfo<MTA>::cols != 0) && (MatrixInfo<MTB>::rows != 0)) ?
1229  (noexcept(AB.first.enumerate_row(i)) && noexcept(AB.second.enumerate_col(j)) &&
1230  noexcept(helper::make_type_lvalue<typename MTA::ConstRowEnumerator>().next()) &&
1231  noexcept(helper::make_type_lvalue<typename MTB::ConstColEnumerator>().next()) &&
1232  noexcept(result = helper::make_type_lvalue<typename MTA::ConstRowEnumerator>().current() * helper::make_type_lvalue<typename MTB::ConstColEnumerator>().current()) &&
1233  noexcept(result += helper::make_type_lvalue<typename MTA::ConstRowEnumerator>().current() * helper::make_type_lvalue<typename MTB::ConstColEnumerator>().current())) : true))
1234  {
1235  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_matrix_multiplication::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << " " << getAddress(AB) << ") const");
1236  assert(i < rows(AB));
1237  assert(j < cols(AB));
1238  size_type tt = MatrixInfo<MTA>::cols < 0 ? AB.second.rows() : AB.first.cols();
1239  if (tt == 0)
1240  setZero(result);
1241  else
1242  {
1243  typename MTA::ConstRowEnumerator eA = AB.first.enumerate_row(i);
1244  typename MTB::ConstColEnumerator eB = AB.second.enumerate_col(j);
1245  result = eA.current() * eB.current();
1246  for (eA.next(), eB.next(); eA.has_current(); eA.next(), eB.next())
1247  result += eA.current() * eB.current();
1248  }
1249  }
1250 
1251  static inline bool get_coeff_alwayszero(const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1252  {
1253  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_matrix_multiplication::get_coeff_alwayszero(" << getAddress(*this) << "; " << getAddress(AB) << ")");
1254  return (MatrixInfo<MTA>::cols < 0 ? AB.second.rows() : AB.first.cols()) == 0;
1255  }
1256 
1258  {
1259  protected:
1260  mutable typename MTA::ConstRowEnumerator d_eA;
1261  mutable typename MTB::ConstColEnumerator d_eB;
1262 
1263  public:
1264  inline GetCoeffSteps_Type(typename MTA::ConstRowEnumerator eA, typename MTB::ConstColEnumerator eB)
1265  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(typename MTA::ConstRowEnumerator(eA)) &&
1266  noexcept(typename MTB::ConstColEnumerator(eB)))
1267  : d_eA(eA), d_eB(eB)
1268  {
1269  }
1270 
1271  typedef typename arithmetic::binary_operation<typename MTA::CoeffType_Get, typename MTB::CoeffType_Get,
1272  arithmetic::op::multiplication>::IntermediateType Step1_Type;
1273 
1274  inline Step1_Type step1() const
1275  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_eA.current() * d_eB.current()))
1276  {
1277  return d_eA.current() * d_eB.current();
1278  }
1279 
1280  template<typename ResultType>
1281  inline void step2(ResultType & result) const
1282  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result += d_eA.current() * d_eB.current()))
1283  {
1284  for (d_eA.next(), d_eB.next(); d_eA.has_current(); d_eA.next(), d_eB.next())
1285  result += d_eA.current() * d_eB.current();
1286  }
1287  };
1288 
1289  static inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j, const std::pair<MTA, MTB> & AB)
1290  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(AB.first.enumerate_row(i), AB.second.enumerate_col(j))))
1291  {
1292  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_matrix_multiplication::get_coeff_steps(" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(AB) << ")");
1293  assert(i < rows(AB));
1294  assert(j < cols(AB));
1295  return GetCoeffSteps_Type(AB.first.enumerate_row(i), AB.second.enumerate_col(j));
1296  }
1297 
1298  inline CoeffType_Get operator () (size_type i, size_type j, const std::pair<MTA, MTB> & AB) const
1299  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(setZero(helper::make_type_lvalue<CoeffType>())) &&
1300  noexcept(CoeffType()) &&
1301  (((MatrixInfo<MTA>::cols != 0) && (MatrixInfo<MTB>::rows != 0)) ?
1302  (noexcept(AB.first.enumerate_row(i)) && noexcept(AB.second.enumerate_col(j)) &&
1303  noexcept(helper::make_type_lvalue<typename MTA::ConstRowEnumerator>().next()) &&
1304  noexcept(helper::make_type_lvalue<typename MTB::ConstColEnumerator>().next()) &&
1305  noexcept(helper::make_type_lvalue<CoeffType>() = helper::make_type_lvalue<typename MTA::ConstRowEnumerator>().current() * helper::make_type_lvalue<typename MTB::ConstColEnumerator>().current()) &&
1306  noexcept(helper::make_type_lvalue<CoeffType>() += helper::make_type_lvalue<typename MTA::ConstRowEnumerator>().current() * helper::make_type_lvalue<typename MTB::ConstColEnumerator>().current())) : true))
1307  {
1308  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_matrix_multiplication::operator () (" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(AB) << ")");
1309  assert(i < rows(AB));
1310  assert(j < cols(AB));
1311  size_type tt = MatrixInfo<MTA>::cols < 0 ? AB.second.rows() : AB.first.cols();
1312  if (tt == 0)
1313  {
1314  CoeffType res;
1315  setZero(res);
1316  return res;
1317  }
1318  else
1319  {
1320  typename MTA::ConstRowEnumerator eA = AB.first.enumerate_row(i);
1321  typename MTB::ConstColEnumerator eB = AB.second.enumerate_col(j);
1322  CoeffType res = eA.current() * eB.current();
1323  for (eA.next(), eB.next(); eA.has_current(); eA.next(), eB.next())
1324  res += eA.current() * eB.current();
1325  return res;
1326  }
1327  }
1328 
1329  static inline size_type rows(const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1330  {
1331  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_matrix_multiplication::rows(" << getAddress(*this) << "; " << getAddress(AB) << ")");
1332  return AB.first.rows();
1333  }
1334 
1335  static inline size_type cols(const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1336  {
1337  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_matrix_multiplication::cols(" << getAddress(*this) << "; " << getAddress(AB) << ")");
1338  return AB.second.cols();
1339  }
1340 
1341  static inline size_type size(const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1342  {
1343  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_matrix_multiplication::size(" << getAddress(*this) << "; " << getAddress(AB) << ")");
1344  return AB.first.rows() * AB.second.cols();
1345  }
1346 
1347  template<typename MatrixType>
1348  static inline bool involves_this_matrix(const MatrixType & matrix, const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1349  {
1350  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_matrix_multiplication::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(AB) << ")");
1351  return AB.first.involves_this_matrix(matrix) || AB.second.involves_this_matrix(matrix);
1352  }
1353 
1354  template<typename MatrixType>
1355  static inline bool test_involvement(const MatrixType & matrix, const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1356  {
1357  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_matrix_multiplication::test_involvement(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(AB) << ")");
1358  return AB.first.test_involvement(matrix) || AB.second.test_involvement(matrix);
1359  }
1360 
1362  {
1363  private:
1364  typename MTA::ConstRowEnumerator d_row;
1365  typename MTB::ConstColsEnumerator d_cols;
1366 
1367  public:
1368  typedef typename matrix_matrix_multiplication<std::pair<MTA, MTB> >::CoeffType_Get Type;
1370 
1371  inline ConstRowEnumerator(typename MTA::ConstRowEnumerator row, typename MTB::ConstColsEnumerator cols)
1372  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(typename MTA::ConstRowEnumerator(row)) &&
1373  noexcept(typename MTB::ConstColsEnumerator(cols)))
1374  : d_row(row), d_cols(cols)
1375  {
1376  }
1377 
1378  inline Type current() const
1379  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(setZero(helper::make_type_lvalue<Type>())) &&
1380  noexcept(helper::make_type_lvalue<Type>() = d_row.current() * d_cols.current().current()) &&
1381  noexcept(helper::make_type_lvalue<Type>() += d_row.current() * d_cols.current().current()))
1382  {
1383  typename MTA::ConstRowEnumerator er = d_row;
1384  if (er.has_current())
1385  {
1386  typename MTB::ConstColsEnumerator::Type ec = d_cols.current();
1387  Type result = er.current() * ec.current();
1388  for (er.next(), ec.next(); er.has_current(); er.next(), ec.next())
1389  result += er.current() * ec.current();
1390  return result;
1391  }
1392  else
1393  {
1394  Type result;
1395  setZero(result);
1396  return result;
1397  }
1398  }
1399 
1400  template<typename Result>
1401  inline void get_current(Result & result) const
1402  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(setZero(result)) &&
1403  noexcept(result = d_row.current() * d_cols.current().current()) &&
1404  noexcept(result += d_row.current() * d_cols.current().current()))
1405  {
1406  typename MTA::ConstRowEnumerator er = d_row;
1407  if (er.has_current())
1408  {
1409  typename MTB::ConstColsEnumerator::Type ec = d_cols.current();
1410  result = er.current() * ec.current();
1411  for (er.next(), ec.next(); er.has_current(); er.next(), ec.next())
1412  result += er.current() * ec.current();
1413  }
1414  else
1415  setZero(result);
1416  }
1417 
1418  inline GetCoeffSteps_Type get_current_steps() const
1419  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(d_row, d_cols.current())))
1420  {
1421  return GetCoeffSteps_Type(d_row, d_cols.current());
1422  }
1423 
1424  inline bool has_current() const
1425  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_cols.has_current()))
1426  {
1427  return d_cols.has_current();
1428  }
1429 
1430  inline void next()
1431  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_cols.next()))
1432  {
1433  d_cols.next();
1434  }
1435  };
1436 
1438  {
1439  private:
1440  typename MTA::ConstRowsEnumerator d_rows;
1441  typename MTB::ConstColEnumerator d_col;
1442 
1443  public:
1444  typedef typename matrix_matrix_multiplication<std::pair<MTA, MTB> >::CoeffType_Get Type;
1446 
1447  inline ConstColEnumerator(typename MTA::ConstRowsEnumerator rows, typename MTB::ConstColEnumerator col)
1448  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(typename MTA::ConstRowsEnumerator(rows)) &&
1449  noexcept(typename MTB::ConstColEnumerator(col)))
1450  : d_rows(rows), d_col(col)
1451  {
1452  }
1453 
1454  inline Type current() const
1455  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(setZero(helper::make_type_lvalue<Type>())) &&
1456  noexcept(helper::make_type_lvalue<Type>() = d_rows.current().current() * d_col.current()) &&
1457  noexcept(helper::make_type_lvalue<Type>() += d_rows.current().current() * d_col.current()))
1458  {
1459  typename MTA::ConstRowsEnumerator::Type er = d_rows.current();
1460  if (er.has_current())
1461  {
1462  typename MTB::ConstColEnumerator ec = d_col;
1463  Type result = er.current() * ec.current();
1464  for (er.next(), ec.next(); er.has_current(); er.next(), ec.next())
1465  result += er.current() * ec.current();
1466  return result;
1467  }
1468  else
1469  {
1470  Type result;
1471  setZero(result);
1472  return result;
1473  }
1474  }
1475 
1476  template<typename Result>
1477  inline void get_current(Result & result) const
1478  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(setZero(result)) &&
1479  noexcept(result = d_rows.current().current() * d_col.current()) &&
1480  noexcept(result += d_rows.current().current() * d_col.current()))
1481  {
1482  typename MTA::ConstRowsEnumerator::Type er = d_rows.current();
1483  if (er.has_current())
1484  {
1485  typename MTB::ConstColEnumerator ec = d_col;
1486  result = er.current() * ec.current();
1487  for (er.next(), ec.next(); er.has_current(); er.next(), ec.next())
1488  result += er.current() * ec.current();
1489  }
1490  else
1491  setZero(result);
1492  }
1493 
1494  inline GetCoeffSteps_Type get_current_steps() const
1495  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(d_rows.current(), d_col)))
1496  {
1497  return GetCoeffSteps_Type(d_rows.current(), d_col);
1498  }
1499 
1500  inline bool has_current() const
1501  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_rows.has_current()))
1502  {
1503  return d_rows.has_current();
1504  }
1505 
1506  inline void next()
1507  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_rows.next()))
1508  {
1509  d_rows.next();
1510  }
1511  };
1512 
1514  {
1515  private:
1516  typename MTA::ConstRowsEnumerator d_rows;
1517  typename MTB::ConstColsEnumerator d_cols, d_cols_init;
1518 
1519  public:
1520  typedef typename matrix_matrix_multiplication<std::pair<MTA, MTB> >::CoeffType_Get Type;
1522 
1523  inline ConstEnumerator_Generic(typename MTA::ConstRowsEnumerator rows, typename MTB::ConstColsEnumerator cols)
1524  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(typename MTA::ConstRowsEnumerator(rows)) &&
1525  noexcept(typename MTB::ConstColsEnumerator(cols)))
1526  : d_rows(rows), d_cols(cols), d_cols_init(d_cols)
1527  {
1528  }
1529 
1530  inline Type current() const
1531  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(setZero(helper::make_type_lvalue<Type>())) &&
1532  noexcept(helper::make_type_lvalue<Type>() = d_rows.current().current() * d_cols.current().current()) &&
1533  noexcept(helper::make_type_lvalue<Type>() += d_rows.current().current() * d_cols.current().current()))
1534  {
1535  typename MTA::ConstRowsEnumerator::Type er = d_rows.current();
1536  if (er.has_current())
1537  {
1538  typename MTB::ConstColsEnumerator::Type ec = d_cols.current();
1539  Type result = er.current() * ec.current();
1540  for (er.next(), ec.next(); er.has_current(); er.next(), ec.next())
1541  result += er.current() * ec.current();
1542  return result;
1543  }
1544  else
1545  {
1546  Type result;
1547  setZero(result);
1548  return result;
1549  }
1550  }
1551 
1552  template<typename Result>
1553  inline void get_current(Result & result) const
1554  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(setZero(result)) &&
1555  noexcept(result = d_rows.current().current() * d_cols.current().current()) &&
1556  noexcept(result += d_rows.current().current() * d_cols.current().current()))
1557  {
1558  typename MTA::ConstRowsEnumerator::Type er = d_rows.current();
1559  if (er.has_current())
1560  {
1561  typename MTB::ConstColsEnumerator::Type ec = d_cols.current();
1562  result = er.current() * ec.current();
1563  for (er.next(), ec.next(); er.has_current(); er.next(), ec.next())
1564  result += er.current() * ec.current();
1565  }
1566  else
1567  setZero(result);
1568  }
1569 
1570  inline GetCoeffSteps_Type get_current_steps() const
1571  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(d_rows.current(), d_cols.current())))
1572  {
1573  return GetCoeffSteps_Type(d_rows.current(), d_cols.current());
1574  }
1575 
1576  inline bool has_current() const
1577  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_cols.has_current()))
1578  {
1579  return d_cols.has_current();
1580  }
1581 
1582  inline void next()
1583  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_cols.next()) && noexcept(d_cols.has_current()) &&
1584  noexcept(d_rows.next()) && noexcept(d_rows.has_current()) &&
1585  noexcept(d_cols = d_cols_init))
1586  {
1587  d_cols.next();
1588  if (!d_cols.has_current())
1589  {
1590  d_rows.next();
1591  if (d_rows.has_current())
1592  d_cols = d_cols_init;
1593  }
1594  }
1595  };
1596 
1598  {
1599  public:
1600  inline ConstEnumerator_OneRow(typename MTA::ConstRowsEnumerator rows, typename MTB::ConstColsEnumerator cols)
1601  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(rows.current()))
1602  : ConstRowEnumerator(rows.current(), cols)
1603  {
1604  }
1605  };
1606 
1608  {
1609  public:
1610  inline ConstEnumerator_OneCol(typename MTA::ConstRowsEnumerator rows, typename MTB::ConstColsEnumerator cols)
1611  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(cols.current()))
1612  : ConstColEnumerator(rows, cols.current())
1613  {
1614  }
1615  };
1616 
1617  typedef typename helper::SelectFirstType<MatrixInfo<MTB>::cols == 1,
1621  ConstEnumerator_Generic>::result>::result ConstEnumerator;
1622 
1623  typedef void Enumerator;
1624  typedef void RowEnumerator;
1625  typedef void ColEnumerator;
1626 
1627  typedef ConstEnumerator DefaultEnumerator;
1630 
1631  static inline DefaultEnumerator enumerate(const std::pair<MTA, MTB> & AB)
1632  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(AB.first.enumerate_rows()) && noexcept(AB.second.enumerate_cols()))
1633  {
1634  return DefaultEnumerator(AB.first.enumerate_rows(), AB.second.enumerate_cols());
1635  }
1636 
1637  static inline DefaultRowEnumerator enumerate_row(size_type row, const std::pair<MTA, MTB> & AB)
1638  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(AB.second.enumerate_row(row)) && noexcept(AB.second.enumerate_cols()))
1639  {
1640  return DefaultRowEnumerator(AB.first.enumerate_row(row), AB.second.enumerate_cols());
1641  }
1642 
1643  static inline DefaultColEnumerator enumerate_col(size_type col, const std::pair<MTA, MTB> & AB)
1644  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(AB.first.enumerate_rows()) && noexcept(AB.second.enumerate_col(col)))
1645  {
1646  return DefaultColEnumerator(AB.first.enumerate_rows(), AB.second.enumerate_col(col));
1647  }
1648 
1650  {
1651  private:
1652  typename MTA::ConstRowsEnumerator d_rows;
1653  typename MTB::ConstColsEnumerator d_cols;
1654 
1655  public:
1656  typedef ConstRowEnumerator Type;
1657 
1658  ConstRowsEnumerator(const std::pair<MTA, MTB> & AB)
1659  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(AB.first.enumerate_rows()) && noexcept(AB.second.enumerate_cols()))
1660  : d_rows(AB.first.enumerate_rows()), d_cols(AB.second.enumerate_cols())
1661  {
1662  }
1663 
1664  Type current() const
1665  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ConstRowEnumerator(d_rows.current(), d_cols)))
1666  {
1667  return ConstRowEnumerator(d_rows.current(), d_cols);
1668  }
1669 
1670  inline bool has_current() const
1671  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_rows.has_current()))
1672  {
1673  return d_rows.has_current();
1674  }
1675 
1676  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_rows.next()))
1677  {
1678  d_rows.next();
1679  }
1680  };
1681 
1683  {
1684  private:
1685  typename MTA::ConstRowsEnumerator d_rows;
1686  typename MTB::ConstColsEnumerator d_cols;
1687 
1688  public:
1689  typedef ConstColEnumerator Type;
1690 
1691  ConstColsEnumerator(const std::pair<MTA, MTB> & AB)
1692  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(AB.first.enumerate_rows()) && noexcept(AB.second.enumerate_cols()))
1693  : d_rows(AB.first.enumerate_rows()), d_cols(AB.second.enumerate_cols())
1694  {
1695  }
1696 
1697  Type current() const PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ConstColEnumerator(d_rows, d_cols.current())))
1698  {
1699  return ConstColEnumerator(d_rows, d_cols.current());
1700  }
1701 
1702  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_cols.has_current()))
1703  {
1704  return d_cols.has_current();
1705  }
1706 
1707  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_cols.next()))
1708  {
1709  d_cols.next();
1710  }
1711  };
1712 
1713  typedef void RowsEnumerator;
1714  typedef void ColsEnumerator;
1717 
1718  inline DefaultRowsEnumerator enumerate_rows(const std::pair<MTA, MTB> & AB) const
1719  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowsEnumerator(AB)))
1720  {
1721  return DefaultRowsEnumerator(AB);
1722  }
1723 
1724  inline DefaultColsEnumerator enumerate_cols(const std::pair<MTA, MTB> & AB) const
1725  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColsEnumerator(AB)))
1726  {
1727  return DefaultColsEnumerator(AB);
1728  }
1729  };
1730 
1731  template<typename OpA, typename OpB>
1732  class MSMul
1733  {
1734  public:
1737 
1738  static inline ReturnType op(const OpA & a, const OpB & b)
1739  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ReturnType(a * b)))
1740  {
1741  return a * b;
1742  }
1743 
1744  template<typename ResultType_>
1745  static inline void op(ResultType_ & result, const OpA & a, const OpB & b)
1746  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = a * b))
1747  {
1748  result = a * b;
1749  }
1750  };
1751 
1752  template<typename OpA, typename OpB>
1753  class SMMul
1754  {
1755  public:
1758 
1759  static inline ReturnType op(const OpA & a, const OpB & b)
1760  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ReturnType(b * a)))
1761  {
1762  return b * a;
1763  }
1764 
1765  template<typename ResultType_>
1766  static inline void op(ResultType_ & result, const OpA & a, const OpB & b)
1767  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = b * a))
1768  {
1769  result = b * a;
1770  }
1771  };
1772 
1773  template<typename OpA, typename OpB>
1774  class MSDiv
1775  {
1776  public:
1779 
1780  static inline ReturnType op(const OpA & a, const OpB & b)
1781  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ReturnType(a / b)))
1782  {
1783  return a / b;
1784  }
1785 
1786  template<typename ResultType_>
1787  static inline void op(ResultType_ & result, const OpA & a, const OpB & b)
1788  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = a / b))
1789  {
1790  result = a / b;
1791  }
1792  };
1793 
1794  template<typename OpA, typename OpB>
1795  class MSMod
1796  {
1797  public:
1800 
1801  static inline ReturnType op(const OpA & a, const OpB & b)
1802  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ReturnType(a % b)))
1803  {
1804  return a % b;
1805  }
1806 
1807  template<typename ResultType_>
1808  static inline void op(ResultType_ & result, const OpA & a, const OpB & b)
1809  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = a % b))
1810  {
1811  result = a % b;
1812  }
1813  };
1814 
1815  template<template<typename OpA, typename OpB> class Operation>
1817  {
1818  public:
1819  template<typename MatrixScalarPair>
1821  {
1822  private:
1823  typedef typename MatrixScalarPair::first_type MT;
1824  typedef typename MatrixScalarPair::second_type ST;
1825  typedef Operation<typename plll::helper::remove_decorations<typename MT::CoeffType_Get>::Result,
1827 
1828  public:
1829  typedef typename Op::ResultType CoeffType;
1830  typedef typename Op::ReturnType CoeffType_Get;
1831  typedef base_matrix<CoeffType,
1834  typename MatrixInfo<MT>::StorageTraits,
1835  true> ValueType;
1836  typedef void data_pointer_type;
1837  typedef void data_ref_type;
1838 
1839  enum { use_temporary_on_evaluate = MatrixInfo<MT>::use_temporary_on_evaluate,
1840  coeffs_are_simple_expressions = true,
1841  is_const = true,
1842  can_assign_to = false,
1843  can_move_from = false,
1844  can_resize_rows = false,
1845  can_resize_cols = false,
1846  has_direct_access = false };
1847 
1848  operation() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1849  {
1851  }
1852 
1853  template<typename ResultType>
1854  static inline void get_coeff(ResultType & result, size_type i, size_type j, const std::pair<MT, ST> & AB)
1855  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Op::op(result, AB.first(i, j), AB.second.evaluate())))
1856  {
1857  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_scalar_operation::operation::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << " " << getAddress(AB) << ") const");
1858  assert(i < rows(AB));
1859  assert(j < cols(AB));
1860  Op::op(result, AB.first(i, j), AB.second.evaluate());
1861  }
1862 
1863  static inline bool get_coeff_alwayszero(const std::pair<MT, ST> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1864  {
1865  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_scalar_operation::operation::get_coeff_alwayszero(" << getAddress(*this) << "; " << getAddress(AB) << ")");
1866  return false;
1867  }
1868 
1870  {
1871  protected:
1872  typename Op::ReturnType d_value;
1873 
1874  public:
1875  inline GetCoeffSteps_Type(const typename Op::ReturnType & value)
1876  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(typename Op::ReturnType(value)))
1877  : d_value(value)
1878  {
1879  }
1880 
1881 #if __cplusplus >= 201103L
1882  inline GetCoeffSteps_Type(typename Op::ReturnType && value)
1883  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(typename Op::ReturnType(std::move(value))))
1884  : d_value(std::move(value))
1885  {
1886  }
1887 #endif
1888 
1889  typedef const typename Op::ReturnType & Step1_Type;
1890 
1891  inline Step1_Type step1() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1892  {
1893  return d_value;
1894  }
1895 
1896  template<typename ResultType>
1897  inline void step2(ResultType & result) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1898  {
1899  }
1900  };
1901 
1902  static inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j, const std::pair<MT, ST> & AB)
1903  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(Op::op(AB.first(i, j), AB.second.evaluate()))))
1904  {
1905  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_scalar_operation::operation::get_coeff_steps(" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(AB) << ")");
1906  assert(i < rows(AB));
1907  assert(j < cols(AB));
1908  return GetCoeffSteps_Type(Op::op(AB.first(i, j), AB.second.evaluate()));
1909  }
1910 
1911  inline CoeffType_Get operator () (size_type i, size_type j, const std::pair<MT, ST> & AB) const
1912  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Op::op(AB.first(i, j), AB.second.evaluate())))
1913  {
1914  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_scalar_operation::operation::operator () (" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(AB) << ")");
1915  assert(i < rows(AB));
1916  assert(j < cols(AB));
1917  return Op::op(AB.first(i, j), AB.second.evaluate());
1918  }
1919 
1920  static inline size_type rows(const std::pair<MT, ST> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1921  {
1922  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_scalar_operation::operation::rows(" << getAddress(*this) << "; " << getAddress(AB) << ")");
1923  return AB.first.rows();
1924  }
1925 
1926  static inline size_type cols(const std::pair<MT, ST> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1927  {
1928  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_scalar_operation::operation::cols(" << getAddress(*this) << "; " << getAddress(AB) << ")");
1929  return AB.first.cols();
1930  }
1931 
1932  static inline size_type size(const std::pair<MT, ST> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1933  {
1934  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_scalar_operation::operation::size(" << getAddress(*this) << "; " << getAddress(AB) << ")");
1935  return AB.first.size();
1936  }
1937 
1938  template<typename MatrixType>
1939  static inline bool involves_this_matrix(const MatrixType & matrix, const std::pair<MT, ST> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1940  {
1941  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_scalar_operation::operation::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(AB) << ")");
1942  return AB.first.involves_this_matrix(matrix);
1943  }
1944 
1945  template<typename MatrixType>
1946  static inline bool test_involvement(const MatrixType & matrix, const std::pair<MT, ST> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
1947  {
1948  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_scalar_operation::operation::test_involvement(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(AB) << ")");
1949  return AB.first.test_involvement(matrix);
1950  }
1951 
1952  template<typename Enum>
1954  {
1955  private:
1956  Enum d_enum;
1957  const ST & d_B;
1958 
1959  public:
1960  typedef CoeffType_Get Type;
1962 
1963  inline MSEnumerator(const Enum & e, const ST & B)
1964  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum(e)))
1965  : d_enum(e), d_B(B)
1966  {
1967  }
1968 
1969 #if __cplusplus >= 201103L
1970  inline MSEnumerator(Enum && e, const ST & B)
1971  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum(std::move(e))))
1972  : d_enum(std::move(e)), d_B(B)
1973  {
1974  }
1975 #endif
1976 
1977  inline Type current() const
1978  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Op::op(d_enum.current(), d_B.evaluate())))
1979  {
1980  return Op::op(d_enum.current(), d_B.evaluate());
1981  }
1982 
1983  template<typename Result>
1984  inline void get_current(Result & result) const
1985  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Op::op(result, d_enum.current(), d_B.evaluate())))
1986  {
1987  Op::op(result, d_enum.current(), d_B.evaluate());
1988  }
1989 
1990  inline GetCoeffSteps_Type get_current_steps() const
1991  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(Op::op(d_enum.current(), d_B.evaluate()))))
1992  {
1993  return GetCoeffSteps_Type(Op::op(d_enum.current(), d_B.evaluate()));
1994  }
1995 
1996  inline bool has_current() const
1997  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum.has_current()))
1998  {
1999  return d_enum.has_current();
2000  }
2001 
2002  inline void next()
2003  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum.next()))
2004  {
2005  d_enum.next();
2006  }
2007  };
2008 
2009  typedef void Enumerator;
2012  typedef void RowEnumerator;
2015  typedef void ColEnumerator;
2018 
2019  static inline DefaultEnumerator enumerate(const std::pair<MT, ST> & AB)
2020  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultEnumerator(AB.first.enumerate(), AB.second)))
2021  {
2022  return DefaultEnumerator(AB.first.enumerate(), AB.second);
2023  }
2024 
2025  static inline DefaultRowEnumerator enumerate_row(size_type row, const std::pair<MT, ST> & AB)
2026  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowEnumerator(AB.first.enumerate_row(row), AB.second)))
2027  {
2028  return DefaultRowEnumerator(AB.first.enumerate_row(row), AB.second);
2029  }
2030 
2031  static inline DefaultColEnumerator enumerate_col(size_type col, const std::pair<MT, ST> & AB)
2032  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColEnumerator(AB.first.enumerate_col(col), AB.second)))
2033  {
2034  return DefaultColEnumerator(AB.first.enumerate_col(col), AB.second);
2035  }
2036 
2037  template<typename Enum_meta, typename Enum>
2039  {
2040  private:
2041  Enum_meta d_enum;
2042  const ST & d_B;
2043 
2044  public:
2045  typedef MSEnumerator<Enum> Type;
2046 
2047  inline MSEnumerator_meta(const Enum_meta & e, const ST & B)
2048  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum_meta(e)))
2049  : d_enum(e), d_B(B)
2050  {
2051  }
2052 
2053 #if __cplusplus >= 201103L
2054  inline MSEnumerator_meta(Enum_meta && e, const ST & B)
2055  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum_meta(std::move(e))))
2056  : d_enum(std::move(e)), d_B(B)
2057  {
2058  }
2059 #endif
2060 
2061  inline Type current() const
2062  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(d_enum.current(), d_B)))
2063  {
2064  return Type(d_enum.current(), d_B);
2065  }
2066 
2067  inline bool has_current() const
2068  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum.has_current()))
2069  {
2070  return d_enum.has_current();
2071  }
2072 
2073  inline void next()
2074  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum.next()))
2075  {
2076  d_enum.next();
2077  }
2078  };
2079 
2080  typedef void RowsEnumerator;
2081  typedef void ColsEnumerator;
2086 
2087  inline DefaultRowsEnumerator enumerate_rows(const std::pair<MT, ST> & AB) const
2088  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowsEnumerator(AB.first.enumerate_rows(), AB.second)))
2089  {
2090  return DefaultRowsEnumerator(AB.first.enumerate_rows(), AB.second);
2091  }
2092 
2093  inline DefaultColsEnumerator enumerate_cols(const std::pair<MT, ST> & AB) const
2094  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColsEnumerator(AB.first.enumerate_cols(), AB.second)))
2095  {
2096  return DefaultColsEnumerator(AB.first.enumerate_cols(), AB.second);
2097  }
2098  };
2099  };
2100 
2101  template<typename OpA, typename OpB>
2102  class CWAdd
2103  {
2104  public:
2107 
2108  static inline ReturnType op(const OpA & a, const OpB & b)
2109  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ReturnType(a + b)))
2110  {
2111  return a + b;
2112  }
2113 
2114  template<typename ResultType_>
2115  static inline void op(ResultType_ & result, const OpA & a, const OpB & b)
2116  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = a + b))
2117  {
2118  result = a + b;
2119  }
2120  };
2121 
2122  template<typename OpA, typename OpB>
2123  class CWSub
2124  {
2125  public:
2128 
2129  static inline ReturnType op(const OpA & a, const OpB & b)
2130  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ReturnType(a - b)))
2131  {
2132  return a - b;
2133  }
2134 
2135  template<typename ResultType_>
2136  static inline void op(ResultType_ & result, const OpA & a, const OpB & b)
2137  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = a - b))
2138  {
2139  result = a - b;
2140  }
2141  };
2142 
2143  template<typename OpA, typename OpB>
2144  class CWMul
2145  {
2146  public:
2149 
2150  static inline ReturnType op(const OpA & a, const OpB & b)
2151  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ReturnType(a * b)))
2152  {
2153  return a * b;
2154  }
2155 
2156  template<typename ResultType_>
2157  static inline void op(ResultType_ & result, const OpA & a, const OpB & b)
2158  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = a * b))
2159  {
2160  result = a * b;
2161  }
2162  };
2163 
2164  template<typename OpA, typename OpB>
2165  class CWDiv
2166  {
2167  public:
2170 
2171  static inline ReturnType op(const OpA & a, const OpB & b)
2172  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ReturnType(a / b)))
2173  {
2174  return a / b;
2175  }
2176 
2177  template<typename ResultType_>
2178  static inline void op(ResultType_ & result, const OpA & a, const OpB & b)
2179  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = a / b))
2180  {
2181  result = a / b;
2182  }
2183  };
2184 
2185  template<typename OpA, typename OpB>
2186  class CWMod
2187  {
2188  public:
2191 
2192  static inline ReturnType op(const OpA & a, const OpB & b)
2193  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(ReturnType(a % b)))
2194  {
2195  return a % b;
2196  }
2197 
2198  template<typename ResultType_>
2199  static inline void op(ResultType_ & result, const OpA & a, const OpB & b)
2200  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = a % b))
2201  {
2202  result = a % b;
2203  }
2204  };
2205 
2206  template<template<typename OpA, typename OpB> class Operation>
2208  {
2209  public:
2210  template<typename PairMatrices>
2212  {
2213  private:
2214  typedef typename PairMatrices::first_type MTA;
2215  typedef typename PairMatrices::second_type MTB;
2216  typedef Operation<typename plll::helper::remove_decorations<typename MTA::CoeffType_Get>::Result,
2218 
2219  public:
2220  typedef typename Op::ResultType CoeffType;
2221  typedef typename Op::ReturnType CoeffType_Get;
2222  typedef base_matrix<CoeffType,
2223  MatrixInfo<MTA>::rows < 0 ? static_cast<int>(MatrixInfo<MTB>::rows) : static_cast<int>(MatrixInfo<MTA>::rows),
2224  MatrixInfo<MTA>::cols < 0 ? static_cast<int>(MatrixInfo<MTB>::cols) : static_cast<int>(MatrixInfo<MTA>::cols),
2225  typename MatrixInfo<MTA>::StorageTraits,
2226  true> ValueType;
2227  typedef void data_pointer_type;
2228  typedef void data_ref_type;
2229 
2231  coeffs_are_simple_expressions = true,
2232  is_const = true,
2233  can_assign_to = false,
2234  can_move_from = false,
2235  can_resize_rows = false,
2236  can_resize_cols = false,
2237  has_direct_access = false };
2238 
2239  operation() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2240  {
2242  (static_cast<size_type>(MatrixInfo<MTA>::cols) == static_cast<size_type>(MatrixInfo<MTB>::cols)), FormatsDoNotMatch);
2244  (static_cast<size_type>(MatrixInfo<MTA>::rows) == static_cast<size_type>(MatrixInfo<MTB>::rows)), FormatsDoNotMatch);
2247  }
2248 
2249  template<typename ResultType>
2250  static inline void get_coeff(ResultType & result, size_type i, size_type j, const std::pair<MTA, MTB> & AB)
2251  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Op::op(result, AB.first(i, j), AB.second(i, j))))
2252  {
2253  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::componentwise_operation::operation::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << " " << getAddress(AB) << ")");
2254  assert(i < rows(AB));
2255  assert(j < cols(AB));
2256  Op::op(result, AB.first(i, j), AB.second(i, j));
2257  }
2258 
2259  static inline bool get_coeff_alwayszero(const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2260  {
2261  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::componentwise_operation::operation::get_coeff_alwayszero(" << getAddress(*this) << "; " << getAddress(AB) << ")");
2262  return false;
2263  }
2264 
2265  class GetCoeffSteps_Type
2266  {
2267  protected:
2268  typename Op::ReturnType d_value;
2269 
2270  public:
2271  inline GetCoeffSteps_Type(const typename Op::ReturnType & value)
2272  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(typename Op::ReturnType(value)))
2273  : d_value(value)
2274  {
2275  }
2276 
2277 #if __cplusplus >= 201103L
2278  inline GetCoeffSteps_Type(typename Op::ReturnType && value)
2279  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(typename Op::ReturnType(std::move(value))))
2280  : d_value(std::move(value))
2281  {
2282  }
2283 #endif
2284 
2285  typedef const typename Op::ReturnType & Step1_Type;
2286 
2287  inline Step1_Type step1() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2288  {
2289  return d_value;
2290  }
2291 
2292  template<typename ResultType>
2293  inline void step2(ResultType & result) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2294  {
2295  }
2296  };
2297 
2298  static inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j, const std::pair<MTA, MTB> & AB)
2299  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(Op::op(AB.first(i, j), AB.second(i, j)))))
2300  {
2301  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::componentwise_operation::operation::get_coeff_steps(" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(AB) << ")");
2302  assert(i < rows(AB));
2303  assert(j < cols(AB));
2304  return GetCoeffSteps_Type(Op::op(AB.first(i, j), AB.second(i, j)));
2305  }
2306 
2307  inline CoeffType_Get operator () (size_type i, size_type j, const std::pair<MTA, MTB> & AB) const
2308  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Op::op(AB.first(i, j), AB.second(i, j))))
2309  {
2310  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::componentwise_operation::operation::operator () (" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(AB) << ")");
2311  assert(i < rows(AB));
2312  assert(j < cols(AB));
2313  return Op::op(AB.first(i, j), AB.second(i, j));
2314  }
2315 
2316  static inline size_type rows(const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2317  {
2318  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::componentwise_operation::operation::rows(" << getAddress(*this) << "; " << getAddress(AB) << ")");
2319  return AB.first.rows();
2320  }
2321 
2322  static inline size_type cols(const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2323  {
2324  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::componentwise_operation::operation::cols(" << getAddress(*this) << "; " << getAddress(AB) << ")");
2325  return AB.first.cols();
2326  }
2327 
2328  static inline size_type size(const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2329  {
2330  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::componentwise_operation::operation::size(" << getAddress(*this) << "; " << getAddress(AB) << ")");
2331  return AB.first.rows() * AB.first.cols();
2332  }
2333 
2334  template<typename MatrixType>
2335  static inline bool involves_this_matrix(const MatrixType & matrix, const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2336  {
2337  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::componentwise_operation::operation::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(AB) << ")");
2338  return AB.first.involves_this_matrix(matrix) || AB.second.involves_this_matrix(matrix);
2339  }
2340 
2341  template<typename MatrixType>
2342  static inline bool test_involvement(const MatrixType & matrix, const std::pair<MTA, MTB> & AB) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2343  {
2344  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::componentwise_operation::operation::test_involvement(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(AB) << ")");
2345  return AB.first.test_involvement(matrix) || AB.second.test_involvement(matrix);
2346  }
2347 
2348  template<typename EnumA, typename EnumB>
2349  class CWEnumerator
2350  {
2351  private:
2352  EnumA d_enum_A;
2353  EnumB d_enum_B;
2354 
2355  public:
2356  typedef CoeffType_Get Type;
2357  typedef operation<PairMatrices>::GetCoeffSteps_Type GetCoeffSteps_Type;
2358 
2359  inline CWEnumerator(const EnumA & eA, const EnumB & eB)
2360  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(EnumA(eA)) && noexcept(EnumB(eB)))
2361  : d_enum_A(eA), d_enum_B(eB)
2362  {
2363  }
2364 
2365 #if __cplusplus >= 201103L
2366  inline CWEnumerator(EnumA && eA, EnumB && eB)
2367  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(EnumA(std::move(eA))) && noexcept(EnumB(std::move(eB))))
2368  : d_enum_A(std::move(eA)), d_enum_B(std::move(eB))
2369  {
2370  }
2371 #endif
2372 
2373  inline Type current() const
2374  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Op::op(d_enum_A.current(), d_enum_B.current())))
2375  {
2376  return Op::op(d_enum_A.current(), d_enum_B.current());
2377  }
2378 
2379  template<typename Result>
2380  inline void get_current(Result & result) const
2381  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Op::op(result, d_enum_A.current(), d_enum_B.current())))
2382  {
2383  Op::op(result, d_enum_A.current(), d_enum_B.current());
2384  }
2385 
2386  inline GetCoeffSteps_Type get_current_steps() const
2387  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(Op::op(d_enum_A.current(), d_enum_B.current()))))
2388  {
2389  return GetCoeffSteps_Type(Op::op(d_enum_A.current(), d_enum_B.current()));
2390  }
2391 
2392  inline bool has_current() const
2393  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum_A.has_current()))
2394  {
2395  return d_enum_A.has_current();
2396  }
2397 
2398  inline void next()
2399  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum_A.next()) && noexcept(d_enum_B.next()))
2400  {
2401  d_enum_A.next();
2402  d_enum_B.next();
2403  }
2404  };
2405 
2406  typedef void Enumerator;
2407  typedef CWEnumerator<typename MTA::ConstEnumerator, typename MTB::ConstEnumerator> ConstEnumerator;
2408  typedef CWEnumerator<typename MTA::ConstEnumerator, typename MTB::ConstEnumerator> DefaultEnumerator;
2409  typedef void RowEnumerator;
2410  typedef CWEnumerator<typename MTA::ConstRowEnumerator, typename MTB::ConstRowEnumerator> ConstRowEnumerator;
2411  typedef CWEnumerator<typename MTA::ConstRowEnumerator, typename MTB::ConstRowEnumerator> DefaultRowEnumerator;
2412  typedef void ColEnumerator;
2413  typedef CWEnumerator<typename MTA::ConstColEnumerator, typename MTB::ConstColEnumerator> ConstColEnumerator;
2414  typedef CWEnumerator<typename MTA::ConstColEnumerator, typename MTB::ConstColEnumerator> DefaultColEnumerator;
2415 
2416  static inline DefaultEnumerator enumerate(const std::pair<MTA, MTB> & AB)
2417  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultEnumerator(AB.first.enumerate(), AB.second.enumerate())))
2418  {
2419  return DefaultEnumerator(AB.first.enumerate(), AB.second.enumerate());
2420  }
2421 
2422  static inline DefaultRowEnumerator enumerate_row(size_type row, const std::pair<MTA, MTB> & AB)
2423  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowEnumerator(AB.first.enumerate_row(row), AB.second.enumerate_row(row))))
2424  {
2425  return DefaultRowEnumerator(AB.first.enumerate_row(row), AB.second.enumerate_row(row));
2426  }
2427 
2428  static inline DefaultColEnumerator enumerate_col(size_type col, const std::pair<MTA, MTB> & AB)
2429  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColEnumerator(AB.first.enumerate_col(col), AB.second.enumerate_col(col))))
2430  {
2431  return DefaultColEnumerator(AB.first.enumerate_col(col), AB.second.enumerate_col(col));
2432  }
2433 
2434  template<typename Enum_meta_A, typename Enum_meta_B, typename Enum_A, typename Enum_B>
2435  class CWEnumerator_meta
2436  {
2437  private:
2438  Enum_meta_A d_enum_A;
2439  Enum_meta_B d_enum_B;
2440 
2441  public:
2442  typedef CWEnumerator<Enum_A, Enum_B> Type;
2443 
2444  inline CWEnumerator_meta(const Enum_meta_A & eA, const Enum_meta_B & eB)
2445  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum_meta_A(eA)) && noexcept(Enum_mbeta_B(eB)))
2446  : d_enum_A(eA), d_enum_B(eB)
2447  {
2448  }
2449 
2450 #if __cplusplus >= 201103L
2451  inline CWEnumerator_meta(Enum_meta_A && eA, Enum_meta_B && eB)
2452  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum_meta_A(std::move(eA))) && noexcept(Enum_mbeta_B(std::move(eB))))
2453  : d_enum_A(std::move(eA)), d_enum_B(std::move(eB))
2454  {
2455  }
2456 #endif
2457 
2458  inline Type current() const
2459  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(d_enum_A.current(), d_enum_B.current())))
2460  {
2461  return Type(d_enum_A.current(), d_enum_B.current());
2462  }
2463 
2464  inline bool has_current() const
2465  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum_A.has_current()))
2466  {
2467  return d_enum_A.has_current();
2468  }
2469 
2470  inline void next()
2471  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum_A.next()) && noexcept(d_enum_B.next()))
2472  {
2473  d_enum_A.next();
2474  d_enum_B.next();
2475  }
2476  };
2477 
2478  typedef void RowsEnumerator;
2479  typedef void ColsEnumerator;
2480  typedef CWEnumerator_meta<typename MTA::ConstRowsEnumerator, typename MTB::ConstRowsEnumerator,
2481  typename MTA::ConstRowEnumerator, typename MTB::ConstRowEnumerator> ConstRowsEnumerator;
2482  typedef CWEnumerator_meta<typename MTA::ConstColsEnumerator, typename MTB::ConstColsEnumerator,
2483  typename MTA::ConstColEnumerator, typename MTB::ConstColEnumerator> ConstColsEnumerator;
2484  typedef ConstRowsEnumerator DefaultRowsEnumerator;
2485  typedef ConstColsEnumerator DefaultColsEnumerator;
2486 
2487  inline DefaultRowsEnumerator enumerate_rows(const std::pair<MTA, MTB> & AB) const
2488  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowsEnumerator(AB.first.enumerate_rows(), AB.second.enumerate_rows())))
2489  {
2490  return DefaultRowsEnumerator(AB.first.enumerate_rows(), AB.second.enumerate_rows());
2491  }
2492 
2493  inline DefaultColsEnumerator enumerate_cols(const std::pair<MTA, MTB> & AB) const
2494  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColsEnumerator(AB.first.enumerate_cols(), AB.second.enumerate_cols())))
2495  {
2496  return DefaultColsEnumerator(AB.first.enumerate_cols(), AB.second.enumerate_cols());
2497  }
2498  };
2499  };
2500 
2501  template<typename MTIn>
2503  {
2504  public:
2507  typedef base_matrix<CoeffType,
2510  typename MatrixInfo<MTIn>::StorageTraits,
2511  true> ValueType;
2512  typedef void data_pointer_type;
2513  typedef void data_ref_type;
2514 
2515  enum { use_temporary_on_evaluate = MatrixInfo<MTIn>::use_temporary_on_evaluate,
2516  coeffs_are_simple_expressions = true,
2517  is_const = true,
2518  can_assign_to = false,
2519  can_move_from = false,
2520  can_resize_rows = false,
2521  can_resize_cols = false,
2522  has_direct_access = false };
2523 
2524  matrix_negation() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2525  {
2527  }
2528 
2529  template<typename ResultType>
2530  static inline void get_coeff(ResultType & result, size_type i, size_type j, const MTIn & A)
2531  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = -A(i, j)))
2532  {
2533  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_negation::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << " " << getAddress(A) << ") const");
2534  assert(i < rows(A));
2535  assert(j < cols(A));
2536  result = -A(i, j);
2537  }
2538 
2539  static inline bool get_coeff_alwayszero(const MTIn & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2540  {
2541  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_negation::get_coeff_alwayszero(" << getAddress(*this) << "; " << getAddress(A) << ")");
2542  return false;
2543  }
2544 
2546  {
2547  protected:
2549  Type d_value;
2550 
2551  public:
2552  inline GetCoeffSteps_Type(const Type & value)
2553  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(value)))
2554  : d_value(value)
2555  {
2556  }
2557 
2558 #if __cplusplus >= 201103L
2559  inline GetCoeffSteps_Type(Type && value)
2560  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(std::move(value))))
2561  : d_value(std::move(value))
2562  {
2563  }
2564 #endif
2565 
2566  typedef const Type & Step1_Type;
2567 
2568  inline Step1_Type step1() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2569  {
2570  return d_value;
2571  }
2572 
2573  template<typename ResultType>
2574  inline void step2(ResultType & result) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2575  {
2576  }
2577  };
2578 
2579  static inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j, const MTIn & A)
2580  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(-A(i, j))))
2581  {
2582  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_negation::get_coeff_steps(" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
2583  assert(i < rows(A));
2584  assert(j < cols(A));
2585  return GetCoeffSteps_Type(-A(i, j));
2586  }
2587 
2588  inline CoeffType_Get operator () (size_type i, size_type j, const MTIn & A) const
2589  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(-A(i, j)))
2590  {
2591  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_negation::operator () (" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
2592  assert(i < rows(A));
2593  assert(j < cols(A));
2594  return -A(i, j);
2595  }
2596 
2597  static inline size_type rows(const MTIn & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2598  {
2599  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_negation::rows(" << getAddress(*this) << "; " << getAddress(A) << ")");
2600  return A.rows();
2601  }
2602 
2603  static inline size_type cols(const MTIn & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2604  {
2605  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_negation::cols(" << getAddress(*this) << "; " << getAddress(A) << ")");
2606  return A.cols();
2607  }
2608 
2609  static inline size_type size(const MTIn & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2610  {
2611  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_negation::size(" << getAddress(*this) << "; " << getAddress(A) << ")");
2612  return A.rows() * A.cols();
2613  }
2614 
2615  template<typename MatrixType>
2616  static inline bool involves_this_matrix(const MatrixType & matrix, const MTIn & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2617  {
2618  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_negation::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
2619  return A.involves_this_matrix(matrix);
2620  }
2621 
2622  template<typename MatrixType>
2623  static inline bool test_involvement(const MatrixType & matrix, const MTIn & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2624  {
2625  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::matrix_negation::test_involvement(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
2626  return A.test_involvement(matrix);
2627  }
2628 
2629  template<typename Enum>
2631  {
2632  private:
2633  Enum d_enum;
2634 
2635  public:
2636  typedef CoeffType_Get Type;
2638 
2639  inline NegEnumerator(const Enum & e)
2640  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum(e)))
2641  : d_enum(e)
2642  {
2643  }
2644 
2645 #if __cplusplus >= 201103L
2646  NegEnumerator(Enum && e)
2647  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum(std::move(e))))
2648  : d_enum(std::move(e))
2649  {
2650  }
2651 #endif
2652 
2653  inline Type current() const
2654  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(-d_enum.current())))
2655  {
2656  return -d_enum.current();
2657  }
2658 
2659  template<typename Result>
2660  inline void get_current(Result & result) const
2661  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = -d_enum.current()))
2662  {
2663  result = -d_enum.current();
2664  }
2665 
2666  inline GetCoeffSteps_Type get_current_steps() const
2667  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(GetCoeffSteps_Type(-d_enum.current())))
2668  {
2669  return GetCoeffSteps_Type(-d_enum.current());
2670  }
2671 
2672  inline bool has_current() const
2673  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum.has_current()))
2674  {
2675  return d_enum.has_current();
2676  }
2677 
2678  inline void next()
2679  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum.next()))
2680  {
2681  d_enum.next();
2682  }
2683  };
2684 
2685  typedef void Enumerator;
2688  typedef void RowEnumerator;
2691  typedef void ColEnumerator;
2694 
2695  static inline DefaultEnumerator enumerate(const MTIn & A)
2696  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultEnumerator(A.enumerate())))
2697  {
2698  return DefaultEnumerator(A.enumerate());
2699  }
2700 
2701  static inline DefaultRowEnumerator enumerate_row(size_type row, const MTIn & A)
2702  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowEnumerator(A.enumerate_row(row))))
2703  {
2704  return DefaultRowEnumerator(A.enumerate_row(row));
2705  }
2706 
2707  static inline DefaultColEnumerator enumerate_col(size_type col, const MTIn & A)
2708  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColEnumerator(A.enumerate_col(col))))
2709  {
2710  return DefaultColEnumerator(A.enumerate_col(col));
2711  }
2712 
2713  template<typename Enum_meta, typename Enum>
2715  {
2716  private:
2717  Enum_meta d_enum;
2718 
2719  public:
2720  typedef NegEnumerator<Enum> Type;
2721 
2722  inline NegEnumerator_meta(const Enum_meta & e)
2723  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum_meta(e)))
2724  : d_enum(e)
2725  {
2726  }
2727 
2728 #if __cplusplus >= 201103L
2729  inline NegEnumerator_meta(Enum_meta && e)
2730  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Enum_meta(std::move(e))))
2731  : d_enum(std::move(e))
2732  {
2733  }
2734 #endif
2735 
2736  inline Type current() const
2737  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(d_enum.current())))
2738  {
2739  return Type(d_enum.current());
2740  }
2741 
2742  inline bool has_current() const
2743  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum.has_current()))
2744  {
2745  return d_enum.has_current();
2746  }
2747 
2748  inline void next()
2749  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_enum.next()))
2750  {
2751  d_enum.next();
2752  }
2753  };
2754 
2755  typedef void RowsEnumerator;
2756  typedef void ColsEnumerator;
2761 
2762  inline DefaultRowsEnumerator enumerate_rows(const MTIn & A) const
2763  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowsEnumerator(A.enumerate_rows())))
2764  {
2765  return DefaultRowsEnumerator(A.enumerate_rows());
2766  }
2767 
2768  inline DefaultColsEnumerator enumerate_cols(const MTIn & A) const
2769  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColsEnumerator(A.enumerate_cols())))
2770  {
2771  return DefaultColsEnumerator(A.enumerate_cols());
2772  }
2773  };
2774 
2775  template<int Rows, int Cols>
2776  template<typename MT>
2777  class sub<Rows, Cols>::operation_generic : private row_count_storage<Rows>, private col_count_storage<Cols>
2778  {
2779  private:
2780  size_type d_r_ofs, d_c_ofs;
2781 
2782  public:
2783  typedef typename MT::CoeffType CoeffType;
2784  typedef typename MT::CoeffType_Get CoeffType_Get;
2785  typedef typename MT::GetCoeffSteps_Type GetCoeffSteps_Type;
2787  Rows, Cols,
2788  typename MatrixInfo<MT>::StorageTraits,
2790  typedef void data_pointer_type;
2791  typedef void data_ref_type;
2792 
2793  enum { use_temporary_on_evaluate = MatrixInfo<MT>::use_temporary_on_evaluate,
2794  coeffs_are_simple_expressions = true,
2795  is_const = MatrixInfo<MT>::is_const,
2796  can_assign_to = MatrixInfo<MT>::can_assign_to,
2797  can_move_from = MatrixInfo<MT>::can_move_from,
2798  can_resize_rows = false,
2799  can_resize_cols = false,
2800  has_direct_access = false };
2801 
2802  template<typename MT_>
2803  operation_generic(size_type rows, size_type cols, size_type r_ofs, size_type c_ofs, const MT_ & data) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2804  : row_count_storage<Rows>(rows), col_count_storage<Cols>(cols), d_r_ofs(r_ofs), d_c_ofs(c_ofs)
2805  // data is given only for verification reasons!
2806  {
2807  PLLL_INTERNAL_STATIC_CHECK((Rows < 0) || (MatrixInfo<MT>::rows < 0) ||
2808  (static_cast<size_type>(Rows) == static_cast<size_type>(MatrixInfo<MT>::rows)), TooFewRows);
2809  PLLL_INTERNAL_STATIC_CHECK((Cols < 0) || (MatrixInfo<MT>::cols < 0) ||
2810  (static_cast<size_type>(Cols) == static_cast<size_type>(MatrixInfo<MT>::cols)), TooFewCols);
2812  if (Rows > 0) assert(row_count_storage<Rows>::rows() == static_cast<size_type>(Rows));
2813  if (Cols > 0) assert(col_count_storage<Cols>::cols() == static_cast<size_type>(Cols));
2814  assert(row_count_storage<Rows>::rows() + d_r_ofs <= data.rows());
2815  assert(col_count_storage<Cols>::cols() + d_c_ofs <= data.cols());
2816  }
2817 
2818  template<typename ResultType>
2819  inline void get_coeff(ResultType & result, size_type i, size_type j, const MT & A)
2820  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = A(d_r_ofs + i, d_c_ofs + j)))
2821  {
2822  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub::operation_generic::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << " " << getAddress(A) << ") const");
2823  assert(i < rows(A));
2824  assert(j < cols(A));
2825  result = A(d_r_ofs + i, d_c_ofs + j);
2826  }
2827 
2828  inline bool get_coeff_alwayszero(const MT & A) const
2829  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.get_coeff_alwayszero()))
2830  {
2831  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub::operation_generic::get_coeff_alwayszero(" << getAddress(*this) << "; " << getAddress(A) << ")");
2832  return A.get_coeff_alwayszero();
2833  }
2834 
2835  inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j, const MT & A) const
2836  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.get_coeff_steps(d_r_ofs + i, d_c_ofs + j)))
2837  {
2838  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub::operation_generic::get_coeff_steps(" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
2839  assert(i < rows(A));
2840  assert(j < cols(A));
2841  return A.get_coeff_steps(d_r_ofs + i, d_c_ofs + j);
2842  }
2843 
2844  inline CoeffType_Get operator () (size_type i, size_type j, const MT & A) const
2845  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A(d_r_ofs + i, d_c_ofs + j)))
2846  {
2847  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub::operation_generic::operator () (" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
2848  assert(i < rows(A));
2849  assert(j < cols(A));
2850  return A(d_r_ofs + i, d_c_ofs + j);
2851  }
2852 
2853  inline size_type rows(const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2854  {
2855  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub::operation_generic::rows(" << getAddress(*this) << "; " << getAddress(A) << ")");
2857  }
2858 
2859  inline size_type cols(const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2860  {
2861  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub::operation_generic::cols(" << getAddress(*this) << "; " << getAddress(A) << ")");
2863  }
2864 
2865  inline size_type size(const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2866  {
2867  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub::operation_generic::size(" << getAddress(*this) << "; " << getAddress(A) << ")");
2869  }
2870 
2871  template<typename MatrixType>
2872  inline bool involves_this_matrix(const MatrixType & matrix, const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2873  {
2874  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub::operation_generic::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
2875  return A.involves_this_matrix(matrix);
2876  }
2877 
2878  template<typename MatrixType>
2879  inline bool test_involvement(const MatrixType & matrix, const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2880  {
2881  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub::operation_generic::test_involvement(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
2882  return A.test_involvement(matrix);
2883  }
2884 
2885  class Enumerator : private row_count_storage<Rows>, private col_count_storage<Cols>
2886  {
2887  private:
2888  size_type d_r_ofs, d_c_ofs;
2889  size_type d_row, d_col;
2890  MT d_A;
2891 
2892  public:
2893  typedef CoeffType_Get Type;
2894  typedef typename MT::GetCoeffSteps_Type GetCoeffSteps_Type;
2895 
2896  template<typename SType>
2897  inline Enumerator(const SType & s, const MT & A)
2898  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(MT(A)))
2899  : row_count_storage<Rows>(s.rows(A)), col_count_storage<Cols>(s.cols(A)),
2900  d_r_ofs(s.d_r_ofs), d_c_ofs(s.d_c_ofs), d_row(0), d_col(0), d_A(A)
2901  {
2902  }
2903 
2904  inline Type current() const
2905  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A(d_r_ofs + d_row, d_c_ofs + d_col)))
2906  {
2907  return d_A(d_r_ofs + d_row, d_c_ofs + d_col);
2908  }
2909 
2910  template<typename Result>
2911  inline void get_current(Result & result) const
2912  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeffs(result, d_r_ofs + d_row, d_c_ofs + d_col)))
2913  {
2914  d_A.get_coeffs(result, d_r_ofs + d_row, d_c_ofs + d_col);
2915  }
2916 
2917  inline GetCoeffSteps_Type get_current_steps() const
2918  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeff_steps(d_r_ofs + d_row, d_c_ofs + d_col)))
2919  {
2920  return d_A.get_coeff_steps(d_r_ofs + d_row, d_c_ofs + d_col);
2921  }
2922 
2923  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2924  {
2925  return d_row < row_count_storage<Rows>::rows();
2926  }
2927 
2928  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2929  {
2930  if (++d_col >= col_count_storage<Cols>::cols())
2931  {
2932  d_col = 0;
2933  ++d_row;
2934  }
2935  }
2936  };
2937 
2939  {
2940  private:
2941  MT d_A;
2942  size_type d_row, d_col;
2943  size_type d_left;
2944 
2945  public:
2946  typedef CoeffType_Get Type;
2947  typedef typename MT::GetCoeffSteps_Type GetCoeffSteps_Type;
2948 
2949  template<typename SType>
2950  inline RowEnumerator(const SType & s, size_type row, const MT & A)
2951  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(MT(A)))
2952  : d_A(A), d_row(s.d_r_ofs + row), d_col(s.d_c_ofs), d_left(s.cols(A))
2953  {
2954  }
2955 
2956  inline Type current() const
2957  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A(d_row, d_col)))
2958  {
2959  return d_A(d_row, d_col);
2960  }
2961 
2962  template<typename Result>
2963  inline void get_current(Result & result) const
2964  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeff(result, d_row, d_col)))
2965  {
2966  d_A.get_coeff(result, d_row, d_col);
2967  }
2968 
2969  inline GetCoeffSteps_Type get_current_steps() const
2970  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeff_steps(d_row, d_col)))
2971  {
2972  return d_A.get_coeff_steps(d_row, d_col);
2973  }
2974 
2975  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2976  {
2977  return d_left > 0;
2978  }
2979 
2980  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
2981  {
2982  --d_left;
2983  ++d_col;
2984  }
2985  };
2986 
2988  {
2989  private:
2990  MT d_A;
2991  size_type d_row, d_col;
2992  size_type d_left;
2993 
2994  public:
2995  typedef CoeffType_Get Type;
2996  typedef typename MT::GetCoeffSteps_Type GetCoeffSteps_Type;
2997 
2998  template<typename SType>
2999  inline ColEnumerator(const SType & s, size_type col, const MT & A)
3000  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(MT(A)))
3001  : d_A(A), d_row(s.d_r_ofs), d_col(s.d_c_ofs + col), d_left(s.rows(A))
3002  {
3003  }
3004 
3005  inline Type current() const
3006  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A(d_row, d_col)))
3007  {
3008  return d_A(d_row, d_col);
3009  }
3010 
3011  template<typename Result>
3012  inline void get_current(Result & result) const
3013  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeff(result, d_row, d_col)))
3014  {
3015  d_A.get_coeff(result, d_row, d_col);
3016  }
3017 
3018  inline GetCoeffSteps_Type get_current_steps() const
3019  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeff_steps(d_row, d_col)))
3020  {
3021  return d_A.get_coeff_steps(d_row, d_col);
3022  }
3023 
3024  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3025  {
3026  return d_left > 0;
3027  }
3028 
3029  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3030  {
3031  --d_left;
3032  ++d_row;
3033  }
3034  };
3035 
3036  friend class Enumerator;
3037  friend class RowEnumerator;
3038  friend class ColEnumerator;
3039 
3040  typedef Enumerator ConstEnumerator;
3043  typedef Enumerator DefaultEnumerator;
3046 
3047  inline DefaultEnumerator enumerate(const MT & A) const
3048  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultEnumerator(helper::make_type_lvalue<const operation_generic<MT> >(), A)))
3049  {
3050  return DefaultEnumerator(*this, A);
3051  }
3052 
3053  inline DefaultRowEnumerator enumerate_row(size_type row, const MT & A)
3054  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowEnumerator(helper::make_type_lvalue<const operation_generic<MT> >(), row, A)))
3055  {
3056  return DefaultRowEnumerator(*this, row, A);
3057  }
3058 
3059  inline DefaultColEnumerator enumerate_col(size_type col, const MT & A) const
3060  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColEnumerator(helper::make_type_lvalue<const operation_generic<MT> >(), col, A)))
3061  {
3062  return DefaultColEnumerator(*this, col, A);
3063  }
3064 
3066  {
3067  private:
3069  const MT & d_A;
3070  size_type d_row;
3071 
3072  public:
3073  typedef RowEnumerator Type;
3074 
3075  RowsEnumerator(typename sub<Rows, Cols>::template operation_generic<MT> * data, const MT & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3076  : d_data(data), d_A(A), d_row(0)
3077  {
3078  }
3079 
3080  inline Type current() const
3081  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(*d_data, d_data->d_r_ofs + d_row, d_A)))
3082  {
3083  return Type(*d_data, d_data->d_r_ofs + d_row, d_A);
3084  }
3085 
3086  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3087  {
3088  return d_row < d_data->rows(d_A);
3089  }
3090 
3091  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3092  {
3093  ++d_row;
3094  }
3095  };
3096 
3098  {
3099  private:
3101  const MT & d_A;
3102  size_type d_col;
3103 
3104  public:
3105  typedef ColEnumerator Type;
3106 
3107  ColsEnumerator(typename sub<Rows, Cols>::template operation_generic<MT> * data, const MT & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3108  : d_data(data), d_A(A), d_col(0)
3109  {
3110  }
3111 
3112  inline Type current() const
3113  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(*d_data, d_data->d_c_ofs + d_col, d_A)))
3114  {
3115  return Type(*d_data, d_data->d_c_ofs + d_col, d_A);
3116  }
3117 
3118  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3119  {
3120  return d_col < d_data->cols(d_A);
3121  }
3122 
3123  inline void next()
3124  PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3125  {
3126  ++d_col;
3127  }
3128  };
3129 
3130  friend class RowsEnumerator;
3131  friend class ColsEnumerator;
3132 
3137 
3138  inline DefaultRowsEnumerator enumerate_row(const MT & A) const
3139  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowsEnumerator(helper::make_type_lvalue<const operation_generic<MT> *>(), A)))
3140  {
3141  return DefaultRowsEnumerator(this, A);
3142  }
3143 
3144  inline DefaultColsEnumerator enumerate_col(const MT & A) const
3145  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColsEnumerator(helper::make_type_lvalue<const operation_generic<MT> *>(), A)))
3146  {
3147  return DefaultColsEnumerator(this, A);
3148  }
3149  };
3150 
3151  template<int Cols>
3152  template<typename MT>
3153  class sub_1d<Cols>::operation_row : private col_count_storage<Cols>
3154  {
3155  private:
3156  size_type d_r_ofs;
3157 
3158  public:
3159  typedef typename MT::CoeffType CoeffType;
3160  typedef typename MT::CoeffType_Get CoeffType_Get;
3161  typedef typename MT::GetCoeffSteps_Type GetCoeffSteps_Type;
3163  1, Cols,
3164  typename MatrixInfo<MT>::StorageTraits,
3166  typedef typename MT::data_pointer_type data_pointer_type;
3167  typedef typename MT::data_ref_type data_ref_type;
3168 
3169  enum { use_temporary_on_evaluate = MatrixInfo<MT>::use_temporary_on_evaluate,
3170  coeffs_are_simple_expressions = true,
3171  is_const = MatrixInfo<MT>::is_const,
3172  can_assign_to = MatrixInfo<MT>::can_assign_to,
3173  can_move_from = MatrixInfo<MT>::can_move_from,
3174  can_resize_rows = false,
3175  can_resize_cols = false,
3176  has_direct_access = MT::has_direct_access };
3177 
3178  template<typename MT_>
3179  operation_row(size_type cols, size_type r_ofs, const MT_ & data)
3180  PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3181  : col_count_storage<Cols>(cols), d_r_ofs(r_ofs)
3182  // data is given only for verification reasons!
3183  {
3184  PLLL_INTERNAL_STATIC_CHECK((Cols < 0) || (MatrixInfo<MT>::cols < 0) ||
3185  (static_cast<size_type>(Cols) == static_cast<size_type>(MatrixInfo<MT>::cols)), TooFewCols);
3187  if (Cols > 0) assert(col_count_storage<Cols>::cols() == static_cast<size_type>(Cols));
3188  assert(d_r_ofs < data.rows());
3189  }
3190 
3191  template<typename ResultType>
3192  inline void get_coeff(ResultType & result, size_type i, size_type j, const MT & A) const
3193  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = A(d_r_ofs, j)))
3194  {
3195  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << " " << getAddress(A) << ") const");
3196  assert(i == 0);
3197  assert(j < cols(A));
3198  result = A(d_r_ofs, j);
3199  }
3200 
3201  inline bool get_coeff_alwayszero(const MT & A) const
3202  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.get_coeff_alwayszero()))
3203  {
3204  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::get_coeff_alwayszero(" << getAddress(*this) << "; " << getAddress(A) << ")");
3205  return A.get_coeff_alwayszero();
3206  }
3207 
3208  inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j, const MT & A) const
3209  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.get_coeff_steps(d_r_ofs, j)))
3210  {
3211  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::get_coeff_steps(" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
3212  assert(i == 0);
3213  assert(j < cols(A));
3214  return A.get_coeff_steps(d_r_ofs, j);
3215  }
3216 
3217  inline CoeffType_Get operator () (size_type i, size_type j, const MT & A) const
3218  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A(d_r_ofs, j)))
3219  {
3220  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::operator () (" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
3221  assert(i == 0);
3222  assert(j < cols(A));
3223  return A(d_r_ofs, j);
3224  }
3225 
3226  inline size_type rows(const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3227  {
3228  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::rows(" << getAddress(*this) << "; " << getAddress(A) << ")");
3229  return 1;
3230  }
3231 
3232  inline size_type cols(const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3233  {
3234  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::cols(" << getAddress(*this) << "; " << getAddress(A) << ")");
3236  }
3237 
3238  inline size_type size(const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3239  {
3240  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::size(" << getAddress(*this) << "; " << getAddress(A) << ")");
3242  }
3243 
3244  inline data_pointer_type data(const MT & A) const
3245  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.data() + helper::make_type_lvalue<const operation_row>().d_r_ofs *
3246  helper::make_type_lvalue<const operation_row>().col_count_storage<Cols>::cols()))
3247  {
3248  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::data(" << getAddress(*this) << "; " << getAddress(A) << ") const");
3249  return A.data() + d_r_ofs * col_count_storage<Cols>::cols();
3250  }
3251 
3252  inline data_ref_type data(size_type i, const MT & A) const
3253  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.data(i + helper::make_type_lvalue<const operation_row>().d_r_ofs *
3254  helper::make_type_lvalue<const operation_row>().col_count_storage<Cols>::cols())))
3255  {
3256  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::data(" << getAddress(*this) << "; " << i << " " << getAddress(A) << ") const");
3257  return A.data(i + d_r_ofs * col_count_storage<Cols>::cols());
3258  }
3259 
3260  template<typename MatrixType>
3261  inline bool involves_this_matrix(const MatrixType & matrix, const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3262  {
3263  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
3264  return A.involves_this_matrix(matrix);
3265  }
3266 
3267  template<typename MatrixType>
3268  inline bool test_involvement(const MatrixType & matrix, const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3269  {
3270  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_row::test_involvement(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
3271  return A.test_involvement(matrix);
3272  }
3273 
3274  typedef typename MT::RowEnumerator Enumerator;
3275  typedef typename MT::ConstRowEnumerator ConstEnumerator;
3276  typedef typename MT::DefaultRowEnumerator DefaultEnumerator;
3277  typedef typename MT::RowEnumerator RowEnumerator;
3278  typedef typename MT::ConstRowEnumerator ConstRowEnumerator;
3279  typedef typename MT::DefaultRowEnumerator DefaultRowEnumerator;
3280 
3282  {
3283  private:
3284  MT d_A;
3285  size_type d_row, d_col;
3286  bool d_first;
3287 
3288  public:
3289  typedef CoeffType_Get Type;
3290  typedef typename operation_row<MT>::GetCoeffSteps_Type GetCoeffSteps_Type;
3291 
3292  template<typename SType>
3293  inline ColEnumerator(const SType & s, size_type col, const MT & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3294  : d_A(A), d_row(s.d_r_ofs), d_col(col), d_first(true)
3295  {
3296  }
3297 
3298  inline Type current() const
3299  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A(d_row, d_col)))
3300  {
3301  return d_A(d_row, d_col);
3302  }
3303 
3304  template<typename Result>
3305  inline void get_current(Result & result) const
3306  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeff(result, d_row, d_col)))
3307  {
3308  d_A.get_coeff(result, d_row, d_col);
3309  }
3310 
3311  inline GetCoeffSteps_Type get_current_steps() const
3312  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeff_steps(d_row, d_col)))
3313  {
3314  return d_A.get_coeff_steps(d_row, d_col);
3315  }
3316 
3317  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3318  {
3319  return d_first;
3320  }
3321 
3322  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3323  {
3324  d_first = false;
3325  }
3326  };
3327 
3328  friend class ColEnumerator;
3329 
3332 
3333  inline DefaultEnumerator enumerate(const MT & A) const
3334  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate_row(d_r_ofs)))
3335  {
3336  return A.enumerate_row(d_r_ofs);
3337  }
3338 
3339  inline DefaultRowEnumerator enumerate_row(size_type row, const MT & A) const
3340  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate_row(d_r_ofs)))
3341  {
3342  assert(row == 0);
3343  return A.enumerate_row(d_r_ofs);
3344  }
3345 
3346  inline DefaultColEnumerator enumerate_col(size_type col, const MT & A) const
3347  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColEnumerator(helper::make_type_lvalue<operation_row<MT> >(), col, A)))
3348  {
3349  return DefaultColEnumerator(*this, col, A);
3350  }
3351 
3353  {
3354  private:
3355  DefaultRowEnumerator d_row;
3356  bool d_first;
3357 
3358  public:
3359  typedef DefaultRowEnumerator Type;
3360 
3361  RowsEnumerator(const DefaultRowEnumerator & e)
3362  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowEnumerator(e)))
3363  : d_row(e), d_first(true)
3364  {
3365  }
3366 
3367  inline Type current() const
3368  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(d_row)))
3369  {
3370  return d_row;
3371  }
3372 
3373  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3374  {
3375  return d_first;
3376  }
3377 
3378  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3379  {
3380  d_first = false;
3381  }
3382  };
3383 
3385  {
3386  private:
3387  DefaultRowEnumerator d_row;
3388 
3389  public:
3391  {
3392  private:
3393  const DefaultRowEnumerator * d_row;
3394  bool d_first;
3395 
3396  public:
3397  typedef CoeffType_Get Type;
3398  typedef typename DefaultRowEnumerator::GetCoeffSteps_Type GetCoeffSteps_Type;
3399 
3400  CustomColEnumerator(const DefaultRowEnumerator & row) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3401  : d_row(&row), d_first(true)
3402  {
3403  }
3404 
3405  inline Type current() const
3406  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_row->current()))
3407  {
3408  return d_row->current();
3409  }
3410 
3411  template<typename Result>
3412  inline void get_current(Result & result) const
3413  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_row->get_current(result)))
3414  {
3415  d_row->get_current(result);
3416  }
3417 
3418  inline GetCoeffSteps_Type get_current_steps() const
3419  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_row->get_current_steps()))
3420  {
3421  return d_row->get_current_steps();
3422  }
3423 
3424  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3425  {
3426  return d_first;
3427  }
3428 
3429  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3430  {
3431  d_first = false;
3432  }
3433  };
3434 
3435  typedef CustomColEnumerator Type;
3436 
3437  ColsEnumerator(const RowEnumerator & row)
3438  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(RowEnumerator(row)))
3439  : d_row(row)
3440  {
3441  }
3442 
3443  inline Type current() const
3444  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(d_row)))
3445  {
3446  return Type(d_row);
3447  }
3448 
3449  inline bool has_current() const
3450  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_row.has_current()))
3451  {
3452  return d_row.has_current();
3453  }
3454 
3455  inline void next()
3456  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_row.next()))
3457  {
3458  d_row.next();
3459  }
3460  };
3461 
3462  friend class RowsEnumerator;
3463  friend class ColsEnumerator;
3464 
3465  typedef RowsEnumerator ConstRowsEnumerator;
3466  typedef ColsEnumerator ConstColsEnumerator;
3467  typedef RowsEnumerator DefaultRowsEnumerator;
3468  typedef ColsEnumerator DefaultColsEnumerator;
3469 
3470  inline DefaultRowsEnumerator enumerate_rows(const MT & A) const
3471  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowsEnumerator(helper::make_type_lvalue<const operation_row<MT> >().enumerate_row(0, A))))
3472  {
3473  return DefaultRowsEnumerator(enumerate_row(0, A));
3474  }
3475 
3476  inline DefaultColsEnumerator enumerate_cols(const MT & A) const
3477  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColsEnumerator(helper::make_type_lvalue<const operation_row<MT> >().enumerate_row(0, A))))
3478  {
3479  return DefaultColsEnumerator(enumerate_row(0, A));
3480  }
3481  };
3482 
3483  template<int Rows>
3484  template<typename MT>
3485  class sub_1d<Rows>::operation_col : private row_count_storage<Rows>
3486  {
3487  private:
3488  size_type d_c_ofs;
3489 
3490  public:
3491  typedef typename MT::CoeffType CoeffType;
3492  typedef typename MT::CoeffType_Get CoeffType_Get;
3493  typedef typename MT::GetCoeffSteps_Type GetCoeffSteps_Type;
3495  Rows, 1,
3496  typename MatrixInfo<MT>::StorageTraits,
3498  typedef void data_pointer_type;
3499  typedef void data_ref_type;
3500 
3501  enum { use_temporary_on_evaluate = MatrixInfo<MT>::use_temporary_on_evaluate,
3502  coeffs_are_simple_expressions = true,
3503  is_const = MatrixInfo<MT>::is_const,
3504  can_assign_to = MatrixInfo<MT>::can_assign_to,
3505  can_move_from = MatrixInfo<MT>::can_move_from,
3506  can_resize_rows = false,
3507  can_resize_cols = false,
3508  has_direct_access = false };
3509 
3510  template<typename MT_>
3511  operation_col(size_type rows, size_type c_ofs, const MT_ & data) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3512  : row_count_storage<Rows>(rows), d_c_ofs(c_ofs)
3513  // data is given only for verification reasons!
3514  {
3515  PLLL_INTERNAL_STATIC_CHECK((Rows < 0) || (MatrixInfo<MT>::rows < 0) ||
3516  (static_cast<size_type>(Rows) == static_cast<size_type>(MatrixInfo<MT>::rows)), TooFewRows);
3518  if (Rows > 0) assert(row_count_storage<Rows>::rows() == static_cast<size_type>(Rows));
3519  assert(d_c_ofs < data.cols());
3520  }
3521 
3522  template<typename ResultType>
3523  inline void get_coeff(ResultType & result, size_type i, size_type j, const MT & A) const
3524  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = A(i, d_c_ofs)))
3525  {
3526  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_col::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << " " << getAddress(A) << ") const");
3527  assert(i == 0);
3528  assert(j < cols(A));
3529  result = A(i, d_c_ofs);
3530  }
3531 
3532  inline bool get_coeff_alwayszero(const MT & A) const
3533  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.get_coeff_alwayszero()))
3534  {
3535  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_col::get_coeff_alwayszero(" << getAddress(*this) << "; " << getAddress(A) << ")");
3536  return A.get_coeff_alwayszero();
3537  }
3538 
3539  inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j, const MT & A) const
3540  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.get_coeff_steps(i, d_c_ofs)))
3541  {
3542  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_col::get_coeff_steps(" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
3543  assert(i == 0);
3544  assert(j < cols(A));
3545  return A.get_coeff_steps(i, d_c_ofs);
3546  }
3547 
3548  inline CoeffType_Get operator () (size_type i, size_type j, const MT & A) const
3549  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A(i, d_c_ofs)))
3550  {
3551  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_col::operator () (" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
3552  assert(i == 0);
3553  assert(j < cols(A));
3554  return A(i, d_c_ofs);
3555  }
3556 
3557  inline size_type rows(const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3558  {
3559  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_col::rows(" << getAddress(*this) << "; " << getAddress(A) << ")");
3561  }
3562 
3563  inline size_type cols(const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3564  {
3565  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_col::cols(" << getAddress(*this) << "; " << getAddress(A) << ")");
3566  return 1;
3567  }
3568 
3569  inline size_type size(const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3570  {
3571  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_col::size(" << getAddress(*this) << "; " << getAddress(A) << ")");
3573  }
3574 
3575  template<typename MatrixType>
3576  inline bool involves_this_matrix(const MatrixType & matrix, const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3577  {
3578  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_col::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
3579  return A.involves_this_matrix(matrix);
3580  }
3581 
3582  template<typename MatrixType>
3583  inline bool test_involvement(const MatrixType & matrix, const MT & A) const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3584  {
3585  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::sub_1d::operation_col::test_involvement(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
3586  return A.test_involvement(matrix);
3587  }
3588 
3589  typedef typename MT::ColEnumerator Enumerator;
3590  typedef typename MT::ConstColEnumerator ConstEnumerator;
3591  typedef typename MT::DefaultColEnumerator DefaultEnumerator;
3592  typedef typename MT::ColEnumerator ColEnumerator;
3593  typedef typename MT::ConstColEnumerator ConstColEnumerator;
3594  typedef typename MT::DefaultColEnumerator DefaultColEnumerator;
3595 
3597  {
3598  private:
3599  MT d_A;
3600  size_type d_row, d_col;
3601  bool d_first;
3602 
3603  public:
3604  typedef CoeffType_Get Type;
3605  typedef typename operation_col<MT>::GetCoeffSteps_Type GetCoeffSteps_Type;
3606 
3607  template<typename SType>
3608  inline RowEnumerator(const SType & s, size_type row, const MT & A)
3609  PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3610  : d_A(A), d_row(row), d_col(s.d_c_ofs), d_first(true)
3611  {
3612  }
3613 
3614  inline Type current() const
3615  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A(d_row, d_col)))
3616  {
3617  return d_A(d_row, d_col);
3618  }
3619 
3620  template<typename Result>
3621  inline void get_current(Result & result) const
3622  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeff(result, d_row, d_col)))
3623  {
3624  d_A.get_coeff(result, d_row, d_col);
3625  }
3626 
3627  inline GetCoeffSteps_Type get_current_steps() const
3628  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_A.get_coeff_steps(d_row, d_col)))
3629  {
3630  return d_A.get_coeff_steps(d_row, d_col);
3631  }
3632 
3633  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3634  {
3635  return d_first;
3636  }
3637 
3638  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3639  {
3640  d_first = false;
3641  }
3642  };
3643 
3644  friend class RowEnumerator;
3645 
3648 
3649  inline DefaultEnumerator enumerate(const MT & A) const
3650  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate_col(d_c_ofs)))
3651  {
3652  return A.enumerate_col(d_c_ofs);
3653  }
3654 
3655  inline DefaultRowEnumerator enumerate_row(size_type row, const MT & A) const
3656  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowEnumerator(helper::make_type_lvalue<operation_col<MT> >(), row, A)))
3657  {
3658  return DefaultRowEnumerator(*this, row, A);
3659  }
3660 
3661  inline DefaultColEnumerator enumerate_col(size_type col, const MT & A) const
3662  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate_col(d_c_ofs)))
3663  {
3664  assert(col == 0);
3665  return A.enumerate_col(d_c_ofs);
3666  }
3667 
3669  {
3670  private:
3671  DefaultColEnumerator d_col;
3672 
3673  public:
3675  {
3676  private:
3677  const DefaultColEnumerator & d_col;
3678  bool d_first;
3679 
3680  public:
3681  typedef CoeffType_Get Type;
3682  typedef typename DefaultColEnumerator::GetCoeffSteps_Type GetCoeffSteps_Type;
3683 
3684  CustomRowEnumerator(const DefaultColEnumerator & col) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3685  : d_col(col), d_first(true)
3686  {
3687  }
3688 
3689  inline Type current() const
3690  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_col.current()))
3691  {
3692  return d_col.current();
3693  }
3694 
3695  template<typename Result>
3696  inline void get_current(Result & result) const
3697  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_col.get_current(result)))
3698  {
3699  d_col.get_current(result);
3700  }
3701 
3702  inline GetCoeffSteps_Type get_current_steps() const
3703  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_col.get_current_steps()))
3704  {
3705  return d_col.get_current_steps();
3706  }
3707 
3708  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3709  {
3710  return d_first;
3711  }
3712 
3713  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3714  {
3715  d_first = false;
3716  }
3717  };
3718 
3719  typedef CustomRowEnumerator Type;
3720 
3721  RowsEnumerator(const ColEnumerator & col)
3722  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColEnumerator(col)))
3723  : d_col(col)
3724  {
3725  }
3726 
3727  inline Type current() const
3728  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(d_col)))
3729  {
3730  return Type(d_col);
3731  }
3732 
3733  inline bool has_current() const
3734  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_col.has_current()))
3735  {
3736  return d_col.has_current();
3737  }
3738 
3739  inline void next()
3740  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_col.next()))
3741  {
3742  d_col.next();
3743  }
3744  };
3745 
3747  {
3748  private:
3749  DefaultColEnumerator d_col;
3750  bool d_first;
3751 
3752  public:
3753  typedef DefaultColEnumerator Type;
3754 
3755  ColsEnumerator(const DefaultColEnumerator & e)
3756  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColEnumerator(e)))
3757  : d_col(e), d_first(true)
3758  {
3759  }
3760 
3761  inline Type current() const
3762  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(d_col)))
3763  {
3764  return d_col;
3765  }
3766 
3767  inline bool has_current() const PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3768  {
3769  return d_first;
3770  }
3771 
3772  inline void next() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3773  {
3774  d_first = false;
3775  }
3776  };
3777 
3778  friend class RowsEnumerator;
3779  friend class ColsEnumerator;
3780 
3785 
3786  inline DefaultRowsEnumerator enumerate_rows(const MT & A) const
3787  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowsEnumerator(helper::make_type_lvalue<const operation_col<MT> >().enumerate_col(0, A))))
3788  {
3789  return DefaultRowsEnumerator(enumerate_col(0, A));
3790  }
3791 
3792  inline DefaultColsEnumerator enumerate_cols(const MT & A) const
3793  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColsEnumerator(helper::make_type_lvalue<const operation_col<MT> >().enumerate_col(0, A))))
3794  {
3795  return DefaultColsEnumerator(enumerate_col(0, A));
3796  }
3797  };
3798 
3799  template<typename MT>
3801  {
3802  public:
3803  typedef typename MT::CoeffType CoeffType;
3804  typedef typename MT::CoeffType_Get CoeffType_Get;
3805  typedef typename MT::GetCoeffSteps_Type GetCoeffSteps_Type;
3806  typedef base_matrix<CoeffType,
3808  typename MatrixInfo<MT>::StorageTraits,
3810  typedef void data_pointer_type;
3811  typedef void data_ref_type;
3812 
3813  enum { use_temporary_on_evaluate = MatrixInfo<MT>::use_temporary_on_evaluate,
3814  coeffs_are_simple_expressions = true,
3815  is_const = MatrixInfo<MT>::is_const,
3816  can_assign_to = MatrixInfo<MT>::can_assign_to,
3817  can_move_from = MatrixInfo<MT>::can_move_from,
3818  can_resize_rows = false,
3819  can_resize_cols = false,
3820  has_direct_access = false };
3821 
3822  transpose() PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3823  {
3825  }
3826 
3827  template<typename ResultType>
3828  static inline void get_coeff(ResultType & result, size_type i, size_type j, const MT & A)
3829  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(result = A(j, i)))
3830  {
3831  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::transpose::get_coeff(" << getAddress(*this) << "; " << getAddress(result) << " " << i << " " << j << " " << getAddress(A) << ") const");
3832  assert(i < rows(A));
3833  assert(j < cols(A));
3834  result = A(j, i);
3835  }
3836 
3837  static inline bool get_coeff_alwayszero(const MT & A)
3838  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.get_coeff_alwayszero()))
3839  {
3840  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::transpose::get_coeff_alwayszero(" << getAddress(*this) << "; " << getAddress(A) << ")");
3841  return A.get_coeff_alwayszero();
3842  }
3843 
3844  static inline GetCoeffSteps_Type get_coeff_steps(size_type i, size_type j, const MT & A)
3845  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.get_coeff_steps(j, i)))
3846  {
3847  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::transpose::get_coeff_steps(" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
3848  assert(i < rows(A));
3849  assert(j < cols(A));
3850  return A.get_coeff_steps(j, i);
3851  }
3852 
3853  inline CoeffType_Get operator () (size_type i, size_type j, const MT & A) const
3854  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CoeffType_Get(A(j, i))))
3855  {
3856  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::transpose::operator () (" << getAddress(*this) << "; " << i << " " << j << " " << getAddress(A) << ")");
3857  assert(i < rows(A));
3858  assert(j < cols(A));
3859  return A(j, i);
3860  }
3861 
3862  static inline size_type rows(const MT & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3863  {
3864  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::transpose::rows(" << getAddress(*this) << "; " << getAddress(A) << ")");
3865  return A.cols();
3866  }
3867 
3868  static inline size_type cols(const MT & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3869  {
3870  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::transpose::cols(" << getAddress(*this) << "; " << getAddress(A) << ")");
3871  return A.rows();
3872  }
3873 
3874  static inline size_type size(const MT & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3875  {
3876  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::transpose::size(" << getAddress(*this) << "; " << getAddress(A) << ")");
3877  return A.size();
3878  }
3879 
3880  template<typename MatrixType>
3881  static inline bool involves_this_matrix(const MatrixType & matrix, const MT & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3882  {
3883  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::transpose::involves_this_matrix(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
3884  return A.involves_this_matrix(matrix);
3885  }
3886 
3887  template<typename MatrixType>
3888  static inline bool test_involvement(const MatrixType & matrix, const MT & A) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
3889  {
3890  PLLL_DEBUG_OUTPUT_MESSAGE("expressions::transpose::test_involvement(" << getAddress(*this) << "; " << getAddress(matrix) << " " << getAddress(A) << ")");
3891  return A.test_involvement(matrix);
3892  }
3893 
3894  class Enumerator : private row_count_storage<MatrixInfo<MT>::rows>, private col_count_storage<MatrixInfo<MT>::cols>
3895  {
3896  private:
3897  typename MT::DefaultColsEnumerator d_cols;
3898  typename MT::DefaultColsEnumerator::Type d_col;
3899 
3900  public:
3901  typedef typename MT::DefaultColsEnumerator::Type::Type Type;
3902  typedef typename MT::DefaultColsEnumerator::Type::GetCoeffSteps_Type GetCoeffSteps_Type;
3903 
3904  inline Enumerator(const MT & matrix)
3905  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(typename MT::DefaultColsEnumerator(matrix.enumerate_cols())) &&
3906  noexcept(typename MT::DefaultColsEnumerator::Type(d_cols.current())))
3907  : d_cols(matrix.enumerate_cols()), d_col(d_cols.current())
3908  {
3909  }
3910 
3911  inline Type current() const
3912  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Type(d_col.current())))
3913  {
3914  return d_col.current();
3915  }
3916 
3917  template<typename Result>
3918  inline void get_current(Result & result) const
3919  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_col.current(result)))
3920  {
3921  d_col.current(result);
3922  }
3923 
3924  inline GetCoeffSteps_Type get_current_steps() const
3925  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_col.get_current_steps()))
3926  {
3927  return d_col.get_current_steps();
3928  }
3929 
3930  inline bool has_current() const
3931  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_col.has_current()))
3932  {
3933  return d_col.has_current();
3934  }
3935 
3936  inline void next()
3937  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(d_col.next()) &&
3938  noexcept(d_col.has_current()) &&
3939  noexcept(d_cols.next()) &&
3940  noexcept(d_cols.has_current()) &&
3941  noexcept(d_col = d_cols.current()))
3942  {
3943  d_col.next();
3944  if (!d_col.has_current())
3945  {
3946  d_cols.next();
3947  if (d_cols.has_current())
3948  d_col = d_cols.current();
3949  }
3950  }
3951  };
3952 
3953  typedef Enumerator ConstEnumerator;
3954  typedef Enumerator DefaultEnumerator;
3955  typedef typename MT::ColEnumerator RowEnumerator;
3956  typedef typename MT::RowEnumerator ColEnumerator;
3957  typedef typename MT::ConstColEnumerator ConstRowEnumerator;
3958  typedef typename MT::ConstRowEnumerator ConstColEnumerator;
3959  typedef typename MT::DefaultColEnumerator DefaultRowEnumerator;
3960  typedef typename MT::DefaultRowEnumerator DefaultColEnumerator;
3961 
3962  static inline DefaultEnumerator enumerate(const MT & A)
3963  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultEnumerator(A)))
3964  {
3965  return DefaultEnumerator(A);
3966  }
3967 
3968  static inline DefaultRowEnumerator enumerate_row(size_type row, const MT & A)
3969  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate_col(row)))
3970  {
3971  return A.enumerate_col(row);
3972  }
3973 
3974  static inline DefaultColEnumerator enumerate_col(size_type col, const MT & A)
3975  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate_row(col)))
3976  {
3977  return A.enumerate_row(col);
3978  }
3979 
3980  typedef typename MT::ColsEnumerator RowsEnumerator;
3981  typedef typename MT::RowsEnumerator ColsEnumerator;
3982  typedef typename MT::ConstColsEnumerator ConstRowsEnumerator;
3983  typedef typename MT::ConstRowsEnumerator ConstColsEnumerator;
3984  typedef typename MT::DefaultColsEnumerator DefaultRowsEnumerator;
3985  typedef typename MT::DefaultRowsEnumerator DefaultColsEnumerator;
3986 
3987  inline DefaultRowsEnumerator enumerate_rows(const MT & A) const
3988  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultRowsEnumerator(A.enumerate_cols())))
3989  {
3990  return DefaultRowsEnumerator(A.enumerate_cols());
3991  }
3992 
3993  inline DefaultColsEnumerator enumerate_cols(const MT & A) const
3994  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(DefaultColsEnumerator(A.enumerate_rows())))
3995  {
3996  return DefaultColsEnumerator(A.enumerate_rows());
3997  }
3998  };
3999  }
4000 
4001  template<typename MatrixType>
4002  struct MatrixInfo<expressions::ConstMatrixWrapper<MatrixType> >
4003  {
4004  enum { is_matrix = MatrixInfo<const MatrixType>::is_matrix,
4005  is_const = true,
4007  is_expression = true,
4008  only_defined_for_matrices = 1,
4009  can_move_from = false,
4010  can_assign_to = false,
4011  can_resize_rows = false,
4012  can_resize_cols = false,
4013  use_temporary_on_evaluate = MatrixInfo<const MatrixType>::use_temporary_on_evaluate,
4014  coeffs_are_simple_expressions = MatrixInfo<const MatrixType>::coeffs_are_simple_expressions };
4016  typedef typename MatrixInfo<MatrixType>::Type Type;
4017  typedef typename MatrixInfo<MatrixType>::StorageTraits StorageTraits;
4018  };
4019 
4020  template<typename MatrixType>
4021  struct MatrixInfo<const expressions::ConstMatrixWrapper<MatrixType> >
4022  {
4023  enum { is_matrix = MatrixInfo<const MatrixType>::is_matrix,
4024  is_const = true,
4026  is_expression = true,
4027  only_defined_for_matrices = 1,
4028  can_move_from = false,
4029  can_assign_to = false,
4030  can_resize_rows = false,
4031  can_resize_cols = false,
4032  use_temporary_on_evaluate = MatrixInfo<const MatrixType>::use_temporary_on_evaluate,
4033  coeffs_are_simple_expressions = MatrixInfo<const MatrixType>::coeffs_are_simple_expressions };
4035  typedef typename MatrixInfo<MatrixType>::Type Type;
4036  typedef typename MatrixInfo<MatrixType>::StorageTraits StorageTraits;
4037  };
4038 
4039  template<typename MatrixType>
4040  struct MatrixInfo<expressions::MatrixWrapper<MatrixType> >
4041  {
4042  enum { is_matrix = MatrixInfo<MatrixType>::is_matrix,
4044  is_math_object = MatrixInfo<MatrixType>::is_math_object,
4045  is_expression = true,
4046  only_defined_for_matrices = 1,
4047  can_move_from = MatrixInfo<MatrixType>::can_move_from,
4048  can_assign_to = MatrixInfo<MatrixType>::can_assign_to,
4049  can_resize_rows = MatrixInfo<MatrixType>::can_resize_rows,
4050  can_resize_cols = MatrixInfo<MatrixType>::can_resize_cols,
4051  use_temporary_on_evaluate = MatrixInfo<MatrixType>::use_temporary_on_evaluate,
4052  coeffs_are_simple_expressions = MatrixInfo<MatrixType>::coeffs_are_simple_expressions };
4054  typedef typename MatrixInfo<MatrixType>::Type Type;
4055  typedef typename MatrixInfo<MatrixType>::StorageTraits StorageTraits;
4056  };
4057 
4058  template<typename MatrixType>
4059  struct MatrixInfo<const expressions::MatrixWrapper<MatrixType> >
4060  {
4061  enum { is_matrix = MatrixInfo<MatrixType>::is_matrix,
4063  is_math_object = MatrixInfo<MatrixType>::is_math_object,
4064  is_expression = true,
4065  only_defined_for_matrices = 1,
4066  can_move_from = MatrixInfo<MatrixType>::can_move_from,
4067  can_assign_to = MatrixInfo<MatrixType>::can_assign_to,
4068  can_resize_rows = MatrixInfo<MatrixType>::can_resize_rows,
4069  can_resize_cols = MatrixInfo<MatrixType>::can_resize_cols,
4070  use_temporary_on_evaluate = MatrixInfo<MatrixType>::use_temporary_on_evaluate,
4071  coeffs_are_simple_expressions = MatrixInfo<MatrixType>::coeffs_are_simple_expressions };
4073  typedef typename MatrixInfo<MatrixType>::Type Type;
4074  typedef typename MatrixInfo<MatrixType>::StorageTraits StorageTraits;
4075  };
4076 
4077  template<typename MatrixType>
4078  struct MatrixInfo<expressions::MatrixTemporaryWrapper<MatrixType> >
4079  {
4080  enum { is_matrix = MatrixInfo<const MatrixType>::is_matrix,
4081  is_const = true,
4083  is_expression = true,
4084  only_defined_for_matrices = 1,
4085  can_move_from = true,
4086  can_assign_to = false,
4087  can_resize_rows = false,
4088  can_resize_cols = false,
4089  use_temporary_on_evaluate = false,
4090  coeffs_are_simple_expressions = true };
4092  typedef typename MatrixInfo<MatrixType>::Type Type;
4093  typedef typename MatrixInfo<MatrixType>::StorageTraits StorageTraits;
4094  };
4095 
4096  template<typename MatrixType>
4097  struct MatrixInfo<const expressions::MatrixTemporaryWrapper<MatrixType> >
4098  {
4099  enum { is_matrix = MatrixInfo<const MatrixType>::is_matrix,
4100  is_const = true,
4102  is_expression = true,
4103  only_defined_for_matrices = 1,
4104  can_move_from = true,
4105  can_assign_to = false,
4106  can_resize_rows = false,
4107  can_resize_cols = false,
4108  use_temporary_on_evaluate = false,
4109  coeffs_are_simple_expressions = true };
4111  typedef typename MatrixInfo<MatrixType>::Type Type;
4112  typedef typename MatrixInfo<MatrixType>::StorageTraits StorageTraits;
4113  };
4114 
4115  template<typename ScalarType>
4116  struct MatrixInfo<expressions::ScalarWrapper<ScalarType> >
4117  {
4118  enum { is_matrix = false,
4119  is_const = true,
4120  is_math_object = true,
4121  is_expression = true,
4122  can_move_from = false,
4123  can_assign_to = false,
4124  can_resize_rows = false,
4125  can_resize_cols = false,
4126  use_temporary_on_evaluate = false,
4127  coeffs_are_simple_expressions = true };
4128  typedef ScalarType Type;
4129  };
4130 
4131  template<typename ScalarType>
4132  struct MatrixInfo<const expressions::ScalarWrapper<ScalarType> >
4133  {
4134  enum { is_matrix = false,
4135  is_const = true,
4136  is_math_object = true,
4137  is_expression = true,
4138  can_move_from = false,
4139  can_assign_to = false,
4140  can_resize_rows = false,
4141  can_resize_cols = false,
4142  use_temporary_on_evaluate = false,
4143  coeffs_are_simple_expressions = true };
4144  typedef ScalarType Type;
4145  };
4146 
4147  // Operations: binary matrix operations
4148 
4149  template<typename A, bool A_is_matrix, bool A_needs_wrapper, typename B, bool B_is_matrix, bool B_needs_wrapper>
4151 
4152  template<typename A, typename B>
4153  class BinaryMatrixOperationImpl_Impl<A, true, false, B, true, false>
4154  {
4155  public:
4157 
4158  inline static Mul_ReturnType multiply(const A & a, const B & b)
4159  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mul_ReturnType(std::make_pair(a.lazy_evaluate(), b.lazy_evaluate()))))
4160  {
4161  assert(a.cols() == b.rows());
4162  return Mul_ReturnType(std::make_pair(a.lazy_evaluate(), b.lazy_evaluate()));
4163  }
4164 
4165  typedef void Div_ReturnType;
4166  typedef void Mod_ReturnType;
4167 
4169 
4170  inline static Add_ReturnType add(const A & a, const B & b)
4171  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Add_ReturnType(std::make_pair(a, b))))
4172  {
4173  assert(a.rows() == b.rows());
4174  assert(a.cols() == b.cols());
4175  return Add_ReturnType(std::make_pair(a, b));
4176  }
4177 
4179 
4180  inline static Sub_ReturnType sub(const A & a, const B & b)
4181  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Sub_ReturnType(std::make_pair(a, b))))
4182  {
4183  assert(a.rows() == b.rows());
4184  assert(a.cols() == b.cols());
4185  return Sub_ReturnType(std::make_pair(a, b));
4186  }
4187 
4189 
4190  inline static CwMul_ReturnType componentwise_mul(const A & a, const B & b)
4191  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwMul_ReturnType(std::make_pair(a, b))))
4192  {
4193  assert(a.rows() == b.rows());
4194  assert(a.cols() == b.cols());
4195  return CwMul_ReturnType(std::make_pair(a, b));
4196  }
4197 
4199 
4200  inline static CwDiv_ReturnType componentwise_div(const A & a, const B & b)
4201  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwDiv_ReturnType(std::make_pair(a, b))))
4202  {
4203  assert(a.rows() == b.rows());
4204  assert(a.cols() == b.cols());
4205  return CwDiv_ReturnType(std::make_pair(a, b));
4206  }
4207 
4209 
4210  inline static CwMod_ReturnType componentwise_mod(const A & a, const B & b)
4211  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwMod_ReturnType(std::make_pair(a, b))))
4212  {
4213  assert(a.rows() == b.rows());
4214  assert(a.cols() == b.cols());
4215  return CwMod_ReturnType(std::make_pair(a, b));
4216  }
4217  };
4218 
4219  template<typename A, typename B>
4220  class BinaryMatrixOperationImpl_Impl<A, true, true, B, true, false>
4221  {
4222  public:
4224  std::pair<expressions::ConstMatrixWrapper<A>, typename B::LazyEvalType> > Mul_ReturnType;
4225 
4226  inline static Mul_ReturnType multiply(const A & a, const B & b)
4227  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b.lazy_evaluate()))))
4228  {
4229  assert(a.cols() == b.rows());
4230  return Mul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b.lazy_evaluate()));
4231  }
4232 
4233  typedef void Div_ReturnType;
4234  typedef void Mod_ReturnType;
4235 
4237  std::pair<expressions::ConstMatrixWrapper<A>, B> > Add_ReturnType;
4238 
4239  inline static Add_ReturnType add(const A & a, const B & b)
4240  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Add_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b))))
4241  {
4242  assert(a.rows() == b.rows());
4243  assert(a.cols() == b.cols());
4244  return Add_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b));
4245  }
4246 
4248  std::pair<expressions::ConstMatrixWrapper<A>, B> > Sub_ReturnType;
4249 
4250  inline static Sub_ReturnType sub(const A & a, const B & b)
4251  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Sub_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b))))
4252  {
4253  assert(a.rows() == b.rows());
4254  assert(a.cols() == b.cols());
4255  return Sub_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b));
4256  }
4257 
4259  std::pair<expressions::ConstMatrixWrapper<A>, B> > CwMul_ReturnType;
4260 
4261  inline static CwMul_ReturnType componentwise_mul(const A & a, const B & b)
4262  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwMul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b))))
4263  {
4264  assert(a.rows() == b.rows());
4265  assert(a.cols() == b.cols());
4266  return CwMul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b));
4267  }
4268 
4270  std::pair<expressions::ConstMatrixWrapper<A>, B> > CwDiv_ReturnType;
4271 
4272  inline static CwDiv_ReturnType componentwise_div(const A & a, const B & b)
4273  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwDiv_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b))))
4274  {
4275  assert(a.rows() == b.rows());
4276  assert(a.cols() == b.cols());
4277  return CwDiv_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b));
4278  }
4279 
4281  std::pair<expressions::ConstMatrixWrapper<A>, B> > CwMod_ReturnType;
4282 
4283  inline static CwMod_ReturnType componentwise_mod(const A & a, const B & b)
4284  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwMod_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b))))
4285  {
4286  assert(a.rows() == b.rows());
4287  assert(a.cols() == b.cols());
4288  return CwMod_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a), b));
4289  }
4290  };
4291 
4292  template<typename A, typename B>
4293  class BinaryMatrixOperationImpl_Impl<A, true, false, B, true, true>
4294  {
4295  public:
4297  std::pair<typename A::LazyEvalType, expressions::ConstMatrixWrapper<B> > > Mul_ReturnType;
4298 
4299  inline static Mul_ReturnType multiply(const A & a, const B & b)
4300  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mul_ReturnType(std::make_pair(a.lazy_evaluate(), expressions::make_matrix_wrapper(b)))))
4301  {
4302  assert(a.cols() == b.rows());
4303  return Mul_ReturnType(std::make_pair(a.lazy_evaluate(), expressions::make_matrix_wrapper(b)));
4304  }
4305 
4306  typedef void Div_ReturnType;
4307  typedef void Mod_ReturnType;
4308 
4310  std::pair<A, expressions::ConstMatrixWrapper<B> > > Add_ReturnType;
4311 
4312  inline static Add_ReturnType add(const A & a, const B & b)
4313  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Add_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)))))
4314  {
4315  assert(a.rows() == b.rows());
4316  assert(a.cols() == b.cols());
4317  return Add_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)));
4318  }
4319 
4321  std::pair<A, expressions::ConstMatrixWrapper<B> > > Sub_ReturnType;
4322 
4323  inline static Sub_ReturnType sub(const A & a, const B & b)
4324  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Sub_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)))))
4325  {
4326  assert(a.rows() == b.rows());
4327  assert(a.cols() == b.cols());
4328  return Sub_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)));
4329  }
4330 
4332  std::pair<A, expressions::ConstMatrixWrapper<B> > > CwMul_ReturnType;
4333 
4334  inline static CwMul_ReturnType componentwise_mul(const A & a, const B & b)
4335  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwMul_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)))))
4336  {
4337  assert(a.rows() == b.rows());
4338  assert(a.cols() == b.cols());
4339  return CwMul_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)));
4340  }
4341 
4343  std::pair<A, expressions::ConstMatrixWrapper<B> > > CwDiv_ReturnType;
4344 
4345  inline static CwDiv_ReturnType componentwise_div(const A & a, const B & b)
4346  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwDiv_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)))))
4347  {
4348  assert(a.rows() == b.rows());
4349  assert(a.cols() == b.cols());
4350  return CwDiv_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)));
4351  }
4352 
4354  std::pair<A, expressions::ConstMatrixWrapper<B> > > CwMod_ReturnType;
4355 
4356  inline static CwMod_ReturnType componentwise_mod(const A & a, const B & b)
4357  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwMod_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)))))
4358  {
4359  assert(a.rows() == b.rows());
4360  assert(a.cols() == b.cols());
4361  return CwMod_ReturnType(std::make_pair(a, expressions::make_matrix_wrapper(b)));
4362  }
4363  };
4364 
4365  template<typename A, typename B>
4366  class BinaryMatrixOperationImpl_Impl<A, true, true, B, true, true>
4367  {
4368  public:
4370  std::pair<expressions::ConstMatrixWrapper<A>,
4372 
4373  inline static Mul_ReturnType multiply(const A & a, const B & b)
4374  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4375  expressions::make_matrix_wrapper(b)))))
4376  {
4377  assert(a.cols() == b.rows());
4378  return Mul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4379  expressions::make_matrix_wrapper(b)));
4380  }
4381 
4382  typedef void Div_ReturnType;
4383  typedef void Mod_ReturnType;
4384 
4386  std::pair<expressions::ConstMatrixWrapper<A>,
4388 
4389  inline static Add_ReturnType add(const A & a, const B & b)
4390  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Add_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4391  expressions::make_matrix_wrapper(b)))))
4392  {
4393  assert(a.rows() == b.rows());
4394  assert(a.cols() == b.cols());
4395  return Add_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4396  expressions::make_matrix_wrapper(b)));
4397  }
4398 
4400  std::pair<expressions::ConstMatrixWrapper<A>,
4402 
4403  inline static Sub_ReturnType sub(const A & a, const B & b)
4404  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Sub_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4405  expressions::make_matrix_wrapper(b)))))
4406  {
4407  assert(a.rows() == b.rows());
4408  assert(a.cols() == b.cols());
4409  return Sub_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4410  expressions::make_matrix_wrapper(b)));
4411  }
4412 
4414  std::pair<expressions::ConstMatrixWrapper<A>,
4416 
4417  inline static CwMul_ReturnType componentwise_mul(const A & a, const B & b)
4418  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwMul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4419  expressions::make_matrix_wrapper(b)))))
4420  {
4421  assert(a.rows() == b.rows());
4422  assert(a.cols() == b.cols());
4423  return CwMul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4424  expressions::make_matrix_wrapper(b)));
4425  }
4426 
4428  std::pair<expressions::ConstMatrixWrapper<A>,
4430 
4431  inline static CwDiv_ReturnType componentwise_div(const A & a, const B & b)
4432  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwDiv_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4433  expressions::make_matrix_wrapper(b)))))
4434  {
4435  assert(a.rows() == b.rows());
4436  assert(a.cols() == b.cols());
4437  return CwDiv_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4438  expressions::make_matrix_wrapper(b)));
4439  }
4440 
4442  std::pair<expressions::ConstMatrixWrapper<A>,
4444 
4445  inline static CwMod_ReturnType componentwise_mod(const A & a, const B & b)
4446  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(CwMod_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4447  expressions::make_matrix_wrapper(b)))))
4448  {
4449  assert(a.rows() == b.rows());
4450  assert(a.cols() == b.cols());
4451  return CwMod_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4452  expressions::make_matrix_wrapper(b)));
4453  }
4454  };
4455 
4456  template<typename A, typename B>
4457  class BinaryMatrixOperationImpl_Impl<A, false, true, B, true, false>
4458  {
4459  public:
4461  std::pair<B, expressions::ScalarWrapper<A> > > Mul_ReturnType;
4462 
4463  inline static Mul_ReturnType multiply(const A & a, const B & b)
4464  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mul_ReturnType(std::make_pair(b, expressions::make_scalar_wrapper(a)))))
4465  {
4466  return Mul_ReturnType(std::make_pair(b, expressions::make_scalar_wrapper(a)));
4467  }
4468 
4469  typedef void Div_ReturnType;
4470  typedef void Mod_ReturnType;
4471  typedef void Add_ReturnType;
4472  typedef void Sub_ReturnType;
4473  typedef void CwMul_ReturnType;
4474  typedef void CwDiv_ReturnType;
4475  typedef void CwMod_ReturnType;
4476  };
4477 
4478  template<typename A, typename B>
4479  class BinaryMatrixOperationImpl_Impl<A, false, true, B, true, true>
4480  {
4481  public:
4483  std::pair<expressions::ConstMatrixWrapper<B>,
4485 
4486  inline static Mul_ReturnType multiply(const A & a, const B & b)
4487  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(b),
4488  expressions::make_scalar_wrapper(a)))))
4489  {
4490  return Mul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(b),
4491  expressions::make_scalar_wrapper(a)));
4492  }
4493 
4494  typedef void Div_ReturnType;
4495  typedef void Mod_ReturnType;
4496  typedef void Add_ReturnType;
4497  typedef void Sub_ReturnType;
4498  typedef void CwMul_ReturnType;
4499  typedef void CwDiv_ReturnType;
4500  typedef void CwMod_ReturnType;
4501  };
4502 
4503  template<typename A, typename B>
4504  class BinaryMatrixOperationImpl_Impl<A, true, false, B, false, true>
4505  {
4506  public:
4508  std::pair<A, expressions::ScalarWrapper<B> > > Mul_ReturnType;
4509 
4510  inline static Mul_ReturnType multiply(const A & a, const B & b)
4511  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mul_ReturnType(std::make_pair(a, expressions::make_scalar_wrapper(b)))))
4512  {
4513  return Mul_ReturnType(std::make_pair(a, expressions::make_scalar_wrapper(b)));
4514  }
4515 
4517  std::pair<A, expressions::ScalarWrapper<B> > > Div_ReturnType;
4518 
4519  inline static Div_ReturnType divide(const A & a, const B & b)
4520  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Div_ReturnType(std::make_pair(a, expressions::make_scalar_wrapper(b)))))
4521  {
4522  return Div_ReturnType(std::make_pair(a, expressions::make_scalar_wrapper(b)));
4523  }
4524 
4526  std::pair<A, expressions::ScalarWrapper<B> > > Mod_ReturnType;
4527 
4528  inline static Mod_ReturnType modulo(const A & a, const B & b)
4529  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mod_ReturnType(std::make_pair(a, expressions::make_scalar_wrapper(b)))))
4530  {
4531  return Mod_ReturnType(std::make_pair(a, expressions::make_scalar_wrapper(b)));
4532  }
4533 
4534  typedef void Add_ReturnType;
4535  typedef void Sub_ReturnType;
4536  typedef void CwMul_ReturnType;
4537  typedef void CwDiv_ReturnType;
4538  typedef void CwMod_ReturnType;
4539  };
4540 
4541  template<typename A, typename B>
4542  class BinaryMatrixOperationImpl_Impl<A, true, true, B, false, true>
4543  {
4544  public:
4546  std::pair<expressions::ConstMatrixWrapper<A>,
4548 
4549  inline static Mul_ReturnType multiply(const A & a, const B & b)
4550  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4551  expressions::make_scalar_wrapper(b)))))
4552  {
4553  return Mul_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4554  expressions::make_scalar_wrapper(b)));
4555  }
4556 
4558  std::pair<expressions::ConstMatrixWrapper<A>,
4560 
4561  inline static Div_ReturnType divide(const A & a, const B & b)
4562  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Div_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4563  expressions::make_scalar_wrapper(b)))))
4564  {
4565  return Div_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4566  expressions::make_scalar_wrapper(b)));
4567  }
4568 
4570  std::pair<expressions::ConstMatrixWrapper<A>,
4572 
4573  inline static Mod_ReturnType modulo(const A & a, const B & b)
4574  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Mod_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4575  expressions::make_scalar_wrapper(b)))))
4576  {
4577  return Mod_ReturnType(std::make_pair(expressions::make_matrix_wrapper(a),
4578  expressions::make_scalar_wrapper(b)));
4579  }
4580 
4581  typedef void Add_ReturnType;
4582  typedef void Sub_ReturnType;
4583  typedef void CwMul_ReturnType;
4584  typedef void CwDiv_ReturnType;
4585  typedef void CwMod_ReturnType;
4586  };
4587 
4588  template<typename A, typename B>
4590  {
4591  public:
4594  typedef typename BMOII::Mul_ReturnType Mul_ReturnType;
4595  typedef typename BMOII::Div_ReturnType Div_ReturnType;
4596  typedef typename BMOII::Mod_ReturnType Mod_ReturnType;
4597  typedef typename BMOII::Add_ReturnType Add_ReturnType;
4598  typedef typename BMOII::Sub_ReturnType Sub_ReturnType;
4599  typedef typename BMOII::CwMul_ReturnType CwMul_ReturnType;
4600  typedef typename BMOII::CwDiv_ReturnType CwDiv_ReturnType;
4601  typedef typename BMOII::CwMod_ReturnType CwMod_ReturnType;
4602 
4603  inline static Mul_ReturnType multiply(const A & a, const B & b)
4604  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(BMOII::multiply(a, b)))
4605  {
4606  return BMOII::multiply(a, b);
4607  }
4608 
4609  inline static Div_ReturnType divide(const A & a, const B & b)
4610  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(BMOII::divide(a, b)))
4611  {
4612  return BMOII::divide(a, b);
4613  }
4614 
4615  inline static Mod_ReturnType modulo(const A & a, const B & b)
4616  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(BMOII::modulo(a, b)))
4617  {
4618  return BMOII::modulo(a, b);
4619  }
4620 
4621  inline static Add_ReturnType add(const A & a, const B & b)
4622  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(BMOII::add(a, b)))
4623  {
4624  return BMOII::add(a, b);
4625  }
4626 
4627  inline static Sub_ReturnType sub(const A & a, const B & b)
4628  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(BMOII::sub(a, b)))
4629  {
4630  return BMOII::sub(a, b);
4631  }
4632 
4633  inline static CwMul_ReturnType componentwise_mul(const A & a, const B & b)
4634  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(BMOII::componentwise_mul(a, b)))
4635  {
4636  return BMOII::componentwise_mul(a, b);
4637  }
4638 
4639  inline static CwDiv_ReturnType componentwise_div(const A & a, const B & b)
4640  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(BMOII::componentwise_div(a, b)))
4641  {
4642  return BMOII::componentwise_div(a, b);
4643  }
4644 
4645  inline static CwMod_ReturnType componentwise_mod(const A & a, const B & b)
4646  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(BMOII::componentwise_mod(a, b)))
4647  {
4648  return BMOII::componentwise_mod(a, b);
4649  }
4650  };
4651 
4652  // operations: unary operations
4653 
4654  template<typename A, bool A_needs_wrapper>
4656 
4657  template<typename A>
4659  {
4660  public:
4662 
4663  inline static Neg_ReturnType negate(const A & a)
4664  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Neg_ReturnType(a)))
4665  {
4666  return Neg_ReturnType(a);
4667  }
4668  };
4669 
4670  template<typename A>
4672  {
4673  public:
4675 
4676  inline static Neg_ReturnType negate(const A & a)
4677  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(Neg_ReturnType(expressions::make_matrix_wrapper(a))))
4678  {
4679  return Neg_ReturnType(expressions::make_matrix_wrapper(a));
4680  }
4681  };
4682 
4683  template<typename A>
4685  {
4686  public:
4688  typedef typename UMOII::Neg_ReturnType Neg_ReturnType;
4689 
4690  inline static Neg_ReturnType negate(const A & a)
4691  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(UMOII::negate(a)))
4692  {
4693  return UMOII::negate(a);
4694  }
4695  };
4696 
4697  // operations: assign-operations
4698 
4699  template<typename MT1, typename MT2>
4701  {
4702  private:
4703  // A += B
4704 
4705  template<typename MT2_>
4706  static inline void add_assign_impl(const MT1 & A, const MT2_ & B)
4707  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate()) && noexcept(B.enumerate()) &&
4708  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().has_current()) &&
4709  noexcept(helper::make_type_lvalue<typename MT2_::ConstEnumerator>().has_current()) &&
4710  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().next()) &&
4711  noexcept(helper::make_type_lvalue<typename MT2_::ConstEnumerator>().next()) &&
4712  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().current() += helper::make_type_lvalue<typename MT2_::ConstEnumerator>().current()))
4713  {
4714  typename MT1::Enumerator eA = A.enumerate();
4715  typename MT2_::ConstEnumerator eB = B.enumerate();
4716  for (; eA.has_current(); eA.next(), eB.next())
4717  eA.current() += eB.current();
4718  }
4719 
4720  // A -= B
4721 
4722  template<typename MT2_>
4723  static inline void sub_assign_impl(const MT1 & A, const MT2_ & B)
4724  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate()) && noexcept(B.enumerate()) &&
4725  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().has_current()) &&
4726  noexcept(helper::make_type_lvalue<typename MT2_::ConstEnumerator>().has_current()) &&
4727  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().next()) &&
4728  noexcept(helper::make_type_lvalue<typename MT2_::ConstEnumerator>().next()) &&
4729  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().current() -= helper::make_type_lvalue<typename MT2_::ConstEnumerator>().current()))
4730  {
4731  typename MT1::Enumerator eA = A.enumerate();
4732  typename MT2_::ConstEnumerator eB = B.enumerate();
4733  for (; eA.has_current(); eA.next(), eB.next())
4734  eA.current() -= eB.current();
4735  }
4736 
4737  // A *= B
4738 
4739  template<typename MT2_>
4740  static inline void mul_assign(helper::BoolToType<true>, const MT1 & A, const MT2_ & B) // A *= B with B matrix
4741 #if __cplusplus >= 201103L
4742  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT2_>::cols, typename MatrixInfo<MT1>::StorageTraits>(A * B)) &&
4743  noexcept(A = std::move(math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT2_>::cols, typename MatrixInfo<MT1>::StorageTraits>(A * B))))
4744 #endif
4745  {
4746  assert(A.cols() == B.rows());
4747  // matrix-matrix multiplication
4749  (static_cast<size_type>(MatrixInfo<MT1>::cols) == static_cast<size_type>(MatrixInfo<MT2_>::rows)), FormatsDoNotMatch);
4751  temporary = A * B;
4752 #if __cplusplus >= 201103L
4753  A = std::move(temporary);
4754 #else
4755  swap(A, temporary);
4756 #endif
4757  }
4758 
4759  template<typename MT2_>
4760  static inline void mul_assign_cw_impl(const MT1 & A, const MT2_ & B)
4761  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate()) &&
4762  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().has_current()) &&
4763  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().next()) &&
4764  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().current() /= B))
4765  {
4766  typename MT1::Enumerator eA = A.enumerate();
4767  for (; eA.has_current(); eA.next())
4768  eA.current() *= B;
4769  }
4770 
4771  template<typename MT2_>
4772  static inline void mul_assign(helper::BoolToType<false>, const MT1 & A, const MT2_ & B) // A *= B with B scalar
4773  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(mul_assign_cw_impl(A, B)))
4774  {
4775  // matrix-scalar multiplication
4776  mul_assign_cw_impl(A, B);
4777  }
4778 
4779  // A /= B
4780 
4781  template<typename MT2_>
4782  static inline void div_assign_impl(const MT1 & A, const MT2_ & B)
4783  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate()) &&
4784  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().has_current()) &&
4785  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().next()) &&
4786  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().current() /= B))
4787  {
4788  typename MT1::Enumerator eA = A.enumerate();
4789  for (; eA.has_current(); eA.next())
4790  eA.current() /= B;
4791  }
4792 
4793  // A %= B
4794 
4795  template<typename MT2_>
4796  static inline void mod_assign_impl(const MT1 & A, const MT2_ & B)
4797  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(A.enumerate()) &&
4798  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().has_current()) &&
4799  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().next()) &&
4800  noexcept(helper::make_type_lvalue<typename MT1::Enumerator>().current() %= B))
4801  {
4802  typename MT1::Enumerator eA = A.enumerate();
4803  for (; eA.has_current(); eA.next())
4804  eA.current() /= B;
4805  }
4806 
4807  public:
4808  static inline const MT1 & add_assign(const MT1 & A, const MT2 & B) // A += B
4809  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(MatrixInfo<MT2>::use_temporary_on_evaluate ?
4810  (noexcept(math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT1>::cols, typename MatrixInfo<MT1>::StorageTraits>(A * B)) &&
4811  noexcept(add_assign_impl(A, helper::make_type_lvalue<math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT1>::cols, typename MatrixInfo<MT1>::StorageTraits> >()))) :
4812  (noexcept(add_assign_impl(A, B)) &&
4813  noexcept(math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT1>::cols, typename MatrixInfo<MT1>::StorageTraits>(A * B)) &&
4814  noexcept(add_assign_impl(A, helper::make_type_lvalue<math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT1>::cols, typename MatrixInfo<MT1>::StorageTraits> >()))))
4815  {
4820  (static_cast<size_type>(MatrixInfo<MT1>::rows) == static_cast<size_type>(MatrixInfo<MT2>::rows)), FormatsDoNotMatch);
4822  (static_cast<size_type>(MatrixInfo<MT1>::cols) == static_cast<size_type>(MatrixInfo<MT2>::cols)), FormatsDoNotMatch);
4823  assert(A.rows() == B.rows());
4824  assert(A.cols() == B.cols());
4825  if (MatrixInfo<MT2>::use_temporary_on_evaluate && A.test_involvement(B))
4826  {
4828  temporary = B;
4829  add_assign_impl(A, temporary);
4830  }
4831  else
4832  add_assign_impl(A, B);
4833  return A;
4834  }
4835 
4836  static inline const MT1 & sub_assign(const MT1 & A, const MT2 & B) // A -= B
4837  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(MatrixInfo<MT2>::use_temporary_on_evaluate ?
4838  (noexcept(math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT1>::cols, typename MatrixInfo<MT1>::StorageTraits>(A * B)) &&
4839  noexcept(sub_assign_impl(A, helper::make_type_lvalue<math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT1>::cols, typename MatrixInfo<MT1>::StorageTraits> >()))) :
4840  (noexcept(sub_assign_impl(A, B)) &&
4841  noexcept(math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT1>::cols, typename MatrixInfo<MT1>::StorageTraits>(A * B)) &&
4842  noexcept(sub_assign_impl(A, helper::make_type_lvalue<math_matrix<typename MatrixInfo<MT1>::Type, MatrixInfo<MT1>::rows, MatrixInfo<MT1>::cols, typename MatrixInfo<MT1>::StorageTraits> >()))))
4843  {
4848  (static_cast<size_type>(MatrixInfo<MT1>::rows) == static_cast<size_type>(MatrixInfo<MT2>::rows)), FormatsDoNotMatch);
4850  (static_cast<size_type>(MatrixInfo<MT1>::cols) == static_cast<size_type>(MatrixInfo<MT2>::cols)), FormatsDoNotMatch);
4851  assert(A.rows() == B.rows());
4852  assert(A.cols() == B.cols());
4853  if (MatrixInfo<MT2>::use_temporary_on_evaluate && A.test_involvement(B))
4854  {
4856  temporary = B;
4857  sub_assign_impl(A, temporary);
4858  }
4859  else
4860  sub_assign_impl(A, B);
4861  return A;
4862  }
4863 
4864  static inline const MT1 & mul_assign(const MT1 & A, const MT2 & B) // A *= B
4865  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(mul_assign(helper::BoolToType<MatrixInfo<MT2>::is_matrix>(), A, B)))
4866  {
4870  mul_assign(helper::BoolToType<MatrixInfo<MT2>::is_matrix>(), A, B);
4871  return A;
4872  }
4873 
4874  static inline const MT1 & div_assign(const MT1 & A, const MT2 & B) // A /= B
4875  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(div_assign_impl(A, B)))
4876  {
4880  div_assign_impl(A, B);
4881  return A;
4882  }
4883 
4884  static inline const MT1 & mod_assign(const MT1 & A, const MT2 & B) // A %= B
4885  PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(mod_assign_impl(A, B)))
4886  {
4890  mod_assign_impl(A, B);
4891  return A;
4892  }
4893  };
4894  }
4895  }
4896 }
4897 
4898 #endif
void assign(const implementation::expressions::expr< DestOp, DestData > &destination, const implementation::expressions::expr< SourceOp, SourceData > &source, helper::BoolToType< move > ittm)
Assigns the content of matrix source to matrix destination. Allows to force move. ...
implementation::BinaryMatrixOperationImpl< base_matrix< T, Rows, Cols, ST, true >, MT >::CwMod_ReturnType componentwise_mod(const base_matrix< T, Rows, Cols, ST, true > &A, const MT &B) PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(implementation::BinaryMatrixOperationImpl< base_matrix< T, Rows, Cols, ST, true >, MT >::componentwise_mod(A, B)))
Computes the componentwise modulo of A with B.
T & make_type_lvalue() PLLL_INTERNAL_NOTHROW_POSTFIX_ENFORCE
This is a pseudo-template which should only be used in expressions which are never evaluated...
implementation::binary_operation_impl< typename helper::remove_decorations< A >::Result, typename helper::remove_decorations< B >::Result, Op >::ResultType ResultType
Definition: arithmetic.hpp:110
void swap(base_matrix< T, R, C, ST, MO > &A, base_matrix< T, R, C, ST, MO > &B) PLLL_INTERNAL_NOTHROW_POSTFIX_INLINE
Swaps matrices A and B efficiently.
Definition: matrix-ops2.hpp:49
#define PLLL_INTERNAL_STATIC_CHECK(condition, IdentifierWhichIsAMessage)
Definition: helper.hpp:83
Provides information on the result of a binary arithmetic operation.
Definition: arithmetic.hpp:93
void add(base_matrix< T, Rows, Cols, ST, true > &result, const MT1 &A, const MT2 &B) PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(assign(result, implementation::BinaryMatrixOperationImpl< MT1, MT2 >::add(A, B))))
Computes the sum of A and B and stores the result in result.
Represents a matrix with coefficients in T.
Definition: matrix.hpp:165
void setZero(Integer &)
Sets the given integer to zero.
implementation::remove_decorations_impl< A >::result Result
The stripped type.
Definition: helper.hpp:289
implementation::unary_operation_impl< typename helper::remove_decorations< A >::Result, Op >::IntermediateType IntermediateType
Definition: arithmetic.hpp:166
implementation::binary_operation_impl< typename helper::remove_decorations< A >::Result, typename helper::remove_decorations< B >::Result, Op >::IntermediateType IntermediateType
Definition: arithmetic.hpp:114
Conversion from compile-time known bools to types.
Definition: helper.hpp:220
implementation::BinaryMatrixOperationImpl< base_matrix< T, Rows, Cols, ST, true >, MT >::CwDiv_ReturnType componentwise_div(const base_matrix< T, Rows, Cols, ST, true > &A, const MT &B) PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(implementation::BinaryMatrixOperationImpl< base_matrix< T, Rows, Cols, ST, true >, MT >::componentwise_div(A, B)))
Computes the componentwise division of A with B.
unsigned int size_type
Definition: matrix.hpp:141
implementation::BinaryMatrixOperationImpl< base_matrix< T, Rows, Cols, ST, true >, MT >::CwMul_ReturnType componentwise_mul(const base_matrix< T, Rows, Cols, ST, true > &A, const MT &B) PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(implementation::BinaryMatrixOperationImpl< base_matrix< T, Rows, Cols, ST, true >, MT >::componentwise_mul(A, B)))
Computes the componentwise multiplication of A with B.
void add(Integer &r, const Integer &a, const Integer &b)
Adds a and b and stores the result in r.
implementation::unary_operation_impl< typename helper::remove_decorations< A >::Result, Op >::ResultType ResultType
Definition: arithmetic.hpp:164
A type selector template.
Definition: helper.hpp:120
void sub(base_matrix< T, Rows, Cols, ST, true > &result, const MT1 &A, const MT2 &B) PLLL_INTERNAL_NOTHROW_POSTFIX_CONDITIONAL(noexcept(assign(result, implementation::BinaryMatrixOperationImpl< MT1, MT2 >::sub(A, B))))
Computes the difference of A and B and stores the result in result.
Represents a math matrix with coefficients in T.
Definition: matrix.hpp:210
Main arithmetic header.
void sub(Integer &r, const Integer &a, const Integer &b)
Subtracts b from a and stores the result in r.