Search code examples
c++eigen

How to have a function return several different type Eigen matrixes (C++)


I'd like to call a function that allocates, compute, and then returns to the calling function several Eigen matrixes.

The output size of each matrix is not known before hand, ergo we cannot allocate such matrices in the calling function.

Here is what I though was the way (passing Matrices in by Ref class, and resize inside):

FromImageToAb(image, 
Eigen::Ref<Eigen::SparseMatrix<double>> Aout, Eigen::Ref<Eigen::VectorXd> bout){

    ... // determine what size matrixes must have: int equationcounter, numberofunknowns

    // Allocate matrixes of the correct size
    SparseMatrix<double> A(equationcounter, numberofunknowns);
    SparseMatrix<double> bM(equationcounter, 1);

    ... // fill A and bM 

    VectorXd b(bM); // Now we have successfully created a dense vector of the correct size that cannot be known before hand

    Aout = A;
    bout = b;
}


main(){
    SparseMatrix<double> Aout(1,1); // Creating matrix with token size
    VectorXd bout(1); // Creating matrix with token size
    FromImageToAb(image, Aout, bout);

}

but Aout = A; doesn't allocate memory and copy the values so it's usable outside and bout = b; doesn't compile, as dense matrices cannot be resized to increase memory

What's the correct way to go about this?


Solution

  • Why not return a value that contains both?

    std::tuple<Eigen::SparseMatrix<double>, Eigen::VectorXd> FromImageToAb(image_t image)
    {
        ... // determine what size matrixes must have: int equationcounter, numberofunknowns
    
        // Allocate matrixes of the correct size
        SparseMatrix<double> A(equationcounter, numberofunknowns);
        SparseMatrix<double> bM(equationcounter, 1);
    
        ... // fill A and bM 
    
        return { a, bM }; // Uses implicit conversion of SparseMatrix<double> -> VectorXd
    }
    

    If you have a C++17 compiler, you can avoid default constructing the values with structured bindings

    int main(){
        auto [a, b] = FromImageToAb(image);
        // use a and b
    }
    

    Otherwise you can assign multiple things with std::tie

    int main(){
        SparseMatrix<double> a; // Default construct
        VectorXd b; // Default construct
        std::tie(a, b) = FromImageToAb(image);
        // use a and b
    }