@@ -928,7 +928,7 @@ int mj_sizeModel(const mjModel* m) {
928928// construct sparse representation of dof-dof matrix
929929static void makeDofDofSparse (const mjModel * m , mjData * d ,
930930 int * rownnz , int * rowadr , int * diag , int * colind ,
931- int reduced ) {
931+ int reduced , int upper ) {
932932 int nv = m -> nv ;
933933
934934 // no dofs, nothing to do
@@ -947,13 +947,13 @@ static void makeDofDofSparse(const mjModel* m, mjData* d,
947947 rownnz [i ]++ ;
948948
949949 // process below diagonal unless reduced and dof is simple
950- if (!reduced || ! m -> dof_simplenum [i ]) {
950+ if (!( reduced && m -> dof_simplenum [i ]) ) {
951951 while ((j = m -> dof_parentid [j ]) >= 0 ) {
952952 // both reduced and non-reduced have lower triangle
953953 rownnz [i ]++ ;
954954
955- // only non-reduced has upper triangle
956- if (! reduced ) rownnz [j ]++ ;
955+ // add upper triangle if requested
956+ if (upper ) rownnz [j ]++ ;
957957 }
958958 }
959959 }
@@ -972,14 +972,14 @@ static void makeDofDofSparse(const mjModel* m, mjData* d,
972972 colind [rowadr [i ] + remaining [i ]] = i ;
973973
974974 // process below diagonal unless reduced and dof is simple
975- if (!reduced || ! m -> dof_simplenum [i ]) {
975+ if (!( reduced && m -> dof_simplenum [i ]) ) {
976976 int j = i ;
977977 while ((j = m -> dof_parentid [j ]) >= 0 ) {
978978 remaining [i ]-- ;
979979 colind [rowadr [i ] + remaining [i ]] = j ;
980980
981- // only non-reduced has upper triangle
982- if (! reduced ) {
981+ // add upper triangle if requested
982+ if (upper ) {
983983 remaining [j ]-- ;
984984 colind [rowadr [j ] + remaining [j ]] = i ;
985985 }
@@ -995,7 +995,8 @@ static void makeDofDofSparse(const mjModel* m, mjData* d,
995995 }
996996
997997 // check total nnz; SHOULD NOT OCCUR
998- if (rowadr [nv - 1 ] + rownnz [nv - 1 ] != (reduced ? m -> nC : m -> nD )) {
998+ int expected_nnz = upper ? m -> nD : (reduced ? m -> nC : m -> nM );
999+ if (rowadr [nv - 1 ] + rownnz [nv - 1 ] != expected_nnz ) {
9991000 mjERROR ("sum of rownnz different from expected" );
10001001 }
10011002
@@ -1131,18 +1132,23 @@ static void checkDBSparse(const mjModel* m, mjData* d) {
11311132
11321133
11331134
1134- // integer valued dst[D or C] = src[M], handle different sparsity representations
1135+ // integer valued dst[D or C or M ] = src[M (legacy) ], handle different sparsity representations
11351136static void copyM2Sparse (const mjModel * m , mjData * d , int * dst , const int * src ,
1136- int reduced ) {
1137+ int reduced , int upper ) {
11371138 int nv = m -> nv ;
11381139 const int * rownnz ;
11391140 const int * rowadr ;
1140- if (reduced ) {
1141+ if (reduced && ! upper ) {
11411142 rownnz = d -> C_rownnz ;
11421143 rowadr = d -> C_rowadr ;
1143- } else {
1144+ } else if (!reduced && !upper ) {
1145+ rownnz = d -> M_rownnz ;
1146+ rowadr = d -> M_rowadr ;
1147+ } else if (!reduced && upper ) {
11441148 rownnz = d -> D_rownnz ;
11451149 rowadr = d -> D_rowadr ;
1150+ } else {
1151+ mjERROR ("unsupported sparsity structure (reduced + upper)" );
11461152 }
11471153
11481154 mj_markStack (d );
@@ -1160,14 +1166,14 @@ static void copyM2Sparse(const mjModel* m, mjData* d, int* dst, const int* src,
11601166 adr ++ ;
11611167
11621168 // process below diagonal unless reduced and dof is simple
1163- if (!reduced || ! m -> dof_simplenum [i ]) {
1169+ if (!( reduced && m -> dof_simplenum [i ]) ) {
11641170 int j = i ;
11651171 while ((j = m -> dof_parentid [j ]) >= 0 ) {
11661172 remaining [i ]-- ;
11671173 dst [rowadr [i ] + remaining [i ]] = src [adr ];
11681174
1169- // only non-reduced has upper triangle
1170- if (! reduced ) {
1175+ // add upper triangle if requested
1176+ if (upper ) {
11711177 remaining [j ]-- ;
11721178 dst [rowadr [j ] + remaining [j ]] = src [adr ];
11731179 }
@@ -1213,16 +1219,16 @@ static void copyD2MSparse(const mjModel* m, const mjData* d, int* dst, const int
12131219
12141220
12151221
1216- // construct index mappings between M <-> D and M -> C
1217- static void makeDofDofmap (const mjModel * m , mjData * d ) {
1222+ // construct index mappings between M <-> D, M -> C, M (legacy) -> M (CSR)
1223+ static void makeDofDofmaps (const mjModel * m , mjData * d ) {
12181224 int nM = m -> nM , nC = m -> nC , nD = m -> nD ;
12191225 mj_markStack (d );
12201226
12211227 // make mapM2D
12221228 int * M = mjSTACKALLOC (d , nM , int );
12231229 for (int i = 0 ; i < nM ; i ++ ) M [i ] = i ;
12241230 for (int i = 0 ; i < nD ; i ++ ) d -> mapM2D [i ] = -1 ;
1225- copyM2Sparse (m , d , d -> mapM2D , M , /*reduced=*/ 0 );
1231+ copyM2Sparse (m , d , d -> mapM2D , M , /*reduced=*/ 0 , /*upper=*/ 1 );
12261232
12271233 // check that all indices are filled in
12281234 for (int i = 0 ; i < nD ; i ++ ) {
@@ -1246,7 +1252,7 @@ static void makeDofDofmap(const mjModel* m, mjData* d) {
12461252
12471253 // make mapM2C
12481254 for (int i = 0 ; i < nC ; i ++ ) d -> mapM2C [i ] = -1 ;
1249- copyM2Sparse (m , d , d -> mapM2C , M , /*reduced=*/ 1 );
1255+ copyM2Sparse (m , d , d -> mapM2C , M , /*reduced=*/ 1 , /*upper=*/ 0 );
12501256
12511257 // check that all indices are filled in
12521258 for (int i = 0 ; i < nC ; i ++ ) {
@@ -1255,6 +1261,17 @@ static void makeDofDofmap(const mjModel* m, mjData* d) {
12551261 }
12561262 }
12571263
1264+ // make mapM2M
1265+ for (int i = 0 ; i < nM ; i ++ ) d -> mapM2M [i ] = -1 ;
1266+ copyM2Sparse (m , d , d -> mapM2M , M , /*reduced=*/ 0 , /*upper=*/ 0 );
1267+
1268+ // check that all indices are filled in
1269+ for (int i = 0 ; i < nM ; i ++ ) {
1270+ if (d -> mapM2M [i ] < 0 ) {
1271+ mjERROR ("unassigned index in mapM2M" );
1272+ }
1273+ }
1274+
12581275 mj_freeStack (d );
12591276}
12601277
@@ -1965,15 +1982,19 @@ static void _resetData(const mjModel* m, mjData* d, unsigned char debug_value) {
19651982 // construct sparse matrix representations
19661983 if (m -> body_dofadr ) {
19671984 // make D
1968- makeDofDofSparse (m , d , d -> D_rownnz , d -> D_rowadr , d -> D_diag , d -> D_colind , /*reduced=*/ 0 );
1985+ makeDofDofSparse (m , d , d -> D_rownnz , d -> D_rowadr , d -> D_diag , d -> D_colind ,
1986+ /*reduced=*/ 0 , /*upper=*/ 1 );
19691987
19701988 // make B, check D and B
19711989 makeBSparse (m , d );
19721990 checkDBSparse (m , d );
19731991
1974- // make C
1975- makeDofDofSparse (m , d , d -> C_rownnz , d -> C_rowadr , NULL , d -> C_colind , /*reduced=*/ 1 );
1976- makeDofDofmap (m , d );
1992+ // make M, C
1993+ makeDofDofSparse (m , d , d -> M_rownnz , d -> M_rowadr , NULL , d -> M_colind , /*reduced=*/ 0 , /*upper=*/ 0 );
1994+ makeDofDofSparse (m , d , d -> C_rownnz , d -> C_rowadr , NULL , d -> C_colind , /*reduced=*/ 1 , /*upper=*/ 0 );
1995+
1996+ // make index mappings: mapM2D, mapD2M, mapM2C, mapM2M
1997+ makeDofDofmaps (m , d );
19771998 }
19781999
19792000 // restore pluginstate and plugindata
0 commit comments