Boost logo

Ublas :

Subject: [ublas] matrix_range for matrix
From: pmamales_at_[hidden]
Date: 2013-07-05 10:51:02


In order to accommodate for special memory layout for FORTRAN-type matrices I need to use a "matrix" which is really a ublas::matrix_range on a
ublas::matrix ( memory has to be aligned on 32-byte memory and actually every column of the matrix has to use this kind of boundary ).
In order to do this, I am defining my own ublas-conformant type (called MatrixGeneralT and declared as a ublas::matrix_expression) which has the same template arguments as the ublas::matrix and defines
the type-"interface" of a matrix range. To make things "happen" I create an automatic conversion from my class to the ublas::matrix_range.
However, when I try, as a first test, to calculate the product of 2 matrices, the matrix_matrix_binary constructor fails to convert my class to matrix_range !
Unless, I have done something that c++ forbids ( which I don't think, since tried the "trick" with toy classes ) there must be something in ublas preventing this from
working.
Any ideas/input will be greatly appreciated.
TIA for your help,
Petros
ps: I use intel compiler 12.1 on windows 7 64bit plugged into msvc2010 ( hence the stl "flavor" ) and C++0x.

I supply here a pseudo code for anyone interested in it :
#include <boost/numeric/ublas/matrix_expression.hpp>
template < typename _T, typename _L = ublas::column_major, typename _A = ublas::unbounded_array<_T> >
class MatrixGeneralT
        :public ublas::matrix_expression< MatrixGeneralT<_T, _L, _A> >
{
        size_t ld_ ;

        size_t
                determineLDA (
                        const size_t nRows
                        , const bool mklLeadingDimension
        ) {
                if ( ! mklLeadingDimension )
                        return ( ld_ = nRows ) ;
                ld_ = nRows ;
        // the nbr of bytes per lda should be divisible by MKL::LDA_DIVISOR_IN_BYTES.
                size_t bytesNbrRows =
                        nRows * sizeof( _T ) ;
                const ldiv_t qr =
                        div( long(bytesNbrRows), long( 32/*MKL::LDA_DIVISOR_IN_BYTES*/ ) ) ;
        //if not, resize lda so that this is true.
                if ( qr.rem != 0 )
                        bytesNbrRows =
                                ( qr.quot + 1 ) * 32 /*MKL::LDA_DIVISOR_IN_BYTES */;
        // but avoid the bad dimension ( e.g. 2048)
                while ( bytesNbrRows % MKL::LDA_DIVISOR_IN_BYTES_FORBITTEN == 0 )
                        bytesNbrRows += MKL::LDA_DIVISOR_IN_BYTES ;
                return
                        ( ld_ = bytesNbrRows / sizeof( _T ) ) ;
        }

        size_t size1_ ;
        size_t size2_ ;

public:
        typedef typename
                _T value_type ;
        typedef typename
                ublas::matrix< _T, _L, _A > internal_matrix_type ;
        typedef typename
                ublas::matrix_range<
                        internal_matrix_type
> matrix_range_type ;
        typedef typename
                ublas::matrix_range<
                        const internal_matrix_type
> const_matrix_range_type ;

        typedef typename internal_matrix_type M ;
        typedef typename M matrix_type;
        typedef typename M::size_type size_type;
        typedef typename M::difference_type difference_type;
        typedef typename M::const_reference const_reference;
        typedef typename boost::mpl::if_<boost::is_const<M>,
                typename M::const_reference,
                typename M::reference>::type reference;
        typedef typename boost::mpl::if_<boost::is_const<M>,
                typename M::const_closure_type,
                typename M::closure_type>::type matrix_closure_type;
        typedef typename ublas::basic_range<size_type, difference_type> range_type;

        typedef typename matrix_range_type self_type ;
        typedef const self_type const_closure_type;
        typedef self_type closure_type;
        typedef typename ublas::storage_restrict_traits<typename M::storage_category,
                ublas::dense_proxy_tag>::storage_category storage_category;
        typedef typename M::orientation_category orientation_category;

#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
        typedef indexed_iterator1<matrix_range<matrix_type>,
                                  typename subiterator1_type::iterator_category> iterator1;
        typedef indexed_iterator2<matrix_range<matrix_type>,
                                  typename subiterator2_type::iterator_category> iterator2;
        typedef indexed_const_iterator1<matrix_range<matrix_type>,
                                        typename const_subiterator1_type::iterator_category> const_iterator1;
        typedef indexed_const_iterator2<matrix_range<matrix_type>,
                                        typename const_subiterator2_type::iterator_category> const_iterator2;
#else
        class const_iterator1;
        class iterator1;
        class const_iterator2;
        class iterator2;
#endif
        typedef ublas::reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
        typedef ublas::reverse_iterator_base1<iterator1> reverse_iterator1;
        typedef ublas::reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
        typedef ublas::reverse_iterator_base2<iterator2> reverse_iterator2;
private :
        typename internal_matrix_type matrix_ ;
public :
        typedef MatrixGeneralT< _T, _L, _A> matrix_ge_self_type ;
        MatrixGeneralT( bool optimalLDA = true )
                :size1_(0), size2_(0)
        {}
        MatrixGeneralT( const size_t nbrRows,
                const size_t nbrCols = 0,
                bool optimalLDA = true
                )
                : size1_(nbrRows), size2_(nbrCols )
                , matrix_( determineLDA( nbrRows, optimalLDA), nbrCols )
        {}
        virtual ~MatrixGeneralT()
        {}

        
        template <typename _me>
        matrix_ge_self_type &
        operator = (_me const & me )
        {
                        matrix_range_type
                        (
                                matrix_
                                , ublas::range( 0, size1_ )
                                , ublas::range( 0, size2_ )
                        ) = me ;
                return
                        *this ;
        }
        operator matrix_range_type()
        {
                return
                        matrix_range_type
                        (
                                matrix_
                                , ublas::range( 0, size1_ )
                                , ublas::range( 0, size2_ )
                        )
        }
        //operator const_matrix_range_type () const {
        // return
        // const_matrix_range_type
        // (
        // matrix_
        // , ublas::range( 0, size1_ )
        // , ublas::range( 0, size2_ )
        // )
        //}

} ;

int main() {

        typedef MatrixGeneralT< double > matrix ;
        
        matrix m(3,3) ;
        ublas::vector< double > x( 3 ) ;
        x[0] = 1; x[1] = 2 ; x[2] = 3;
// matrix::matrix_range_type mr(m) ;
        m = ( ublas::outer_prod( x,x ) ) ;

        matrix m1( 3, 5 );
        matrix m2( 5, 4 ) ;
        matrix m3( 3, 4 ) ;

        m3 = ublas::prod( m1, m2 ) ;
        return
                1;
}