## Expression templates for evaluating algebraic terms

Currently within elsa, each operation, `+`

for example, on `DataContainer`

s creates an intermediate result. Therefore, in algebraic terms like

`DataContainer d = a + c * d`

intermediate results for the individual terms like `c*d`

will be calculated and stored in memory before the whole expression is evaluated. This can amount to multiple GBs of data for large `DataContainer`

s. Instead the element-wise result could be calculated directly for the whole term (here `d[i] = a[i] + c[i] * d[i]`

).

Expression templates solve this problem by introducing delayed evaluation. Quoting wikipedia:

Expression templates implement delayed evaluation using expression trees that only exist at compile time. Each assignment to a Vec, such as Vec x = a + b + c, generates a new Vec constructor if needed by template instantiation. This constructor operates on three Vec; it allocates the necessary memory and then performs the computation. Thus only one memory allocation is performed.

For elsa context, replace `Vec`

with `DataContainer`

. The goal is to achieve a considerable reduction in memory usage as well as an increase in speed for longer algebraic terms.