@@ -1607,39 +1607,88 @@ void mj_solveLD(const mjModel* m, mjtNum* restrict x, int n,
1607
1607
1608
1608
// in-place sparse backsubstitution: x = inv(L'*D*L)*x
1609
1609
// like mj_solveLD, but using the CSR representation of L
1610
- void mj_solveLDs (mjtNum * restrict x , const mjtNum * qLDs , const mjtNum * qLDiagInv , int nv ,
1610
+ void mj_solveLDs (mjtNum * restrict x , const mjtNum * qLDs , const mjtNum * qLDiagInv , int nv , int n ,
1611
1611
const int * rownnz , const int * rowadr , const int * diagnum , const int * colind ) {
1612
- // x <- L^-T x
1613
- for (int i = nv - 1 ; i > 0 ; i -- ) {
1614
- // skip diagonal (simple) rows, exploit sparsity of input vector
1615
- if (diagnum [i ] || x [i ] == 0 ) {
1616
- continue ;
1612
+ // single vector
1613
+ if (n == 1 ) {
1614
+ // x <- L^-T x
1615
+ for (int i = nv - 1 ; i > 0 ; i -- ) {
1616
+ // skip diagonal rows, zero elements in input vector
1617
+ mjtNum x_i = x [i ];
1618
+ if (x_i == 0 || diagnum [i ]) {
1619
+ continue ;
1620
+ }
1621
+
1622
+ int start = rowadr [i ];
1623
+ int end = start + rownnz [i ] - 1 ;
1624
+ for (int adr = start ; adr < end ; adr ++ ) {
1625
+ x [colind [adr ]] -= qLDs [adr ] * x_i ;
1626
+ }
1617
1627
}
1618
1628
1619
- int d = rownnz [i ] - 1 ;
1620
- int adr_i = rowadr [i ];
1621
- mjtNum x_i = x [i ];
1622
- for (int j = 0 ; j < d ; j ++ ) {
1623
- int adr = adr_i + j ;
1624
- x [colind [adr ]] -= qLDs [adr ] * x_i ;
1629
+ // x <- D^-1 x
1630
+ for (int i = 0 ; i < nv ; i ++ ) {
1631
+ x [i ] *= qLDiagInv [i ];
1625
1632
}
1626
- }
1627
1633
1628
- // x(i) /= D(i,i)
1629
- for (int i = 0 ; i < nv ; i ++ ) {
1630
- x [i ] *= qLDiagInv [i ];
1634
+ // x <- L^-1 x
1635
+ for (int i = 1 ; i < nv ; i ++ ) {
1636
+ // skip diagonal rows
1637
+ if (diagnum [i ]) {
1638
+ i += diagnum [i ] - 1 ; // iterating forward: skip ahead, adjust i
1639
+ continue ;
1640
+ }
1641
+
1642
+ int adr = rowadr [i ];
1643
+ x [i ] -= mju_dotSparse (qLDs + adr , x , rownnz [i ] - 1 , colind + adr , /*flg_unc1=*/ 0 );
1644
+ }
1631
1645
}
1632
1646
1633
- // x <- L^-1 x
1634
- for (int i = 1 ; i < nv ; i ++ ) {
1635
- // skip diagonal (simple) rows
1636
- if (diagnum [i ]) {
1637
- i += diagnum [i ] - 1 ; // when iterating forward we can skip ahead
1638
- continue ;
1647
+ // multiple vectors
1648
+ else {
1649
+ // x <- L^-T x
1650
+ for (int i = nv - 1 ; i > 0 ; i -- ) {
1651
+ // skip diagonal rows
1652
+ if (diagnum [i ]) {
1653
+ continue ;
1654
+ }
1655
+
1656
+ int start = rowadr [i ];
1657
+ int end = start + rownnz [i ] - 1 ;
1658
+ for (int adr = start ; adr < end ; adr ++ ) {
1659
+ int j = colind [adr ];
1660
+ mjtNum val = qLDs [adr ];
1661
+ for (int offset = 0 ; offset < n * nv ; offset += nv ) {
1662
+ mjtNum x_i ;
1663
+ if ((x_i = x [i + offset ])) {
1664
+ x [j + offset ] -= val * x_i ;
1665
+ }
1666
+ }
1667
+ }
1668
+ }
1669
+
1670
+ // x <- D^-1 x
1671
+ for (int i = 0 ; i < nv ; i ++ ) {
1672
+ mjtNum invD_i = qLDiagInv [i ];
1673
+ for (int offset = 0 ; offset < n * nv ; offset += nv ) {
1674
+ x [i + offset ] *= invD_i ;
1675
+ }
1639
1676
}
1640
1677
1641
- int adr = rowadr [i ];
1642
- x [i ] -= mju_dotSparse (qLDs + adr , x , rownnz [i ] - 1 , colind + adr , /*flg_unc1=*/ 0 );
1678
+ // x <- L^-1 x
1679
+ for (int i = 1 ; i < nv ; i ++ ) {
1680
+ // skip diagonal rows
1681
+ if (diagnum [i ]) {
1682
+ i += diagnum [i ] - 1 ; // iterating forward: skip ahead, adjust i
1683
+ continue ;
1684
+ }
1685
+
1686
+ int adr = rowadr [i ];
1687
+ int d = rownnz [i ] - 1 ;
1688
+ for (int offset = 0 ; offset < n * nv ; offset += nv ) {
1689
+ x [i + offset ] -= mju_dotSparse (qLDs + adr , x + offset , d , colind + adr , /*flg_unc1=*/ 0 );
1690
+ }
1691
+ }
1643
1692
}
1644
1693
}
1645
1694
0 commit comments