Assigning vectors to columns of matrices

Issue #359 resolved
Nafis Sadat created an issue

Hello! I’ve been trying to convert a bunch of my Armadillo code into Blaze, and one method I can’t seem to do efficiently is replacing the columns of a matrix with a vector. I have pasted my Armadillo code (which works) and the Blaze code which I can’t seem to find the right methods for:

I think essentially, I’m looking for methods to replace one whole column/row of a matrix with a vector (provided that the sizes are matching up perfectly). Any feedback would be super helpful!! Thanks!!

//// We have two matrices: mat_x and mat_y as inputs, and num_facts as in 'int' niput

// Allocate output matrix
arma::mat outmat(mat_x.n_rows, num_facts);

// We loop over num_facts
for (int x = 1; x < num_facts + 1; x++) {

    // Remove the x'th factor from input matrix 
    //// We need to make a copy since shed_col() is in-place 
    arma::mat xshed = mat_x;
    arma::mat yshed = mat_y;
    xshed.shed_col(x - 1);
    yshed.shed_col(x - 1);

    ///// The function ArmaInnerSum_ returns a column vector
    //// Compute ArmaInnerSum_ and assign that output vector to 
    //// column 'x-1' of outmat
    outmat.col(x - 1) = ArmaInnerSum_(num_facts, xshed, yshed);

    //// Compute diff of mat_x and mat_y 's x-1 columns
    arma::colvec tmpcol = mat_y.col(x - 1) - mat_x.col(x - 1);

    // Multiply x-1th column of outmat with tmpcol element-wise
    outmat.col(x - 1) = outmat.col(x - 1) % tmpcol;

}



/////// Blaze implementation ////

// Allocate output matrix
blaze::DynamicMatrix<double> outmat(mat_x.rows(), num_facts);

// Loop over num_facts
for (int x = 1; x < num_facts + 1; x++) {

    // Remove the x'th factor from input matrix and
    // use over BlazeInnerSum_()
    ////// I first create a matrix xshed and yshed with being
    ////// equal to mat_x and mat_y
    ////// and then I call dropColumnX() on that matrix
    ////// to drop a column

    blaze::DynamicMatrix<double> xshed(mat_x);
    blaze::DynamicMatrix<double> yshed(mat_y);
    xshed = dropColumnX(xshed, x-1);
    yshed = dropColumnX(yshed, x-1);


    //// The function BlazeInnerSum_ returns a DynamicVector
    blaze::DynamicVector<double> tempvec = BlazeInnerSum_(num_facts, xshed, yshed);


    //// So here, instead of a direct assignment of the vector to column x-1
    //// of outmat, I loop over outmat and assign the vector element by element
    for (int r = 0; r < outmat.rows(); r++) {

      // Multiply tempvec with the difference in mat_x and mat_y and column x-1
      outmat(r, x - 1) = tempvec[r] * (mat_y(r, x - 1) - mat_x(r, x - 1));
    }

}

Comments (3)

  1. Klaus Iglberger

    Hi Nafis!

    In Blaze the tool you need are views, and in particular column views. As the wiki explains, a column can appear on both sides of an assignment: You can use it to read from or to write to a specific column of a matrix. In your example, the column would appear on the left of the assignment:

    // ...
    column( outmat, x-1 ) = tempvec[r] * (mat_y(r,x-1) - mat_x(r,x-1));
    // ...
    

    I hope this helps,

    Best regards,

    Klaus!

  2. Nafis Sadat reporter

    Hey @Klaus Iglberger , thanks a lot for replying. A quick about the right hand side: is it possible to slice the matrix mat_x so that instead of looking over the rows of mat_x , I can just directly assign the column, something along the lines of:

    // ...
    column( outmat, x-1 ) = tempvec * ( column( mat_y ,x-1) ) - column( mat_x, x-1) );
    // ...
    

  3. Klaus Iglberger

    Hi Nafis!

    Yes, this is possible. The code you posted should already work: On the right-hand side you create two columns (which correspond to column vectors), subtract them, then perform an element-wise multiplication (which again yields a column vector, assuming that tempvec is a column vector) and in the end assign the result to a column of outmat. If you encounter any problem, please ask again.

    Best regards,

    Klaus!

  4. Log in to comment