Aubergine
Aubergine

Reputation: 407

C++ Armadillo: arrays of indices from 2D-matrix

I come from Python. I have a linear algebra problem to treat in C++, and I chose to use Armadillo to do so, as it advertises itself as being MATLAB-like, thus SciPy-like.

I'm looking for a way to populate two matrices, one with the rows, one with the columns of a 2D-matrix of given shape (in Python, that would be numpy.indices).

For instance, if I have a 4 rows/3 columns matrix shape, what I want is to build a row matrix:

0 0 0
1 1 1
2 2 2
3 3 3

and a column matrix:

0 1 2
0 1 2
0 1 2
0 1 2

in order to do some calculations afterwards.

It is similar to C++ Armadillo Generate Indices uvec of a given vec or matrix without looping it but with a matrix instead of a 1D-vector.

Is there a way to do so without too much looping? I know about linspace to populate a vector, but I'd prefer not to loop over a a bunch of vectors to merge them in a matrix. I am just starting with Armadillo, and I am not really aware of its capabilities yet (basically, I just have matrices products and inversion to do).

Upvotes: 0

Views: 2237

Answers (2)

ShawSa
ShawSa

Reputation: 154

While the answer given does generate the requested matrices the OP asked for a solution not using loops. This answer uses regspace and repmat and is perhaps conceptually simpler:

#include <iostream>
#include <armadillo>

using namespace std;
using namespace arma;

int main (int argc, char const* argv[])
{
    ivec a_col = regspace<ivec>(0, 3);
    imat A = repmat(a_col, 1, 3);

    irowvec b_row = regspace<irowvec>(0,2);
    imat B = repmat(b_row, 4, 1);

    cout << A << endl;
    cout << B << endl;
    return 0;
}

I have to confess that I'm a little new to armadillo so I won't promise that this is fast or follows best practices, but I think it's probably closest to equivalent SciPy code.

Upvotes: 1

eapetcho
eapetcho

Reputation: 527

@Aubergine. The armadillo library is very useful for scientific computing and easy to pick up. I would encourage to get family with its documentation page armadillo documentation

Concerning your particular problem, here is a solution I am proposing:

#include<iostream>
#include<armadillo>

using namespace std;
using namespace arma;

int main(int argc, char **argv)
{
    // Create two matrices A and B of shape 4x3 filled with zeros
    imat A = zeros<imat>(4, 3);
    imat B = zeros<imat>(4, 3);

    // Fill each row
    for(int i=0; i < 4; i++)
    {
        A.row(i) = i * ones<ivec>(3).t();  // 
    }

    // Fill each column
    for(int i=0; i < 3; i++)
    {
        B.col(i) = i * ones<ivec>(4);
    }
    cout << "A = \n" << A << endl;
    cout << "B = \n" << B << endl;

    return 0;
}

The compilation goes like this on my computers (Mac OSX and Ubuntu):

g++ -std=c++11 -O2 `pkg-config --cflags --libs armadillo` testArmadillo.cpp -o a.out

Then, we can run the executable simply by typing:

./a.out

and the output is as follows:

A =
    0        0        0
    1        1        1
    2        2        2
    3        3        3

B =
    0        1        2
    0        1        2
    0        1        2
    0        1        2

For more information about imat, ivec, see imat and ivec

Upvotes: 1

Related Questions