So-Bogus
A c++ sparse block matrix library aimed at Second Order cone problems
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
BlockBindings.hpp
1 /*
2  * This file is part of bogus, a C++ sparse block matrix library.
3  *
4  * Copyright 2013 Gilles Daviet <gdaviet@gmail.com>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
10 
17 #ifndef BLOCK_EIGENBINDINGS_HPP
18 #define BLOCK_EIGENBINDINGS_HPP
19 
20 #include <Eigen/Core>
21 
22 #ifndef BOGUS_BLOCK_WITHOUT_EIGEN_SPARSE
23 #include "SparseHeader.hpp"
24 #endif
25 
26 #include "../Block/BlockMatrixBase.hpp"
27 #include "../Block/Expressions.hpp"
28 
29 #ifndef BOGUS_BLOCK_WITHOUT_LINEAR_SOLVERS
30 #include "EigenLinearSolvers.hpp"
31 #ifndef BOGUS_BLOCK_WITHOUT_EIGEN_SPARSE
32 #include "EigenSparseLinearSolvers.hpp"
33 #endif
34 #endif
35 
36 #include "../Utils/CppTools.hpp"
37 
38 #define BOGUS_EIGEN_NEW_EXPRESSIONS EIGEN_VERSION_AT_LEAST(3,2,90)
39 
40 namespace bogus
41 {
42 
43 // transpose_block, is_zero, resize, set_identity
44 
45 template< typename EigenDerived >
46 inline bool is_zero ( const Eigen::MatrixBase< EigenDerived >& block,
47  typename EigenDerived::Scalar precision )
48 {
49  return block.isZero( precision ) ;
50 }
51 
52 template< typename EigenDerived >
53 inline void set_zero ( Eigen::MatrixBase< EigenDerived >& block )
54 {
55  block.derived().setZero( ) ;
56 }
57 
58 template< typename EigenDerived >
59 inline void set_identity ( Eigen::MatrixBase< EigenDerived >& block )
60 {
61  block.derived().setIdentity( ) ;
62 }
63 
64 template< typename EigenDerived >
65 inline void resize ( Eigen::MatrixBase< EigenDerived >& block, int rows, int cols )
66 {
67  block.derived().resize( rows, cols ) ;
68 }
69 
70 template< typename EigenDerived >
71 inline const typename EigenDerived::Scalar* data_pointer ( const Eigen::MatrixBase< EigenDerived >& block )
72 {
73  return block.derived().data() ;
74 }
75 
76 #ifndef BOGUS_BLOCK_WITHOUT_EIGEN_SPARSE
77 
78 #if !BOGUS_EIGEN_NEW_EXPRESSIONS
79 template < typename BlockT >
80 struct BlockTransposeTraits< Eigen::SparseMatrixBase < BlockT > > {
81  typedef const Eigen::Transpose< const BlockT > ReturnType ;
82 } ;
83 template<typename _Scalar, int _Flags, typename _Index>
84 struct BlockTransposeTraits< Eigen::SparseMatrix < _Scalar, _Flags, _Index > >
85  : public BlockTransposeTraits< Eigen::SparseMatrixBase< Eigen::SparseMatrix < _Scalar, _Flags, _Index > > >
86 {} ;
87 template<typename _Scalar, int _Flags, typename _Index>
88 struct BlockTransposeTraits< Eigen::SparseVector < _Scalar, _Flags, _Index > >
89  : public BlockTransposeTraits< Eigen::SparseMatrixBase< Eigen::SparseVector < _Scalar, _Flags, _Index > > >
90 {} ;
91 template<typename _Scalar, int _Flags, typename _Index>
92 struct BlockTransposeTraits< Eigen::MappedSparseMatrix < _Scalar, _Flags, _Index > >
93  : public BlockTransposeTraits< Eigen::SparseMatrixBase< Eigen::MappedSparseMatrix < _Scalar, _Flags, _Index > > >
94 {} ;
95 
96 template< typename EigenDerived >
97 inline const Eigen::Transpose< const EigenDerived >
98 transpose_block( const Eigen::SparseMatrixBase< EigenDerived >& block )
99 {
100  return block.transpose() ;
101 }
102 #endif
103 
104 template< typename EigenDerived >
105 inline bool is_zero ( const Eigen::SparseMatrixBase< EigenDerived >& block,
106  typename EigenDerived::Scalar precision )
107 {
108  return block.isZero( precision ) ;
109 }
110 
111 template < typename Scalar, int Options, typename Index >
112 inline void set_identity ( Eigen::SparseMatrix< Scalar, Options, Index >& block )
113 {
114  return block.setIdentity( ) ;
115 }
116 
117 template < typename Scalar, int Options, typename Index >
118 inline void resize ( Eigen::SparseMatrix< Scalar, Options, Index >& block, Index rows, Index cols )
119 {
120  block.resize( rows, cols ) ;
121 }
122 
123 #endif
124 
125 // Block traits for Eigen::Matrix
126 
127 template< typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols >
128 struct BlockTraits < Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
129 {
130  typedef _Scalar Scalar ;
131  enum {
132  RowsAtCompileTime = _Rows,
133  ColsAtCompileTime = _Cols,
135  is_row_major = !!( _Options & Eigen::RowMajor ),
136  is_self_transpose = ( _Rows == _Cols ) && ( _Rows == 1 )
137  } ;
138 
139  // Manipulates _Options so that row and column vectorz have the correct RowMajor value
140  // Should we default to _Options ^ Eigen::RowMajor ?
141  typedef Eigen::Matrix< _Scalar, _Cols, _Rows,
142  ( _Options | ((_Cols==1&&_Rows!=1)?Eigen::RowMajor:0)) & ~((_Rows==1&&_Cols!=1)?Eigen::RowMajor:0),
143  _MaxCols, _MaxRows >
144  TransposeStorageType ;
145 
146 } ;
147 
148 // Block/block product return type
149 
150 template<
151  typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols,
152  typename _Scalar2, int _Rows2, int _Cols2, int _Options2, int _MaxRows2, int _MaxCols2,
153  bool TransposeLhs, bool TransposeRhs >
155  Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>,
156  Eigen::Matrix<_Scalar2, _Rows2, _Cols2, _Options2, _MaxRows2, _MaxCols2>,
157  TransposeLhs, TransposeRhs >
158 {
159  typedef Eigen::Matrix< _Scalar,
162  _Options,
165  ReturnType ;
166 } ;
167 
168 template< typename Derived >
169 inline typename Eigen::internal::plain_matrix_type<Derived>::type
170 get_mutable_vector( const Eigen::MatrixBase< Derived > & )
171 {
172  return typename Eigen::internal::plain_matrix_type<Derived>::type() ;
173 }
174 
175 } //ns bogus
176 
177 // Matrix vector product return types and operator*
178 
179 namespace bogus {
180 namespace mv_impl {
181 
183 template< typename Derived >
184 struct EigenBlockWrapper : public Eigen::EigenBase< EigenBlockWrapper< Derived > >
185 {
186  typedef EigenBlockWrapper Nested ;
189  typedef Eigen::internal::traits< EigenBlockWrapper< Derived > > Traits ;
190  typedef typename Traits::Scalar Scalar ;
191  typedef typename Traits::Index Index ;
192 
193  enum { Flags = Traits::Flags, IsVectorAtCompileTime = 0,
194  MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime,
195  MaxColsAtCompileTime = Traits::MaxColsAtCompileTime
196  } ;
197 
198  EigenBlockWrapper ( const Derived &obj_, Scalar s = 1 )
199  : obj( obj_ ), scaling(s)
200  {}
201 
202  Index rows() const { return obj.rows() ; }
203  Index cols() const { return obj.cols() ; }
204 
205  // Mult by scalar
206 
207  inline EigenBlockWrapper
208  operator*(const Scalar& scalar) const
209  { return EigenBlockWrapper( obj, scaling * scalar ) ; }
210 
211  inline friend EigenBlockWrapper
212  operator*(const Scalar& scalar, const EigenBlockWrapper& matrix)
213  { return EigenBlockWrapper( matrix.obj, matrix.scaling * scalar ) ; }
214 
215 
216  // Product with other Eigen expr
217 #if BOGUS_EIGEN_NEW_EXPRESSIONS
218  template < typename EigenDerived >
219  inline Eigen::Product< EigenBlockWrapper, EigenDerived > operator* (
220  const EigenDerived &rhs ) const
221  {
222  return Eigen::Product< EigenBlockWrapper, EigenDerived > (*this, rhs) ;
223  }
224  template < typename EigenDerived >
225  friend inline Eigen::Product< EigenDerived, EigenBlockWrapper > operator* (
226  const EigenDerived &lhs, const EigenBlockWrapper &matrix )
227  {
228  return Eigen::Product< EigenDerived, EigenBlockWrapper > (lhs, matrix) ;
229  }
230 #endif
231 
232  const Derived &obj ;
233  const Scalar scaling ;
234 };
235 
237 
238 template< typename Lhs, typename Rhs >
240 
241 #if BOGUS_EIGEN_NEW_EXPRESSIONS
242 template < typename Lhs, typename Rhs >
243 struct BlockEigenProduct
244  : public Eigen::Product< Lhs, Rhs >
245 {
246  typedef Eigen::Product< Lhs, Rhs > Base ;
247 
248  BlockEigenProduct( const Lhs& lhs, const Rhs& rhs )
249  : Base( lhs, rhs)
250  {}
251 } ;
252 #else
253 
254 template < typename Lhs, typename Rhs >
256  : public Eigen::ProductBase< BlockEigenProduct< Lhs, Rhs>, Lhs, Rhs >
257 {
258  typedef Eigen::ProductBase< BlockEigenProduct, Lhs, Rhs > Base ;
259 
260  BlockEigenProduct( const Lhs& lhs, const Rhs& rhs )
261  : Base( lhs, rhs)
262  {}
263 
264  EIGEN_DENSE_PUBLIC_INTERFACE( BlockEigenProduct )
265  using Base::m_lhs;
266  using Base::m_rhs;
268 
269  template<typename Dest> inline void evalTo(Dest& dst) const
270  {
271  product_impl::evalTo( dst, m_lhs, this->m_rhs ) ;
272  }
273  template<typename Dest> inline void scaleAndAddTo(Dest& dst, Scalar alpha) const
274  {
275  product_impl::scaleAndAddTo( dst, m_lhs, m_rhs, alpha ) ;
276  }
277 };
278 #endif
279 
280 template< typename Derived, typename EigenDerived >
281 BlockEigenProduct< EigenBlockWrapper< Derived >, EigenDerived > block_eigen_product(
282  const Derived &matrix, const EigenDerived &vector, typename Derived::Scalar scaling = 1 )
283 {
284  return BlockEigenProduct< EigenBlockWrapper< Derived >, EigenDerived > ( EigenBlockWrapper< Derived >(matrix, scaling), vector ) ;
285 }
286 
287 template< typename Derived, typename EigenDerived >
288 BlockEigenProduct< EigenDerived, EigenBlockWrapper< Derived > > eigen_block_product(
289  const EigenDerived &vector, const Derived &matrix, typename Derived::Scalar scaling = 1 )
290 {
291  return BlockEigenProduct< EigenDerived, EigenBlockWrapper< Derived > > ( vector, EigenBlockWrapper< Derived >(matrix, scaling) ) ;
292 }
293 
294 template<typename Derived, typename EigenDerived >
295 struct block_product_impl< bogus::mv_impl::EigenBlockWrapper<Derived>, EigenDerived >
296 {
298  typedef EigenDerived Rhs ;
299  typedef typename Derived::Scalar Scalar;
300 
301  template<typename Dst>
302  static void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
303  {
304  lhs.obj.template multiply< false >( rhs.derived(), dst, lhs.scaling, 0 ) ;
305  }
306  template<typename Dst>
307  static void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
308  {
309  lhs.obj.template multiply< false >( rhs.derived(), dst, alpha*lhs.scaling, 1 ) ;
310  }
311 };
312 
313 template<typename Derived, typename EigenDerived >
314  struct block_product_impl< EigenDerived, bogus::mv_impl::EigenBlockWrapper<Derived> >
315 {
316  typedef EigenDerived Lhs ;
318  typedef typename Derived::Scalar Scalar;
319 
320  template<typename Dst>
321  static void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
322  {
323  Eigen::Transpose< Dst > transposed( dst.transpose() ) ;
324  rhs.obj.template multiply< true >( lhs.transpose(), transposed, rhs.scaling, 0 ) ;
325  }
326  template<typename Dst>
327  static void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
328  {
329  Eigen::Transpose< Dst > transposed( dst.transpose() ) ;
330  rhs.obj.template multiply< true >( lhs.transpose(), transposed, alpha * rhs.scaling, 1 ) ;
331  }
332 };
333 
334 } //namespace mv_impl
335 } //namespace bogus
336 
337 
338 #if BOGUS_EIGEN_NEW_EXPRESSIONS
339 namespace Eigen {
340 namespace internal {
341 
342 template<typename Derived, typename EigenDerived, int ProductType >
343 struct generic_product_impl< bogus::mv_impl::EigenBlockWrapper<Derived>, EigenDerived, SparseShape, DenseShape, ProductType>
344  : public generic_product_impl_base <
345  bogus::mv_impl::EigenBlockWrapper<Derived>, EigenDerived,
346  generic_product_impl< bogus::mv_impl::EigenBlockWrapper<Derived>, EigenDerived, SparseShape, DenseShape, ProductType > >
347 {
349  typedef EigenDerived Rhs ;
350  typedef typename Derived::Scalar Scalar;
351 
352  typedef typename nested_eval<Rhs,Dynamic>::type RhsNested;
354 
355  template<typename Dst>
356  static void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
357  {
358  RhsNested rhsNested( rhs ) ;
359  product_impl::evalTo( dst, lhs, rhsNested ) ;
360  }
361  template<typename Dst>
362  static void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, Scalar alpha)
363  {
364  RhsNested rhsNested( rhs ) ;
365  product_impl::scaleAndAddTo( dst, lhs, rhsNested, alpha ) ;
366  }
367 };
368 
369 template<typename Derived, typename EigenDerived, int ProductType >
370 struct generic_product_impl< EigenDerived, bogus::mv_impl::EigenBlockWrapper<Derived>, DenseShape, SparseShape, ProductType >
371  : public generic_product_impl_base <
372  EigenDerived, bogus::mv_impl::EigenBlockWrapper<Derived>,
373  generic_product_impl< EigenDerived, bogus::mv_impl::EigenBlockWrapper<Derived>, DenseShape, SparseShape, ProductType > >
374 {
375  typedef EigenDerived Lhs ;
377  typedef typename Derived::Scalar Scalar;
378 
379  typedef typename nested_eval<Lhs,Dynamic>::type LhsNested;
381 
382  template<typename Dst>
383  static void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
384  {
385  LhsNested lhsNested(lhs);
386  product_impl::evalTo( dst, lhsNested, rhs) ;
387  }
388  template<typename Dst>
389  static void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
390  {
391  LhsNested lhsNested(lhs);
392  product_impl::scaleAndAddTo( dst, lhsNested, rhs, alpha ) ;
393  }
394 };
395 
396 // (A * B * s ) -> ( (s*A) * B )
397 template<typename Derived, typename Rhs, typename Scalar>
398 struct evaluator<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const Product<bogus::mv_impl::EigenBlockWrapper<Derived>, Rhs, DefaultProduct> > >
399  : public evaluator<Product<bogus::mv_impl::EigenBlockWrapper<Derived>, Rhs, DefaultProduct> >
400 {
401  typedef CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const Product<bogus::mv_impl::EigenBlockWrapper<Derived>, Rhs, DefaultProduct> > XprType;
402  typedef evaluator<Product<bogus::mv_impl::EigenBlockWrapper<Derived>, Rhs, DefaultProduct> > Base;
403 
404  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
405  : Base( ( xpr.functor().m_other * xpr.nestedExpression().lhs() ) * xpr.nestedExpression().rhs() )
406  {}
407 };
408 
409 } //internal
410 } //Eigen
411 #endif
412 
413 
414 
415 // Eigen traits for our new structs
416 namespace Eigen{
417 namespace internal {
418 
419 template < typename Lhs, typename Rhs >
420 struct traits< bogus::mv_impl::BlockEigenProduct< Lhs, Rhs > >
421 #if BOGUS_EIGEN_NEW_EXPRESSIONS
422  : public traits< typename bogus::mv_impl::BlockEigenProduct< Lhs, Rhs >::Base >
423  #else
424  : public traits< ProductBase< bogus::mv_impl::BlockEigenProduct< Lhs, Rhs >, Lhs, Rhs > >
425  #endif
426 {
427  typedef Dense StorageKind;
428 } ;
429 
430 template<typename Derived>
431 struct traits<bogus::mv_impl::EigenBlockWrapper<Derived> >
432 {
433  typedef typename Derived::Scalar Scalar;
434  typedef typename Derived::Index Index;
435  typedef typename Derived::Index StorageIndex;
436 #if BOGUS_EIGEN_NEW_EXPRESSIONS
437  typedef Sparse StorageKind;
438 #else
439  typedef Dense StorageKind;
440 #endif
441  typedef MatrixXpr XprKind;
442  enum {
443  RowsAtCompileTime = Dynamic,
444  ColsAtCompileTime = Dynamic,
445  MaxRowsAtCompileTime = Dynamic,
446  MaxColsAtCompileTime = Dynamic,
447  Flags = 0
448  };
449 };
450 }
451 
452 } //namespace Eigen
453 
454 
455 // Matrix-Vector operators
456 
457 namespace bogus{
458 
459 template < typename Derived, typename EigenDerived >
460 mv_impl::BlockEigenProduct< mv_impl::EigenBlockWrapper<Derived>, EigenDerived > operator* (
461  const BlockObjectBase< Derived >& lhs,
462  const Eigen::MatrixBase< EigenDerived > &rhs )
463 {
464  assert( rhs.rows() == lhs.cols() ) ;
465  return mv_impl::block_eigen_product ( lhs.derived(), rhs.derived() ) ;
466 }
467 
468 template < typename Derived, typename EigenDerived >
469 mv_impl::BlockEigenProduct< mv_impl::EigenBlockWrapper<Derived>, EigenDerived > operator* (
470  const Scaling< Derived >& lhs,
471  const Eigen::MatrixBase< EigenDerived > &rhs )
472 {
473  assert( rhs.rows() == lhs.cols() ) ;
474  return mv_impl::block_eigen_product ( lhs.operand.object, rhs.derived(), lhs.operand.scaling ) ;
475 }
476 
477 template < typename Derived, typename EigenDerived >
478 mv_impl::BlockEigenProduct< EigenDerived, mv_impl::EigenBlockWrapper<Derived> > operator* (
479  const Eigen::MatrixBase< EigenDerived > &lhs,
480  const BlockObjectBase< Derived >& rhs )
481 {
482  assert( lhs.cols() == rhs.rows() ) ;
483  return mv_impl::eigen_block_product ( lhs.derived(), rhs.derived() ) ;
484 }
485 
486 template < typename Derived, typename EigenDerived >
487 mv_impl::BlockEigenProduct< EigenDerived, mv_impl::EigenBlockWrapper<Derived> > operator* (
488  const Eigen::MatrixBase< EigenDerived > &lhs,
489  const Scaling< Derived >& rhs )
490 {
491  assert( lhs.cols() == rhs.rows() ) ;
492  return mv_impl::eigen_block_product ( lhs.derived(), rhs.operand.object, rhs.operand.scaling ) ;
493 }
494 
495 
496 } //namespace bogus
497 
498 #endif // EIGENBINDINGS_HPP
SparseBlockMatrix / Dense producty expression.
Definition: BlockBindings.hpp:239
Definition: BlockBindings.hpp:255
EnableIf< BlockTraits< SelfTransposeT >::is_self_transpose, const SelfTransposeT & >::ReturnType transpose_block(const SelfTransposeT &block)
Specialization of transpose_block() for self-adjoint types.
Definition: Access.hpp:25
Number of rows spanned by a block at compile time ; useful for efficient segmentation.
Definition: Traits.hpp:37
Defines the return type of the product of two blocks potentially transposed.
Definition: Traits.hpp:64
Whether this block is equal to its transpose.
Definition: Traits.hpp:46
Definition: Traits.hpp:29
Ordering inside the block ; only useful uses_plain_array_storage is true.
Definition: Traits.hpp:44
Can be set to true if &quot;const Scalar* data_pointer( const BlockType&amp; )&quot; exist.
Definition: Traits.hpp:42
Number of cols spanned by a block at compile time ; useful for efficient segmentation.
Definition: Traits.hpp:39
Definition: CppTools.hpp:49
Wrapper so our SparseBlockMatrix can be used inside Eigen expressions.
Definition: BlockBindings.hpp:184
Defines the return type of an associated transpose_block( const BlockType&amp; ) function.
Definition: Traits.hpp:55