in src/hit/api/linearalgebra/linearalgebra.cpp [561:599]
EncryptedRowVector LinearAlgebra::extract_row(const EncryptedMatrix &enc_mat_a_trans, int row) {
EncodingUnit unit = enc_mat_a_trans.encoding_unit();
// create a mask for the k^th column of A^T, which is the k^th row of A
// col_mask is a single encoding unit which will be replicated for every
// vertical unit of the encoding of A^T
vector<double> col_mask(enc_mat_a_trans.num_slots());
// compute which unit column the desired row is in
int unit_col = row / unit.encoding_width();
// col_in_unit is the column within the encoding unit that contains the masked column
int col_in_unit = row % unit.encoding_width();
// create the column mask encoding unit
for (size_t i = 0; i < enc_mat_a_trans.num_slots(); i++) {
if (i % unit.encoding_width() == col_in_unit) {
col_mask[i] = 1;
} else {
col_mask[i] = 0;
}
}
vector<CKKSCiphertext> isolated_col_cts(enc_mat_a_trans.num_vertical_units());
parallel_for(enc_mat_a_trans.num_vertical_units(), [&](int i) {
isolated_col_cts[i] = eval.multiply_plain(enc_mat_a_trans.cts[i][unit_col], col_mask);
eval.rescale_to_next_inplace(isolated_col_cts[i]);
// we now have isolated the k^th column of A^T. To get an encoding of the k^th row of A
// we need to replicate this column across all columns of the encoding unit
// first step is to shift the column to the left
if (col_in_unit != 0) {
eval.rotate_left_inplace(isolated_col_cts[i], col_in_unit);
}
// now replicate this column to all other columns of the unit
rot(isolated_col_cts[i], unit.encoding_width(), 1, false);
});
return EncryptedRowVector(enc_mat_a_trans.height(), unit, isolated_col_cts);
}