2D Names functionality for Arrays and Matrices

Ok, second attempt, this time from an up-to-date branch....

I have added two modules `With2DNames` and `With2DSizes` which could be used to expand the functionality of objects of type `Array` and `Matrix`. The latter module can be applied only to arrays and gives the array some matrix-like capabilities (getting rows and columns, etc...) without changing the internal data representation of the array, the data is still preserved in a flat `Array`. `With2DNames` instead aims at providing to both Matrices and 2D-enhanced Arrays the capability of knowing the meaning of rows and columns and to access data by name.  If we assume a Matrix with rows called `r1, r2, r3` and columns `c1, c2, c3, c4`, it is now possible to access element at [1,2] with

    matrix.by_name("r2","c3")

the same syntax is also valid for an array. One thing worth noting is that if there are repeated column or row names, `by_name` method will only return the first hit. Elements in a 2D-enhanced array can also be accessed using their indices like

    array.at_2d(2,3)

All new functionality comes with new specs.