I'm using Eigen 3.4. I'd like to subtract two vectors of unequal length, padding the shorter one with zeros along the bottom, while avoiding reallocation of memory. Rough example:
VectorXd A (4), B (2);
A << 1, 2, 3, 4;
B << 5, 6;
VectorXd C = paddedSubtract(A, B); // computes A - B but pads B with zeros to match A
The result should be
C = [-4, -4, 3, 4]
Note that I don't know beforehand which of the two vectors will be shorter.
conservativeResize
to resize both vectors to the size of the larger of the two, and then manually set the padded values to zeros. However, this requires some checking of sizes, which is fine, but I'm wondering if there's a cleaner way.conservativeResizeLike
, passing in a vector of zeros with the size of the larger vector, but my concern is that a temporary zero vector will be allocated unnecessarily in the background; performance is important because this operation will be performed many times (but on small vectors).My two questions are:
Thanks.
am I correct in thinking that there will be extra memory allocation of the zero vector
Yes. You can make your own padding operator, however, it will likely defeat Eigen's explicit vectorization since it introduces a condition into the loop. It's the same reason why there is no concatenation operator. See Vector concatenation in Eigen returning an expression
is there a cleaner / more Eigen-ey way than (1) or (3)?
Keep it simple:
Eigen::Index maxSize = std::max(A.size(), B.size());
Eigen::Index minSize = std::min(A.size(), B.size());
Eigen::Index tailSize = maxSize - minSize;
Eigen::VectorXd C(maxSize);
C.head(minSize) = A.head(minSize) - B.head(minSize);
if(A.size() == maxSize)
C.tail(tailSize) = A.tail(tailSize);
else
C.tail(tailSize) = -B.tail(tailSize);
This would be optimized to avoid redundant memory operations. If you want fewer lines with slightly less efficiency:
Eigen::VectorXd C = Eigen::VectorXd::Zero(std::max(A.size(), B.size());
C.head(A.size()) = A;
C.head(B.size()) -= B;
You can also use the comma initializer
Eigen::Index maxsize = std::max(A.size(), B.size());
Eigen::Index minsize = std::min(A.size(), B.size());
Eigen::VectorXd C(maxsize);
C << (A.head(minsize) - B.head(minsize)),
-B.tail(B.size() - minsize),
A.tail(A.size() - minsize);