@@ -1440,10 +1440,9 @@ void mj_factorI(const mjModel* m, mjData* d, const mjtNum* M, mjtNum* qLD, mjtNu
1440
1440
}
1441
1441
}
1442
1442
1443
- // compute 1/diag(D), 1/sqrt(diag(D))
1443
+ // compute 1/diag(D)
1444
1444
for (int i = 0 ; i < nv ; i ++ ) {
1445
- mjtNum qLDi = qLD [dof_Madr [i ]];
1446
- qLDiagInv [i ] = 1.0 /qLDi ;
1445
+ qLDiagInv [i ] = 1.0 / qLD [dof_Madr [i ]];
1447
1446
}
1448
1447
}
1449
1448
@@ -1458,6 +1457,40 @@ void mj_factorM(const mjModel* m, mjData* d) {
1458
1457
1459
1458
1460
1459
1460
+ // sparse L'*D*L factorizaton of inertia-like matrix M, assumed spd
1461
+ // like mj_factorI, but using CSR representation
1462
+ void mj_factorIs (mjtNum * mat , mjtNum * diaginv , int nv ,
1463
+ const int * rownnz , const int * rowadr , const int * diagnum , const int * colind ) {
1464
+ // backward loop over rows
1465
+ for (int k = nv - 1 ; k >= 0 ; k -- ) {
1466
+ // get row k's address, diagonal index, inverse diagonal value
1467
+ int rowadr_k = rowadr [k ];
1468
+ int diag_k = rowadr_k + rownnz [k ] - 1 ;
1469
+ mjtNum invD = 1 / mat [diag_k ];
1470
+ if (diaginv ) diaginv [k ] = invD ;
1471
+
1472
+ // skip if simple
1473
+ if (diagnum [k ]) {
1474
+ continue ;
1475
+ }
1476
+
1477
+ // update triangle above row k, inclusive
1478
+ for (int adr = diag_k - 1 ; adr >= rowadr_k ; adr -- ) {
1479
+ // tmp = L(k, i) / L(k, k)
1480
+ mjtNum tmp = mat [adr ] * invD ;
1481
+
1482
+ // update row i < k: L(i, 0..i) -= L(i, 0..i) * L(k, i) / L(k, k)
1483
+ int i = colind [adr ];
1484
+ mju_addToScl (mat + rowadr [i ], mat + rowadr_k , - tmp , rownnz [i ]);
1485
+
1486
+ // update ith element of row k: L(k, i) /= L(k, k)
1487
+ mat [adr ] = tmp ;
1488
+ }
1489
+ }
1490
+ }
1491
+
1492
+
1493
+
1461
1494
// in-place sparse backsubstitution: x = inv(L'*D*L)*x
1462
1495
// L is in lower triangle of qLD; D is on diagonal of qLD
1463
1496
// handle n vectors at once
@@ -1575,16 +1608,15 @@ void mj_solveLD(const mjModel* m, mjtNum* restrict x, int n,
1575
1608
// in-place sparse backsubstitution: x = inv(L'*D*L)*x
1576
1609
// like mj_solveLD, but using the CSR representation of L
1577
1610
void mj_solveLDs (mjtNum * restrict x , const mjtNum * qLDs , const mjtNum * qLDiagInv , int nv ,
1578
- const int * rownnz , const int * rowadr , const int * diagind , const int * diagnum ,
1579
- const int * colind ) {
1611
+ const int * rownnz , const int * rowadr , const int * diagnum , const int * colind ) {
1580
1612
// x <- L^-T x
1581
1613
for (int i = nv - 1 ; i > 0 ; i -- ) {
1582
1614
// skip diagonal (simple) rows, exploit sparsity of input vector
1583
1615
if (diagnum [i ] || x [i ] == 0 ) {
1584
1616
continue ;
1585
1617
}
1586
1618
1587
- int d = diagind [i ];
1619
+ int d = rownnz [i ] - 1 ;
1588
1620
int adr_i = rowadr [i ];
1589
1621
mjtNum x_i = x [i ];
1590
1622
for (int j = 0 ; j < d ; j ++ ) {
@@ -1607,7 +1639,7 @@ void mj_solveLDs(mjtNum* restrict x, const mjtNum* qLDs, const mjtNum* qLDiagInv
1607
1639
}
1608
1640
1609
1641
int adr = rowadr [i ];
1610
- x [i ] -= mju_dotSparse (qLDs + adr , x , diagind [i ], colind + adr , /*flg_unc1=*/ 0 );
1642
+ x [i ] -= mju_dotSparse (qLDs + adr , x , rownnz [i ] - 1 , colind + adr , /*flg_unc1=*/ 0 );
1611
1643
}
1612
1644
}
1613
1645
0 commit comments