user2520385 user2520385 - 2 months ago 23
C++ Question

Variadic Function for Kronecker Product

I'm having trouble constructing a variadic function that does a particular task. For my particular example I'm using 2x2 matrices but you could imagine that my issue generalises to many data types. Also, for my example, "eye" is the 2x2 identity matrix.

Ok, so I would like to construct a variadic function f whose inputs might be (to give 3 examples):

f(Y, 2, Z, 5, X, 3)
f(X, 4)
f(X, 2, Y, 1)


where X, Y, Z are matrices, and the numbers are positive ints. It should return the following pseudo-code kronecker products, respectively:

KroneckerProduct(eye, Y, X, eye, Z)

KroneckerProduct(eye, eye, eye, X)

KroneckerProduct(Y, X)


So essentially it applies a matrix at the position in the KroneckerProduct specified by the int that follows the matrix, and fills in identity matrices in between.

Due to my inexperience with variadic functions, I haven't gotten far with it. My biggest problem is getting 'recursive' step of the variadic function to do what I need (see comments at end):

template<typename M, typename I, typename... Args>
arma::mat f(M matrix, I position, Args... args)
{
std::vector<arma::mat> matrixList;

while(position > matrixList.size())
{
matrixList.push_back(eye<arma::mat>(2,2));
}

matrixList(position-1) = matrix;

//Up until here, it's satisfied the first pair of arguments.
//However, if I call f(args...) now, it'll just re-initialize matrixList
}


Is there a workaround that I'm missing?

Answer

I don't know how you are going to calculate the return value (I don't understand that sort of math yet), but if you calculate it from the final matrixList, you can do a wrapper around the function:

template<typename... Args>
arma::mat calculateSomething(Args&&... args) {
    std::vevctor<arma::mat> list;
    f(list, std::forward<Args...>(args...)); //First argument for recursion

    //Calculate return value
    return return_value;
 };

And f would look like this:

//Default case with just 1 argument
void f(std::vector<arma::mat>&) {}

template<typename M, typename I, typename... Ts>
void f(std::vector<arma::mat>& matrixList, M matrix, I position, Ts... args) 
{
    while(position > matrixList.size()) 
    {
        matrixList.push_back(eye<arma::mat>(2,2));
    }

    //This is not valid syntax, not idea what you are trying to do here
    //matrixList(position-1) = matrix;

    //recursive call
    f(matrixList, args...);
}