CODE: Eigen Vectors — Types, Initialization, and Conversion

Eigen provides two vector types — fixed-size and dynamic — supporting double, float, and complex scalars. This post covers vector initialization patterns, merging vectors, and converting between Eigen vectors and STL vectors, which are essential operations in any numerical C++ application.

Vectors are the fundamental building block of linear algebra, and Eigen makes working with them natural and efficient in C++. Whether you need a small, fixed-size 3D vector for geometric operations or a large, dynamic vector for data processing, Eigen provides the right type with a consistent API.


Vector Types

Eigen provides two categories of vector types:

Fixed-Size Vectors

Fixed-size vectors have their dimensions known at compile time. This enables:

  • Stack allocation (no heap overhead)
  • Compile-time size checks
  • Maximum compiler optimization

cpp
Eigen::Vector2d  // 2-element vector of double
Eigen::Vector3d  // 3-element vector of double
Eigen::Vector4d  // 4-element vector of double

Dynamic-Size Vectors

Dynamic vectors have their size determined at runtime:

cpp
Eigen::VectorXd  // dynamic vector of double
Eigen::VectorXf  // dynamic vector of float


Scalar Type Suffixes

Every Eigen vector type has a suffix indicating the scalar type:

SuffixC++ Type
ddouble
ffloat
iint
cfstd::complex<float>
cdstd::complex<double>

Examples:

text
Eigen::Vector2d    2-element double (2x1 matrix of double)
Eigen::Vector3f    3-element float
Eigen::Vector4cd   4-element complex<double>
Eigen::VectorXd    dynamic double
Eigen::VectorXf    dynamic float
Eigen::Vector2cf   2-element complex<float>


Initializing Vectors

Zero Initialization

cpp
// Dynamic vector: 5 zeros
Eigen::VectorXd x = Eigen::VectorXd::Zero(5);
// x = [0, 0, 0, 0, 0]

// Fixed-size vector: always 3 zeros
Eigen::Vector3d v = Eigen::Vector3d::Zero();
// v = [0, 0, 0]

Comma Initialization

The comma initializer fills the vector element by element, left to right:

cpp
Eigen::Vector2d a;
a << 1.0, 2.0;
// a = [1.0, 2.0]

Eigen::VectorXd b(2);
b << 2.0, 3.0;
// b = [2.0, 3.0]

For fixed-size vectors, you can also use the constructor directly:

cpp
Eigen::Vector2d a(5.0, 6.0);          // 2-element
Eigen::Vector3d b(5.0, 6.0, 7.0);     // 3-element
Eigen::Vector4d c(5.0, 6.0, 7.0, 8.0); // 4-element

Other Initialization Methods

cpp
// All ones
Eigen::VectorXd ones = Eigen::VectorXd::Ones(4);
// [1, 1, 1, 1]

// Random values (uniform in [-1, 1])
Eigen::VectorXd rand = Eigen::VectorXd::Random(4);

// Constant value
Eigen::VectorXd constant = Eigen::VectorXd::Constant(4, 3.14);
// [3.14, 3.14, 3.14, 3.14]

// LinSpaced: evenly spaced values
Eigen::VectorXd linspace = Eigen::VectorXd::LinSpaced(5, 0.0, 1.0);
// [0.0, 0.25, 0.5, 0.75, 1.0]


Accessing Vector Elements

cpp
Eigen::Vector3d v(1.0, 2.0, 3.0);

// By index (0-based)
std::cout << v(0) << std::endl;  // 1.0
std::cout << v(1) << std::endl;  // 2.0
std::cout << v[2] << std::endl;  // 3.0 (alternative syntax)

// Named accessors for small vectors
std::cout << v.x() << std::endl; // 1.0
std::cout << v.y() << std::endl; // 2.0
std::cout << v.z() << std::endl; // 3.0


Vector Operations

cpp
Eigen::Vector3d a(1.0, 2.0, 3.0);
Eigen::Vector3d b(4.0, 5.0, 6.0);

// Addition and subtraction
Eigen::Vector3d sum = a + b;   // [5, 7, 9]
Eigen::Vector3d diff = b - a;  // [3, 3, 3]

// Scalar multiplication
Eigen::Vector3d scaled = 2.0 * a;  // [2, 4, 6]

// Dot product
double dot = a.dot(b);  // 1*4 + 2*5 + 3*6 = 32

// Cross product (3D only)
Eigen::Vector3d cross = a.cross(b);  // [-3, 6, -3]

// Norm (magnitude)
double norm = a.norm();          // sqrt(1+4+9) = sqrt(14)
double norm_sq = a.squaredNorm(); // 14

// Normalize (unit vector)
Eigen::Vector3d unit = a.normalized();


Merging Vectors

You can concatenate two vectors into a larger vector using the comma initializer:

cpp
Eigen::VectorXd vec1(3);
vec1 << 1.0, 2.0, 3.0;

