Re: [eigen] combine matrix blocks |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: Re: [eigen] combine matrix blocks
- From: Stefan Ulbrich <s.ulbrich@xxxxxxxxxxxxxx>
- Date: Mon, 6 Jul 2009 20:04:58 +0200
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:message-id:from:to :in-reply-to:content-type:content-transfer-encoding:mime-version :subject:date:references:x-mailer; bh=5VU/N4AQE1yP5LPJ6UyOkm4GSU79WypXUc8NPc9srew=; b=OKuAGZct4MvVYmASCiC7nxoFAgV1zkPXLsvn1IY4T+P8YwfpIrHPzLdYJaxMa5Ppxi d1lW7qE8OK1ipDun/G67r+jXpPSj30SrnXrZjQ6Rl9AllMX5cdJ2fXMmK4un9qsTtoB6 wmqF6BIIMIvxXvDISkWaLoZbOnpzZe4eXQJM8=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=message-id:from:to:in-reply-to:content-type :content-transfer-encoding:mime-version:subject:date:references :x-mailer; b=mWcYS68IaBHgL4PjEMmXWFNwNol2FVEo/vbduVgaXXMmQprFU2ffLj6kjWdQfpfMh3 FGGVSCclW0pcPVEQVLok1iA5gd4Yz9yMCE6o3g6Br5UUsWPbYr/RYJPXraoSvBH67Owp jnZOhlv3lc5n30aaWj1ZaELrl1Hmbe9oH940s=
Hi,
this is how I implemented the "Proxy" class. In MatrixBase one could
add a ::getColumnProxy (and Row,RowColumn).
In case only a partial proxy is chosen, matrix base could pass some
kind of Range Vector class which efficiently returns the index as
coeff().
Alternatively, one could do a type check at compile time if the
template parameter was a constant 'identity'.
What do you think?
cheers,
stefan
template<typename MatrixType, typename RowType, typename ColType>
class Proxy
: public MatrixBase<Proxy<MatrixType, RowType, ColType> >
{
public:
EIGEN_GENERIC_PUBLIC_INTERFACE(Proxy)
inline Proxy(const MatrixType& matrix, RowType rows, ColType cols)
: m_matrix(matrix), m_rows(rows), m_cols(cols)
{
std::cout << "Debug: " << m_rows.minCoeff() << "," <<
m_rows.maxCoeff() << "," << matrix.rows() << std::endl;
std::cout << "Debug: " << m_cols.minCoeff() << "," <<
m_cols.maxCoeff() << "," << matrix.cols() << std::endl;
ei_assert(m_rows.minCoeff() >= 0 && m_rows.maxCoeff() <
matrix.rows()
&& m_cols.minCoeff() >= 0 && m_cols.maxCoeff() <
matrix.cols());
}
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Proxy)
inline int rows() const { return m_rows.rows(); }
inline int cols() const { return m_cols.rows(); }
inline Scalar& coeffRef(int row, int col)
{
return m_matrix.const_cast_derived().coeffRef(m_rows(row),
m_cols(col));
}
inline const Scalar coeff(int row, int col) const
{
return m_matrix.coeff(m_rows(row), m_cols(col));
}
protected:
const typename MatrixType::Nested m_matrix;
const typename RowType::Nested m_rows;
const typename ColType::Nested m_cols;
};
template<typename MatrixType, typename RowType, typename ColType>
struct ei_traits<Proxy<MatrixType, RowType, ColType> >
{
typedef typename MatrixType::Scalar Scalar;
typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
enum {
RowsAtCompileTime = (MatrixType::RowsAtCompileTime != Dynamic &&
RowType::RowsAtCompileTime != Dynamic) ?
int(RowType::RowsAtCompileTime) : Dynamic,
ColsAtCompileTime = (MatrixType::ColsAtCompileTime != Dynamic &&
ColType::RowsAtCompileTime != Dynamic) ?
int(ColType::RowsAtCompileTime) : Dynamic,
MaxRowsAtCompileTime = (MatrixType::MaxRowsAtCompileTime !=
Dynamic ) ?
int(RowType::MaxRowsAtCompileTime) :
Dynamic,
MaxColsAtCompileTime = (MatrixType::MaxColsAtCompileTime !=
Dynamic ) ?
int(ColType::MaxRowsAtCompileTime) :
Dynamic,
Flags = _MatrixTypeNested::Flags & HereditaryBits,
CoeffReadCost = _MatrixTypeNested::CoeffReadCost
};
};
Am 03.07.2009 um 09:55vorm. schrieb Gael Guennebaud:
On Fri, Jul 3, 2009 at 9:12 AM, Stefan Ulbrich<s.ulbrich@xxxxxxxxxxxxxx
> wrote:
thanks for the answer. Actually, block / corner and minor don't
allow you to
select the for example the columns 1,3,4,6. The closest thing I
found in
Eigen is the Minor Class which allows to omit one row/col. I now
tried to
clone and to modificate this class but haven't finished it yet (still
problems with io.h). This class will take two row-vectors that
serve as a
proxy for the addressing of the coefficients (allows for
permutations,
repetition of elements...). What do you think: do I have to worry
about
speed using this method? Does the use of Minor result in lower speed?
Indeed this requires a novel expression with a coeff(i,j) method which
looks like:
Scalar coeff(i,j) {
return m_matrix.coeff(m_rowIndices[i], m_colIndices[j]);
}
Assuming the compiler is able to move one of the m_*Indices[] out of
the inner evaluation loop, I guess this should be quite efficient.
Regarding API I think it'd be nice to be able to only provide a list
of rows or columns. To this end, the type of m_rowIndices could be a
template parameter for which the possibilities would be any kind of
integer vectors and a special class having n operator[i] always
returning "i". Regarding the names of these additional classes and
methods, I have no clue.
In the same way I want to create a class that connects matrix with
the same
amount of rows (cols) to a single one.
yes it is quite easy to write such a matrix expression. Here is how
the coeff(i,j) method would look like:
Scalar coeff(i,j) {
if (j<m_matrixA.cols())
return m_matrixA.coeff(i,j);
else
return m_matrixB.coeff(i,j-m_matrixA.cols());
}
The problem is the "if" which will kill the performance (+ no
vectorization, etc.). So, if the memory consumption is not critical
for you I suggest you to copy the matrices to a single bigger one:
MatrixXf A, B, C;
/* ... */
A.resize(B.rows(), B.cols()+C.cols());
A << B, C;
This assignment is fast (vectorized), and then the use of A will be
fast too. Also note that this syntax is very powerful: it allows you
to assemble as many as scalars and/or matrix expressions as you want
in any direction. This is also why you have to set the size of the
matrix A manually. For instance you can also assemble B and C
vertically:
A.resize(B.rows()+C.rows(), B.cols());
A << B, C;
See the tutorial for other more fancy examples.
cheers,
Gael
cheers,
stefan
Am 02.07.2009 um 19:46nachm. schrieb Thomas Capricelli:
Erm, all of this seems already available,have you read the tutorial
http://eigen.tuxfamily.org/dox/TutorialCore.html
especially the part
http://eigen.tuxfamily.org/dox/TutorialCore.html#TutorialCoreMatrixBlocks
Anything specific you think about that can not currently be done ?
regards,
Thomas
In data giovedì 02 luglio 2009 18:47:16, Stefan Ulbrich ha scritto:
: > Hello,
in matlab you can select a partial matrix by explicitly specifying
which cols and rows to take from the original matrix, e.g. with
A([1,3],[2 4])
further, it would be interesting to combine blocks into a matrix
that
serves as a proxy to the elements: A = [B C]
I'd really would really like to see that functionality in eigen2.
Do
you think this is possible? Do you have any suggestions on how to
start implementing it?
best regards,
Stefan
--
Thomas Capricelli <orzel@xxxxxxxxxxxxxxx>
http://www.freehackers.org/thomas