Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Expression Templates Library (ETL)
branch: master

Fetching latest commit…

Cannot retrieve the latest commit at this time


Expression Templates Library (ETL)

ETL is a header only library for cC+ that provides vector and matrix classes with support for Expression Templates to perform very efficient operations on them.

At this time, the library support compile-time sized matrix and vector and runtime-sized matrix and vector with all element-wise operations implemented. It also supports 1D and 2D convolution and matrix multiplication (naive algorithm and strassen).


The library is header-only and does not need to be built it at all, you just have to include its header files.

Here are the header that can be included:

  • etl.hpp: Should always be included, provide the basic features
  • multiplication.hpp: Include if you want matrix multiplication
  • convolution: Include if you want 1D/2D convolution
  • print.hpp: Include if you want to print elements

Data structures

Several structures are available:

  • fast_matrix<T, Dim...>: A matrix of variadic size with elements of type T. This must be used when you know the size of the vector at compile-time. The number of dimensions can be anything.
  • dyn_matrix<T, D>: A matrix with element of type T. The size of the matrix can be set at runtime. The matrix can have D dimensions.

There also exists typedefs for vectors:

  • fast_vector<T, Rows>
  • dyn_vector<T>

You have to keep in mind that fast_matrix directly store its values inside it, therefore, it can be very large and should rarely be stored on the stack. Moreover, that also makes it very expensive to move and copy.

Element-wise operations

Classic element-wise operations can be done on vector and matrix as if it was done on scalars. Matrices and vectors can also be added,subtracted,divided, ... by scalars.

etl::dyn_vector<double> a({1.0,2.0,3.0});
etl::dyn_vector<double> b({3.0,2.0,1.0});

etl::dyn_vector<double> c(1.4 * (a + b) / b + b + a / 1.2);

All the operations are only executed once the expression is evaluated to construct the dyn_vector.

Unary operators

Several unary operators are available. Each operation is performed on every element of the vector or the matrix.

Available operators:

  • log
  • abs
  • sign
  • max/min
  • sigmoid
  • noise: Add standard normal noise to each element
  • logistic_noise: Add normal noise of mean zero and variance sigmoid(x) to each element
  • exp
  • softplus
  • bernoulli

Several transformations are also available:

  • hflip: Flip the vector or the matrix horizontally
  • vflip: Flip the vector or the matrix vertically
  • fflip: Flip the vector or the matrix horizontally and verticaly. It is the equivalent of hflip(vflip(x))
  • sub: Return a sub part of the matrix. The first dimension is forced to a special value. It works with matrices of any dimension.
  • dim/row/col: Return a vector representing a sub part of a matrix (a row or a col)
  • reshape: Interpet a vector as a matrix

Lazy evaluation

All binary and unary operations are applied lazily, only when they are assigned to a concrete vector or matrix class.

The expression can be evaluated using the s(x) function that returns a concrete class (fast_matrix or dyn_matrix) based on the expression.

Multiplication, convolution and all reductions are not lazily evaluated.


Several reduction functions are available:

  • sum: Return the sum of a vector or matrix
  • mean: Return the sum of a vector or matrix
  • dot: Return the dot product of two vector or matrices


The header convolution.hpp provides several convolution operations both in 1D (vector) and 2D (matrix).

The header mutiplication.hpp provides the matrix multiplication operation. mmul is the naive algorithm (ijk), which strassen_mmul implements Strassen algorithm.

It is possible to pass an expression rather than an data structure to functions. Keep in mind that expression are lazy, therefore if you pass a + b to a matrix multiplication, an addition will be run each time an element is accessed, therefore, it is not often efficient.


It is also possible to generate sequences of data and perform operations on them.

For now, two generators are available:

  • normal_generator: Generates real numbers distributed on a normal distribution
  • sequence_generator(c=0): Generates numbers in sequence from c

All sequences are considered to have infinite size, therefore, they can be used to initialize or modify any containers or expressions.

Why compile-time sizes ?

Some people have asked me why I bothered at all to create the fast_matrix template, where all the dimensions are fixed at compile-time. There are several reasons for that:

  • It improves data locality since the data can be directly stored inside the structure and not with one level of indirection to the heap
  • It makes vectorization easier for the compiler. All the sizes and therefore the number of iterations of the lopp are known at compile-time, which is a really great information for the compiler who can optimize each loop very well and doesn't have to rely on estimating the number of iterations.
  • Better diagnostics. It makes all the errors come at compile-time. If you try to add two matrices of different sizes, the error won't come at runtime, but at compile-time, which makes it much better.
  • I knew the sizes of the matrices I was working for at compile-time
  • It is more fun to implement. Yes, I love templates and TMP :)


This library is completely header-only, there is no need to build it.

However, this library makes extensive use of C++11 and C++14, therefore, a recent compiler is necessary to use it. This library is tested on the following compilers:

  • CLang 3.4 and greater
  • GCC 4.9.1 and greater
  • icc 15.0.2 and greater

The library has never been tested on Windows.

The folder include must be included with the -I option.

There are no link-time dependencies.

If you have problems compiling this library, I'd be glad to help, but I do not guarantee that this will work on every compiler. I strongly expect it to not build under Visual Studio.


This library is distributed under the terms of the MIT license, see LICENSE file for details.

Something went wrong with that request. Please try again.