Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.!

like image 269
userJ Avatar asked Feb 25 '14 04:02

userJ


2 Answers

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);
};
like image 110
Martin J. Avatar answered Oct 22 '22 06:10

Martin J.


You can use Martin J.'s code which uses dynamically sized matrices, or the code below which uses fixed size matrices.

There are pros and cons for using fixed size matrices. On one hand, the fixed sizes can let a smart C++ compiler (eg. gcc) optimize more. On the other hand, matrix size can't be changed and gains from optimization are only useful for small matrices. Using large fixed-size matrices (ie. greater than 10x10, or 100 elements) can also eat up stack memory.

#include <iostream>
#include <armadillo>

using namespace std;
using namespace arma;

class myclass{
private:
   // a fixed-size matrix: allows more optimization
   // (generally recommended only for sizes <= 10x10)
   mat::fixed<2,2> A;
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;
}
like image 1
mtall Avatar answered Oct 22 '22 06:10

mtall