Add mju_mulSymVecSparse, private engine function

Multiply sparse symmetric matrix (only lower triangle represented) by vector

PiperOrigin-RevId: 752926934
Change-Id: I5aaae1266256aa88aee8c25e242b7a7c51ea8dd7
This commit is contained in:
Yuval Tassa
2025-04-29 16:32:49 -07:00
committed by Copybara-Service
parent 1766a388cc
commit 7742f62803
3 changed files with 80 additions and 0 deletions
+38
View File
@@ -193,6 +193,44 @@ void mju_mulMatTVecSparse(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int
// multiply symmetric matrix (only lower triangle represented) by vector:
// res = (mat + strict_upper(mat')) * vec
void mju_mulSymVecSparse(mjtNum* restrict res, const mjtNum* restrict mat,
const mjtNum* restrict vec, int n,
const int* restrict rownnz, const int* restrict rowadr,
const int* restrict diagnum, const int* restrict colind) {
// clear res
mju_zero(res, n);
// multiply
for (int i=0; i < n; i++) {
int adr = rowadr[i];
int diag = rownnz[i] - 1;
const mjtNum* row = mat + adr;
// diagonal
res[i] = row[diag] * vec[i];
// TODO: consider using SIMD if diagnum[i] >= 4
// shortcut for diagonal row/column
if (diagnum[i]) {
continue;
}
// off-diagonals
const int* ind = colind + adr;
for (int k=0; k < diag; k++) {
int j = ind[k];
mjtNum val = row[k];
res[i] += val * vec[j]; // strict lower
res[j] += val * vec[i]; // strict upper
}
}
}
// count the number of non-zeros in the sum of two sparse vectors
int mju_combineSparseCount(int a_nnz, int b_nnz, const int* a_ind, const int* b_ind) {
int a = 0, b = 0, c_nnz = 0;