https://github.com/cran/RandomFields
Tip revision: bf048cf5b6fe6ebdb3ae8163d45656c75c6243e9 authored by Martin Schlather on 18 February 2019, 12:44:05 UTC
version 3.3.1
version 3.3.1
Tip revision: bf048cf
primitive.gauss.mix.cc
/*
Authors
Martin Schlather, schlather@math.uni-mannheim.de
Definition of correlation functions that are gaussian scale mixtures
Copyright (C) 2017 -- 2018 Olga Moreva (bivariate models) & Martin Schlather
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <Rmath.h>
#include <R_ext/Lapack.h>
#include <R_ext/Linpack.h>
#include "questions.h"
#include "primitive.h"
#include "operator.h"
#include "AutoRandomFields.h"
#include "shape.h"
#include "Processes.h"
//#include "xport_import.h"
//#define LOG2 M_LN2
#define i11 0
#define i21 1
#define i22 2
#define epsilon 1e-15
/* Cauchy models */
#define CAUCHY_GAMMA 0
void Cauchy(double *x, model *cov, double *v){
double gamma = P0(CAUCHY_GAMMA);
*v = POW(1.0 + *x * *x, -gamma);
}
void logCauchy(double *x, model *cov, double *v, double *Sign){
double gamma = P0(CAUCHY_GAMMA);
*v = LOG(1.0 + *x * *x) * -gamma;
*Sign = 1.0;
}
void TBM2Cauchy(double *x, model *cov, double *v){
double gamma = P0(CAUCHY_GAMMA), y2, lpy2;
y2 = *x * *x;
lpy2 = 1.0 + y2;
switch ((int) (gamma * 2.0 + 0.001)) {// ueber check sichergestellt
case 1 : *v = 1.0 / lpy2; break;
case 3 : *v = (1.0 - y2)/ (lpy2 * lpy2); break;
case 5 : *v = (1.0-y2*(2.0+0.333333333333333333333*y2))/(lpy2*lpy2*lpy2);
break;
case 7 : lpy2 *= lpy2;
*v = (1.0- y2*(3.0+y2*(1.0+0.2*y2)))/(lpy2 * lpy2);
break;
default :
ERR("TBM2 for cauchy only possible for alpha=0.5 + k; k=0, 1, 2, 3 ");
}
}
void DCauchy(double *x, model *cov, double *v){
double y=*x, gamma = P0(CAUCHY_GAMMA);
*v = (-2.0 * gamma * y) * POW(1.0 + y * y, -gamma - 1.0);
}
void DDCauchy(double *x, model *cov, double *v){
double ha = *x * *x, gamma = P0(CAUCHY_GAMMA);
*v = 2.0 * gamma * ((2.0 * gamma + 1.0) * ha - 1.0) *
POW(1.0 + ha, -gamma - 2.0);
}
void InverseCauchy(double*x, model *cov, double *v){
double
gamma = P0(CAUCHY_GAMMA);
if (*x == 0.0) *v = RF_INF;
else *v = SQRT(POW(*x, -1.0 / gamma) - 1.0);
}
int checkCauchy(model VARIABLE_IS_NOT_USED *cov){
RETURN_NOERROR;
}
void rangeCauchy(model VARIABLE_IS_NOT_USED *cov, range_type *range){
range->min[CAUCHY_GAMMA] = 0.0;
range->max[CAUCHY_GAMMA] = RF_INF;
range->pmin[CAUCHY_GAMMA] = 0.09;
range->pmax[CAUCHY_GAMMA] = 10.0;
range->openmin[CAUCHY_GAMMA] = true;
range->openmax[CAUCHY_GAMMA] = true;
}
void coinitCauchy(model VARIABLE_IS_NOT_USED *cov, localinfotype *li) {
li->instances = 1;
li->value[0] = 1.0; // q[CUTOFF_A]
li->msg[0] = MSGLOCAL_JUSTTRY;
}
void DrawMixCauchy(model VARIABLE_IS_NOT_USED *cov, double *random) { //better GR 3.381.4 ?? !!!!
// split into parts <1 and >1 ?>
*random = -LOG(1.0 -UNIFORM_RANDOM);
}
double LogMixDensCauchy(double VARIABLE_IS_NOT_USED *x, double logV, model *cov) {
double gamma = P0(CAUCHY_GAMMA);
// da dort 1/w vorgezogen
return 0.5 * (gamma - 1.0) * logV - 0.5 * lgammafn(gamma);
}
/** another Cauchy model */
#define CTBM_ALPHA 0
#define CTBM_BETA 1
#define CTBM_GAMMA 2
void Cauchytbm(double *x, model *cov, double *v){
double ha,
alpha = P0(CTBM_ALPHA),
beta = P0(CTBM_BETA),
gamma = P0(CTBM_GAMMA),
y=*x;
if (y==0) {
*v = 1.0;
} else {
ha = POW(y, alpha);
*v = (1.0 + (1.0 - beta / gamma) * ha) * POW(1.0 + ha, -beta / alpha - 1.0);
}
}
void DCauchytbm(double *x, model *cov, double *v){
double y= *x, ha,
alpha = P0(CTBM_ALPHA),
beta = P0(CTBM_BETA),
gamma = P0(CTBM_GAMMA);
if (y == 0.0) *v = 0.0; // WRONG VALUE, but multiplied
else { // by zero anyway
ha = POW(y, alpha - 1.0);
*v = beta * ha * (-1.0 - alpha / gamma + ha * y * (beta / gamma - 1.0)) *
POW(1.0 + ha * y, -beta /alpha - 2.0);
}
}
void rangeCauchytbm(model *cov, range_type *range){
range->min[CTBM_ALPHA] = 0.0;
range->max[CTBM_ALPHA] = 2.0;
range->pmin[CTBM_ALPHA] = 0.05;
range->pmax[CTBM_ALPHA] = 2.0;
range->openmin[CTBM_ALPHA] = true;
range->openmax[CTBM_ALPHA] = false;
range->min[CTBM_BETA] = 0.0;
range->max[CTBM_BETA] = RF_INF;
range->pmin[CTBM_BETA] = 0.05;
range->pmax[CTBM_BETA] = 10.0;
range->openmin[CTBM_BETA] = true;
range->openmax[CTBM_BETA] = true;
range->min[CTBM_GAMMA] = (double) OWNLOGDIM(0);
range->max[CTBM_GAMMA] = RF_INF;
range->pmin[CTBM_GAMMA] = range->min[CTBM_GAMMA];
range->pmax[CTBM_GAMMA] = range->pmin[CTBM_GAMMA] + 10.0;
range->openmin[CTBM_GAMMA] = false;
range->openmax[CTBM_GAMMA] = true;
}
// spatially constant (matrix);
#define CONSTANT_M 0
void kappaconstant(int i, model VARIABLE_IS_NOT_USED *cov, int *nr, int *nc) {
*nr = *nc = i == CONSTANT_M ? 0 : -1;
}
void constant(double VARIABLE_IS_NOT_USED *x, model *cov, double *v){
int
vdimSq = VDIM0 * VDIM1;
MEMCOPY(v, P(CONSTANT_M), vdimSq * sizeof(double));
}
void nonstatconstant(double VARIABLE_IS_NOT_USED *x, double VARIABLE_IS_NOT_USED *y, model *cov, double *v){
int
vdimSq = VDIM0 * VDIM1;
MEMCOPY(v, P(CONSTANT_M), vdimSq * sizeof(double));
}
int checkconstant(model *cov) {
int err; // anzahl listen elemente
if (GLOBAL.internal.warn_constant) {
GLOBAL.internal.warn_constant = false;
warning("NOTE that the definition of 'RMconstant' has changed in version 3.0.61. Maybe 'RMfixcov' is the model your are looking for");
}
VDIM0 = VDIM1 = cov->nrow[CONSTANT_M];
if (VDIM0 != VDIM1) RETURN_ERR(ERROR_MATRIX_SQUARE);
if (equalsVariogram(OWNTYPE(0))) { // ACHTUNG wirklich genau VariogramType
SERR("strange call");
}
if (cov->q != NULL) {
return (int) cov->q[0];
} else QALLOC(1);
cov->q[0] = NOERROR;
// check whether positive eigenvalue
if (!Ext_is_positive_definite(P(CONSTANT_M), VDIM0)) {
cov->monotone = MONOTONE;
cov->ptwise_definite = pt_indef;
if (isnowPosDef(cov)) return cov->q[0] = ERROR_MATRIX_POSDEF;
} else {
cov->monotone = COMPLETELY_MON;
cov->ptwise_definite = pt_posdef;
}
cov->matrix_indep_of_x = true;
int
vdim = VDIM0,
vdimP1 = vdim + 1;
double *p = P(CONSTANT_M);
for (int i=0; i<vdim; i++) cov->mpp.maxheights[i] = p[i * vdimP1];
err = checkkappas(cov);
RETURN_ERR(err);
}
void rangeconstant(model VARIABLE_IS_NOT_USED *cov, range_type *range){
// auch in rangec verwendet!
int dim = VDIM0;
if (isnowPosDef(cov)) {
if (isnowTcf(cov)) {
range->min[CONSTANT_M] = (int) (dim == 1);
range->max[CONSTANT_M] = 1;
range->pmin[CONSTANT_M] = range->min[CONSTANT_M];
range->pmax[CONSTANT_M] = 1;
range->openmin[CONSTANT_M] = false;
range->openmax[CONSTANT_M] = false;
} else {
range->min[CONSTANT_M] = dim == 1 ? 0 : RF_NEGINF;
range->max[CONSTANT_M] = RF_INF;
range->pmin[CONSTANT_M] = dim == 1 ? 0 : -1e10;
range->pmax[CONSTANT_M] = 1e10;
range->openmin[CONSTANT_M] = dim != 1;
range->openmax[CONSTANT_M] = true;
}
} else {
range->min[CONSTANT_M] = RF_NEGINF;
range->max[CONSTANT_M] = RF_INF;
range->pmin[CONSTANT_M] = - 1e10;
range->pmax[CONSTANT_M] = 1e10;
range->openmin[CONSTANT_M] = true;
range->openmax[CONSTANT_M] = true;
}
}
/* exponential model */
void exponential(double *x, model VARIABLE_IS_NOT_USED *cov, double *v){
*v = EXP(- *x);
// printf(": %10g %10g\n", *x, *v);
}
void logexponential(double *x, model VARIABLE_IS_NOT_USED *cov, double *v, double *Sign){
*v = - *x;
*Sign = 1.0;
}
void TBM2exponential(double *x, model VARIABLE_IS_NOT_USED *cov, double *v)
{
double y = *x;
*v = 1.0;
if (y!=0.0) *v = 1.0 - PIHALF * y * Ext_I0mL0(y);
}
void Dexponential(double *x, model VARIABLE_IS_NOT_USED *cov, double *v){
*v = - EXP(- *x);
}
void DDexponential(double *x, model VARIABLE_IS_NOT_USED *cov, double *v){
*v = EXP(-*x);
}
void Inverseexponential(double *x, model VARIABLE_IS_NOT_USED *cov, double *v){
*v = (*x == 0.0) ? RF_INF : -LOG(*x);
}
void nonstatLogInvExp(double *x, model *cov,
double *left, double *right){
double
z = *x <= 0.0 ? - *x : 0.0;
int d,
dim = PREVLOGDIM(0);
for (d=0; d<dim; d++) {
left[d] = -z;
right[d] = z;
}
}
double densityexponential(double *x, model *cov) {
// to do: ersetzen durch die Familien
// spectral density
int d,
dim=PREVLOGDIM(0);
double x2 = 0.0,
dim12 = 0.5 * ((double) (dim + 1));
for (d=0; d<dim; d++) x2 += x[d] * x[d];
//printf("de = %f %d\n",
return gammafn(dim12) * POW(M_PI * (1.0 + x2), -dim12);
}
int initexponential(model *cov, gen_storage *s) {
int dim = PREVLOGDIM(0);
double D = (double) dim;
// TREE0(cov);
// PMI(cov);
if (HAS_SPECTRAL_FRAME(cov)) {
spec_properties *cs = &(s->spec);
if (PREVLOGDIM(0) <= 2) RETURN_NOERROR;
cs->density = densityexponential;
return search_metropolis(cov, s);
}
else if (hasSmithFrame(cov)) {
//Inverseexponential(&GLOBAL.mpp. about_ zero, NULL, &(cov->mpp.refradius));
// R *= GLOBAL.mpp.radius_natscale_factor;
/*
if (cov->mpp.moments >= 1) {
int xi, d;
double i[3], dimfak, Rfactor, sum,
dimHalf = 0.5 * D;
dimfak = gammafn(D);
for (xi=1; xi<=2; xi++) {
R = xi * cov->mpp.refradius; //
// http://de.wikipedia.org/wiki/Kugel
i[xi] = dimfak * 2 * POW(M_PI / (double) (xi*xi), dimHalf) /
gammafn(dimHalf);
if (R < RF_INF) {
// Gradstein 3.351 fuer n=d-1
//printf("here\n");
for (sum = 1.0, factor=1.0, d=1; d<dim; d++) {
factor *= R / D;
sum += factor;
// printf("%d %10g %10g %10g\n", d, sum, factor, R);
}
sum *= dimfak * EXP(-R);
// printf("%d %10g %10g %10g\n", d, sum, factor, R);
i[xi] -= sum;
}
}
cov->mpp.mM[1] = cov->mpp.mMplus[1] = i[1];
if (cov->mpp.moments >= 2) {
cov->mpp.mM[2] = cov->mpp.mMplus[2] = i[2];
}
}
*/
assert(cov->mpp.maxheights[0] == 1.0);
if (cov->mpp.moments >= 1) {
cov->mpp.mM[1]= cov->mpp.mMplus[1] =
SurfaceSphere(dim - 1, 1.0) * gammafn(D);
}
}
else if (hasRandomFrame(cov)) { RETURN_NOERROR; }
else ILLEGAL_FRAME;
RETURN_NOERROR;
}
void do_exp(model VARIABLE_IS_NOT_USED *cov, gen_storage VARIABLE_IS_NOT_USED *s) {
}
void spectralexponential(model *cov, gen_storage *S, double *e) {
spectral_storage *s = &(S->Sspectral);
int dim = PREVLOGDIM(0);
if (dim <= 2) {
double A = 1.0 - UNIFORM_RANDOM;
E12(s, dim, SQRT(1.0 / (A * A) - 1.0), e);
// printf("dim = %d %f %f %f\n", dim, A, e[0]);
} else {
metropolis(cov, S, e);
}
}
int checkexponential(model *cov) {
int dim = OWNLOGDIM(0);
if (dim > 2)
cov->pref[CircEmbedCutoff] = cov->pref[CircEmbedIntrinsic] = PREF_NONE;
if (dim != 2) cov->pref[Hyperplane] = PREF_NONE;
RETURN_NOERROR;
}
int hyperexponential(double radius, double *center, double *rx,
model VARIABLE_IS_NOT_USED *cov, bool simulate,
double ** Hx, double ** Hy, double ** Hr)
{
// lenx : half the length of the rectangle
// center : center of the rectangle
// simulate=false: estimated number of lines returned;
// simulate=true: number of simulated lines returned;
// hx, hy : direction of line
// hr : distance of the line from the origin
// rectangular area where center gives the center
//
// the function expects scale = 1;
double lambda, phi, lx, ly, *hx, *hy, *hr;
long i, p,
//
q=0;
// q = RF_NA; assert(false);
int k,
Err;
assert(OWNLOGDIM(0)==2);
// we should be in two dimensions
// first, we simulate the lines for a rectangle with center (0,0)
// and half the side length equal to lenx
lx = rx[0];
ly = rx[1];
lambda = TWOPI * radius * 0.5; /* total, integrated, intensity */
// 0.5 in order to get scale 1
if (!simulate) return lambda < 999999 ? (int) lambda : 999999 ;
assert(*Hx==NULL);
assert(*Hy==NULL);
assert(*Hr==NULL);
p = (long) rpois(lambda);
if ((hx=*Hx=(double *) MALLOC(sizeof(double) * (p + 8 * sizeof(int))))==NULL||
(hy=*Hy=(double *) MALLOC(sizeof(double) * (p + 8 *sizeof(int))))==NULL||
(hr=*Hr=(double *) MALLOC(sizeof(double) * (p + 8 * sizeof(int))))==NULL){
Err=ERRORMEMORYALLOCATION; goto ErrorHandling;
}
/* creating the lines; some of the lines are not relevant as they
do not intersect the rectangle investigated --> k!=4
(it is checked if all the corners of the rectangle are on one
side (?) )
*/
for(i=0; i<p; i++) {
phi = UNIFORM_RANDOM * TWOPI;
hx[q] = COS(phi); hy[q] = SIN(phi);
hr[q] = UNIFORM_RANDOM * radius;
k = (hx[q] * (-lx) + hy[q] * (-ly) < hr[q]) +
(hx[q] * (-lx) + hy[q] * ly < hr[q]) +
(hx[q] * lx + hy[q] * (-ly) < hr[q]) +
(hx[q] * lx + hy[q] * ly < hr[q]);
if (k!=4) { // line inside rectangle, so stored
// now the simulated line is shifted into the right position
hr[q] += center[0] * hx[q] + center[1] * hy[q];
q++; // set pointer for storing to the next element
}
}
return q;
ErrorHandling:
return -Err;
}
void coinitExp(model VARIABLE_IS_NOT_USED *cov, localinfotype *li) {
li->instances = 1;
li->value[0] = 1.0; // q[CUTOFF_A]
li->msg[0] = MSGLOCAL_OK;
}
void ieinitExp(model VARIABLE_IS_NOT_USED *cov, localinfotype *li) {
li->instances = 1;
li->value[0] = 1.0;
li->msg[0] = MSGLOCAL_OK;
}
void DrawMixExp(model VARIABLE_IS_NOT_USED *cov, double *random) {
// GR 3.325: int_-infty^infty EXP(x^2/2 - b/x^2) = EXP(-\sqrt b)
double x = GAUSS_RANDOM(1.0);
*random = 1.0 / (x * x);
}
double LogMixDensExp(double VARIABLE_IS_NOT_USED *x, double VARIABLE_IS_NOT_USED logV, model VARIABLE_IS_NOT_USED *cov) {
// todo: check use of mixdens --- likely to programme it now completely differently
return 0.0;
}
/* Gausian model */
void Gauss(double *x, model VARIABLE_IS_NOT_USED *cov, double *v) {
*v = EXP(- *x * *x);
//printf("x =%10g v=%10g\n", x[0], *v);
}
void logGauss(double *x, model VARIABLE_IS_NOT_USED *cov, double *v, double *Sign) {
*v = - *x * *x;
*Sign = 1.0;
}
void DGauss(double *x, model VARIABLE_IS_NOT_USED *cov, double *v) {
double y = *x;
*v = -2.0 * y * EXP(- y * y);
}
void DDGauss(double *x, model VARIABLE_IS_NOT_USED *cov, double *v) {
double y = *x * *x;
*v = (4.0 * y - 2.0)* EXP(- y);
}
void D3Gauss(double *x, model VARIABLE_IS_NOT_USED *cov, double *v) {
double y = *x * *x;
*v = *x * (12 - 8 * y) * EXP(- y);
}
void D4Gauss(double *x, model VARIABLE_IS_NOT_USED *cov, double *v) {
double y = *x * *x;
*v = ((16 * y - 48) * y + 12) * EXP(- y);
}
void InverseGauss(double *x, model VARIABLE_IS_NOT_USED *cov, double *v) {
*v = SQRT(-LOG(*x));
}
void nonstatLogInvGauss(double *x, model VARIABLE_IS_NOT_USED *cov,
double *left, double *right) {
double
z = 0.0;
if (*x < 0.0) z =SQRT(- *x);
int d,
dim = PREVLOGDIM(0);
for (d=0; d<dim; d++) {
left[d] = -z;
right[d] = z;
}
}
double densityGauss(double *x, model *cov) {
int d, dim=PREVLOGDIM(0);
double x2=0.0;
for (d=0; d<dim; d++) x2 += x[d] * x[d];
return EXP(- 0.25 * x2 - (double) dim * (M_LN2 + M_LN_SQRT_PI));
}
int struct_Gauss(model *cov, model **newmodel) {
ASSERT_NEWMODEL_NOT_NULL;
//printf("dleete next lines\n"); ILLEGAL_FRAME_STRUCT;
// masse von Rect ist ok (unnormedmass)
// supportmin / max macht ergebnis auch nicht besser
switch (cov->frame) {
case PoissonGaussType :// optimierte density fuer den Gauss-Fall
double invscale;
addModel(newmodel, GAUSS, cov);
addModel(newmodel, DOLLAR);
kdefault(*newmodel, DSCALE, INVSQRTTWO);
addModel(newmodel, TRUNCSUPPORT);
InverseGauss(&GLOBAL.mpp.about_zero, cov, &invscale);
kdefault(*newmodel, TRUNC_RADIUS, invscale);
break;
default :
if (hasSmithFrame(cov)) { // optimierte density fuer den Gauss-Fall
// crash();
addModel(newmodel, GAUSS_DISTR, cov); // to
kdefault(*newmodel, GAUSS_DISTR_MEAN, 0.0);
kdefault(*newmodel, GAUSS_DISTR_SD, INVSQRTTWO);
RETURN_NOERROR;
}
ILLEGAL_FRAME_STRUCT;
}
RETURN_NOERROR;
}
double IntUdeU2_intern(int d, double R, double expMR2) {
// int_0^R u^{d-1} EXP(-u^2) \D u
if (d==0) return (pnorm(R, 0.0, INVSQRTTWO, true, false) - 0.5) * SQRTPI;
else if (d == 1) return 0.5 * (1.0 - expMR2);
return 0.5 * (expMR2 + (d - 1.0) * IntUdeU2_intern(d - 2, R, expMR2));
}
double IntUdeU2(int d, double R) {
// int_0^R u^{d-1} EXP(-u^2) \D u
return IntUdeU2_intern(d, R, EXP(-R*R));
}
int initGauss(model *cov, gen_storage *s) {
// if (hasAnyFrame(cov)) RETURN_NOERROR;
if (HAS_SPECTRAL_FRAME(cov)) {
spec_properties *cs = &(s->spec);
if (OWNLOGDIM(0) <= 2) RETURN_NOERROR;
cs->density = densityGauss;
return search_metropolis(cov, s);
}
else if (hasSmithFrame(cov)) {
// int_{b(0,R) e^{-a r^2} dr = d b_d int_0^R r^{d-1} e^{-a r^2} dr
// where a = 2.0 * xi / sigma^2
// here : 2.0 is a factor so that the mpp function leads to the
// gaussian covariance model EXP(-x^2)
// xi : 1 : integral ()
// 2 : integral ()^2
double R = RF_INF;
int
dim = OWNLOGDIM(0);
assert(COVNR == GAUSS);
assert(cov->mpp.maxheights[0] = 1.0);
if (cov->mpp.moments >= 1) {
cov->mpp.mM[1] = cov->mpp.mMplus[1] =
SurfaceSphere(dim - 1, 1.0) * IntUdeU2(dim - 1, R);
int i;
for (i=2; i<=cov->mpp.moments; i++) {
cov->mpp.mM[i] = cov->mpp.mM[1] * POW((double) i, -0.5 * dim);
}
}
// cov->mpp.maxheights[0] = 1.0;
}
else if (hasRandomFrame(cov) || hasAnyPoissonFrame(cov)) { RETURN_NOERROR; }
else ILLEGAL_FRAME;
RETURN_NOERROR;
}
void do_Gauss(model VARIABLE_IS_NOT_USED *cov, gen_storage VARIABLE_IS_NOT_USED *s) {
}
void spectralGauss(model *cov, gen_storage *S, double *e) {
spectral_storage *s = &(S->Sspectral);
int dim = PREVLOGDIM(0);
if (dim <= 2) {
E12(s, dim, 2.0 * SQRT(-LOG(1.0 - UNIFORM_RANDOM)), e);
} else {
metropolis(cov, S, e);
}
}
void DrawMixGauss(model VARIABLE_IS_NOT_USED *cov, double VARIABLE_IS_NOT_USED *random) {
*random = 1.0;
}
double LogMixDensGauss(double VARIABLE_IS_NOT_USED *x, double VARIABLE_IS_NOT_USED logV, model VARIABLE_IS_NOT_USED *cov) {
return 0.0;
}
/*
void densGauss(double *x, model *cov, double *v) {
int
factor[MAXMPPDIM+1] = {0, 1 / M_SQRT_PI, INVPI, INVPI / M_SQRT_PI,
INVPI * INVPI},
dim = cov->tsdim;
*v = factor[dim] * EXP(- *x * *x);
}
*/
/*
void getMassGauss(double *a, model *cov, double *kappas, double *m) {
int i, j, k, kold,
dim = cov->tsdim;
double val[MAXMPPDIM + 1],
sqrt2pi = SQRT2 * SQRTPI,
factor[MAXMPPDIM+1] = {1,
SQRT(2) / M_SQRT_PI,
2 * INVPI,
2 * SQRT(2) * INVPI / M_SQRT_PI,
4 * INVPI * INVPI};
val[0] = 1.0;
for (i=1; i<=dim; i++)
val[i] = (2.0 * pnorm(SQRT2 * a[i], 0.0, 1.0, false, false) - 1.0) * M_SQRT_PI;
for (k=kold=i=0; i<dim; i++) {
m[k++] = val[i];
for (j=1; j< kold; j++) m[k++] = val[i] * m[j];
kold = k;
pr intf("kold = %d k=%d\n", kold, k);
}
}
*/
/*
void simuGauss(model *cov, int dim, double *v) {
int i;
double
dummy;
*v = 0.0;
if (dim <= 2) {
*v = dim == 1 ? FABS(GAUSS_RANDOM(1.0)) : rexp(1.0);
} else {
for (i=0; i<dim; i++) {
dummy = GAUSS_RANDOM(1.0);
*v += dummy * dummy;
}
*v = SQRT(*v);
}
}
*/
/* gencauchy */
#define GENC_ALPHA 0
#define GENC_BETA 1
void generalisedCauchy(double *x, model *cov, double *v){
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA);
*v = POW(1.0 + POW(*x, alpha), -beta/alpha);
}
void DgeneralisedCauchy(double *x, model *cov, double *v){
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA), ha, y=*x;
if (y ==0.0) {
*v = ((alpha > 1.0) ? 0.0 : (alpha < 1.0) ? RF_NEGINF : -beta);
} else {
ha = POW(y, alpha - 1.0);
*v = -beta * ha * POW(1.0 + ha * y, -beta / alpha - 1.0);
}
}
void DDgeneralisedCauchy(double *x, model *cov, double *v){
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA), ha, y=*x;
if (y ==0.0) {
*v = ((alpha==1.0) ? beta * (beta + 1.0)
: (alpha==2.0) ? -beta
: (alpha < 1) ? RF_INF : RF_NEGINF);
} else {
ha = POW(y, alpha);
*v = beta * ha / (y * y) * (1.0 - alpha + (1.0 + beta) * ha)
* POW(1.0 + ha, -beta / alpha - 2.0);
}
}
void D3generalisedCauchy(double *x, model *cov, double *v){
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA), ha, y=*x;
if (y ==0.0) {
*v = ((alpha==2.0) ? 0 : (alpha == 1)? -beta*(beta+1)*(beta+2) :
(alpha < 1)? RF_NEGINF : RF_INF);
} else {
ha=POW(y, alpha);
*v = -beta * ha / (y * y* y) * ( (beta + 1)*(beta + 2)*ha*ha -
(3*beta + alpha + 4)*(alpha - 1)*ha + (alpha-1)*(alpha -2) )
* POW(1.0 + ha, -beta / alpha - 3.0);
}
}
void D4generalisedCauchy(double *x, model *cov, double *v){
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA), y=*x;
if (y ==0.0) {
*v = ((alpha==2.0) ? 3*beta*(beta + 2) : (alpha == 1)?
beta*(beta+1)*(beta+2)*(beta + 3) :
(alpha < 1)? RF_INF : RF_NEGINF);
} else {
int ha=POW(y, alpha),
haSq = ha * ha;
*v = beta * ha / (y * y* y *y) *
( -(alpha-1) * (alpha-2)*(alpha-3) -
(alpha - 1) * ( 4*alpha*beta + alpha * (alpha + 7) +
6*beta*beta + 22*beta + 18 ) * haSq +
(alpha - 1) * (alpha * (4 * alpha + 7 * beta + 4) - 11*beta - 18) * ha +
(beta + 1) * (beta +2) * (beta + 3) * ha * haSq) *
POW(1.0 + ha, -beta / alpha - 4.0);
}
}
void loggeneralisedCauchy(double *x, model *cov, double *v, double *Sign){
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA);
*v = LOG(1.0 + POW(*x, alpha)) * -beta/alpha;
*Sign = 1.0;
}
void InversegeneralisedCauchy(double *x, model *cov, double *v) {
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA);
*v = RF_INF;
if (*x != 0.0) *v = POW(POW(*x, -alpha / beta) - 1.0, 1.0 / alpha);
// MLE works much better with 0.01 then with 0.05
}
int checkgeneralisedCauchy(model *cov){
if (OWNLOGDIM(0) > 2)
cov->pref[CircEmbedCutoff] = cov->pref[CircEmbedIntrinsic] = PREF_NONE;
cov->monotone = P0(GENC_ALPHA) <= 1.0 ? COMPLETELY_MON : NORMAL_MIXTURE;
RETURN_NOERROR;
}
void rangegeneralisedCauchy(model *cov, range_type *range) {
bool tcf = isnowTcf(cov) || equalsSphericalIsotropic(OWNISO(0));
range->min[GENC_ALPHA] = 0.0;
range->max[GENC_ALPHA] = tcf ? 1.0 : 2.0;
range->pmin[GENC_ALPHA] = 0.05;
range->pmax[GENC_ALPHA] = range->max[GENC_ALPHA];
range->openmin[GENC_ALPHA] = true;
range->openmax[GENC_ALPHA] = false;
range->min[GENC_BETA] = 0.0;
range->max[GENC_BETA] = RF_INF;
range->pmin[GENC_BETA] = 0.05;
range->pmax[GENC_BETA] = 10.0;
range->openmin[GENC_BETA] = true;
range->openmax[GENC_BETA] = true;
}
void coinitgenCauchy(model *cov, localinfotype *li) {
double
thres[2] = {0.5, 1.0},
alpha=P0(GENC_ALPHA);
if (alpha <= thres[0]) {
li->instances = 2;
li->value[0] = 0.5;
li->value[1] = 1.0;
li->msg[0] = li->msg[1] = MSGLOCAL_OK;
} else {
li->instances = 1;
li->value[0] = 1.0; // q[CUTOFF_A]
li->msg[0] = (alpha <= thres[1]) ? MSGLOCAL_OK : MSGLOCAL_JUSTTRY;
}
}
void ieinitgenCauchy(model *cov, localinfotype *li) {
li->instances = 1;
if (P0(GENC_ALPHA) <= 1.0) {
li->value[0] = 1.0;
li->msg[0] = MSGLOCAL_OK;
} else {
li->value[0] = 1.5;
li->msg[0] = MSGLOCAL_JUSTTRY;
}
}
/*---------------------------------*/
// ************************* bivariate Cauchy
void kappa_biCauchy(int i, model VARIABLE_IS_NOT_USED *cov, int *nr, int *nc){
*nc = 1;
*nr = i == BICauchyalpha || i == BICauchybeta|| i == BICauchyscale ? 3 : 1;
}
int checkbiCauchy(model *cov) {
if (OWNLOGDIM(0) > 2)
cov->pref[CircEmbedCutoff] = cov->pref[CircEmbedIntrinsic] = PREF_NONE;
RETURN_NOERROR;
}
void rangebiCauchy(model VARIABLE_IS_NOT_USED *cov, range_type *range){
range->min[BICauchyalpha] = 0.0;
range->max[BICauchyalpha] = 1;
range->pmin[BICauchyalpha] = 0.05;
range->pmax[BICauchyalpha] = 1;
range->openmin[BICauchyalpha] = true;
range->openmax[BICauchyalpha] = true;
range->min[BICauchybeta] = 0.0;
range->max[BICauchybeta] = RF_INF;
range->pmin[BICauchybeta] = 0.05;
range->pmax[BICauchybeta] = 10.0;
range->openmin[BICauchybeta] = true;
range->openmax[BICauchybeta] = true;
range->min[BICauchyscale] = 0.0;
range->max[BICauchyscale] = RF_INF;
range->pmin[BICauchyscale] = 1e-2;
range->pmax[BICauchyscale] = 100.0;
range->openmin[BICauchyscale] = true;
range->openmax[BICauchyscale] = true;
// to do: check rhos
range->min[BICauchyrho] = - 1;
range->max[BICauchyrho] = 1;
range->pmin[BICauchyrho] = - 1;
range->pmax[BICauchyrho] = 1;
range->openmin[BICauchyrho] = false;
range->openmax[BICauchyrho] = false;
}
void coinitbiCauchy(model *cov, localinfotype *li) {
double
thres = 1,
*alpha = P(BICauchyalpha);
if ( (alpha[0] <= thres) && (alpha[1] <= thres) && (alpha[2] <= thres) ) {
li->instances = 1;
li->value[0] = CUTOFF_THIRD_CONDITION; // q[CUTOFF_A]
li->msg[0] =MSGLOCAL_OK;
}
else {
li->instances = 1;
li->value[0] = CUTOFF_THIRD_CONDITION ; // q[CUTOFF_A]
li->msg[0] = MSGLOCAL_JUSTTRY;
}
}
void biCauchy (double *x, model *cov, double *v) {
int i;
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA),
y = *x, z;
assert(BICauchyalpha == GENC_ALPHA);
assert(BICauchybeta == GENC_BETA);
for (i=0; i<3; i++) {
z = y/P(BICauchyscale)[i];
P(GENC_ALPHA)[0] = P(BICauchyalpha)[i];
P(GENC_BETA)[0] = P(BICauchybeta)[i];
generalisedCauchy(&z, cov, v + i);
}
P(BICauchyalpha)[0] = alpha;
P(BICauchybeta)[0] = beta;
v[3] = v[2];
v[1] *= P0(BICauchyrho);
v[2] = v[1];
}
void DbiCauchy(double *x, model *cov, double *v) {
int i;
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA),
y = *x, z;
assert(BICauchyalpha == GENC_ALPHA);
assert(BICauchybeta == GENC_BETA);
for (i=0; i<3; i++) {
z = y/P(BICauchyscale)[i];
P(GENC_ALPHA)[0] = P(BICauchyalpha)[i];
P(GENC_BETA)[0] = P(BICauchybeta)[i];
DgeneralisedCauchy(&z, cov, v + i);
v[i] /=P(BICauchyscale)[i];
}
P(BICauchyalpha)[0] = alpha;
P(BICauchybeta)[0] = beta;
v[3] = v[2];
v[1] *= P0(BICauchyrho);
v[2] = v[1];
}
void DDbiCauchy(double *x, model *cov, double *v) {
int i;
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA),
y = *x, z;
assert(BICauchyalpha == GENC_ALPHA);
assert(BICauchybeta == GENC_BETA);
for (i=0; i<3; i++) {
z = y/P(BICauchyscale)[i];
P(GENC_ALPHA)[0] = P(BICauchyalpha)[i];
P(GENC_BETA)[0] = P(BICauchybeta)[i];
DDgeneralisedCauchy(&z, cov, v + i);
v[i] /=(P(BICauchyscale)[i]*P(BICauchyscale)[i]);
}
P(BICauchyalpha)[0] = alpha;
P(BICauchybeta)[0] = beta;
v[3] = v[2];
v[1] *= P0(BICauchyrho);
v[2] = v[1];
}
void D3biCauchy(double *x, model *cov, double *v) {
int i;
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA),
y = *x, z;
assert(BICauchyalpha == GENC_ALPHA);
assert(BICauchybeta == GENC_BETA);
for (i=0; i<3; i++) {
z = y/P(BICauchyscale)[i];
P(GENC_ALPHA)[0] = P(BICauchyalpha)[i];
P(GENC_BETA)[0] = P(BICauchybeta)[i];
D3generalisedCauchy(&z, cov, v + i);
v[i] /=(P(BICauchyscale)[i]*P(BICauchyscale)[i]*P(BICauchyscale)[i]);
}
P(BICauchyalpha)[0] = alpha;
P(BICauchybeta)[0] = beta;
v[3] = v[2];
v[1] *= P0(BICauchyrho);
v[2] = v[1];
}
void D4biCauchy(double *x, model *cov, double *v) {
int i;
double alpha = P0(GENC_ALPHA), beta=P0(GENC_BETA),
y = *x, z;
assert(BICauchyalpha == GENC_ALPHA);
assert(BICauchybeta == GENC_BETA);
for (i=0; i<3; i++) {
z = y/P(BICauchyscale)[i];
P(GENC_ALPHA)[0] = P(BICauchyalpha)[i];
P(GENC_BETA)[0] = P(BICauchybeta)[i];
D4generalisedCauchy(&z, cov, v + i);
double dummy = P(BICauchyscale)[i]*P(BICauchyscale)[i];
v[i] /=(dummy*dummy);
}
P(BICauchyalpha)[0] = alpha;
P(BICauchybeta)[0] = beta;
v[3] = v[2];
v[1] *= P0(BICauchyrho);
v[2] = v[1];
}
/* epsC -> generalised Cauchy : leading 1 is now an eps */
#define EPS_ALPHA 0
#define EPS_BETA 1
#define EPS_EPS 2
void epsC(double *x, model *cov, double *v){
double
alpha = P0(EPS_ALPHA),
beta=P0(EPS_BETA),
eps=P0(EPS_EPS);
*v = POW(eps + POW(*x, alpha), -beta/alpha);
}
void logepsC(double *x, model *cov, double *v, double *Sign){
double
alpha = P0(EPS_ALPHA),
beta=P0(EPS_BETA),
eps=P0(EPS_EPS);
*v = LOG(eps + POW(*x, alpha)) * -beta/alpha;
*Sign = 1.0;
}
void DepsC(double *x, model *cov, double *v){
double ha,
y=*x,
alpha = P0(EPS_ALPHA),
beta=P0(EPS_BETA),
eps=P0(EPS_EPS);
if (y ==0.0) {
*v = (eps == 0.0) ? RF_NEGINF :
((alpha > 1.0) ? 0.0 : (alpha < 1.0) ? RF_NEGINF : -beta);
} else {
ha = POW(y, alpha - 1.0);
*v = -beta * ha * POW(eps + ha * y, -beta / alpha - 1.0);
}
}
void DDepsC(double *x, model *cov, double *v){
double ha,
y=*x,
alpha = P0(EPS_ALPHA),
beta=P0(EPS_BETA),
eps=P0(EPS_EPS);
if (y ==0.0) {
*v = (eps == 0.0) ? RF_INF : ((alpha==2.0) ? beta * (beta + 1.0) : RF_INF);
} else {
ha = POW(y, alpha);
*v = beta * ha / (y * y) * ( (1.0 - alpha) * eps + (1.0 + beta) * ha)
* POW(eps + ha, -beta / alpha - 2.0);
}
}
void InverseepsC(double *x, model *cov, double *v){
double
alpha = P0(EPS_ALPHA),
beta=P0(EPS_BETA),
eps=P0(EPS_EPS);
*v = RF_INF;
if (*x != 0.0) *v = POW(POW(*x, -alpha / beta) - eps, 1.0 / alpha);
}
int checkepsC(model *cov){
double eps=P0(EPS_ALPHA);
int i, err;
if (OWNLOGDIM(0) > 2)
cov->pref[CircEmbedCutoff] = cov->pref[CircEmbedIntrinsic] = PREF_NONE;
if ((err = checkkappas(cov, false)) != NOERROR) RETURN_ERR(err);
kdefault(cov, EPS_ALPHA, 1.0);
kdefault(cov, EPS_BETA, 1.0);
kdefault(cov, EPS_EPS, 0.0);
if (ISNAN(eps) || eps == 0.0) {
// OWNDOM(0)=GENERALISEDCOVARIANCE; // later
for (i=CircEmbed; i<Nothing; i++) cov->pref[i] = PREF_NONE;
}
RETURN_NOERROR;
}
void rangeepsC(model VARIABLE_IS_NOT_USED *cov, range_type *range){
range->min[EPS_ALPHA] = 0.0;
range->max[EPS_ALPHA] = 2.0;
range->pmin[EPS_ALPHA] = 0.05;
range->pmax[EPS_ALPHA] = 2.0;
range->openmin[EPS_ALPHA] = true;
range->openmax[EPS_ALPHA] = false;
range->min[EPS_BETA] = 0.0;
range->max[EPS_BETA] = RF_INF;
range->pmin[EPS_BETA] = 0.05;
range->pmax[EPS_BETA] = 10.0;
range->openmin[EPS_BETA] = true;
range->openmax[EPS_BETA] = true;
range->min[EPS_EPS] = 0.0;
range->max[EPS_EPS] = RF_INF;
range->pmin[EPS_EPS] = 0.0;
range->pmax[EPS_EPS] = 10.0;
range->openmin[EPS_EPS] = true; // false for generlised covariance
range->openmax[EPS_EPS] = true;
}
/* hyperbolic */
#define BOLIC_NU 0
#define BOLIC_XI 1
#define BOLIC_DELTA 2
void hyperbolic(double *x, model *cov, double *v){
double Sign;
loghyperbolic(x, cov, v, &Sign);
*v = EXP(*v);
}
void loghyperbolic(double *x, model *cov, double *v, double *Sign){
double
nu = P0(BOLIC_NU),
xi=P0(BOLIC_XI),
delta=P0(BOLIC_DELTA),
y=*x;
*Sign = 1.0;
if (y==0.0) {
*v = 0.0;
return;
} else if (y==RF_INF) {
*v = RF_NEGINF;
*Sign = 0.0;
return;
}
if (delta==0) { // whittle matern
if (nu > 80) warning("extremely imprecise results due to nu>80");
*v = logWM(y * xi, nu, cov->q[WM_LOGGAMMA], 0.0);
} else if (xi==0) { //cauchy => NU2 < 0 !
y /= delta;
/* note change in Sign as NU2<0 */
*v = LOG(1.0 + y * y) * 0.5 * nu;
} else {
y=SQRT(delta * delta + y * y);
double bk[MATERN_NU_THRES + 1L],
xiy = xi * y,
nuThres = nu <= MATERN_NU_THRES ? nu : MATERN_NU_THRES,
factor = 1 / SQRT(nuThres);
if (xiy <= LOW_MATERN) {*v = 1.0; return;}
if (xiy == RF_INF) {*v = 0.0; return;} // also for cosine i.e. nu=-1/2
*v = QVALUE3 + nu * LOG(y) + LOG(bessel_k_ex(xiy, nu, 2.0, bk)) - xiy;
if (nu > MATERN_NU_THRES) { // factor!=0.0 &&
// printf("UU \n");
double w,
g = MATERN_NU_THRES / nu;
y = 0.5 * xiy * factor;
Gauss(&y, NULL, &w);
*v = *v * g + (1.0 - g) * w;
}
}
}
void Dhyperbolic(double *x, model *cov, double *v)
{
double
nu = P0(BOLIC_NU),
xi=P0(BOLIC_XI),
delta=P0(BOLIC_DELTA);
double
y = *x;
if (y==0.0) {
*v = 1.0;
return;
}
if (delta==0) { // whittle matern
*v = xi * Ext_DWM(y * xi, nu, cov->q[WM_LOGGAMMA], 0.0);
*v *= xi;
} else if (xi==0) { //cauchy
double ha;
y /= delta;
ha = y * y;
/* note change in Sign as NU2<0 */
*v = nu * FABS(y) * POW(1.0 + ha, 0.5 * nu - 1.0) / delta;
} else {
double nuThres = nu <= MATERN_NU_THRES ? nu : MATERN_NU_THRES,
s=SQRT(delta * delta + y * y),
xi_s = xi * s,
logs = LOG(s),
bk[MATERN_NU_THRES + 1L];
*v = - y * xi * EXP(QVALUE3 + (nuThres-1.0) * logs
+ LOG(bessel_k_ex(xi_s, nuThres-1.0, 2.0, bk)) - xi_s);
if (nu > MATERN_NU_THRES) {
double w,
g = MATERN_NU_THRES / nu,
factor = 1.0 / SQRT(nuThres),
scale = 0.5 * factor;
y = xi_s * scale;
DGauss(&y, NULL, &w);
w *= scale;
*v = *v * g + (1.0 - g) * w;
}
}
}
int inithyperbolic(model *cov, gen_storage VARIABLE_IS_NOT_USED *s) {
double nu = P0(BOLIC_NU),
nuThres = nu <= MATERN_NU_THRES ? nu : MATERN_NU_THRES,
xi=P0(BOLIC_XI),
delta=P0(BOLIC_DELTA),
xd = xi * delta, // xidelta
bk[MATERN_NU_THRES + 1L];
QVALUE3 = xd - LOG(bessel_k_ex(xd, nuThres, 2.0, bk)) - nuThres * LOG(delta);
if (nu > MATERN_NU_THRES) { // factor!=0.0 &&
// printf("UU \n");
double w,
factor = 1 / SQRT(nuThres),
g = MATERN_NU_THRES / nu,
y = 0.5 * xd * factor;
Gauss(&y, NULL, &w);
QVALUE3 = QVALUE3 * g + (1.0 - g) * w;
}
if (!ISNA(delta) && delta == 0.0 && !ISNA(nu)) {
assert(cov->q + WM_LOGGAMMA == &(QVALUE));
assert(cov->q + WM_GAMMA == &(QVALUE2));
cov->q[WM_LOGGAMMA] = lgammafn(nuThres); // QVALUE
cov->q[WM_GAMMA] = gammafn(nuThres); // QVALUE2
}
RETURN_NOERROR;
}
int checkhyperbolic(model *cov){
double
nu = P0(BOLIC_NU),
xi=P0(BOLIC_XI),
delta=P0(BOLIC_DELTA);
int i;
for (i=0; i<= Nothing; i++)
cov->pref[i] *= ( ((bool) ISNAN(nu)) || nu < WhittleUpperNu[i]);
if (nu>0) {
if ((delta<0) || (xi<=0)) {
SERR3("xi>0 and delta>=0 if nu>0. Got nu=%10g and delta=%10g for xi=%10g",
nu, delta, xi);
}
} else if (nu<0) {
if ((delta<=0) || (xi<0)) {
SERR3("xi>=0 and delta>0 if nu<0. Got nu=%10g and delta=%10g for xi=%10g",
nu, delta, xi);
}
} else { // nu==0.0
if ((delta<=0) || (xi<=0)) {
SERR3("xi>0 and delta>0 if nu=0. Got nu=%10g and delta=%10g for xi=%10g",
nu, delta, xi);
}
}
if (cov->q == NULL) {
EXTRA_Q;
inithyperbolic(cov, NULL);
}
RETURN_NOERROR;
}
void rangehyperbolic(model VARIABLE_IS_NOT_USED *cov, range_type *range){
range->min[BOLIC_NU] = RF_NEGINF;
range->max[BOLIC_NU] = RF_INF;
range->pmin[BOLIC_NU] = -20.0;
range->pmax[BOLIC_NU] = 20.0;
range->openmin[BOLIC_NU] = true;
range->openmax[BOLIC_NU] = true;
int i;
for (i=1; i<=2; i++) {
range->min[i] = 0.0;
range->max[i] = RF_INF;
range->pmin[i] = 0.000001;
range->pmax[i] = 10.0;
range->openmin[i] = false;
range->openmax[i] = true;
}
}
/* stable model */
#define STABLE_ALPHA 0
void stable(double *x, model *cov, double *v){
double y = *x, alpha = P0(STABLE_ALPHA);
*v = 1.0;
if (y!=0.0) *v = EXP(-POW(y, alpha));
}
void logstable(double *x, model *cov, double *v, double *Sign){
double y = *x, alpha = P0(STABLE_ALPHA);
*v = 0.0;
if (y!=0.0) *v= -POW(y, alpha);
*Sign = 1.0;
}
void Dstable(double *x, model *cov, double *v){
double z, y = *x, alpha = P0(STABLE_ALPHA);
if (y == 0.0) {
*v = (alpha > 1.0) ? 0.0 : (alpha < 1.0) ? RF_NEGINF : -1.0;
} else {
z = POW(y, alpha - 1.0);
*v = -alpha * z * EXP(-z * y);
}
}
/* stable: second derivative at t=1 */
void DDstable(double *x, model *cov, double *v)
{
double z, y = *x, alpha = P0(STABLE_ALPHA), xalpha;
if (y == 0.0) {
// olga please check
*v = (alpha == 1.0) ? 1.0 : (alpha == 2.0) ? -2.0 : //alpha * (1 - alpha)
alpha < 1.0 ? RF_INF : RF_NEGINF;
} else {
z = POW(y, alpha - 2.0);
xalpha = z * y * y;
*v = alpha * (1.0 - alpha + alpha * xalpha) * z * EXP(-xalpha);
}
}
void D3stable(double *x, model *cov, double *v)
{
double z, y = *x, alpha = P0(STABLE_ALPHA), xalpha;
if (y == 0.0) {
// olga, please check; please note that RF_INF has been incorrect (reserved for integer variables only)
*v = (alpha == 1.0) ? -1.0 : (alpha == 2.0) ? 0 :
alpha < 1.0 ? RF_NEGINF : RF_INF;
} else {
z = POW(y, alpha - 3.0);
xalpha = z * y * y * y;
*v = -alpha * ( 3*alpha*(xalpha -1) + alpha*alpha*
(xalpha*xalpha - 3*xalpha + 1) + 2) * z * EXP(-xalpha);
}
}
void D4stable(double *x, model *cov, double *v)
{
double z, y = *x, alpha = P0(STABLE_ALPHA), xalpha;
if (y == 0.0) {
*v = (alpha == 1.0) ? 1.0 : (alpha == 2.0) ? 0 :
alpha < 1.0 ? RF_INF : RF_NEGINF;
} else {
z = POW(y, alpha - 4.0);
xalpha = z * y * y * y * y;
*v = alpha*( alpha*alpha*alpha*(7*xalpha -6*xalpha*xalpha +
xalpha*xalpha*xalpha - 1 ) +
+6*alpha*alpha*(-3*xalpha + xalpha*xalpha +1 )+
11*alpha*(xalpha - 1 ) + 6 ) * z * EXP(-xalpha);
}
}
void D5stable(double *x, model *cov, double *v)
{
double z, y = *x, alpha = P0(STABLE_ALPHA), xalpha;
if (y == 0.0) {
*v = (alpha == 1.0) ? -1.0 : (alpha == 2.0) ? 0 :
alpha < 1.0 ? RF_NEGINF : RF_INF;;
} else {
z = POW(y, alpha - 5.0);
xalpha = z * y * y * y * y * y;
*v = -alpha*( POW(alpha, 4)*(-15*xalpha +25*xalpha*xalpha -
10*POW(xalpha, 3) + POW(xalpha, 4)+ 1 ) +
10*alpha*alpha*alpha*(7*xalpha -6*xalpha*xalpha +
POW(xalpha, 3) - 1 )+
35*alpha*alpha*(-3*xalpha + xalpha*xalpha + 1 )+
50*alpha*(xalpha -1 ) + 24 )* z * EXP(-xalpha);
}
}
void Inversestable(double *x, model *cov, double *v){
double y = *x, alpha = P0(STABLE_ALPHA);
*v = y>1.0 ? 0.0 : y == 0.0 ? RF_INF : POW( - LOG(y), 1.0 / alpha);
}
void nonstatLogInversestable(double *x, model *cov,
double *left, double *right){
double
alpha = P0(STABLE_ALPHA),
z = *x <= 0.0 ? POW( - *x, 1.0 / alpha) : 0.0;
int d,
dim = OWNLOGDIM(0);
for (d=0; d<dim; d++) {
left[d] = -z;
right[d] = z;
}
}
int checkstable(model *cov) {
double alpha = P0(STABLE_ALPHA);
if (OWNLOGDIM(0) > 2)
cov->pref[CircEmbedCutoff] = cov->pref[CircEmbedIntrinsic] = PREF_NONE;
if (alpha == 2.0)
cov->pref[CircEmbed] = 2;
cov->monotone = alpha <= 1.0 ? COMPLETELY_MON : NORMAL_MIXTURE;
RETURN_NOERROR;
}
void rangestable(model *cov, range_type *range){
bool tcf = isnowTcf(cov) || equalsSphericalIsotropic(OWNISO(0));
range->min[STABLE_ALPHA] = 0.0;
range->max[STABLE_ALPHA] = tcf ? 1.0 : 2.0;
range->pmin[STABLE_ALPHA] = 0.06;
range->pmax[STABLE_ALPHA] = range->max[STABLE_ALPHA];
range->openmin[STABLE_ALPHA] = true;
range->openmax[STABLE_ALPHA] = false;
}
void coinitstable(model *cov, localinfotype *li) {
coinitgenCauchy(cov, li);
}
void ieinitstable(model *cov, localinfotype *li) {
ieinitgenCauchy(cov, li);
}
/* DOUBLEISOTROPIC stable model for testing purposes only */
void stableX(double *x, model *cov, double *v){
double y, alpha = P0(STABLE_ALPHA);
y = x[0] * x[0] + x[1] * x[1];
*v = 1.0;
if (y!=0.0) *v = EXP(-POW(y, 0.5 * alpha));
}
void DstableX(double *x, model *cov, double *v){
double z, y, alpha = P0(STABLE_ALPHA);
y = x[0] * x[0] + x[1] * x[1];
if (y == 0.0) {
*v = ((alpha > 1.0) ? 0.0 : (alpha < 1.0) ? RF_INF : 1.0);
} else {
z = POW(y, 0.5 * alpha - 1.0);
*v = -alpha * x[0] * z * EXP(- z * y);
}
}
/* END DOUBLEISOTROPIC stable model for testing purposes only */
// ************************* bivariate powered exponential or bivariate stable
void kappa_biStable(int i, model VARIABLE_IS_NOT_USED *cov, int *nr,
int *nc){
*nc = 1;
*nr = ( i == BIStablealpha || i == BIStablescale ) ? 3 :
(i == BIStablecdiag || i == BIStablealphadiag ) ? 2 :
(i == BIStablerho || i == BIStablebetared || i == BIStablerhored ) ?
1 : -1;
}
int checkbiStable(model *cov) {
int err;
gen_storage s;
gen_NULL(&s);
s.check = true;
if ((err = checkkappas(cov, false)) != NOERROR) RETURN_ERR(err);
// bistable_storage *S = cov->Sbistable;
if (cov->Sbistable == NULL) {
ONCE_NEW_STORAGE(bistable);
bistable_storage *S = cov->Sbistable;
S->alphadiag_given = !PisNULL(BIStablealphadiag);
S->rhored_given = !PisNULL(BIStablerhored);
// printf("check: alphadiag_given = %d\n", S->alphadiag_given);
}
if ((err=initbiStable(cov, &s)) != NOERROR) RETURN_ERR(err);
VDIM0 = VDIM1 = 2;
if ((err = checkkappas(cov)) != NOERROR) RETURN_ERR(err);
//PMI(cov);
RETURN_NOERROR;
}
// alphadiag always out
sortsofparam sortof_bistable(model *cov, int k,
int VARIABLE_IS_NOT_USED *row,
int VARIABLE_IS_NOT_USED *col,
sort_origin origin) {
bistable_storage *S = cov->Sbistable;
if (S == NULL) return UNKNOWNPARAM;
switch(k) {
case BIStablealphadiag : case BIStablebetared :
return S->alphadiag_given || origin != original ? ANYPARAM : IGNOREPARAM;
case BIStablescale: return SCALEPARAM;
case BIStablecdiag : return VARPARAM;
case BIStablerho :
return S->rhored_given || origin == mle_conform ? IGNOREPARAM : ONLYRETURN;
case BIStablerhored :
return S->rhored_given || origin != original ? ANYPARAM : IGNOREPARAM;
case BIStablealpha : return S->alphadiag_given || origin == mle_conform
? IGNOREPARAM : ONLYRETURN;
default : BUG;
}
}
sortsofparam sortof_bistable_INisOUT(model *cov, int k,
int VARIABLE_IS_NOT_USED *row,
int VARIABLE_IS_NOT_USED *col) {
bistable_storage *S = cov->Sbistable;
if (S == NULL) return UNKNOWNPARAM;
switch(k) {
case BIStablealphadiag : return !S->alphadiag_given ? ONLYMLE : ANYPARAM;
case BIStablescale: return SCALEPARAM;
case BIStablecdiag : return VARPARAM;
case BIStablerho : return S->rhored_given ? ONLYRETURN : IGNOREPARAM;
case BIStablerhored : return S->rhored_given ? ONLYMLE : ANYPARAM;
case BIStablebetared : return !S->alphadiag_given ? ONLYMLE : ANYPARAM;
case BIStablealpha : return !S->alphadiag_given ? ONLYRETURN : IGNOREPARAM;
default : BUG;
}
}
void rangebiStable(model VARIABLE_IS_NOT_USED *cov, range_type *range){
range->min[BIStablealpha] = 0.0;
range->max[BIStablealpha] = 1;
range->pmin[BIStablealpha] = 0.06;
range->pmax[BIStablealpha] = 1;
range->openmin[BIStablealpha] = true;
range->openmax[BIStablealpha] = false;
range->min[BIStablealphadiag] = 0.0;
range->max[BIStablealphadiag] = 1;
range->pmin[BIStablealphadiag] = 0.06;
range->pmax[BIStablealphadiag] = 1;
range->openmin[BIStablealphadiag] = true;
range->openmax[BIStablealphadiag] = false;
range->min[BIStablebetared] = 0.0;
range->max[BIStablebetared] = 1.0;
range->pmin[BIStablebetared] = 0.0;
range->pmax[BIStablebetared] =1.0;
range->openmin[BIStablebetared] = false;
range->openmax[BIStablebetared] = false;
range->min[BIStablescale] = 0.0;
range->max[BIStablescale] = RF_INF;
range->pmin[BIStablescale] = 1e-2;
range->pmax[BIStablescale] = 100.0;
range->openmin[BIStablescale] = true;
range->openmax[BIStablescale] = true;
// *c = P0(BIc];
// to do: check rhos
// int dim = cov->tsdim;
// double *scale = P(BIStablescale);
range->min[BIStablerho] = - 1.0;
range->max[BIStablerho] = 1.0;
range->pmin[BIStablerho] = - 1.0;
range->pmax[BIStablerho] = 1.0;
range->openmin[BIStablerho] = false;
range->openmax[BIStablerho] = false;
range->min[BIStablerhored] = - 1.0;
range->max[BIStablerhored] = 1.0;
range->pmin[BIStablerhored] = - 1.0;
range->pmax[BIStablerhored] = 1.0;
range->openmin[BIStablerhored] = false;
range->openmax[BIStablerhored] = false;
range->min[BIStablecdiag] = 0;
range->max[BIStablecdiag] = RF_INF;
range->pmin[BIStablecdiag] = 0.001;
range->pmax[BIStablecdiag] = 1000;
range->openmin[BIStablecdiag] = false;
range->openmax[BIStablecdiag] = true;
}
void biStablePolynome(double r, double alpha, double a, int dim, double *v ) {
double x = POW(a*r, alpha);
if (dim == 1) {
*v = alpha*x - alpha + 1;
}
if ( dim == 2 || dim == 3 ) {
*v = alpha*alpha*x*x - 3*alpha*alpha*x + 4*alpha*x + alpha*alpha -
4*alpha + 3;
}
}
void biStableUnderInfLog(double r, double *alpha, double *a,
int dim, double *res ) {
double x = POW(a[i11]*r, alpha[i11]),
y = POW(a[i21]*r, alpha[i21]),
z = POW(a[i22]*r, alpha[i22]);
double p1, p2, p3;
biStablePolynome(r, alpha[i11], a[i11], dim, &p1 );
biStablePolynome(r, alpha[i21], a[i21], dim, &p2 );
biStablePolynome(r, alpha[i22], a[i22], dim, &p3 );
if (r == 0) {
*res = 0;
}
else {
*res = (alpha[i11] + alpha[i22] - 2*alpha[i21])*LOG(r) +
(2*y - x - z) + LOG(p1*p3/(p2*p2));
}
}
void biStableInterval(double *alpha, double *a, int dim,
double *left, double *right ) {
double middle = 1,
fmiddle, fright, fleft,
scalesratio1, scalesratio2, firstmin = 1.0/epsilon;
*left = *right = middle;
// check first if POW(a[0]/a[1], alpha[0] > 11 or
// check first if POW(a[2]/a[1], alpha[2] > 11
scalesratio1 = POW(a[0]/a[1], alpha[0]);
scalesratio2 = POW(a[2]/a[1], alpha[2]);
if ( (scalesratio1 >= 11) || (scalesratio2 >= 11) ) {
biStableUnderInfLog( 1.0/(POW(2, 1/alpha[1])*a[1] ), alpha, a, dim, &firstmin);
if (EXP(firstmin) < epsilon ) {
*left = 0;
*right = 0;
return;
}
}
biStableUnderInfLog(middle, alpha, a, dim, &fmiddle);
// if the value at 1/(POW(2, 1/alpha[1])*a[1] ) is smaller that the value at 1
// start searching around 1/(POW(2, 1/alpha[1])*a[1] )
if ( fmiddle > firstmin ) {
middle = 1.0/(POW(2, 1/alpha[1])*a[1] );
*left = *right = middle;
fmiddle = firstmin;
}
fright = fleft = fmiddle;
while (( fmiddle >= MIN(fleft, fright)) &&
(EXP(MIN(fleft, MIN(fright, fmiddle))) > epsilon ) ) {
if ( fleft <= fmiddle ) {
middle = *left;
fmiddle = fleft;
*left = *left/2;
}
if (fright <= fmiddle) {
middle = *right;
fmiddle = fright;
*right = *right*2;
}
biStableUnderInfLog(*right, alpha, a, dim, &fright );
biStableUnderInfLog(*left, alpha, a, dim, &fleft );
}
if (EXP(MIN(fleft, MIN(fright, fmiddle))) <= epsilon ) {
*left = 0;
*right = 0;
}
}
/*
* Golden search algorithm from Numerical Recipes in C,
* book by William H. Press
*
* (c, c) - interval for searching
* *alpha, *a - array of parameters of biStable model
* *rhomax - maximum allowable rho for *alpha, *a, the result of
* the searching
* dim - dimension of the model
* */
#define GOLDENR 0.61803399
#define GOLDENC (1.0 -GOLDENR)
#define GOLDENTOL 1e-9
#define GOLDENSHIFT2(a, b, c) (a) = (b); (b) = (c);
#define GOLDENSHIFT3(a, b, c, d) (a) = (b); (b) = (c); (c) = (d);
void biStableMinRho(model *cov, double *alpha, double *a, double ax, double cx, double *rhomax) {
double bx = ax + (cx - ax)*GOLDENC,
f1, f2, x0, x1, x2, x3, dummy,
logconst = LOG(alpha[i11]*alpha[i22]/(alpha[i21]*alpha[i21])*
POW(a[i11], alpha[i11])*POW(a[i22], alpha[i22])/
POW(a[i21], 2*alpha[i21]));
x0 = ax;
x3 = cx;
if ( FABS(cx - bx) > FABS(bx - ax) ) {
x1 = bx;
x2 = bx + GOLDENC*(cx - bx);
} else {
x2 = bx;
x1 = bx - GOLDENC*(bx - ax);
}
int dim = OWNLOGDIM(0);
biStableUnderInfLog(x1, alpha, a, dim, &f1);
biStableUnderInfLog(x2, alpha, a, dim, &f2);
while ( FABS(x3 - x0) > GOLDENTOL*(FABS(x1) + FABS(x2) ) ) {
if (f2 < f1) {
GOLDENSHIFT3(x0, x1, x2, GOLDENR*x1 + GOLDENC*x3 )
biStableUnderInfLog(x2, alpha, a, dim, &dummy);
GOLDENSHIFT2(f1, f2, dummy )
} else {
GOLDENSHIFT3(x3, x2, x1, GOLDENR*x2 + GOLDENC*x0 )
biStableUnderInfLog(x1, alpha, a, dim, &dummy);
GOLDENSHIFT2(f2, f1, dummy )
}
}
if (f1 < f2) {
*rhomax = SQRT(EXP(f1+logconst));
} else {
*rhomax = SQRT(EXP(f2+logconst));
}
*rhomax = MIN(*rhomax, 1);
}
int initbiStable(model *cov, gen_storage VARIABLE_IS_NOT_USED *s) {
double a[3],
*cdiag = P(BIStablecdiag),
*rho = P(BIStablerho),
*rhored = P(BIStablerhored),
// *cdiag = P(BIStablecdiag),
*alpha = P(BIStablealpha),
betared = RF_NAN,
*alphadiag,
*scale = P(BIStablescale),
betaa, betac, //beta_red in [0, 1]; beta_red*betaa + betac in [betac, betaa + betac]
rhomax = -2,
left = 0,
right = 0;
int dim = OWNLOGDIM(0);
bool notallowed = false;
bistable_storage *S = cov->Sbistable;
assert(S != NULL);
if (PisNULL(BIStablescale)) {
PALLOC(BIStablescale, 3, 1);
scale = P(BIStablescale);
for (int i = 0; i < 3; scale[i++] = 1.0);
}
// set a = 1/s
a[i11] = 1.0/scale[i11];
a[i21] = 1.0/scale[i21];
a[i22] = 1.0/scale[i22];
// default variance is 1
if (PisNULL(BIStablecdiag)) {
PALLOC(BIStablecdiag, 2, 1);
cdiag = P(BIStablecdiag);
cdiag[0] = 1;
cdiag[1] = 1;
}
// alpha diagonal are set => we are in likelohood estimation
// we map alphadiag and beta red to alpha[i11], alpha[i21], alpha[i22]
// alpha[i21] = betared*betaa + betac
// beta = betaa + (2 - betaa)*beta_red
if (S->alphadiag_given) {
alphadiag = P(BIStablealphadiag);
betaa = MAX(alphadiag[0], alphadiag[1]);
betac = 2 - betaa;
if (!PisNULL(BIStablebetared)) {
betared = P0(BIStablebetared);
}
if (s->check && !PisNULL(BIStablealpha) ) {
// if both alphas and alphadiag are given and check is true,
// then check if they alphas and alphadiag are equal (or close to equal)
alpha = P(BIStablealpha);
if (cov->nrow[BIStablealpha] != 3 || cov->ncol[BIStablealpha] != 1)
QERRC(BIStablealpha, "must be a 3 x 1 vector");
if (FABS(alpha[i11] - alphadiag[0]) > alpha[i11] * epsilon ||
FABS(alpha[i22] - alphadiag[1]) > alpha[i22] * epsilon ||
FABS(alpha[i21] - (betaa + betac*betared) )
> alpha[i21] * epsilon) {
// PMI(cov);
//printf("\n\n\n --- FABS(alpha[i21] - (betared*betaa + betac) ) = %10g \n", FABS(alpha[i21] - (betaa + betared*betac) ) );
// printf("\n\n\n --- alpha[i21] * epsilon = %10g \n", alpha[i21] * epsilon );
QERRC2(BIStablealpha, "does not match '%.50s' and '%.50s'.",
BIStablealphadiag, BIStablebetared);
}
}
// allocate memory for the alphas
if (PisNULL(BIStablealpha)) {
PALLOC(BIStablealpha, 3, 1);
}
alpha = P(BIStablealpha);
// fill the alphas
alpha[i11] = alphadiag[0];
alpha[i22] = alphadiag[1];
alpha[i21] = betaa + betared*betac;
// These combinations of smoothness parameters are not allowed
// if user mode, return an Error and stop
// if likelihood mode, set correlation to 0
//notallowed = ( alpha[i21] < MAX(alpha[i11], alpha[i22]) ) ||
} else {
//alphas are given
if ( !PisNULL(BIStablealpha) ) {
// all alphas are given, s->check => parameters are set by user,
// not likelihood, or they are NA
// we map alphas to alphadiag and betared
if (PisNULL(BIStablealphadiag)) PALLOC(BIStablealphadiag, 2, 1);
alphadiag = P(BIStablealphadiag);
if (PisNULL(BIStablebetared)) PALLOC(BIStablebetared, 1, 1);
alphadiag[0] = alpha[i11];
// alpha[i21];
alphadiag[1] = alpha[i22];
betaa = MAX(alphadiag[0], alphadiag[1]);
betac = 2 - MAX(alphadiag[0], alphadiag[1]);
P(BIStablebetared)[0] = (alpha[i21] - betaa)/betac ;
betared = P(BIStablebetared)[0];
}
if (PisNULL(BIStablealpha)) {
// PMI(cov);
QERRC2(BIStablealpha, "either '%.50s' or '%.50s' must be set", BIStablealpha,
BIStablealphadiag);
}
}
notallowed =
( ( alpha[i11] == alpha[i21] ) && ( alpha[i22] == alpha[i21] ) &&
( POW(a[i21], alpha[i11]) < 0.5*POW(a[i11], alpha[i11])+0.5*
POW(a[i22], alpha[i11]) ) ) ||
( ( alpha[i11] == alpha[i21] ) && ( alpha[i11] > alpha[i22] ) &&
( a[i21] <= POW(0.5, 1/alpha[i11])*a[i11] ) ) ||
( ( alpha[i22] == alpha[i21] ) && ( alpha[i22] > alpha[i11] ) &&
( a[i21] <= POW(0.5, 1/alpha[i22])*a[i22] ) )||
( alpha[i11] > alpha[i21] ) || ( alpha[i22] > alpha[i21] ) ;
if( notallowed && !s->check ) {
{rhomax = 0;}
}
if( notallowed && s->check ) {
QERRC(BIStablealpha, "This combination of smoothness parameters is not allowed.");
}
// alphas are set
// find maximum allowable rho
if (rhomax != 0) {
biStableInterval(alpha, a, dim, &left, &right );
if ( (right == 0) && (left == 0) ) {
rhomax = 0;
} else {
// PMI(cov);
// printf("\nDear Olga, please check the PMI output; if the output looks reasonable you should check your code in the next line.\n");
biStableMinRho(cov, alpha, a, left, right, &rhomax);
// printf("done\n");
}
}
// if rho is given, then it is set by user. Check if it is correct or not
// ERR("Olga, there must be a call of type \"if (rhored_given)...\"");
// if (!PisNULL(BIStablerhored) ){
if ( S->rhored_given ){
//if rhored is given, we are in the likelihood estimation
if (PisNULL(BIStablerho)) PALLOC(BIStablerho, 1, 1);
rho = P(BIStablerho);
*rho = P(BIStablerho)[0] = (*rhored)*rhomax;
} else if (!PisNULL(BIStablerho) && s->check ) {
if ( PisNULL(BIStablerhored) ) PALLOC(BIStablerhored, 1, 1);
rhored = P(BIStablerhored);
*rhored = (*rho)/rhomax;
} else if (!PisNULL(BIStablerho) && s->check ) {
if (FABS(*rho) > rhomax ) {
QERRC(BIStablealpha,
"The value of cross-correlation parameter rho is too high.");
}
if ( PisNULL(BIStablerhored) ) PALLOC(BIStablerhored, 1, 1);
rhored = P(BIStablerhored);
*rhored = P(BIStablerhored)[0]= (*rho)/rhomax;
}
// printf("end init: alphadiag_given = %d\n", S->alphadiag_given);
cov->initialised = true;
RETURN_NOERROR;
}
void coinitbiStable(model *cov, localinfotype *li) {
double
thres = 1,
*alpha = P(BIStablealpha);
if ( ( alpha[0] <= thres ) && ( alpha[1] <= thres ) &&
( alpha[2] <= thres ) ) {
li->instances = 1;
li->value[0] = 1; // q[CUTOFF_A]
li->msg[0] =MSGLOCAL_OK;
}
else {
li->instances = 1;
li->value[0] = CUTOFF_THIRD_CONDITION ; // q[CUTOFF_A]
li->msg[0] = MSGLOCAL_JUSTTRY;
}
}
void biStable (double *x, model *cov, double *v) {
int i;
double
alpha = P0(STABLE_ALPHA),
*cdiag = P(BIStablecdiag),
y = *x, z;
assert(BIStablealpha == STABLE_ALPHA);
/* biStable_storage *S = cov->SbiStable;
assert(S != NULL);
*/
for (i=0; i<3; i++) {
z = y/P(BIStablescale)[i];
P(STABLE_ALPHA)[0] = P(BIStablealpha)[i];
stable(&z, cov, v + i);
}
P(BIStablealpha)[0] = alpha;
v[0] = v[0]*cdiag[0];
v[3] = v[2]*cdiag[1];
v[1] *= P0(BIStablerho)*SQRT(cdiag[0]*cdiag[1]);
v[2] = v[1];
// printf("(%4.3f, %4.3f; %4.3e %4.3e %4.3e %4.3e)\t", x[0], x[1], v[0], v[1], v[2], v[3]);
// PMI(cov->calling->calling);
// if (!R_FINITE(v[0]) || !R_FINITE(v[1]) || !R_FINITE(v[2]) || !R_FINITE(v[3])) { PMI(cov); printf("(%4.3f, %4.3f; %4.3e %4.3e %4.3e %4.3e)\t", x[0], x[1], v[0], v[1], v[2], v[3]); BUG; }
}
void DbiStable(double *x, model *cov, double *v) {
int i;
double
alpha = P0(STABLE_ALPHA),
*cdiag = P(BIStablecdiag),
y = *x, z;
assert(BIStablealpha == STABLE_ALPHA);
/* biStable_storage *S = cov->SbiStable;
assert(S != NULL);
*/
for (i=0; i<3; i++) {
z = y/P(BIStablescale)[i];
P(STABLE_ALPHA)[0] = P(BIStablealpha)[i];
Dstable(&z, cov, v + i);
v[i] /= P(BIStablescale)[i];
}
P(BIStablealpha)[0] = alpha;
v[0] = v[0]*cdiag[0];
v[3] = v[2]*cdiag[1];
v[1] *= P0(BIStablerho)*SQRT(cdiag[0]*cdiag[1]);
v[2] = v[1];
}
void DDbiStable(double *x, model *cov, double *v) {
int i;
double
alpha = P0(STABLE_ALPHA),
*cdiag = P(BIStablecdiag),
y = *x, z;
assert(BIStablealpha == STABLE_ALPHA);
/* biStable_storage *S = cov->SbiStable;
assert(S != NULL);
*/
for (i=0; i<3; i++) {
z = y/P(BIStablescale)[i];
P(STABLE_ALPHA)[0] = P(BIStablealpha)[i];
DDstable(&z, cov, v + i);
v[i] /= P(BIStablescale)[i]*P(BIStablescale)[i];
}
P(BIStablealpha)[0] = alpha;
v[0] = v[0]*cdiag[0];
v[3] = v[2]*cdiag[1];
v[1] *= P0(BIStablerho)*SQRT(cdiag[0]*cdiag[1]);
v[2] = v[1];
}
void D3biStable(double *x, model *cov, double *v) {
int i;
double
alpha = P0(STABLE_ALPHA),
*cdiag = P(BIStablecdiag),
y = *x, z;
assert(BIStablealpha == STABLE_ALPHA);
/* biStable_storage *S = cov->SbiStable;
assert(S != NULL);
*/
for (i=0; i<3; i++) {
z = y/P(BIStablescale)[i];
P(STABLE_ALPHA)[0] = P(BIStablealpha)[i];
D3stable(&z, cov, v + i);
v[i] /= P(BIStablescale)[i]*P(BIStablescale)[i]*P(BIStablescale)[i];
}
P(BIStablealpha)[0] = alpha;
v[0] = v[0]*cdiag[0];
v[3] = v[2]*cdiag[1];
v[1] *= P0(BIStablerho)*SQRT(cdiag[0]*cdiag[1]);
v[2] = v[1];
}
void D4biStable(double *x, model *cov, double *v) {
int i;
double
alpha = P0(STABLE_ALPHA),
*cdiag = P(BIStablecdiag),
y = *x, z;
// assert(BIStablealpha == STABLE_ALPHA);
/* biStable_storage *S = cov->SbiStable;
assert(S != NULL);
*/
// assert(cov->initialised);
for (i=0; i<3; i++) {
z = y/P(BIStablescale)[i];
P(STABLE_ALPHA)[0] = P(BIStablealpha)[i];
D4stable(&z, cov, v + i);
double dummy =P(BIStablescale)[i]*P(BIStablescale)[i];
v[i] /= dummy*dummy;
}
P(BIStablealpha)[0] = alpha;
v[0] = v[0]*cdiag[0];
v[3] = v[2]*cdiag[1];
v[1] *= P0(BIStablerho)*SQRT(cdiag[0]*cdiag[1]);
v[2] = v[1];
}