77 rMCspMF - return final state only
88 rMCspMH - return history of chain
99
10- Sparse matrix is required to be in row-major sparse form
11- (class 'dgRmatrix') which can be achieved using 'as(, "RsparseMatrix")'
12- Information passed to the C code:
10+ These C functions are called from 'sparseMarkov.R'
11+
12+ The transition matrix M is required to be in row-major sparse form
13+ (virtual class 'RsparseMatrix' which embraces 'dgRMatrix' and 'dtRMatrix')
14+ Matrices can be converted to this form using 'as(M, "RsparseMatrix")'
15+
16+ Data passed to the C code from the sparse matrix M:
1317
14- nrows Number of rows (and columns) of matrix dim(M)[1]
15- nsparse Number of nonzero entries in matrix length(M@x)
16- probval Vector of nonzero entries M@x
17- colindex Vector of column indices for nonzero entries M@j
18- rowstart Start position in M@x, M@j of each row M@p
18+ nrows Number of rows (and columns) of matrix dim(M)[1]
19+ nsparse Number of nonzero entries in matrix length(M@x)
20+ probval Vector of nonzero entries M@x
21+ colindex Vector of column indices for nonzero entries M@j
22+ rowstart Start position in M@x, M@j of each row of matrix M@p
1923
2024 The indices in 'colindex' and 'rowstart' are zero-based.
2125
22- $Revision: 1.4 $ $Date: 2026/04/10 08:04:44 $
26+ $Revision: 1.8 $ $Date: 2026/04/11 09:54:48 $
2327
2428 Copyright (c) Adrian Baddeley 2026
2529 GNU Public Licence (>= 2.0)
@@ -50,41 +54,59 @@ void rMCspMF(
5054 int * nsteps ,
5155 /* output: final state for each point */
5256 int * endpos ) {
53- register int istep , ipoint , currentpos , thisrowstart , nextrowstart , j , k ;
57+ register int steps , points , entries , currentpos , j ;
58+ int thisrowstart , nextrowstart , thisrowlength ;
5459 register double u ;
5560 int Nrows , Nsparse , Npoints , Nsteps ;
61+ register int * sp , * ep , * cp ;
62+ register double * pp ;
5663
5764 Nrows = * nrows ;
5865 Nsparse = * nsparse ;
5966 Npoints = * npoints ;
6067 Nsteps = * nsteps ;
6168
6269 GetRNGstate ();
70+
71+ /* initialise pointers */
72+ sp = startpos ;
73+ ep = endpos ;
6374
64- for (ipoint = 0 ; ipoint < Npoints ; ipoint ++ ) {
75+ for (points = Npoints ; points > 0 ; -- points , ++ sp , ++ ep ) {
6576 /* initialise position */
66- currentpos = startpos [ ipoint ] ;
77+ currentpos = * sp ;
6778 /* run chain */
68- for (istep = 0 ; istep < Nsteps ; istep ++ ) {
69- /* transition probabilities from current position */
79+ for (steps = Nsteps ; steps > 0 ; -- steps ) {
80+ /* nonzero transition probabilities from current position */
7081 thisrowstart = rowstart [currentpos ];
7182 nextrowstart = ((currentpos + 1 ) < Nrows ) ? rowstart [currentpos + 1 ] : Nsparse ;
83+ thisrowlength = nextrowstart - thisrowstart ;
7284 /* random number */
7385 u = unif_rand ();
86+ /* pointers into probval[] and colindex[] for this row */
87+ pp = probval + thisrowstart ;
88+ cp = colindex + thisrowstart ;
89+ /* loop over nonzero entries in current row */
7490 j = -1 ;
75- for (k = thisrowstart ; k < nextrowstart ; k ++ ) {
76- u -= probval [ k ] ;
91+ for (entries = thisrowlength ; entries > 0 ; -- entries , pp ++ , cp ++ ) {
92+ u -= * pp ;
7793 if (u <= 0.0 ) {
7894 /* jump */
79- j = colindex [ k ] ;
95+ j = * cp ;
8096 break ;
8197 }
8298 }
83- if (j < 0 ) j = colindex [nextrowstart - 1 ];
99+ if (j < 0 ) {
100+ /*
101+ Random number exceeded row sum of transition matrix.
102+ theoretically impossible -- can occur due to numerical error
103+ */
104+ j = colindex [nextrowstart - 1 ];
105+ }
84106 currentpos = j ;
85107 }
86108 /* save state */
87- endpos [ ipoint ] = currentpos ;
109+ * ep = currentpos ;
88110 }
89111
90112 PutRNGstate ();
@@ -111,11 +133,13 @@ void rMCspMH(
111133 int * nsteps ,
112134 /* output: history for each point ( (Nsteps + 1) * Npoints ) */
113135 int * history ) {
114- register int istep , ipoint , currentpos , thisrowstart , nextrowstart , j , k ;
136+ register int steps , points , entries , currentpos , j ;
137+ int thisrowstart , nextrowstart , thisrowlength ;
115138 register double u ;
116139 int Nrows , Nsparse , Npoints , Nsteps , Nhistory ;
117- int * histp ;
118-
140+ register int * sp , * cp , * histp ;
141+ register double * pp ;
142+
119143 Nrows = * nrows ;
120144 Nsparse = * nsparse ;
121145 Npoints = * npoints ;
@@ -127,30 +151,43 @@ void rMCspMH(
127151
128152 /* pointer to next entry in 'history' */
129153 histp = history ;
154+ /* pointer to initial state */
155+ sp = startpos ;
130156
131- for (ipoint = 0 ; ipoint < Npoints ; ipoint ++ ) {
157+ for (points = Npoints ; points > 0 ; -- points , ++ sp ) {
132158 /* initialise position */
133- currentpos = startpos [ ipoint ] ;
159+ currentpos = * sp ;
134160 /* save initial state */
135161 * histp = currentpos ;
136162 ++ histp ;
137- /* run chain for point number 'ipoint' */
138- for (istep = 0 ; istep < Nsteps ; istep ++ , histp ++ ) {
139- /* transition probabilities from current position */
163+ /* run chain */
164+ for (steps = Nsteps ; steps > 0 ; -- steps , ++ histp ) {
165+ /* nonzero transition probabilities from current position */
140166 thisrowstart = rowstart [currentpos ];
141167 nextrowstart = ((currentpos + 1 ) < Nrows ) ? rowstart [currentpos + 1 ] : Nsparse ;
168+ thisrowlength = nextrowstart - thisrowstart ;
142169 /* random number */
143170 u = unif_rand ();
171+ /* pointers into probval[] and colindex[] for this row */
172+ pp = probval + thisrowstart ;
173+ cp = colindex + thisrowstart ;
174+ /* loop over nonzero entries in current row */
144175 j = -1 ;
145- for (k = thisrowstart ; k < nextrowstart ; k ++ ) {
146- u -= probval [ k ] ;
176+ for (entries = thisrowlength ; entries > 0 ; -- entries , pp ++ , cp ++ ) {
177+ u -= * pp ;
147178 if (u <= 0.0 ) {
148179 /* jump */
149- j = colindex [ k ] ;
180+ j = * cp ;
150181 break ;
151182 }
152183 }
153- if (j < 0 ) j = colindex [nextrowstart - 1 ];
184+ if (j < 0 ) {
185+ /*
186+ Random number exceeded row sum of transition matrix.
187+ theoretically impossible -- can occur due to numerical error
188+ */
189+ j = colindex [nextrowstart - 1 ];
190+ }
154191 currentpos = j ;
155192 /* save state */
156193 * histp = currentpos ;
0 commit comments