Eigen Compatibility¶
Au works with Eigen out of the box. You can use Eigen vector and
matrix types as the rep of a Quantity, and the core library operations —
arithmetic, unit conversions, element access, and so on — will
just work. See our Eigen how-to guide for an introduction.
This page documents the additional utilities in "au/compatibility/eigen.hh". Eigen provides much
of its functionality as member functions (v.norm(), v.transpose(), and so on), and Quantity
does not forward arbitrary member calls. This header fills that gap with unit-aware free function
equivalents: for example, norm(q) instead of v.norm(). Each function delegates to the
corresponding member function on the underlying rep, and tracks how the operation transforms the
unit.
Note
This header does not depend on Eigen: it does not include any Eigen headers, and you can include it in any project, in any order, without adding a dependency. Each function is a template that only requires the relevant member function to exist when it’s actually used. (This also means these functions aren’t intrinsically specific to Eigen: they will work with any rep whose member functions follow Eigen’s conventions.)
One consequence: since the functions are unconstrained templates, we deliberately follow Eigen’s
camelCase naming (squaredNorm, cwiseProduct, …) rather than Au’s usual snake_case, so
that each Au function reads as the free-function form of the Eigen member it wraps.
Many Eigen operations are lazy: instead of computing a result, they return an expression template that refers to its operands. The functions on this page preserve that behavior, along with both its performance benefits and its lifetime risks. Every lazy function below carries a warning admonition to that effect; functions without the warning are evaluated eagerly, and their results are always safe to store.
Forcing evaluation¶
eval¶
Force evaluation of a Quantity whose rep is an Eigen expression template, producing a Quantity
of the same unit whose rep owns its own data (for example, a concrete Eigen::Vector3d). This is
the free function form of Eigen’s .eval() member function, and it is the standard tool for
avoiding expression template lifetime issues.
Example: materializing a unit conversion result
Reductions¶
These operations reduce a vector or matrix to a single scalar. They are all evaluated eagerly, so their results are always safe to store.
norm¶
The Euclidean (L2) norm. The result has the same unit as the input.
squaredNorm¶
The squared Euclidean norm (the sum of squared coefficients). The result unit is the square of
the input unit. Use this instead of norm when you can, to avoid a square root.
stableNorm, blueNorm, hypotNorm¶
Numerically robust alternatives to norm, corresponding to the Eigen member functions of the same
names. Each result has the same unit as the input.
template <typename U, typename R>
auto stableNorm(const Quantity<U, R> &q);
template <typename U, typename R>
auto blueNorm(const Quantity<U, R> &q);
template <typename U, typename R>
auto hypotNorm(const Quantity<U, R> &q);
lpNorm¶
The L^p norm, for a compile-time integer p. Pass Eigen::Infinity for the maximum-absolute
norm. The result has the same unit as the input.
sum, mean, minCoeff, maxCoeff, trace¶
The sum of all coefficients; the mean of all coefficients; the smallest coefficient; the largest coefficient; and the trace (the sum of the diagonal coefficients). Each result has the same unit as the input.
template <typename U, typename R>
auto sum(const Quantity<U, R> &q);
template <typename U, typename R>
auto mean(const Quantity<U, R> &q);
template <typename U, typename R>
auto minCoeff(const Quantity<U, R> &q);
template <typename U, typename R>
auto maxCoeff(const Quantity<U, R> &q);
template <typename U, typename R>
auto trace(const Quantity<U, R> &q);
prod¶
The product of all coefficients. The result unit is the input unit raised to the power of the number of coefficients.
Because that unit must be computed at compile time, this function requires a fixed-size operand:
you will get a static_assert failure for dynamic-size types.
determinant¶
The determinant. For an N-by-N matrix, the result unit is the input unit raised to the power
N.
Because that unit must be computed at compile time, this function requires a fixed-size operand:
you will get a static_assert failure for dynamic-size types.
dot¶
The dot (inner) product. When both operands are Quantity, the result unit is the product of the
operand units. We also provide overloads where one operand is a raw (that is, dimensionless) Eigen
object; there, the result carries the unit of the Quantity operand.
template <typename U1, typename R1, typename U2, typename R2>
auto dot(const Quantity<U1, R1> &a, const Quantity<U2, R2> &b);
template <typename U, typename R, typename V>
auto dot(const Quantity<U, R> &a, const V &b);
template <typename V, typename U, typename R>
auto dot(const V &a, const Quantity<U, R> &b);
Vector geometry¶
cross¶
The cross product. When both operands are Quantity, the result unit is the product of the
operand units. We also provide overloads where one operand is a raw (that is, dimensionless) Eigen
object; there, the result carries the unit of the Quantity operand.
template <typename U1, typename R1, typename U2, typename R2>
auto cross(const Quantity<U1, R1> &a, const Quantity<U2, R2> &b);
template <typename U, typename R, typename V>
auto cross(const Quantity<U, R> &a, const V &b);
template <typename V, typename U, typename R>
auto cross(const V &a, const Quantity<U, R> &b);
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
normalized¶
The normalized (unit-length) vector. Evaluated eagerly.
Uniquely on this page, the result is a raw Eigen vector, not a Quantity. The reason is that
this result is unitless by definition of the operation, for all inputs: the norm always carries
the operand’s unit, so the units cancel exactly. Since there is no operand-dependent unit for
a Quantity wrapper to track, we return the raw vector directly.
Coefficient-wise operations¶
cwiseProduct¶
The coefficient-wise (Hadamard) product. When both operands are Quantity, the result unit is the
product of the operand units. We also provide overloads where one operand is a raw (that is,
dimensionless) Eigen object; there, the result carries the unit of the Quantity operand.
template <typename U1, typename R1, typename U2, typename R2>
auto cwiseProduct(const Quantity<U1, R1> &a, const Quantity<U2, R2> &b);
template <typename U, typename R, typename V>
auto cwiseProduct(const Quantity<U, R> &a, const V &b);
template <typename V, typename U, typename R>
auto cwiseProduct(const V &a, const Quantity<U, R> &b);
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
cwiseQuotient¶
The coefficient-wise quotient. When both operands are Quantity, the result unit is the quotient
of the operand units. We also provide overloads where one operand is a raw (that is, dimensionless)
Eigen object; there, the result unit is the Quantity operand’s unit (if it’s the numerator), or
its inverse (if it’s the denominator).
template <typename U1, typename R1, typename U2, typename R2>
auto cwiseQuotient(const Quantity<U1, R1> &a, const Quantity<U2, R2> &b);
template <typename U, typename R, typename V>
auto cwiseQuotient(const Quantity<U, R> &a, const V &b);
template <typename V, typename U, typename R>
auto cwiseQuotient(const V &a, const Quantity<U, R> &b);
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
cwiseAbs¶
The coefficient-wise absolute value. The result has the same unit as the input.
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
cwiseSqrt¶
The coefficient-wise square root. The result unit is the square root of the input unit.
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
Views and accessors¶
Every operation in this section preserves the unit of its input.
transpose¶
The transpose.
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
diagonal¶
The main diagonal; or, with an index argument, the index-th diagonal (positive for
super-diagonals, negative for sub-diagonals).
template <typename U, typename R>
auto diagonal(const Quantity<U, R> &q);
template <typename U, typename R>
auto diagonal(const Quantity<U, R> &q, std::ptrdiff_t index);
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
row, col¶
The i-th row, or the j-th column.
template <typename U, typename R>
auto row(const Quantity<U, R> &q, std::ptrdiff_t i);
template <typename U, typename R>
auto col(const Quantity<U, R> &q, std::ptrdiff_t j);
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
reverse¶
The coefficients in reverse order.
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
conjugate¶
The complex conjugate (a no-op for real reps).
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
head, tail, segment¶
Portions of a vector: the first N (or n) coefficients; the last N (or n) coefficients; or
a length-N (or n) portion starting at start. As in Eigen, sizes given as template arguments
are fixed at compile time, and sizes given as function arguments are dynamic.
template <int N, typename U, typename R>
auto head(const Quantity<U, R> &q);
template <typename U, typename R>
auto head(const Quantity<U, R> &q, std::ptrdiff_t n);
template <int N, typename U, typename R>
auto tail(const Quantity<U, R> &q);
template <typename U, typename R>
auto tail(const Quantity<U, R> &q, std::ptrdiff_t n);
template <int N, typename U, typename R>
auto segment(const Quantity<U, R> &q, std::ptrdiff_t start);
template <typename U, typename R>
auto segment(const Quantity<U, R> &q, std::ptrdiff_t start, std::ptrdiff_t n);
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
block¶
A Rows-by-Cols (or rows-by-cols) block of a matrix, whose top-left corner is at (i, j).
As in Eigen, sizes given as template arguments are fixed at compile time, and sizes given as
function arguments are dynamic.
template <int Rows, int Cols, typename U, typename R>
auto block(const Quantity<U, R> &q, std::ptrdiff_t i, std::ptrdiff_t j);
template <typename U, typename R>
auto block(const Quantity<U, R> &q,
std::ptrdiff_t i,
std::ptrdiff_t j,
std::ptrdiff_t rows,
std::ptrdiff_t cols);
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
replicate¶
The input, tiled into a RowFactor-by-ColFactor (or row_factor-by-col_factor) grid of copies.
As in Eigen, factors given as template arguments are fixed at compile time, and factors given as
function arguments are dynamic.
template <int RowFactor, int ColFactor, typename U, typename R>
auto replicate(const Quantity<U, R> &q);
template <typename U, typename R>
auto replicate(const Quantity<U, R> &q, std::ptrdiff_t row_factor, std::ptrdiff_t col_factor);
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.
Matrix operations¶
inverse¶
The matrix inverse. The result unit is the inverse of the input unit (so that the product of a matrix and its inverse is dimensionless).
Lifetime risk
This operation is lazy: its result is an expression template, which refers to its operands
instead of owning its own copy of the data. The result is valid only as long as its operands
are alive. If it needs to outlive them, materialize it with eval(). See
our Eigen safety guide to learn more.