I need to compute the function value and gradient of a D
-dimensional function and add those values together. I thought it would be computational beneficial to simply store the gradient part in the first D
-components and the value of the function in the last component of a D+1
-dimensional vector.
However, how can I extract the first D
-components (i.e. the gradient part) from that D+1
-dimensional vector? I know that there is the option of slicing, but I don't want to add any senseless overhead here. So, I've tried to simply do a reinterpret_cast<Eigen::Vector<T, D>&>
on my Eigen::Vector<T, D + 1>
and it worked; but is that really guaranteed to work (and safe)?
You don't want the slicing operations, you want the block operations. Most (all?) of them come with template versions. To get the first D
elements of a vector if D
is a runtime variable, call vector.head(D)
. If it is a compile-time constant, use vector.head<D>()
.
The returned block expression object is similar to an Eigen Map in that it is effectively a zero-overhead reference and does exactly what you want.
// act like reference
auto first_d = vector.head<D>();
// copy into new vector
auto copy = first_d.eval();
// or
Eigen::Vector<double, D> copy2 = first_d;
The usual warnings about using auto
in Eigen apply, but this use is okay. If you want to be safe, spell the type out or don't keep it around as a variable, only use it as part of expressions.
If you compile without -DNDEBUG
there will be a range-check unless the compiler can optimize it away (likely the case for template parameter used on fixed-size vector).
And just to return to the original question: No, it would not be safe. Even if you trust that Eigen never changes the internal layout of fixed size types (reasonable assumption), smaller vectors may have bigger alignment. alignof(Vector3d) < alignof(Vector2d)
. This will result in Eigen creating machine instructions that assume that higher alignment (such as movapd
vs. movupd
on x86), which will fail at runtime.