This is a small C library for making simple matrix computations easy. It is built on top of the GNU Scientific Library.
Albeit very powerful, the GSL is definitely not user-friendly for
making simple matrix computations.
Instead, EGSL will try to fool you into thinking that you are using Matlab.
Yes, it's that easy! You can forget all of that gsl_matrix_alloc
and gsl_matrix_free.
Download from here.
This documentation is written using Markdown and a tool called htmlsection.
Its main feature is that matrices are automatically allocated and deallocated. For example, you can write:
egsl_push();
val v1 = zeros(10,10);
val v2 = ones(10,10);
egsl_print("v1+v2=", sum(v1, v2) );
egsl_pop();
and not worry about (de)allocation.
This feature makes EGSL faster than any other C++ equivalent that
uses objects. Consider this code:
egsl_push();
val v1 = zeros(10,10);
for(int i=0;i<1000000;i++) {
egsl_push();
val v2 = zeros(10,10);
// make some operation on v2
....
// add v2 to v1
add_to(v1, v2);
egsl_pop();
}
egsl_pop();
// Prints statistics about EGSL's usage of memory
egsl_print_stats();
The output of this program is:
egsl: total allocations: 2 cache hits: 999999
Even though the loop executes one million times, the total number
of matrix allocations is 2. Note that there is an inner context.
When the loop runs the first time, the gsl_matrix for v2 is allocated.
However, when the egsl_pop() is reached, this matrix is not deallocated.
When the loop runs the second time, EGSL detects that you already
allocated a matrix of the requested size and re-utilizes the memory.
For EGSL to work, you must remember some simple rules:
egsl_push/egsl_pop calls.val structs: val object are not valid outside of the context they are created into (unless you tell EGSL).A first, simple program may look like this:
#include <egsl.h>
int main() {
// First of all, push a context
egsl_push();
// Allocates a matrix
val m1 = egsl_zeros(10, 10);
// Print it
egsl_print("Your first matrix:", m1);
egsl_pop();
// Wrong: you can't use m1 after egsl_pop()
// egsl_print("Your first matrix:", m1);
}
vals to previous contextsIf you want to make a matrix valid also for the previous context,
you may use the egsl_promote(val) function.
#include <egsl.h>
int main() {
// First of all, push a context
egsl_push();
// push another
egsl_push();
// Allocates a matrix
val m1 = egsl_zeros(10, 10);
val m2 = egsl_promote(m1);
egsl_pop();
// ok, m2 is valid
egsl_print("m2 is valid here", m2);
// error: m1 is not valid here
// egsl_print("m1 is not valid here!", m1);
egsl_pop();
}
If you use the include
#include <egsl_macros.h>
you can use a number of short macros instead of the long-named functions
egsl_*. Most of these macros are inspired by Matlab syntax.
For example, consider this line of Matlab code (taken from an actual program):
a = -2 * C_k * v_j1 + 2 * dC_drho_j1 * v2'
Translated into EGSL, with macros defined in <egsl_macros.h>, it turns
into:
val a = sum(sc(-2,m(C_k,v_j1)), sc(2,m(dC_drho_j1,tr(v2))));
where
sum(A, B) is equivalent to A + Bsc(a, B) is scalar--matrix multiplication: a * Bm(A, B) is matrix--matrix multiplication; A + BThis is the best that we can do without operator overloading.
Notice that for evaluating this expression EGSL needs a lot of
intermediate matrices, and it's managing all memory allocations for you.
How many egsl_matrix_alloc would you need to write the same code in GSL?
This is a summary of available operations. It is shown both the
extended function name (beginning with egsl_) and the macro
defined in <egsl_macros.h>
zeros(rows, cols) (egsl_zeros): Allocates a matrix with all zeros.ones(rows, cols) (egsl_ones): Allocates a matrix with all zeros.All this functions return a new val:
sum(A, B) (egsl_sum): Sums two matrices.sc(a, B) (egsl_scale): Represents scalar--matrix multiplication: a * Bm(A, B) (egsl_mult): Represents matrix--matrix multiplication; A * Binv(A) (egsl_inverse): Returns the inverse of A.egsl_glsm(v) will return you the underlying gsl_matrix for v.
For example:
val v = egsl_zeros(10,10);
gsl_matrix* m = egsl_gslm(v);
// now do whatever you want with m