Search code examples
c++matrixarmadillo

Using armadillo matrices inside a class


I am a physicist with not much experience in programming with classes. I will be grateful if someone could help with this. I have successfully used numpy arrays inside python classes, but am lost here.

The motivation is simple. I need to use a class with a few matrices as private members and perform some operations on them. Look at the following.

#include<iostream>
#include<armadillo>

using namespace std;

class myclass{
    // a matrix
    double A[2][2];
public:
    int set_element(double);
};

int main(){
    myclass x;
    x.set_element(2.0);
}

int myclass::set_element(double num){
    // a function to assign a value to the first array element.
    A[0][0] = num;
    cout << A[0][0] << endl;
    return 0;
}

This compiles and runs correctly. But if I try to use an armadillo matrix, things don't work.

#include<iostream>
#include<armadillo>

using namespace std;
using namespace arma;

class myclass{
private:
    // a matrix
    mat A(2,2);
public:
    int set_element(double);
};

int main(){
    myclass x;
    x.set_element(2.0);
}

int myclass::set_element(double num){
    //function to set the first element.
    A(0,0) = num;
    cout << A(0,0) << endl;
    return 0;
}

When i try to compile this, I get a bunch or errors.

----@----:~/comp/cpp$ g++ dummy.cpp -larmadillo
dummy.cpp:10:15: error: expected identifier before numeric constant
dummy.cpp:10:15: error: expected ‘,’ or ‘...’ before numeric constant
dummy.cpp: In member function ‘int myclass::set_element(double)’:
dummy.cpp:22:14: error: no matching function for call to ‘myclass::A(int, int)’
dummy.cpp:22:14: note: candidate is:
dummy.cpp:10:13: note: arma::mat myclass::A(int)
dummy.cpp:10:13: note:   candidate expects 1 argument, 2 provided
dummy.cpp:23:22: error: no matching function for call to ‘myclass::A(int, int)’
dummy.cpp:23:22: note: candidate is:
dummy.cpp:10:13: note: arma::mat myclass::A(int)
dummy.cpp:10:13: note:   candidate expects 1 argument, 2 provided

I am sure I am missing some key aspect here; someone please point it out.

Thanks.!


Solution

  • You need to declare your armadillo matrix in the class body, and initialize it later, for instance in your class constructor. Since armadillo matrixes do not have compile-time sizes, the size of the matrix belongs in the object construction, not its definition.

    class myclass{
    private:
        // a matrix - DECLARATION of a member variable
        mat A;
    public:
        myclass() // Constructor
        : A(2, 2) { // Default matrix member variable initialization
        }
    
        // another constructor where you can supply other dimensions:
        myclass(int rows, int cols)
        : A(rows, cols) { // matrix member variable initialization
        } 
    
        int set_element(double);
    };
    

    Once you have understood that, there are some C++11 syntax changes that allow you to write the default construction case more elegantly, with a syntax close to what you wanted:

    class myclass {
    private:
        // a matrix - this syntax allows you to specify the default initialization parameters for this variable
        mat A {2, 2}; 
    public:
        int set_element(double);
    };
    

    Alternately, you can use a compile-time fixed-size matrix, like suggested by mtall below, which frees you from having to set the size at initialization time:

    class myclass {
    private:
        // a matrix - this syntax allows you to specify a compile-time size
        mat::fixed<2, 2> A; 
    public:
        int set_element(double);
    };