Eigen::VectorXd vec2(2);
vec2 << 4.0, 5.0;

// Merge: create a new vector with both
Eigen::VectorXd vec_joined(vec1.size() + vec2.size());
vec_joined << vec1, vec2;
// vec_joined = [1, 2, 3, 4, 5]


Converting from STL Vector to Eigen Vector

A very common operation: you receive data in a std::vector and need to use it as an Eigen vector.

Simple Method: Map

cpp
#include <Eigen/Dense>
#include <vector>

int N = 100;
std::vector<float> v(N, 1.0f);

// Map the STL vector's memory as an Eigen vector (no copy!)
Eigen::VectorXf ev = Eigen::VectorXf::Map(&v[0], N);

// Generic version using v.size()
Eigen::VectorXf ev2 = Eigen::VectorXf::Map(&v[0], v.size());

Eigen::Map creates an Eigen matrix/vector that references existing memory. This is zero-copy and extremely efficient.


Converting from Eigen Vector to STL Vector

Direct Constructor

cpp
Eigen::VectorXd ev(5);
ev << 1.0, 2.0, 3.0, 4.0, 5.0;

// Method 1: constructor from pointer range
std::vector<double> stl_vec(ev.data(), ev.data() + ev.size());

// Method 2: resize and map
std::vector<double> stl_vec2;
stl_vec2.resize(ev.size());
Eigen::Map<Eigen::VectorXd>(stl_vec2.data(), stl_vec2.size()) = ev;

Generic Template Function

For reusable code that converts any Eigen column matrix to a std::vector:

cpp
template<typename T>
std::vector<T> EigenColumnToVector(
    const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& matrix)
{
    if (matrix.cols() != 1) {
        throw std::invalid_argument("Matrix must have exactly one column");
    }

    std::vector<T> result;
    result.resize(matrix.rows());

    for (Eigen::Index i = 0; i < matrix.rows(); ++i) {
        result[i] = matrix(i, 0);
    }

    return result;
}


Complete Example

cpp
#include <Eigen/Dense>
#include <iostream>
#include <vector>

int main() {
    // Fixed-size vector
    Eigen::Vector3d v1(1.0, 2.0, 3.0);
    std::cout << "v1 = " << v1.transpose() << std::endl;

    // Dynamic vector with zero initialization
    Eigen::VectorXd v2 = Eigen::VectorXd::Zero(5);
    std::cout << "v2 = " << v2.transpose() << std::endl;

    // Comma initialization
    Eigen::VectorXd v3(3);
    v3 << 10.0, 20.0, 30.0;
    std::cout << "v3 = " << v3.transpose() << std::endl;

    // Dot product
    std::cout << "v1 . v1 = " << v1.dot(v1) << std::endl;  // 14

    // Norm
    std::cout << "||v1|| = " << v1.norm() << std::endl;

    // Merge
    Eigen::VectorXd merged(v1.size() + v3.size());
    merged << v1, v3;
    std::cout << "merged = " << merged.transpose() << std::endl;

    // STL -> Eigen
    std::vector<float> stl_data = {1.0f, 2.0f, 3.0f};
    Eigen::VectorXf ev = Eigen::VectorXf::Map(&stl_data[0], stl_data.size());
    std::cout << "ev from STL = " << ev.transpose() << std::endl;

    // Eigen -> STL
    std::vector<double> back(v1.data(), v1.data() + v1.size());
    std::cout << "back to STL: " << back[0] << ", " << back[1] << ", " << back[2] << std::endl;

    return 0;
}


Summary

text
Eigen Vector Quick Reference:
+------------------------+---------------------------------------------+
| Type                   | Description                                 |
+------------------------+---------------------------------------------+
| Eigen::Vector2d/3d/4d  | Fixed 2/3/4 element double vector           |
| Eigen::VectorXd        | Dynamic double vector                       |
| Eigen::VectorXf        | Dynamic float vector                        |
| ::Zero(n)              | Initialize to zeros                         |
| ::Ones(n)              | Initialize to ones                          |
| ::Random(n)            | Initialize to random values                 |
| v << a, b, c           | Comma initializer                           |
| v(i)                   | Element access (0-indexed)                  |
| v.dot(u)               | Dot product                                 |
| v.cross(u)             | Cross product (3D only)                     |
| v.norm()               | Euclidean norm                              |
| v.normalized()         | Unit vector                                 |
| Map(&stl[0], n)        | Zero-copy view of STL vector data           |
+------------------------+---------------------------------------------+


Conclusion

Eigen's vector types provide an elegant and efficient API for numerical computing. Fixed-size vectors benefit from stack allocation and compile-time optimization. Dynamic vectors handle runtime-determined sizes with a consistent interface. The Map facility bridges the gap between Eigen and STL with zero copy overhead.

With this foundation in vector operations, you are ready to tackle the full matrix API and more advanced linear algebra operations available in Eigen.