Hi,

for my C++ course at may university, we were asked to write a small jet analysis for some LHC data. While writing mine, I was confronted with this: How do you store a symmetrical N×NN \times N matrix efficiently in C++?

If you just store it as a normal matrix, the needed space will go with N2N^2. Also, every update has to be done twice. Not very nice (and that does not even take any problem with multidimensional arrays in C++ in to account)

(a_00a_01a_02a_03 a_10a_11a_12a_13 a_20a_21a_22a_23 a_30a_31a_32a_33)\begin{pmatrix} a\_{00} & a\_{01} & a\_{02} & a\_{03} \\\ a\_{10} & a\_{11} & a\_{12} & a\_{13} \\\ a\_{20} & a\_{21} & a\_{22} & a\_{23} \\\ a\_{30} & a\_{31} & a\_{32} & a\_{33} \end{pmatrix}

Now, what do we really need for this matrix?

(a_00a_01a_02a_03a_10a_11a_12a_13a_20a_21a_22a_23a_30a_31a_32a_33)\begin{pmatrix} a\_{00} & \color{gray}{a\_{01}} & \color{gray}{a\_{02}} & \color{gray}{a\_{03}} \\ a\_{10} & a\_{11} & \color{gray}{a\_{12}} & \color{gray}{a\_{13}} \\ a\_{20} & a\_{21} & a\_{22} & \color{gray}{a\_{23}} \\ a\_{30} & a\_{31} & a\_{32} & a\_{33} \end{pmatrix}

Which does not look like its much but for simplicity sake I am only using an N=4N=4-matrix. For my analysis, NN was around 1000010000. So how much elements do we really need?

The first row has 11 element, the second 22 and so on up to the last row which has NN elements. Therefore we have a total of _i=1Ni=N2+N2\sum\_{i=1}^N i = \frac{N^2 + N}{2} elements. Great! We basically need only half the elements and therefore only half the RAM!

But how do we store it? We need a way to transform this multidimensional array into a single dimensional array and then use a simple function which transforms the 2D coordinates i,j to an index p of our single dimensional array. Lets take a look at the matrix again:

(a_00a_01a_02a_03a_10a_11a_12a_13a_20a_21a_22a_23a_30a_31a_32a_33)\begin{pmatrix} \color{red}{a\_{00}} & \color{gray}{a\_{01}} & \color{gray}{a\_{02}} & \color{gray}{a\_{03}} \\ \color{green}{a\_{10}} & \color{green}{a\_{11}} & \color{gray}{a\_{12}} & \color{gray}{a\_{13}} \\ \color{blue}{a\_{20}} & \color{blue}{a\_{21}} & \color{blue}{a\_{22}} & \color{gray}{a\_{23}} \\ \color{orange}{a\_{30}} & \color{orange}{a\_{31}} & \color{orange}{a\_{32}} & \color{orange}{a\_{33}} \end{pmatrix}

Now, then we write this rows just after each other like this:

(a_00a_10a_11a_20a_21a_22a_30a_31a_32a_33)\begin{pmatrix} \color{red}{a\_{00}} & \color{green}{a\_{10}} & \color{green}{a\_{11}} & \color{blue}{a\_{20}} & \color{blue}{a\_{21}} & \color{blue}{a\_{22}} & \color{orange}{a\_{30}} & \color{orange}{a\_{31}} & \color{orange}{a\_{32}} & \color{orange}{a\_{33}} \end{pmatrix}

and use a reference function like this: (we will require iji \geq j for this but if j>ij > i, you can just switch both as the matrix is symmetrical)

p=j+_k=0ik=j+i2+i2p = j + \sum\_{k=0}^i k = j + \frac{i^2 + i}{2}

Yeah! We now can allocate an single dimension array and use it as an symmetrical matrix without worrying about multiple elements!


Published

Category

snippets

Tags