New user self-registration is disabled due to spam. Please email eigen-core-team @ lists.tuxfamily.org if you need an account.
Before reporting a bug, please make sure that your Eigen version is up-to-date!
Bug 749 - Enable resize() on Maps when rows*cols doesn't change
Summary: Enable resize() on Maps when rows*cols doesn't change
Status: NEW
Alias: None
Product: Eigen
Classification: Unclassified
Component: Core - general (show other bugs)
Version: 3.2
Hardware: x86 - general All
: Normal enhancement
Assignee: Nobody
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-02-24 11:42 UTC by Xavier Robin
Modified: 2015-07-05 09:34 UTC (History)
4 users (show)



Attachments

Description Xavier Robin 2014-02-24 11:42:12 UTC
Hope to phrase this correctly.

A typical use-case where one would like to allow resizing of a map is when calling transposeInPlace() on a rectangular Map<...>. Currently this fails because the resulting map has different dimensions than itself:

/path-to-eigen/Eigen/src/Core/Assign.h:498: Derived& Eigen::DenseBase<Derived>::lazyAssign(const Eigen::DenseBase<OtherDerived>&) [with OtherDerived = Eigen::Matrix<int, -0x00000000000000001, -0x00000000000000001, 1, -0x00000000000000001, -0x00000000000000001>, Derived = Eigen::Map<Eigen::Matrix<int, -0x00000000000000001, -0x00000000000000001> >]: Assertion `rows() == other.rows() && cols() == other.cols()' failed.

The following example (that currently produce the above error) ought to work though, as the dimensions of the data doesn't change it should be pretty safe to write:

#include <Eigen/Dense>
using Eigen::Map;
using Eigen::MatrixXi;

int main() {
	// Create an array of integers 0 to 9
	int* dat = new int[10];
	for (int i = 0; i < 10; i++) {
		dat[i] = i;
	}

	// Map it in a 2x5 matrix
	Map<MatrixXi> m(dat, 2, 5);
	
	// Transpose in place
	m.transposeInPlace();
	
	delete[] dat;
	return 0;
}


This feature request was discussed here: http://forum.kde.org/viewtopic.php?f=74&t=119828
Comment 1 Christoph Hertzberg 2014-02-24 12:32:09 UTC
Another restriction would be that there can't be a non-default outer stride. I think an inner-stride actually is no problem.

A workaround for your case would be:
  Map<MatrixXi> m2(dat, 5,2) = m.transpose().eval();
Or even using placement-new (this is untested, maybe you need an explicit temporary to do this):
  new(&m) Map<MatrixXi>(dat, 5,2) = m.transpose().eval();

Note that the eval() is necessary in both cases and essentially what transposeInPlace() does for non-square matrices at the moment (cf. Bug 226).
Comment 2 Christoph Hertzberg 2014-02-24 13:01:17 UTC
Addendum:
Thinking about it again, I'm kind-of against allowing resize on Maps. Otherwise, assigning non-fitting expressions to a Map would be allowed as well, which I think will be a likely source of errors. Also, allowing resize for transposeInPlace() but not for assignments seems inconsistent to me.

I think usually just creating another Map sharing the same memory is a 'good enough' workaround (I just noticed that you already found it yourself).

I'll specify what resizable means in the documentation of transposeInPlace, but keep this bug open.
Comment 3 Gael Guennebaud 2014-02-24 13:40:44 UTC
Indeed, non-default outer stride would be an additional restriction.

The .eval() workaround introduces a temporary while in theory this could be done without any temp. So it seems there is no ideal solution.
Comment 4 Angelos 2015-07-05 09:34:20 UTC
Hi,

Remapping maps can be very useful. Maybe if not resize, there can be a function remap(.,.) which would only work if size() stays the same.
Also, transposeInPlace is a useful operation on a map.

Note You need to log in before you can comment on or make changes to this bug.