forked from kingaa/pomp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimulate.c
125 lines (87 loc) · 3.16 KB
/
simulate.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// -*- C++ -*-
#include <Rdefines.h>
#include "internal.h"
SEXP do_simulate (SEXP object, SEXP params, SEXP nsim, SEXP rettype, SEXP gnsi)
{
SEXP t0, times, x0, x, y;
SEXP ans = R_NilValue, ans_names = R_NilValue;
SEXP simnames;
int return_type = *(INTEGER(rettype)); // 0 = array, 1 = pomps
if (LENGTH(nsim) != 1) err("'nsim' must be a single integer"); // #nocov
PROTECT(params = as_matrix(params));
PROTECT(t0 = GET_SLOT(object,install("t0")));
PROTECT(times = GET_SLOT(object,install("times")));
// initialize the simulations
PROTECT(x0 = do_rinit(object,params,t0,nsim,gnsi));
PROTECT(simnames = GET_COLNAMES(GET_DIMNAMES(x0)));
// call 'rprocess' to simulate state process
PROTECT(x = do_rprocess(object,x0,t0,times,params,gnsi));
// call 'rmeasure' to simulate the measurement process
PROTECT(y = do_rmeasure(object,x,times,params,gnsi));
setcolnames(x,simnames);
setcolnames(y,simnames);
int nprotect = 7;
switch (return_type) {
case 0: // return a list of arrays
PROTECT(ans = NEW_LIST(2));
PROTECT(ans_names = NEW_CHARACTER(2));
nprotect += 2;
SET_STRING_ELT(ans_names,0,mkChar("states"));
SET_STRING_ELT(ans_names,1,mkChar("obs"));
SET_NAMES(ans,ans_names);
SET_ELEMENT(ans,0,x);
SET_ELEMENT(ans,1,y);
break;
case 1: default:
// a list to hold the pomp objects
{
SEXP pp, xx, yy, po;
const int *xdim;
int nvar, npar, nobs, nsim, ntim, nparsets;
int dim[2], i, j, k;
PROTECT(po = duplicate(object));
SET_SLOT(po,install("t0"),t0);
SET_SLOT(po,install("times"),times);
xdim = INTEGER(GET_DIM(x));
nvar = xdim[0]; nsim = xdim[1]; ntim = xdim[2];
xdim = INTEGER(GET_DIM(y));
nobs = xdim[0]; // second dimensions of 'x' and 'y' must agree
xdim = INTEGER(GET_DIM(params));
npar = xdim[0]; nparsets = xdim[1];
dim[0] = nvar; dim[1] = ntim;
PROTECT(xx = makearray(2,dim));
setrownames(xx,GET_ROWNAMES(GET_DIMNAMES(x)),2);
SET_SLOT(po,install("states"),xx);
dim[0] = nobs; dim[1] = ntim;
PROTECT(yy = makearray(2,dim));
setrownames(yy,GET_ROWNAMES(GET_DIMNAMES(y)),2);
SET_SLOT(po,install("data"),yy);
PROTECT(pp = NEW_NUMERIC(npar));
SET_NAMES(pp,GET_ROWNAMES(GET_DIMNAMES(params)));
SET_SLOT(po,install("params"),pp);
PROTECT(ans = NEW_LIST(nsim));
SET_NAMES(ans,simnames);
nprotect += 5;
for (k = 0; k < nsim; k++) {
SEXP po2;
double *xs = REAL(x), *ys = REAL(y), *ps = REAL(params);
double *xt, *yt, *pt;
PROTECT(po2 = duplicate(po));
xt = REAL(GET_SLOT(po2,install("states")));
yt = REAL(GET_SLOT(po2,install("data")));
pt = REAL(GET_SLOT(po2,install("params")));
memcpy(pt,ps+npar*(k%nparsets),npar*sizeof(double));
// copy x[,k,] and y[,k,] into po2
for (j = 0; j < ntim; j++) {
for (i = 0; i < nvar; i++, xt++) *xt = xs[i+nvar*(k+nsim*j)];
for (i = 0; i < nobs; i++, yt++) *yt = ys[i+nobs*(k+nsim*j)];
}
SET_ELEMENT(ans,k,po2);
UNPROTECT(1);
}
break;
}
}
UNPROTECT(nprotect);
return ans;
}