Newer
Older
/*
* SPDX-FileCopyrightText: 2020 Helmholtz-Zentrum Dresden-Rossendorf
* <support@boogaart.de>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
// attention: comment this if not compiling
#include <stdio.h>
#ifdef _OPENMP
#include <omp.h>
#endif

Raimon Tolosana-Delgado
committed
#define USE_FC_LEN_T
#include <Rinternals.h>
#define inR // attention: this must be uncommented if not compiling
#ifdef inR
#include <R.h>
#include <Rmath.h>
#include <R_ext/BLAS.h>
#include <R_ext/Lapack.h>
#endif

Raimon Tolosana-Delgado
committed
#ifndef FCONE
# define FCONE
#endif
#define maxIntervals 1000
short int binBuf[maxIntervals];
double doubleBuf[maxIntervals];
/* int intBuf[maxIntervals];*/
/* massive use of functions to verify: min, max, abs, sqrt, cos, sin */
/* particularly needed: to build the meta-function that calls fbandXXXX
* functions, from line 328 */
typedef void (*vgramDensityFunctionPtr)(int d,double *,double *);
typedef double (*vgramFunctionPtr)(double,const double *);
typedef void (*bandSimFunctionPtr)(int m,const double *,double *,double,const double *);
/* invBitExp2
inverts the sequence of the bits.
this is used for the generation of almost equally space directions in 2D
Lantuejoul (2002), page 194
*/
double invBitExp2(int i) {
int bit = 1;
int inv = 0;
while(i) {
inv <<=1;
inv |= (i&1);
i>>=1;
bit<<=1;
}
return ((double)inv)/bit;
}
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
inverts the sequence of the digits in b-adict representation.
this is used for the generation of almost equally space directions in 3D
Lantuejoul (2002), page 194
*/
double invBitExp(int i,int b) {
int bit = 1;
int inv = 0;
while(i) {
inv *=b;
inv += (i%b);
i/=b;
bit*=b;
}
return ((double)inv)/bit;
}
/*
Gaussian covariance function
*/
double cGauss(double h,const double *extra) {
return exp(-(h*h));
}
/*
Spherical covariance function
*/
double cSph(double h,const double *extra) {
return( h<1 ? 1-1.5*h+0.5*(h*h*h): 0 );
}
/*
Exponential covariance function
*/
double cExp(double h,const double *extra) {
return exp(-h);
}
/*
Switcher for covariance functions
*/
vgramFunctionPtr cgramFunctions[]={
cGauss,cSph,cExp
};
static R_NativePrimitiveArgType CcalcCgram_t[] = {
/* dimX LDX X dimY LDY Y dimC C Nugget nCgr typeCgr A Sill moreC ijEq*/
INTSXP,INTSXP,REALSXP,INTSXP,INTSXP,REALSXP,INTSXP,REALSXP,REALSXP,INTSXP,INTSXP,REALSXP,REALSXP,REALSXP,LGLSXP
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
};
void CcalcCgram(
const int *dimX,
const int *LDX,
const double *X,
const int *dimY,
const int *LDY,
const double *Y,
const int *dimC,
double *C,
const double *Nugget, /* d x d*/
const int *nCgrams, /* 1 */
const int *typeCgram, /* length=nCgrams */
const double *A, /* nCgrams x m x m sqrt inverse Matrices */
const double *Sill, /* nCgrams x d x d*/
const double *moreCgramData, /* n x ?*/
const int *ijEqual
) {
int d=dimC[0];
int nX=dimC[1];
int nY=dimC[3];
int m =dimX[1];
int ldx = *LDX;
int ldy = *LDY;
if( dimC[2]!=d )
error("CcalcVgram: Expected covariance dimensions not compatible");
if( dimX[0]!=nX )
error("CcalcVgram: Output does not fit input size for X");
if( dimY[0]!=nY )
error("CcalcVgram: Output does not fit input size for Y");
if( dimY[1]!=m )
error("CcalcVgram: Column dimensions of X and Y do not fit");
if( m<1 || m>3)
error("Can not handel spatial dimensions outside 1-3");
int outBufSize=d*d*nX*nY;

Raimon Tolosana-Delgado
committed
int i,j,k,lx,ly,s; /* 20220424: ev removed */
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
double delta[3];
double v[3];
double h2,h,val;
for(i=0;i<outBufSize;i++)
C[i]=0.0;
if( *ijEqual ) {
if( nX!=nY )
error("CcalcVgram: ijEqual and rows of X and Y don't fit");
for(lx=0;lx<nX;lx++) {
for(i=0;i<d;i++)
for(j=0;j<d;j++)
C[i+d*(lx+nX*(j+d*lx))]=Nugget[i+d*j];
}
}
for(s=0;s<*nCgrams;s++) { // structure s
for(lx=0;lx<nX;lx++) // sample index on dataset X
for(ly=0;ly<nY;ly++) { // sample index on dataset Y
for(j=0;j<m;j++) // geographic coordinate index
delta[j]=Y[ly+ldy*j]-X[lx+ldx*j]; // compute spatial lags between the selected locations
h2=0;
for(j=0;j<m;j++) {
v[j]=0;
for(k=0;k<m;k++) {
v[j]+=A[s+*nCgrams * (j+m*k)]*delta[k];
}
h2+=v[j]*v[j];
}
h=sqrt(h2);
val=(*(cgramFunctions[typeCgram[s]]))(h,moreCgramData+s);
for(i=0;i<d;i++)
for(j=0;j<d;j++)
C[i+d*(lx+nX*(j+d*ly))] += val*Sill[s+*nCgrams*(i+d*j)];
}
}
}
/* BEGIN deprecated function ? */
/*
vsdfGauss (vector for spatial density function )
generates a vector of independent random normals in a vector
*/
void vsdfGauss(int d,double *extra,double *omega) {
int i;
for(i=0;i<d;i++)
omega[i]=norm_rand();
}
/* END deprecated function ? */
/*
fbandGauss
generates a sinus function with random phase and random frequence on
a band for a gaussian covariance structure.
This is a mixture of turning bands and spectral simulation.
*/
void fbandGauss(int n, /* number of locations */
const double *projs, /* projected locations */
double *band, /* output */
double range, /* projected range */
const double *extra /* extra parameter (unused), for consistency with other covariances */
){
/* Extract a freq. from the 1D Gaussian density along the unitdirection
* where projs were calculated. Evaluate a wave of random phase at the
* projs points. Return that wave */
int i;
double phase,amp,omega,d1;

Raimon Tolosana-Delgado
committed
omega = norm_rand() * M_SQRT2 / range * M_SQRT_3; /* sqrt(3) needed to produce effective range*/
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
phase = unif_rand() * M_2PI;
amp = M_SQRT2; /* Lantuejoul (2002), page 191 */
for(i=0;i<n;i++) {
d1 = phase + projs[i]*omega; // projs, *projs==projs[0], projs[i]==*(projs+i)
d1 = sin(d1);
band[i] = amp*d1;
}
}
// IS THIS RIGHT??
void fbandSph(int n, /* number of locations */
const double *projs, /* projected locations */
double *band, /* output */
double range, /* projected range */
const double *extra /* extra parameter (unused), for consistency with other covariances */
){
int i,j,nIntervals;
double t,x0,x1,effrange;
/* Lantuejoul (2002), page 197 */
/* Find the smallest proj; select a uniform point "x0" left from it at
* most "range" away. Domain = (x0, max(projs)) */
x0 = projs[0]; /* does min exist?? */
x1 = projs[0];
effrange = range;
// effrange = range *2.0; // this was an attempt to get reasonable range fitting
for(i=1;i<n;i++) {
if( projs[i]>x1 )
x1=projs[i];
else if( projs[i]<x0 )
x0=projs[i];
}
x0 += -unif_rand() * effrange;
nIntervals = (int) ceil((x1-x0)/effrange);
if( nIntervals > maxIntervals )
error("fbandSph: Exceeded maxIntervals");
for(i=0;i<nIntervals;i++)
binBuf[i] = unif_rand()<0.5?1:-1;
for(i=0;i<n;i++) {
t=(projs[i]-x0)/effrange;
j=(unsigned int)floor(t);
//band[i]=binBuf[j]*(t-j-0.5)*M_SQRT_3;
band[i]=binBuf[j]*(t-j-0.5)*2.0*M_SQRT_3;
}
}
int bsearchDouble(double x,int n,double *s) {
int j0=0;
int j1=n-1;
int j;
while(j1-j0>1) {
/* We know s[j0] <= x < s[j1] */
j = (j0+j1)/2;
if( x < s[j] )
j1=j;
else
j0=j;
}
return(j0);
}
void fbandExp(int n, /* number of locations */
const double *projs, /* projected locations */
double *band, /* output */
double range, /* projected range */
const double *extra /* extra parameter (unused), for consistency with other covariances */
){
int i,j,ns;

Raimon Tolosana-Delgado
committed
double d1,x0,x1,sign;
/* Lantuejoul (2002), page 196 */
/* Find the smallest proj; select a random exponential point "x0" left
* from it with lambda "2range" away. Domain = (x0, max(projs)) */
sign = unif_rand()>0.5? 1 : -1; /* start + or - randomly */

Raimon Tolosana-Delgado
committed
x0 = projs[0];
x1 = projs[0];
for(i=1;i<n;i++) {
if( projs[i]>x1 )
x1=projs[i];
else if( projs[i]<x0 )
x0=projs[i];
}

Raimon Tolosana-Delgado
committed
x0 -= 2*range*exp_rand();
/* Partition the domain with a Poisson point process of lambda=2range. */
ns = 0;
doubleBuf[0] = x0;
while( doubleBuf[ns]<x1 ){
if( ns>=maxIntervals )
error("fbandExp: too small range; merge with nugget?");

Raimon Tolosana-Delgado
committed
doubleBuf[ns+1] = doubleBuf[ns] + 2*range*exp_rand();
ns ++;
}
/* Assign values*/
for(i=0;i<n;i++){
j=bsearchDouble(projs[i],ns,doubleBuf);
d1 = (doubleBuf[j+1] + doubleBuf[j])/2; /* midpoint */
d1 = projs[i] - d1;
band[i] = d1>0 ? sign : -sign; /* -1 if projs[i]<midpoint; +1 otherwise */
}
}
bandSimFunctionPtr bandSim[]={
fbandGauss,fbandSph,fbandExp
};
void getUnitvec(
int dimX, /* m = 2 or 3 */
int ip, /* number of the band being simulated */
double *unitvec /* out: m x 1*/
) {
/* weak discrepancy sequence of pseudorandom directions in 2D or 3D:
* Lantuejoul (2002), page 194, after Freulon (1992) */

Raimon Tolosana-Delgado
committed
/* 20220424: removed int i; */
double d1,d2,d3;
if(dimX>3)
error("no expression for unit vectors in dimension larger than 3");
if( dimX==3) {
d1=invBitExp2(ip)*2*M_PI;
d2=invBitExp(ip,3);
d3 = sqrt(1-d2*d2);
unitvec[2] = d2;
unitvec[0] = cos(d1)*d3;
unitvec[1] = sin(d1)*d3;
} else if( dimX==2 ) {
Rprintf("Warning: gmGeostatsC.getUnitvec in 2D is incompatible with spherical variograms");
d1=invBitExp2(ip);
unitvec[0] = cos(d1*M_PI);
unitvec[1] = sin(d1*M_PI);
} else if( dimX== 1) {
unitvec[0]=1;
}
}
static R_NativePrimitiveArgType getUnitvecR_t[] = { /* INTSXP,REALSXP */
/* dimX, iP, unitvec */
INTSXP,INTSXP,REALSXP
};
void getUnitvecR(int * dimX,
int * ip,
double *unitvec
) {
getUnitvec(*dimX,*ip,unitvec);
}
static R_NativePrimitiveArgType CMVTurningBands_t[] = { /* INTSXP,REALSXP */
/* dimX, X, dimZ Z nBands sqrtNug nCgram typeCgr A sqrtSill moreCgr */
INTSXP,REALSXP,INTSXP,REALSXP,INTSXP,REALSXP,INTSXP,INTSXP,REALSXP,REALSXP,REALSXP
};
void CMVTurningBands(
const int *dimX, /* n,m */
const double *X,
const int *dimZ, /*d,n,nsim */
double *Z, /* Output Simulation transposed*/
const int *nBands,
const double *sqrtNugget, /* d x d*/
const int *nCgrams, /* 1 */
const int *typeCgram, /* length=nCgrams */
const double *A, /* nCgrams x m x m sqrt inverse Matrices */
const double *sqrtSill, /* nCgrams x d x d*/
const double *moreCgramData /* n x ?*/
) {
const int maxCgramType=2;
const int nsim=dimZ[2];
int i,j,k,s,ss,ev;

Raimon Tolosana-Delgado
committed
double d1,d2; /* 20220424: removed ,d3; */
const double sqrtNBands=sqrt((double) *nBands);

Raimon Tolosana-Delgado
committed
double phase; /* 20220424: removed ,amp; */
const int n=dimX[0];
const int m=dimX[1];
const int d=dimZ[0];
double projs[n];
double band[n];
double v[3];
double omega[3];
int sim;
Rprintf("Starting calculations\n");
if( m<1 || m>3 )
error("CMVTurningBands: illegal X column dimension");
if( dimZ[1]!=n )
error("CMVTurningBands: Z and X do not fit in dimension");
#ifdef inR
GetRNGstate();
#endif
/*setting Z to 0*/
for(sim=0;sim<nsim;sim++) {
for(i=0;i<n;i++)
for(j=0;j<d;j++)
Z[d*i+j]=0.0;
for(s=0;s<*nBands;s++){/* band */

Raimon Tolosana-Delgado
committed
getUnitvec(3, s+1, &(omega[0])); /* obtain a direction; always in 3D, in order for the spherical variogram to be correct */
//getUnitvec(m, s+1, omega); /* obtain a direction */
for(ss=0;ss< *nCgrams;ss++) { /* variogram structure */
if( typeCgram[ss]<0 || typeCgram[ss] > maxCgramType )
error("CMVTurningBands: Unknown variogram type");
/* project all data onto the direction */
for(i=0;i<n;i++){ /* location */
for(j=0;j<m;j++) {
v[j]=0;
for(k=0;k<m;k++)
v[j]+=A[ss+ *nCgrams *(j+m*k)]*X[i+n*k];
}
projs[i]=0;
for(j=0;j<m;j++){ /* spatial dimension */
projs[i]+=omega[j]*v[j];
}
}
/* for each eigenvalue, ... */
for(ev=0;ev<d;ev++) { /* eigenvector */
/* ... obtain a curve at all proj points following the covariance model */
(*bandSim[typeCgram[ss]])(n,projs,band,1.0,moreCgramData+ss);
/* this function takes the projs and returns on band the the curve */
/* ... multiply the eigenvector by the curve, and accumulate */

Raimon Tolosana-Delgado
committed
#ifdef _OPENMP
#pragma omp parallel for \
if(!omp_in_parallel()&&0) \
num_threads(omp_get_num_procs()) \
default(shared) private(i,j,d2)

Raimon Tolosana-Delgado
committed
for(i=0;i<n;i++){ /* location */
for(j=0;j<d;j++){ /* variable */
d2 = sqrtSill[ss + *nCgrams *(j+d*ev)]*band[i];
Z[d*i+j]+=d2;
}
}

Raimon Tolosana-Delgado
committed
#else

Raimon Tolosana-Delgado
committed
for(i=0;i<n;i++){ /* location */
for(j=0;j<d;j++){ /* variable */
d2 = sqrtSill[ss + *nCgrams *(j+d*ev)]*band[i];
Z[d*i+j]+=d2;
}
}

Raimon Tolosana-Delgado
committed
#endif

Raimon Tolosana-Delgado
committed
}
}
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
}
/* Rescale*/
for(i=0;i<n;i++)
for(j=0;j<d;j++)
Z[d*i+j] /= sqrtNBands; // Lantuejoul 2002 p.193
/* Nugget */
for(i=0;i<n;i++)
for(j=0;j<d;j++) {
d1 = norm_rand();
for(k=0;k<d;k++)
Z[d*i+k] += d1*sqrtNugget[k+d*j]; /*check*/
}
Z+=d*n;
}
#ifdef inR
PutRNGstate();
#endif
}
static R_NativePrimitiveArgType CCondSim_t[] = { /* INTSXP,REALSXP */
/* dimZin Zin Cinv dimX, X, dimZ Z nBands sqrtNugget nugget nCgrams typeCgr A sqrtSill sill moreCgr cbuf dbuf */
INTSXP,REALSXP,REALSXP,INTSXP,REALSXP,INTSXP,REALSXP,INTSXP,REALSXP,REALSXP,INTSXP,INTSXP,REALSXP,REALSXP,REALSXP,REALSXP,REALSXP,REALSXP
};
void CCondSim(
const int *dimZin, /* IN: d, nin */
const double *Zin, /*IN: nin x d Randomfield data to condition to */
const double *Cinv,/*IN: (nin * d) x (nin x d) inverse of Covariance*/
const int *dimX, /* IN: n, m */
const double *X, /* IN: All Lokations, first nin conditioning */
const int *dimZ, /* IN: d, n,nsim */
double *Z, /* OUT: t() Output Simulation */
const int *nBands, /* IN: Desired number of Bands*/
const double *sqrtNugget, /* IN: d x d */
const double *nugget, /* IN: dxd */
const int *nCgrams, /* IN: number of variograms */
const int *typeCgram, /* IN: type of each variogram,length=nCgrams */
/* 0=Gauss, 1=Spherical, 2=Exponential */
const double *A, /* IN: Anisotropy matrices, nCgrams x m x m inverse Matrices */
const double *sqrtSill, /* IN: nCgrams x d x d*/
const double *sill, /* IN: nCgrams x d x d*/
const double *moreCgramData, /* nGrams x 1 Extraparamter*/
double *cbuf, /* BUF: Buffer of length d*d*nin */
double *dbuf /* BUF: Buffer of length d*nin*nsim */
) {

Raimon Tolosana-Delgado
committed
/* 20220424 removed: , const int maxCgramType=2; */
const int n=dimX[0];
const int m=dimX[1];
const int d=dimZin[0];
const int nin = dimZin[1];
const int nsim= dimZ[2];
const int nd=n*d;
const char No='N';
const char Transposed='T';
const int dmnin=d*nin;
const int oneI=1;
const int zeroI = 0;
const double zero=0.0;
const double one=1.0;
const double minus1=-1.0;

Raimon Tolosana-Delgado
committed
int i,j,k; /* 20220424 removed: ,s,ss,ev,l; */

Raimon Tolosana-Delgado
committed
/* 20220424 removed: double d1,d2,d3,cv; */
const int dimXin[2] = {nin,m};
const int dimXout[2] = {1,m};
const int dimCbuf[4] = {d,nin,d,1};
// Unconditional Simulation
Rprintf("starting unconditional simulation (%d)\n",nsim);
CMVTurningBands(dimX,
X,
dimZ,
Z,
nBands,
sqrtNugget,
nCgrams,
typeCgram,
A,
sqrtSill,
moreCgramData
);
Rprintf("unconditional simulation done (%d)\n",nsim);
Rprintf("starting conditioning by dual kriging\n");
/* Kriging from simulated using Cinv */
// Create differenes of obs and sim

Raimon Tolosana-Delgado
committed
#ifdef _OPENMP
#pragma omp parallel \
if(!omp_in_parallel()) \
num_threads(omp_get_num_procs()) \
default(shared) private(i,j,sim,shift,k)
{
#pragma omp parallel for
for(int sim=0;sim<nsim;sim++) {
int shift=nd*sim;
for(int i=0;i<nin;i++)
for(int j=0;j<d;j++){
int k=d*i+j;
Z[k+shift]-=Zin[k];
}
}
}

Raimon Tolosana-Delgado
committed
#else
for(int sim=0;sim<nsim;sim++) {
int shift=nd*sim;
for(int i=0;i<nin;i++)
for(int j=0;j<d;j++){
int k=d*i+j;
Z[k+shift]-=Zin[k];
}
}
#endif
/* Z[hinten] -= \hat{Z[hinten]}(Z[vorn]) = cov(hinten,vorn)%*% Cinv %*% Z[vorn] */
/* dbuf = Cinv %*% Z[vorn]
Cinv in R ^ d*nin x d*nin
Z[vorn] in R^d*nin
*/
// Dual Kriging preparation

Raimon Tolosana-Delgado
committed
#ifdef _OPENMP
#pragma omp parallel for \
if(!omp_in_parallel()&&0) \
num_threads(omp_get_num_procs()) \
default(shared) private(sim)
for(sim=0;sim<nsim;sim++) {
F77_NAME(dgemv)(&No,
&dmnin,
&dmnin,
&one,
Cinv,
&dmnin,
Z+nd*sim,
&oneI,
&zero,
dbuf+dmnin*sim,

Raimon Tolosana-Delgado
committed
&oneI FCONE);

Raimon Tolosana-Delgado
committed
#else
for(sim=0;sim<nsim;sim++) {
F77_NAME(dgemv)(&No,
&dmnin,
&dmnin,
&one,
Cinv,
&dmnin,
Z+nd*sim,
&oneI,
&zero,
dbuf+dmnin*sim,

Raimon Tolosana-Delgado
committed
&oneI FCONE);

Raimon Tolosana-Delgado
committed
}
#endif
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
// /* points in*/
//for(i=0;i<nin;i++)
//for(j=0;j<m;j++)
//Xin[m*i+j] = X[m*i+j];
// /* points out*/
//for(i=nin;i<n;i++)
//for(j=0;j<m;j++)
//Xout[m*(i-nin)+j] = X[m*i+j];
/* fill cbuf*/
// ******** Iterate over points
for(i=nin;i<n;i++) {
CcalcCgram(
dimXin,
&n,
X,
dimXout,
&n,
X+i,
dimCbuf,
cbuf,
nugget, /* d x d*/
nCgrams, /* 1 */
typeCgram, /* length=nCgrams */
A, /* nCgrams x m x m sqrt inverse Matrices */
sill, /* nCgrams x d x d*/
moreCgramData,
&zeroI
);
//for(l=0;l<nin;l++) { /* points in*/
//for(j=0;j<d;j++) /* koor point in */
//for(k=0;k<d;k++) /* koor point out */
//cbuf[j+d*(k+d*l)]=0.0; /* geeignet d*d*nin, nugget no */
//for(s=0;s<*nCgrams;s++) { /* structure */
//d1=0;
//for(j=0;j<m;j++) /* spatial dimension */
//for(k=0;k<m;k++) /* spatial dimension */
//d1+=A[s + *nCgrams *(j+m*k)]*omega[j]*omega[k]; /* check */
//cv=(*cgramFunctions[typeCgram[s]])(sqrt(d1),moreCgramData+s);
//for(j=0;j<d;j++) /* koor point in */
//for(k=0;k<d;k++) /* koor point out */
//cbuf[j+d*(k+d*l)]+=cv*sill[s+*nCgrams*(j+d*k)];
//}
//}
/* Z[,i] += t(cbuf(d*nin,d)) %*% dbuf(d*nin) */

Raimon Tolosana-Delgado
committed
#ifdef _OPENMP
#pragma omp parallel for \
if(!omp_in_parallel()&&0) \
num_threads(omp_get_num_procs()) \
default(shared) private(sim)
for(sim=0;sim<nsim;sim++) {
F77_NAME(dgemv)(&Transposed,
&dmnin,
&d,
&minus1,
cbuf,
&dmnin,
dbuf+dmnin*sim,
&oneI,
&one,
Z+i*d+nd*sim,

Raimon Tolosana-Delgado
committed
&oneI FCONE);

Raimon Tolosana-Delgado
committed
#else
for(sim=0;sim<nsim;sim++) {
F77_NAME(dgemv)(&Transposed,
&dmnin,
&d,
&minus1,
cbuf,
&dmnin,
dbuf+dmnin*sim,
&oneI,
&one,
Z+i*d+nd*sim,

Raimon Tolosana-Delgado
committed
&oneI FCONE);

Raimon Tolosana-Delgado
committed
}
#endif
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
}
}
//anaV(v1,m,mx,i*h,dimY,y,sigma0,sigma1);
extern void anaV(double *v, // velocity of a datum
const int m, // number of variables
const double *x, // location of the datum
const double t, // time moment
const int *dimY, // dimension of the data nodes
const double *y, // data nodes
const double *wY, // weights of the data nodes
const double sigma0, // parameter sigma0
const double sigma1 // parameter sigma1
) {
size_t nY=dimY[1]; // number of data nodes
double sigmat=sigma0+t*(sigma1-sigma0); // deviation at this moment
double sigmaD=(sigma1-sigma0);
for(int i=0;i<m;i++){ // initialize velocity
v[i]=0;
}
double ws=0; // sum of weights
for(int j=0;j<nY;j++) { // loop on number of data nodes
// double d=0;
double dz[m];
double s2=0;
for(int i=0;i<m;i++) {
const double ddz=(x[i]-(1-t)*y[m*j+i])/sigmat;
dz[i]=ddz;
s2+=ddz*ddz;
}
double w=exp(-s2/2.0)*wY[j]; // weighting
ws+=w;
for(int i=0;i<m;i++)
v[i]+=w*(sigmaD*dz[i]-y[m*j+i]);
}
for(int i=0;i<m;i++){
v[i]/=ws;
}
}
static R_NativePrimitiveArgType anaForwardC_t[] = { /* INTSXP,REALSXP */
/* dimX, x, dimY y wY stepsp sigma0p sigma1p */
INTSXP,REALSXP,INTSXP,REALSXP,REALSXP,INTSXP, REALSXP, REALSXP
};
extern void anaForwardC(const int *dimX,
double *x,
const int *dimY,
const double *y,
const double *wY, // weights of the data nodes
const int *stepsp,
const double *sigma0p,
const double *sigma1p
) {
const double sigma0=*sigma0p;
const double sigma1=*sigma1p;
const size_t steps=*stepsp;
const size_t m=dimX[0];
const size_t nx=dimX[1];
// const size_t ny=dimY[1];
const double h=((double)1.0)/steps;
if( dimY[0]!=m )
error("anaForwardC: x and y have different number of variables / rows");

Raimon Tolosana-Delgado
committed
#ifdef _OPENMP
#pragma omp parallel for
for(size_t i=0;i<nx;i++) {
double v1[m];
double v2[m];
double xx[m];
double *mx=x+m*i;
for(size_t s=0;s<steps;s++) {
// v1
anaV(v1,m,mx,s*h,dimY,y,wY,sigma0,sigma1);
// xx=x+h*v1
for(int j=0;j<m;j++)
xx[j]=mx[j]+h*v1[j];
// v2
anaV(v2,m,xx,(s+1)*h,dimY,y,wY,sigma0,sigma1);
// x+=0.5*h*(v1+v2)
for(int j=0;j<m;j++)
mx[j]+=0.5*h*(v1[j]+v2[j]);
}
}

Raimon Tolosana-Delgado
committed
#else
for(size_t i=0;i<nx;i++) {
double v1[m];
double v2[m];
double xx[m];
double *mx=x+m*i;
for(size_t s=0;s<steps;s++) {
// v1
anaV(v1,m,mx,s*h,dimY,y,wY,sigma0,sigma1);
// xx=x+h*v1
for(int j=0;j<m;j++)
xx[j]=mx[j]+h*v1[j];
// v2
anaV(v2,m,xx,(s+1)*h,dimY,y,wY,sigma0,sigma1);
// x+=0.5*h*(v1+v2)
for(int j=0;j<m;j++)
mx[j]+=0.5*h*(v1[j]+v2[j]);
}
}
#endif

Raimon Tolosana-Delgado
committed
static R_NativePrimitiveArgType anaBackwardC_t[] = { /* INTSXP,REALSXP */
/* dimX, x, dimY y wY stepsp sigma0p sigma1p */
INTSXP,REALSXP,INTSXP,REALSXP,REALSXP,INTSXP, REALSXP, REALSXP
};
extern void anaBackwardC(const int *dimX,
double *x,
const int *dimY,
const double *y,
const double *wY, // weights of the data nodes
const int *stepsp,
const double *sigma0p,
const double *sigma1p
) {
const double sigma0=*sigma0p;
const double sigma1=*sigma1p;
const size_t steps=*stepsp;
const size_t m=dimX[0];
const size_t nx=dimX[1];
// const size_t ny=dimY[1];
const double h=((double)1.0)/steps;
if( dimY[0]!=m )
error("anaBackwardC: x and y have different number of variables / rows");

Raimon Tolosana-Delgado
committed
#ifdef _OPENMP
#pragma omp parallel for
for(size_t i=0;i<nx;i++) {
double v1[m];
double v2[m];
double xx[m];
double *mx=x+m*i;
for(size_t s=0;s<steps;s++) {
// v1
anaV(v1,m,mx,1-s*h,dimY,y,wY,sigma0,sigma1);
// xx=x-h*v1
for(int j=0;j<m;j++)
xx[j]=mx[j]-h*v1[j];
// v2
anaV(v2,m,xx,1-(s+1)*h,dimY,y,wY,sigma0,sigma1);
// x+=0.5*h*(v1+v2)
for(int j=0;j<m;j++)
mx[j]-=0.5*h*(v1[j]+v2[j]);
}
}

Raimon Tolosana-Delgado
committed
#else
for(size_t i=0;i<nx;i++) {
double v1[m];
double v2[m];
double xx[m];
double *mx=x+m*i;
for(size_t s=0;s<steps;s++) {
// v1
anaV(v1,m,mx,1-s*h,dimY,y,wY,sigma0,sigma1);
// xx=x-h*v1
for(int j=0;j<m;j++)
xx[j]=mx[j]-h*v1[j];
// v2
anaV(v2,m,xx,1-(s+1)*h,dimY,y,wY,sigma0,sigma1);
// x+=0.5*h*(v1+v2)
for(int j=0;j<m;j++)
mx[j]-=0.5*h*(v1[j]+v2[j]);
}
}
#endif
}
/* ======================================
* EXPORT FUNCTIONS TO R
* ======================================
*/
static R_CMethodDef cMethods[] = {
{"CcalcCgram", (DL_FUNC) &CcalcCgram, 15, CcalcCgram_t},
{"CMVTurningBands", (DL_FUNC) &CMVTurningBands, 11, CMVTurningBands_t},
{"CCondSim", (DL_FUNC) & CCondSim, 18, CCondSim_t},
{"anaForwardC", (DL_FUNC) &anaForwardC, 8, anaForwardC_t},
{"anaBackwardC", (DL_FUNC) &anaBackwardC, 8, anaBackwardC_t},
{"getUnitvecR", (DL_FUNC) &getUnitvecR, 3, getUnitvecR_t},
{NULL, NULL, 0}
};
//{"CMVTurningBands2", (DL_FUNC) &CMVTurningBands2, 11, CMVTurningBands2_t},
{
R_registerRoutines(info, cMethods, NULL, NULL, NULL);
R_useDynamicSymbols(info, FALSE);
R_forceSymbols(info, TRUE);
}