Skip to content

Commit c24e7ac

Browse files
Dynamic allocation of logging toggles (#126)
fixes #123 Co-authored-by: Pavel N. Krivitsky <p.krivitsky@unsw.edu.au>
1 parent f84873b commit c24e7ac

File tree

4 files changed

+61
-25
lines changed

4 files changed

+61
-25
lines changed

src/MCMCDyn.c

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,23 @@ SEXP MCMCDyn_wrapper(SEXP stateR, // ergm_state
5252
memset(REAL(sample), 0, (asInteger(nsteps) + 1)*m->n_stats*sizeof(double));
5353
memcpy(REAL(sample), s->stats, m->n_stats*sizeof(double));
5454

55-
SEXP difftime = PROTECT(allocVector(INTSXP, asInteger(log_changes) ? asInteger(maxchanges) : 0));
56-
SEXP difftail = PROTECT(allocVector(INTSXP, asInteger(log_changes) ? asInteger(maxchanges) : 0));
57-
SEXP diffhead = PROTECT(allocVector(INTSXP, asInteger(log_changes) ? asInteger(maxchanges) : 0));
58-
SEXP diffto = PROTECT(allocVector(INTSXP, asInteger(log_changes) ? asInteger(maxchanges) : 0));
59-
memset(INTEGER(difftime), 0, asInteger(log_changes) ? asInteger(maxchanges)*sizeof(int) : 0);
60-
memset(INTEGER(difftail), 0, asInteger(log_changes) ? asInteger(maxchanges)*sizeof(int) : 0);
61-
memset(INTEGER(diffhead), 0, asInteger(log_changes) ? asInteger(maxchanges)*sizeof(int) : 0);
62-
memset(INTEGER(diffto), 0, asInteger(log_changes) ? asInteger(maxchanges)*sizeof(int) : 0);
55+
kvint difftime, difftail, diffhead, diffto;
56+
kv_init(difftime);
57+
kv_init(difftail);
58+
kv_init(diffhead);
59+
kv_init(diffto);
60+
61+
// pre-allocate the 0th element for size
62+
kv_push(int, difftime, 0);
63+
kv_push(int, difftail, 0);
64+
kv_push(int, diffhead, 0);
65+
kv_push(int, diffto, 0);
6366

6467
SEXP status;
6568
if(MHp) status = PROTECT(ScalarInteger(MCMCSampleDyn(s,
6669
dur_inf,
6770
REAL(eta),
68-
asInteger(collect)?REAL(sample):NULL, asInteger(maxedges), asInteger(maxchanges), asInteger(log_changes), (Vertex *)INTEGER(difftime), (Vertex *)INTEGER(difftail), (Vertex *)INTEGER(diffhead), INTEGER(diffto),
71+
asInteger(collect)?REAL(sample):NULL, asInteger(maxedges), asInteger(maxchanges), asInteger(log_changes), &difftime, &difftail, &diffhead, &diffto,
6972
asInteger(nsteps), asInteger(min_MH_interval), asInteger(max_MH_interval), asReal(MH_pval), asReal(MH_interval_add), asInteger(burnin), asInteger(interval),
7073
asInteger(verbose))));
7174
else status = PROTECT(ScalarInteger(MCMCDyn_MH_FAILED));
@@ -81,10 +84,15 @@ SEXP MCMCDyn_wrapper(SEXP stateR, // ergm_state
8184
SET_VECTOR_ELT(outl, 2, ErgmStateRSave(s));
8285
}
8386

84-
SET_VECTOR_ELT(outl, 3, difftime);
85-
SET_VECTOR_ELT(outl, 4, difftail);
86-
SET_VECTOR_ELT(outl, 5, diffhead);
87-
SET_VECTOR_ELT(outl, 6, diffto);
87+
SET_VECTOR_ELT(outl, 3, PROTECT(kvint_to_SEXP(difftime)));
88+
SET_VECTOR_ELT(outl, 4, PROTECT(kvint_to_SEXP(difftail)));
89+
SET_VECTOR_ELT(outl, 5, PROTECT(kvint_to_SEXP(diffhead)));
90+
SET_VECTOR_ELT(outl, 6, PROTECT(kvint_to_SEXP(diffto)));
91+
92+
kv_destroy(difftime);
93+
kv_destroy(difftail);
94+
kv_destroy(diffhead);
95+
kv_destroy(diffto);
8896

8997
ErgmStateDestroy(s);
9098
PutRNGstate(); /* Disable RNG before returning */
@@ -110,7 +118,7 @@ MCMCDynStatus MCMCSampleDyn(ErgmState *s,
110118
int maxedges,
111119
int maxchanges,
112120
int log_changes,
113-
Vertex *difftime, Vertex *difftail, Vertex *diffhead, int *diffto,
121+
kvint *difftime, kvint *difftail, kvint *diffhead, kvint *diffto,
114122
// MCMC settings.
115123
unsigned int nsteps, unsigned int min_MH_interval, unsigned int max_MH_interval, double MH_pval, double MH_interval_add,
116124
unsigned int burnin, unsigned int interval,
@@ -190,7 +198,12 @@ MCMCDynStatus MCMCSampleDyn(ErgmState *s,
190198
}
191199
}
192200

193-
if(log_changes) difftime[0]=difftail[0]=diffhead[0]=diffto[0]=nextdiffedge-1;
201+
if(log_changes) {
202+
kv_A(*difftime, 0) = nextdiffedge - 1;
203+
kv_A(*difftail, 0) = nextdiffedge - 1;
204+
kv_A(*diffhead, 0) = nextdiffedge - 1;
205+
kv_A(*diffto, 0) = nextdiffedge - 1;
206+
}
194207
return MCMCDyn_OK;
195208
}
196209

@@ -223,7 +236,7 @@ MCMCDynStatus MCMCDyn1Step(ErgmState *s,
223236
// Space for output.
224237
double *stats,
225238
unsigned int maxchanges, Edge *nextdiffedge,
226-
Vertex *difftime, Vertex *difftail, Vertex *diffhead, int *diffto,
239+
kvint *difftime, kvint *difftail, kvint *diffhead, kvint *diffto,
227240
// MCMC settings.
228241
unsigned int min_MH_interval, unsigned int max_MH_interval, double MH_pval, double MH_interval_add,
229242
// Verbosity.
@@ -343,7 +356,7 @@ MCMCDynStatus MCMCDyn1Step_advance(ErgmState *s,
343356
// Space for output.
344357
double *stats,
345358
unsigned int maxchanges, Edge *nextdiffedge,
346-
Vertex *difftime, Vertex *difftail, Vertex *diffhead, int *diffto,
359+
kvint *difftime, kvint *difftail, kvint *diffhead, kvint *diffto,
347360
// Verbosity.
348361
int verbose){
349362
StoreDyadMapInt *discord = dur_inf->discord;
@@ -358,10 +371,10 @@ MCMCDynStatus MCMCDyn1Step_advance(ErgmState *s,
358371
kh_foreach_key(discord, dyad,{
359372
if(*nextdiffedge<maxchanges){
360373
// and record the toggle.
361-
if(difftime) difftime[*nextdiffedge] = t;
362-
if(difftail) difftail[*nextdiffedge] = dyad.tail;
363-
if(diffhead) diffhead[*nextdiffedge] = dyad.head;
364-
if(diffto) diffto[*nextdiffedge] = GetEdge(dyad.tail,dyad.head,nwp);
374+
if(difftime) kv_push(int, *difftime, t);
375+
if(difftail) kv_push(int, *difftail, dyad.tail);
376+
if(diffhead) kv_push(int, *diffhead, dyad.head);
377+
if(diffto) kv_push(int, *diffto, GetEdge(dyad.tail,dyad.head,nwp));
365378
(*nextdiffedge)++;
366379
}else{
367380
return(MCMCDyn_TOO_MANY_CHANGES);

src/MCMCDyn.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "tergm_model.h"
1818
#include "ergm_state.h"
1919
#include "changestats_lasttoggle.h"
20+
#include "kvint.h"
2021

2122
// TODO: This might be worth moving into a common "constants.h".
2223
typedef enum MCMCDynStatus_enum {
@@ -34,10 +35,10 @@ MCMCDynStatus MCMCSampleDyn(ErgmState *s,
3435
int maxedges,
3536
int maxchanges,
3637
int log_changes,
37-
Vertex *difftime, Vertex *difftail, Vertex *diffhead, int *diffto,
38+
kvint *difftime, kvint *difftail, kvint *diffhead, kvint *diffto,
3839
// MCMC settings.
3940
unsigned int nsteps, unsigned int min_MH_interval, unsigned int max_MH_interval, double MH_pval, double MH_interval_add,
40-
unsigned int burnin, unsigned int interval,
41+
unsigned int burnin, unsigned int interval,
4142
// Verbosity.
4243
int verbose);
4344

@@ -47,7 +48,7 @@ MCMCDynStatus MCMCDyn1Step(ErgmState *s,
4748
// Space for output.
4849
double *stats,
4950
unsigned int maxchanges, Edge *nextdiffedge,
50-
Vertex *difftime, Vertex *difftail, Vertex *diffhead, int *diffto,
51+
kvint *difftime, kvint *difftail, kvint *diffhead, kvint *diffto,
5152
// MCMC settings.
5253
unsigned int min_MH_interval, unsigned int max_MH_interval, double MH_pval, double MH_interval_add,
5354
// Verbosity.
@@ -58,7 +59,7 @@ MCMCDynStatus MCMCDyn1Step_advance(ErgmState *s,
5859
// Space for output.
5960
double *stats,
6061
unsigned int maxchanges, Edge *nextdiffedge,
61-
Vertex *difftime, Vertex *difftail, Vertex *diffhead, int *diffto,
62+
kvint *difftime, kvint *difftail, kvint *diffhead, kvint *diffto,
6263
// Verbosity.
6364
int verbose);
6465
#endif

src/kvint.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "kvint.h"
2+
3+
SEXP kvint_to_SEXP(kvint v) {
4+
int size = kv_size(v);
5+
SEXP out = PROTECT(allocVector(INTSXP, size));
6+
int *out_ptr = INTEGER(out);
7+
for (int i = 0; i < size; i++) {
8+
out_ptr[i] = kv_A(v, i);
9+
}
10+
UNPROTECT(1);
11+
return out;
12+
}

src/kvint.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef INCLUDE_SRC_KVINT_H_
2+
#define INCLUDE_SRC_KVINT_H_
3+
4+
#include <Rinternals.h>
5+
#include "ergm_kvec.h"
6+
7+
typedef kvec_t(int) kvint;
8+
SEXP kvint_to_SEXP(kvint v);
9+
10+
#endif // INCLUDE_SRC_KVINT_H_

0 commit comments

Comments
 (0)