forked from dankelley/oce
-
Notifications
You must be signed in to change notification settings - Fork 0
/
trap.c
68 lines (65 loc) · 1.89 KB
/
trap.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
#include <R.h>
#include <Rdefines.h>
#include <Rinternals.h>
/*
system("R CMD SHLIB trap.c")
x <- seq(0, 1, 0.1)
y <- 2*x + 3*x^2
dyn.load("trap.so")
print(.Call("trap", x, y, "A"))
print(.Call("trap", x, y, TRUE))
*/
SEXP trap(SEXP x, SEXP y, SEXP type)
{
PROTECT(x = AS_NUMERIC(x));
PROTECT(y = AS_NUMERIC(y));
PROTECT(type = AS_INTEGER(type));
int nx = length(x), ny = length(y);
if ((nx > 1) && nx != ny)
error("lengths of x (%d) and y (%d) must match", nx, ny);
double *xp = REAL(x), *yp = REAL(y);
double dx = 1.0;
if (nx == 1)
dx = *xp;
int *typep = INTEGER(type);
SEXP res;
double *resp = NULL;
switch(*typep) {
case 0: // area
PROTECT(res = NEW_NUMERIC(1));
resp = REAL(res);
*resp = 0.0;
for (int i = 1; i < ny; i++) {
if (nx != 1)
dx = (xp[i] - xp[i-1]);
*resp += 0.5 * (yp[i] + yp[i-1]) * dx;
}
break;
case 1: // area elements
PROTECT(res = NEW_NUMERIC(ny));
resp = REAL(res);
resp[0] = 0.0;
for (int i = 1; i < ny; i++) {
if (nx != 1)
dx = (xp[i] - xp[i-1]);
resp[i] = 0.5 * (yp[i] + yp[i-1]) * dx;
}
break;
case 2: // cumulative area elements
PROTECT(res = NEW_NUMERIC(ny));
resp = REAL(res);
resp[0] = 0.0;
for (int i = 1; i < ny; i++) {
if (nx != 1)
dx = (xp[i] - xp[i-1]);
resp[i] = resp[i-1] + 0.5 * (yp[i] + yp[i-1]) * dx;
}
break;
default:
PROTECT(res = NEW_NUMERIC(1));
resp[0] = 0.0;
error("unknown type %d; must be 0, 1, or 2\n", *typep);
}
UNPROTECT(4);
return(res);
}