Skip to content

Commit

Permalink
In the C implementation of the ergm.eta() family, fixed the memory er…
Browse files Browse the repository at this point in the history
…ror when the dimension of theta is 0.
  • Loading branch information
krivit committed Dec 23, 2024
1 parent 8bd0d94 commit d0c5e5c
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 15 deletions.
27 changes: 15 additions & 12 deletions src/etamap.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,24 @@
#include "ergm_etamap.h"
#include <Rversion.h>

#define SETUP_CALL(fun) \
SEXP cm = VECTOR_ELT(curved, i); \
SEXP toR = getListElement(cm, "to"); \
unsigned int to = INTEGER(toR)[0]; \
unsigned int nto = length(toR); \
SEXP fromR = getListElement(cm, "from"); \
unsigned int from = INTEGER(fromR)[0]; \
unsigned int nfrom = length(fromR); \
SEXP cov = getListElement(cm, "cov"); \
SEXP fun = getListElement(cm, #fun); \
\
/* UINT_MAX's are there to segfault as soon as possible if empty from
and to vectors are actually used rather than return misleading
results. */
#define SETUP_CALL(fun) \
SEXP cm = VECTOR_ELT(curved, i); \
SEXP toR = getListElement(cm, "to"); \
unsigned int nto = length(toR); \
unsigned int to = nto ? INTEGER(toR)[0] : UINT_MAX; \
SEXP fromR = getListElement(cm, "from"); \
unsigned int nfrom = length(fromR); \
unsigned int from = nfrom ? INTEGER(fromR)[0] : UINT_MAX; \
SEXP cov = getListElement(cm, "cov"); \
SEXP fun = getListElement(cm, #fun); \
\
SEXP pos = call, arg; \
SETCAR(pos, fun); pos = CDR(pos); \
SETCAR(pos, (arg = allocVector(REALSXP, nfrom))); pos = CDR(pos); /* Don't need to PROTECT the vector this way. */ \
memcpy(REAL(arg), theta1+from, nfrom*sizeof(double)); \
if(nfrom) memcpy(REAL(arg), theta1+from, nfrom*sizeof(double)); \
SETCAR(pos, ScalarInteger(nto)); pos = CDR(pos); \
SETCAR(pos, cov);

Expand Down
6 changes: 3 additions & 3 deletions tests/testthat/test-C-curved.R
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ ergm.etagradmult.R <- function(theta, v, etamap) {
}

data(faux.mesa.high)
flom <- ergm_model(~edges+gwesp()+gwdegree()+absdiffcat("Grade")+Offset(~nodefactor("Grade"),c(+1,-1), c(2,3))+gwesp()+NodematchFilter(~gwesp()+nodefactor("Grade"), "Grade"), faux.mesa.high)
(neta <- nparam(flom, canonical=TRUE))
(ntheta <- nparam(flom, canonical=FALSE))
flom <- ergm_model(~edges+gwesp()+gwdegree()+absdiffcat("Grade")+Offset(~edges+edges,c(+1,-1))+Offset(~nodefactor("Grade"),c(+1,-1), c(2,3))+gwesp()+NodematchFilter(~gwesp()+nodefactor("Grade"), "Grade"), faux.mesa.high)
neta <- nparam(flom, canonical=TRUE)
ntheta <- nparam(flom, canonical=FALSE)

test_that("C implementation of ergm.eta gives the same answer as R implementation.", {
expect_equal(ergm.eta(1:ntheta, flom$etamap), ergm.eta.R(1:ntheta, flom$etamap))
Expand Down

0 comments on commit d0c5e5c

Please sign in to comment.