NABLA
Nabla Ain't Basic Linear Algebra

This section assumes that operations on element type never throw.
Blame it or not but this library uses native C++ exception mechanism. And, just to mention, all exception types in this library inherit std::exception
.
This library never uses throw()
specification for operations. It is stated in the documentation if an operation may throw an exception. Not to be repititive, here are kinds of operations throughout the library which may throw:
resize()
fall here and actually assignment operations too;As you can see the cases are quite common and intuitive.
All types and functions provide so called basic guarantee (if not explicitly stated otherwise). This means that if an operation fails and throws an exception indicating this situation then all objects remain valid (meaning all internal invariants are preserved). However this does not mean the data holded by such an object remains sensible because an operation may fail to finish its job.
Furthermore, by convention destructors and swap operations never throw.
All types are thread safe provided that only one thread accesses to an object at a time. However it is safe to read from a single object within several threads.
All types and functions are reentrant, i.e. it is safe to operate on distinct objects of the same type within distinct threads.
Some types provide additional guarantees. Here they are.
&m(i, j)==&m(0, 0) + i*m.cols() + j
i<m.rows() && j<m.cols()
. Elements of a matrix<value_t, symmetric>
are stored in memory continuously row by row. Only lower triangular part elements are stored. This implies
&m(i, j)==&m(0, 0) + (i1*(i1 + 1)/2 + j1))
is always satisfied for nonempty matrix and i1 = max(i, j); j1 = min(i, j); i<m.rows() && j<m.cols()
.
Elements of a matrix<value_t, lower_triangular>
are stored in memory continuously row by row. Only lower triangular part elements are stored. This implies
&m(i, j)==&m(0, 0) + ((i*(i + 1))/2 + j)
is always satisfied for nonempty matrix and i<m.rows() && j<m.cols() && j<=i
.
Elements of a matrix<value_t, upper_triangular>
are stored in memory continuously row by row. Only upper triangular part elements are stored. This implies
&m(i, j)==&m(0, 0) + ((i*(2*m.rows()  i  1))/2 + j)
is always satisfied for nonempty matrix and i<m.rows() && j<m.cols() && j>=i
.
&v(i)==&v(0) + i
i<v.size()
.