Rev 80166 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* Copyright (C) 2002-2016 The R Core Team.** 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 2 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, a copy is available at* https://www.R-project.org/Licenses/*/#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <stdlib.h> // for abs#include <string.h>#include <R.h>#include "ts.h"#include "statsR.h" // for getListElement#ifndef max#define max(a,b) ((a < b)?(b):(a))#endif#ifndef min#define min(a,b) ((a < b)?(a):(b))#endif/*KalmanLike, internal to StructTS:.Call(C_KalmanLike, y, mod$Z, mod$a, mod$P, mod$T, mod$V, mod$h, mod$Pn,nit, FALSE, update)KalmanRun:.Call(C_KalmanLike, y, mod$Z, mod$a, mod$P, mod$T, mod$V, mod$h, mod$Pn,nit, TRUE, update)*//* y vector length n of observationsZ vector length p for observation equation y_t = Za_t + eps_ta vector length p of initial stateP p x p matrix for initial state uncertainty (contemparaneous)T p x p transition matrixV p x p = RQR'h = var(eps_t)anew used for a[t|t-1]Pnew used for P[t|t -1]M used for M = P[t|t -1]Zop is FALSE for KalmanLike, TRUE for KalmanRun.The latter computes residuals and states and hasa more elaborate return value.Almost no checking here!*/SEXPKalmanLike(SEXP sy, SEXP mod, SEXP sUP, SEXP op, SEXP update){int lop = asLogical(op);mod = PROTECT(duplicate(mod));SEXP sZ = getListElement(mod, "Z"), sa = getListElement(mod, "a"),sP = getListElement(mod, "P"), sT = getListElement(mod, "T"),sV = getListElement(mod, "V"), sh = getListElement(mod, "h"),sPn = getListElement(mod, "Pn");if (TYPEOF(sy) != REALSXP || TYPEOF(sZ) != REALSXP ||TYPEOF(sa) != REALSXP || TYPEOF(sP) != REALSXP ||TYPEOF(sPn) != REALSXP ||TYPEOF(sT) != REALSXP || TYPEOF(sV) != REALSXP)error(_("invalid argument type"));int n = LENGTH(sy), p = LENGTH(sa);double *y = REAL(sy), *Z = REAL(sZ), *T = REAL(sT), *V = REAL(sV),*P = REAL(sP), *a = REAL(sa), *Pnew = REAL(sPn), h = asReal(sh);double *anew = (double *) R_alloc(p, sizeof(double));double *M = (double *) R_alloc(p, sizeof(double));double *mm = (double *) R_alloc(p * p, sizeof(double));// These are only used if(lop), but avoid -Wall troubleSEXP ans = R_NilValue, resid = R_NilValue, states = R_NilValue;if(lop) {PROTECT(ans = allocVector(VECSXP, 3));SET_VECTOR_ELT(ans, 1, resid = allocVector(REALSXP, n));SET_VECTOR_ELT(ans, 2, states = allocMatrix(REALSXP, n, p));SEXP nm = PROTECT(allocVector(STRSXP, 3));SET_STRING_ELT(nm, 0, mkChar("values"));SET_STRING_ELT(nm, 1, mkChar("resid"));SET_STRING_ELT(nm, 2, mkChar("states"));setAttrib(ans, R_NamesSymbol, nm);UNPROTECT(1);}double sumlog = 0.0, ssq = 0.0;int nu = 0;for (int l = 0; l < n; l++) {for (int i = 0; i < p; i++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += T[i + p * k] * a[k];anew[i] = tmp;}if (l > asInteger(sUP)) {for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += T[i + p * k] * P[k + p * j];mm[i + p * j] = tmp;}for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = V[i + p * j];for (int k = 0; k < p; k++)tmp += mm[i + p * k] * T[j + p * k];Pnew[i + p * j] = tmp;}}if (!ISNAN(y[l])) {nu++;double *rr = NULL /* -Wall */;if(lop) rr = REAL(resid);double resid0 = y[l];for (int i = 0; i < p; i++)resid0 -= Z[i] * anew[i];double gain = h;for (int i = 0; i < p; i++) {double tmp = 0.0;for (int j = 0; j < p; j++)tmp += Pnew[i + j * p] * Z[j];M[i] = tmp;gain += Z[i] * M[i];}ssq += resid0 * resid0 / gain;if(lop) rr[l] = resid0 / sqrt(gain);sumlog += log(gain);for (int i = 0; i < p; i++)a[i] = anew[i] + M[i] * resid0 / gain;for (int i = 0; i < p; i++)for (int j = 0; j < p; j++)P[i + j * p] = Pnew[i + j * p] - M[i] * M[j] / gain;} else {double *rr = NULL /* -Wall */;if(lop) rr = REAL(resid);for (int i = 0; i < p; i++)a[i] = anew[i];for (int i = 0; i < p * p; i++)P[i] = Pnew[i];if(lop) rr[l] = NA_REAL;}if(lop) {double *rs = REAL(states);for (int j = 0; j < p; j++) rs[l + n*j] = a[j];}}SEXP res = PROTECT(allocVector(REALSXP, 2));REAL(res)[0] = ssq/nu; REAL(res)[1] = sumlog/nu;if(lop) {SET_VECTOR_ELT(ans, 0, res);if(asLogical(update)) setAttrib(ans, install("mod"), mod);UNPROTECT(3);return ans;} else {if(asLogical(update)) setAttrib(res, install("mod"), mod);UNPROTECT(2);return res;}}SEXPKalmanSmooth(SEXP sy, SEXP mod, SEXP sUP){SEXP sZ = getListElement(mod, "Z"), sa = getListElement(mod, "a"),sP = getListElement(mod, "P"), sT = getListElement(mod, "T"),sV = getListElement(mod, "V"), sh = getListElement(mod, "h"),sPn = getListElement(mod, "Pn");if (TYPEOF(sy) != REALSXP || TYPEOF(sZ) != REALSXP ||TYPEOF(sa) != REALSXP || TYPEOF(sP) != REALSXP ||TYPEOF(sT) != REALSXP || TYPEOF(sV) != REALSXP)error(_("invalid argument type"));SEXP ssa, ssP, ssPn, res, states = R_NilValue, sN;int n = LENGTH(sy), p = LENGTH(sa);double *y = REAL(sy), *Z = REAL(sZ), *a, *P,*T = REAL(sT), *V = REAL(sV), h = asReal(sh), *Pnew;double *at, *rt, *Pt, *gains, *resids, *Mt, *L, gn, *Nt;Rboolean var = TRUE;PROTECT(ssa = duplicate(sa)); a = REAL(ssa);PROTECT(ssP = duplicate(sP)); P = REAL(ssP);PROTECT(ssPn = duplicate(sPn)); Pnew = REAL(ssPn);PROTECT(res = allocVector(VECSXP, 2));SEXP nm = PROTECT(allocVector(STRSXP, 2));SET_STRING_ELT(nm, 0, mkChar("smooth"));SET_STRING_ELT(nm, 1, mkChar("var"));setAttrib(res, R_NamesSymbol, nm);UNPROTECT(1);SET_VECTOR_ELT(res, 0, states = allocMatrix(REALSXP, n, p));at = REAL(states);SET_VECTOR_ELT(res, 1, sN = allocVector(REALSXP, n*p*p));Nt = REAL(sN);double *anew, *mm, *M;anew = (double *) R_alloc(p, sizeof(double));M = (double *) R_alloc(p, sizeof(double));mm = (double *) R_alloc(p * p, sizeof(double));Pt = (double *) R_alloc(n * p * p, sizeof(double));gains = (double *) R_alloc(n, sizeof(double));resids = (double *) R_alloc(n, sizeof(double));Mt = (double *) R_alloc(n * p, sizeof(double));L = (double *) R_alloc(p * p, sizeof(double));for (int l = 0; l < n; l++) {for (int i = 0; i < p; i++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += T[i + p * k] * a[k];anew[i] = tmp;}if (l > asInteger(sUP)) {for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += T[i + p * k] * P[k + p * j];mm[i + p * j] = tmp;}for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = V[i + p * j];for (int k = 0; k < p; k++)tmp += mm[i + p * k] * T[j + p * k];Pnew[i + p * j] = tmp;}}for (int i = 0; i < p; i++) at[l + n*i] = anew[i];for (int i = 0; i < p*p; i++) Pt[l + n*i] = Pnew[i];if (!ISNAN(y[l])) {double resid0 = y[l];for (int i = 0; i < p; i++)resid0 -= Z[i] * anew[i];double gain = h;for (int i = 0; i < p; i++) {double tmp = 0.0;for (int j = 0; j < p; j++)tmp += Pnew[i + j * p] * Z[j];Mt[l + n*i] = M[i] = tmp;gain += Z[i] * M[i];}gains[l] = gain;resids[l] = resid0;for (int i = 0; i < p; i++)a[i] = anew[i] + M[i] * resid0 / gain;for (int i = 0; i < p; i++)for (int j = 0; j < p; j++)P[i + j * p] = Pnew[i + j * p] - M[i] * M[j] / gain;} else {for (int i = 0; i < p; i++) {a[i] = anew[i];Mt[l + n * i] = 0.0;}for (int i = 0; i < p * p; i++)P[i] = Pnew[i];gains[l] = NA_REAL;resids[l] = NA_REAL;}}/* rt stores r_{t-1} */rt = (double *) R_alloc(n * p, sizeof(double));for (int l = n - 1; l >= 0; l--) {if (!ISNAN(gains[l])) {gn = 1/gains[l];for (int i = 0; i < p; i++)rt[l + n * i] = Z[i] * resids[l] * gn;} else {for (int i = 0; i < p; i++) rt[l + n * i] = 0.0;gn = 0.0;}if (var) {for (int i = 0; i < p; i++)for (int j = 0; j < p; j++)Nt[l + n*i + n*p*j] = Z[i] * Z[j] * gn;}if (l < n - 1) {/* compute r_{t-1} */for (int i = 0; i < p; i++)for (int j = 0; j < p; j++)mm[i + p * j] = ((i==j) ? 1:0) - Mt[l + n * i] * Z[j] * gn;for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += T[i + p * k] * mm[k + p * j];L[i + p * j] = tmp;}for (int i = 0; i < p; i++) {double tmp = 0.0;for (int j = 0; j < p; j++)tmp += L[j + p * i] * rt[l + 1 + n * j];rt[l + n * i] += tmp;}if(var) { /* compute N_{t-1} */for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += L[k + p * i] * Nt[l + 1 + n*k + n*p*j];mm[i + p * j] = tmp;}for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += mm[i + p * k] * L[k + p * j];Nt[l + n*i + n*p*j] += tmp;}}}for (int i = 0; i < p; i++) {double tmp = 0.0;for (int j = 0; j < p; j++)tmp += Pt[l + n*i + n*p*j] * rt[l + n * j];at[l + n*i] += tmp;}}if (var)for (int l = 0; l < n; l++) {for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += Pt[l + n*i + n*p*k] * Nt[l + n*k + n*p*j];mm[i + p * j] = tmp;}for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = Pt[l + n*i + n*p*j];for (int k = 0; k < p; k++)tmp -= mm[i + p * k] * Pt[l + n*k + n*p*j];Nt[l + n*i + n*p*j] = tmp;}}UNPROTECT(4);return res;}SEXPKalmanFore(SEXP nahead, SEXP mod, SEXP update){mod = PROTECT(duplicate(mod));SEXP sZ = getListElement(mod, "Z"), sa = getListElement(mod, "a"),sP = getListElement(mod, "P"), sT = getListElement(mod, "T"),sV = getListElement(mod, "V"), sh = getListElement(mod, "h");if (TYPEOF(sZ) != REALSXP ||TYPEOF(sa) != REALSXP || TYPEOF(sP) != REALSXP ||TYPEOF(sT) != REALSXP || TYPEOF(sV) != REALSXP)error(_("invalid argument type"));int n = asInteger(nahead), p = LENGTH(sa);double *Z = REAL(sZ), *a = REAL(sa), *P = REAL(sP), *T = REAL(sT),*V = REAL(sV), h = asReal(sh);double *mm, *anew, *Pnew;anew = (double *) R_alloc(p, sizeof(double));Pnew = (double *) R_alloc(p * p, sizeof(double));mm = (double *) R_alloc(p * p, sizeof(double));SEXP res, forecasts, se;PROTECT(res = allocVector(VECSXP, 2));SET_VECTOR_ELT(res, 0, forecasts = allocVector(REALSXP, n));SET_VECTOR_ELT(res, 1, se = allocVector(REALSXP, n));{SEXP nm = PROTECT(allocVector(STRSXP, 2));SET_STRING_ELT(nm, 0, mkChar("pred"));SET_STRING_ELT(nm, 1, mkChar("var"));setAttrib(res, R_NamesSymbol, nm);UNPROTECT(1);}for (int l = 0; l < n; l++) {double fc = 0.0;for (int i = 0; i < p; i++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += T[i + p * k] * a[k];anew[i] = tmp;fc += tmp * Z[i];}for (int i = 0; i < p; i++)a[i] = anew[i];REAL(forecasts)[l] = fc;for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = 0.0;for (int k = 0; k < p; k++)tmp += T[i + p * k] * P[k + p * j];mm[i + p * j] = tmp;}for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {double tmp = V[i + p * j];for (int k = 0; k < p; k++)tmp += mm[i + p * k] * T[j + p * k];Pnew[i + p * j] = tmp;}double tmp = h;for (int i = 0; i < p; i++)for (int j = 0; j < p; j++) {P[i + j * p] = Pnew[i + j * p];tmp += Z[i] * Z[j] * P[i + j * p];}REAL(se)[l] = tmp;}if(asLogical(update)) setAttrib(res, install("mod"), mod);UNPROTECT(2);return res;}static void partrans(int p, double *raw, double *new){int j, k;double a, work[100];if(p > 100) error(_("can only transform 100 pars in arima0"));/* Step one: map (-Inf, Inf) to (-1, 1) via tanhThe parameters are now the pacf phi_{kk} */for(j = 0; j < p; j++) work[j] = new[j] = tanh(raw[j]);/* Step two: run the Durbin-Levinson recursions to find phi_{j.},j = 2, ..., p and phi_{p.} are the autoregression coefficients */for(j = 1; j < p; j++) {a = new[j];for(k = 0; k < j; k++)work[k] -= a * new[j - k - 1];for(k = 0; k < j; k++) new[k] = work[k];}}SEXP ARIMA_undoPars(SEXP sin, SEXP sarma){int *arma = INTEGER(sarma), mp = arma[0], mq = arma[1], msp = arma[2],v, n = LENGTH(sin);double *params, *in = REAL(sin);SEXP res = allocVector(REALSXP, n);params = REAL(res);for (int i = 0; i < n; i++) params[i] = in[i];if (mp > 0) partrans(mp, in, params);v = mp + mq;if (msp > 0) partrans(msp, in + v, params + v);return res;}SEXP ARIMA_transPars(SEXP sin, SEXP sarma, SEXP strans){int *arma = INTEGER(sarma), trans = asLogical(strans);int mp = arma[0], mq = arma[1], msp = arma[2], msq = arma[3],ns = arma[4], i, j, p = mp + ns * msp, q = mq + ns * msq, v;double *in = REAL(sin), *params = REAL(sin), *phi, *theta;SEXP res, sPhi, sTheta;PROTECT(res = allocVector(VECSXP, 2));SET_VECTOR_ELT(res, 0, sPhi = allocVector(REALSXP, p));SET_VECTOR_ELT(res, 1, sTheta = allocVector(REALSXP, q));phi = REAL(sPhi);theta = REAL(sTheta);if (trans) {int n = mp + mq + msp + msq;params = (double *) R_alloc(n, sizeof(double));for (i = 0; i < n; i++) params[i] = in[i];if (mp > 0) partrans(mp, in, params);v = mp + mq;if (msp > 0) partrans(msp, in + v, params + v);}if (ns > 0) {/* expand out seasonal ARMA models */for (i = 0; i < mp; i++) phi[i] = params[i];for (i = 0; i < mq; i++) theta[i] = params[i + mp];for (i = mp; i < p; i++) phi[i] = 0.0;for (i = mq; i < q; i++) theta[i] = 0.0;for (j = 0; j < msp; j++) {phi[(j + 1) * ns - 1] += params[j + mp + mq];for (i = 0; i < mp; i++)phi[(j + 1) * ns + i] -= params[i] * params[j + mp + mq];}for (j = 0; j < msq; j++) {theta[(j + 1) * ns - 1] += params[j + mp + mq + msp];for (i = 0; i < mq; i++)theta[(j + 1) * ns + i] += params[i + mp] *params[j + mp + mq + msp];}} else {for (i = 0; i < mp; i++) phi[i] = params[i];for (i = 0; i < mq; i++) theta[i] = params[i + mp];}UNPROTECT(1);return res;}#if !defined(atanh) && defined(HAVE_DECL_ATANH) && !HAVE_DECL_ATANHextern double atanh(double x);#endifstatic void invpartrans(int p, double *phi, double *new){int j, k;double a, work[100];if(p > 100) error(_("can only transform 100 pars in arima0"));for(j = 0; j < p; j++) work[j] = new[j] = phi[j];/* Run the Durbin-Levinson recursions backwardsto find the PACF phi_{j.} from the autoregression coefficients */for(j = p - 1; j > 0; j--) {a = new[j];for(k = 0; k < j; k++)work[k] = (new[k] + a * new[j - k - 1]) / (1 - a * a);for(k = 0; k < j; k++) new[k] = work[k];}for(j = 0; j < p; j++) new[j] = atanh(new[j]);}SEXP ARIMA_Invtrans(SEXP in, SEXP sarma){int *arma = INTEGER(sarma), mp = arma[0], mq = arma[1], msp = arma[2],i, v, n = LENGTH(in);SEXP y = allocVector(REALSXP, n);double *raw = REAL(in), *new = REAL(y);for(i = 0; i < n; i++) new[i] = raw[i];if (mp > 0) invpartrans(mp, raw, new);v = mp + mq;if (msp > 0) invpartrans(msp, raw + v, new + v);return y;}#define eps 1e-3SEXP ARIMA_Gradtrans(SEXP in, SEXP sarma){int *arma = INTEGER(sarma), mp = arma[0], mq = arma[1], msp = arma[2],n = LENGTH(in);SEXP y = allocMatrix(REALSXP, n, n);double *raw = REAL(in), *A = REAL(y), w1[100], w2[100], w3[100];for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)A[i + j*n] = (i == j);if(mp > 0) {for (int i = 0; i < mp; i++) w1[i] = raw[i];partrans(mp, w1, w2);for (int i = 0; i < mp; i++) {w1[i] += eps;partrans(mp, w1, w3);for (int j = 0; j < mp; j++) A[i + j*n] = (w3[j] - w2[j])/eps;w1[i] -= eps;}}if(msp > 0) {int v = mp + mq;for (int i = 0; i < msp; i++) w1[i] = raw[i + v];partrans(msp, w1, w2);for(int i = 0; i < msp; i++) {w1[i] += eps;partrans(msp, w1, w3);for(int j = 0; j < msp; j++)A[i + v + (j+v)*n] = (w3[j] - w2[j])/eps;w1[i] -= eps;}}return y;}SEXPARIMA_Like(SEXP sy, SEXP mod, SEXP sUP, SEXP giveResid){SEXP sPhi = getListElement(mod, "phi"),sTheta = getListElement(mod, "theta"),sDelta = getListElement(mod, "Delta"),sa = getListElement(mod, "a"),sP = getListElement(mod, "P"),sPn = getListElement(mod, "Pn");if (TYPEOF(sPhi) != REALSXP || TYPEOF(sTheta) != REALSXP ||TYPEOF(sDelta) != REALSXP || TYPEOF(sa) != REALSXP ||TYPEOF(sP) != REALSXP || TYPEOF(sPn) != REALSXP)error(_("invalid argument type"));SEXP res, nres, sResid = R_NilValue;int n = LENGTH(sy), rd = LENGTH(sa), p = LENGTH(sPhi),q = LENGTH(sTheta), d = LENGTH(sDelta), r = rd - d;double *y = REAL(sy), *a = REAL(sa), *P = REAL(sP), *Pnew = REAL(sPn);double *phi = REAL(sPhi), *theta = REAL(sTheta), *delta = REAL(sDelta);double sumlog = 0.0, ssq = 0, *anew, *mm = NULL, *M;int nu = 0;Rboolean useResid = asLogical(giveResid);double *rsResid = NULL /* -Wall */;anew = (double *) R_alloc(rd, sizeof(double));M = (double *) R_alloc(rd, sizeof(double));if (d > 0) mm = (double *) R_alloc(rd * rd, sizeof(double));if (useResid) {PROTECT(sResid = allocVector(REALSXP, n));rsResid = REAL(sResid);}for (int l = 0; l < n; l++) {for (int i = 0; i < r; i++) {double tmp = (i < r - 1) ? a[i + 1] : 0.0;if (i < p) tmp += phi[i] * a[0];anew[i] = tmp;}if (d > 0) {for (int i = r + 1; i < rd; i++) anew[i] = a[i - 1];double tmp = a[0];for (int i = 0; i < d; i++) tmp += delta[i] * a[r + i];anew[r] = tmp;}if (l > asInteger(sUP)) {if (d == 0) {for (int i = 0; i < r; i++) {double vi = 0.0;if (i == 0) vi = 1.0; else if (i - 1 < q) vi = theta[i - 1];for (int j = 0; j < r; j++) {double tmp = 0.0;if (j == 0) tmp = vi; else if (j - 1 < q) tmp = vi * theta[j - 1];if (i < p && j < p) tmp += phi[i] * phi[j] * P[0];if (i < r - 1 && j < r - 1) tmp += P[i + 1 + r * (j + 1)];if (i < p && j < r - 1) tmp += phi[i] * P[j + 1];if (j < p && i < r - 1) tmp += phi[j] * P[i + 1];Pnew[i + r * j] = tmp;}}} else {/* mm = TP */for (int i = 0; i < r; i++)for (int j = 0; j < rd; j++) {double tmp = 0.0;if (i < p) tmp += phi[i] * P[rd * j];if (i < r - 1) tmp += P[i + 1 + rd * j];mm[i + rd * j] = tmp;}for (int j = 0; j < rd; j++) {double tmp = P[rd * j];for (int k = 0; k < d; k++)tmp += delta[k] * P[r + k + rd * j];mm[r + rd * j] = tmp;}for (int i = 1; i < d; i++)for (int j = 0; j < rd; j++)mm[r + i + rd * j] = P[r + i - 1 + rd * j];/* Pnew = mmT' */for (int i = 0; i < r; i++)for (int j = 0; j < rd; j++) {double tmp = 0.0;if (i < p) tmp += phi[i] * mm[j];if (i < r - 1) tmp += mm[rd * (i + 1) + j];Pnew[j + rd * i] = tmp;}for (int j = 0; j < rd; j++) {double tmp = mm[j];for (int k = 0; k < d; k++)tmp += delta[k] * mm[rd * (r + k) + j];Pnew[rd * r + j] = tmp;}for (int i = 1; i < d; i++)for (int j = 0; j < rd; j++)Pnew[rd * (r + i) + j] = mm[rd * (r + i - 1) + j];/* Pnew <- Pnew + (1 theta) %o% (1 theta) */for (int i = 0; i <= q; i++) {double vi = (i == 0) ? 1. : theta[i - 1];for (int j = 0; j <= q; j++)Pnew[i + rd * j] += vi * ((j == 0) ? 1. : theta[j - 1]);}}}if (!ISNAN(y[l])) {double resid = y[l] - anew[0];for (int i = 0; i < d; i++)resid -= delta[i] * anew[r + i];for (int i = 0; i < rd; i++) {double tmp = Pnew[i];for (int j = 0; j < d; j++)tmp += Pnew[i + (r + j) * rd] * delta[j];M[i] = tmp;}double gain = M[0];for (int j = 0; j < d; j++) gain += delta[j] * M[r + j];if(gain < 1e4) {nu++;ssq += resid * resid / gain;sumlog += log(gain);}if (useResid) rsResid[l] = resid / sqrt(gain);for (int i = 0; i < rd; i++)a[i] = anew[i] + M[i] * resid / gain;for (int i = 0; i < rd; i++)for (int j = 0; j < rd; j++)P[i + j * rd] = Pnew[i + j * rd] - M[i] * M[j] / gain;} else {for (int i = 0; i < rd; i++) a[i] = anew[i];for (int i = 0; i < rd * rd; i++) P[i] = Pnew[i];if (useResid) rsResid[l] = NA_REAL;}}if (useResid) {PROTECT(res = allocVector(VECSXP, 3));SET_VECTOR_ELT(res, 0, nres = allocVector(REALSXP, 3));REAL(nres)[0] = ssq;REAL(nres)[1] = sumlog;REAL(nres)[2] = (double) nu;SET_VECTOR_ELT(res, 1, sResid);UNPROTECT(2);return res;} else {nres = allocVector(REALSXP, 3);REAL(nres)[0] = ssq;REAL(nres)[1] = sumlog;REAL(nres)[2] = (double) nu;return nres;}}/* do differencing here *//* arma is p, q, sp, sq, ns, d, sd */SEXPARIMA_CSS(SEXP sy, SEXP sarma, SEXP sPhi, SEXP sTheta,SEXP sncond, SEXP giveResid){SEXP res, sResid = R_NilValue;double ssq = 0.0, *y = REAL(sy), tmp;double *phi = REAL(sPhi), *theta = REAL(sTheta), *w, *resid;int n = LENGTH(sy), *arma = INTEGER(sarma), p = LENGTH(sPhi),q = LENGTH(sTheta), ncond = asInteger(sncond);int ns, nu = 0;Rboolean useResid = asLogical(giveResid);w = (double *) R_alloc(n, sizeof(double));for (int l = 0; l < n; l++) w[l] = y[l];for (int i = 0; i < arma[5]; i++)for (int l = n - 1; l > 0; l--) w[l] -= w[l - 1];ns = arma[4];for (int i = 0; i < arma[6]; i++)for (int l = n - 1; l >= ns; l--) w[l] -= w[l - ns];PROTECT(sResid = allocVector(REALSXP, n));resid = REAL(sResid);if (useResid) for (int l = 0; l < ncond; l++) resid[l] = 0;for (int l = ncond; l < n; l++) {tmp = w[l];for (int j = 0; j < p; j++) tmp -= phi[j] * w[l - j - 1];for (int j = 0; j < min(l - ncond, q); j++)tmp -= theta[j] * resid[l - j - 1];resid[l] = tmp;if (!ISNAN(tmp)) {nu++;ssq += tmp * tmp;}}if (useResid) {PROTECT(res = allocVector(VECSXP, 2));SET_VECTOR_ELT(res, 0, ScalarReal(ssq / (double) (nu)));SET_VECTOR_ELT(res, 1, sResid);UNPROTECT(2);return res;} else {UNPROTECT(1);return ScalarReal(ssq / (double) (nu));}}SEXP TSconv(SEXP a, SEXP b){int na, nb, nab;SEXP ab;double *ra, *rb, *rab;PROTECT(a = coerceVector(a, REALSXP));PROTECT(b = coerceVector(b, REALSXP));na = LENGTH(a);nb = LENGTH(b);nab = na + nb - 1;PROTECT(ab = allocVector(REALSXP, nab));ra = REAL(a); rb = REAL(b); rab = REAL(ab);for (int i = 0; i < nab; i++) rab[i] = 0.0;for (int i = 0; i < na; i++)for (int j = 0; j < nb; j++)rab[i + j] += ra[i] * rb[j];UNPROTECT(3);return (ab);}/* based on code from AS154 */static voidinclu2(size_t np, double *xnext, double *xrow, double ynext,double *d, double *rbar, double *thetab){double cbar, sbar, di, xi, xk, rbthis, dpi;size_t i, k, ithisr;/* This subroutine updates d, rbar, thetab by the inclusionof xnext and ynext. */for (i = 0; i < np; i++) xrow[i] = xnext[i];for (ithisr = 0, i = 0; i < np; i++) {if (xrow[i] != 0.0) {xi = xrow[i];di = d[i];dpi = di + xi * xi;d[i] = dpi;cbar = di / dpi;sbar = xi / dpi;for (k = i + 1; k < np; k++) {xk = xrow[k];rbthis = rbar[ithisr];xrow[k] = xk - xi * rbthis;rbar[ithisr++] = cbar * rbthis + sbar * xk;}xk = ynext;ynext = xk - xi * thetab[i];thetab[i] = cbar * thetab[i] + sbar * xk;if (di == 0.0) return;} elseithisr = ithisr + np - i - 1;}}#ifdef DEBUG_Q0bis# include <R_ext/Print.h>double chk_V(double v[], char* nm, int jj, int len) {// len = length(<vector>) <==> index must be in {0, len-1}if(jj < 0 || jj >= len)REprintf(" %s[%2d]\n", nm, jj);return(v[jj]);}#endif/*Matwey V. Kornilov's implementation of algorithm byDr. Raphael RossignolSee https://bugs.r-project.org/show_bug.cgi?id=14682 for details.*/SEXP getQ0bis(SEXP sPhi, SEXP sTheta, SEXP sTol){SEXP res;int p = LENGTH(sPhi), q = LENGTH(sTheta);double *phi = REAL(sPhi), *theta = REAL(sTheta); // tol = REAL(sTol)[0];int i,j, r = max(p, q + 1);/* Final result is block product* Q0 = A1 SX A1^T + A1 SXZ A2^T + (A1 SXZ A2^T)^T + A2 A2^T ,* where A1 [i,j] = phi[i+j],* A2 [i,j] = ttheta[i+j], and SX, SXZ are defined below */PROTECT(res = allocMatrix(REALSXP, r, r));double *P = REAL(res);/* Clean P */Memzero(P, r*r);#ifdef DEBUG_Q0bis#define _ttheta(j) chk_V(ttheta, "ttheta", j, q+1)// was r#define _tphi(j) chk_V(tphi, "tphi", j, p+1)#define _rrz(j) chk_V(rrz, "rrz", j, q)#else#define _ttheta(j) ttheta[j]#define _tphi(j) tphi[j]#define _rrz(j) rrz [j]#endifdouble *ttheta = (double *) R_alloc(q + 1, sizeof(double));/* Init ttheta = c(1, theta) */ttheta[0] = 1.;for (i = 1; i < q + 1; ++i) ttheta[i] = theta[i - 1];if( p > 0 ) {int r2 = max(p + q, p + 1);SEXP sgam = PROTECT(allocMatrix(REALSXP, r2, r2)),sg = PROTECT(allocVector(REALSXP, r2));double *gam = REAL(sgam);double *g = REAL(sg);double *tphi = (double *) R_alloc(p + 1, sizeof(double));/* Init tphi = c(1, -phi) */tphi[0] = 1.;for (i = 1; i < p + 1; ++i) tphi[i] = -phi[i - 1];/* Compute the autocovariance function of U, the AR part of X *//* Gam := C1 + C2 ; initialize */Memzero(gam, r2*r2);/* C1[E] */for (j = 0; j < r2; ++j)for (i = j; i < r2 && i - j < p + 1; ++i)gam[j*r2 + i] += _tphi(i-j);/* C2[E] */for (i = 0; i < r2; ++i)for (j = 1; j < r2 && i + j < p + 1; ++j)gam[j*r2 + i] += _tphi(i+j);/* Initialize g = (1 0 0 .... 0) */g[0] = 1.;for (i = 1; i < r2; ++i)g[i] = 0.;/* rU = solve(Gam, g) -> solve.default() -> .Internal(La_solve, .,)* --> fiddling with R-objects -> C and then F77_CALL(.) of dgesv, dlange, dgecon* FIXME: call these directly here, possibly even use 'info' instead of error(.)* e.g., in case of exact singularity.*/SEXP callS = PROTECT(lang4(install("solve.default"), sgam, sg, sTol)),su = PROTECT(eval(callS, R_BaseEnv));double *u = REAL(su);/* SX = A SU A^T *//* A[i,j] = ttheta[j-i] *//* SU[i,j] = u[abs(i-j)] *//* Q0 += ( A1 SX A1^T == A1 A SU A^T A1^T) */// (relying on good compiler optimization here:)for (i = 0; i < r; ++i)for (j = i; j < r; ++j)for (int k = 0; i + k < p; ++k)for (int L = k; L - k < q + 1; ++L)for (int m = 0; j + m < p; ++m)for (int n = m; n - m < q + 1; ++n)P[r*i + j] += phi[i + k] * phi[j + m] *_ttheta(L - k) * _ttheta(n - m) * u[abs(L - n)];UNPROTECT(4);/* Compute correlation matrix between X and Z *//* forwardsolve(C1, g) *//* C[i,j] = tphi[i-j] *//* g[i] = _ttheta(i) */double *rrz = (double *) R_alloc(q, sizeof(double));if(q > 0) {for (i = 0; i < q; ++i) {rrz[i] = _ttheta(i);for (j = max(0, i - p); j < i; ++j)rrz[i] -= _rrz(j) * _tphi(i-j);}}/* Q0 += A1 SXZ A2^T + (A1 SXZ A2^T)^T *//* SXZ[i,j] = rrz[j-i-1], j > 0 */for (i = 0; i < r; ++i)for (j = i; j < r; ++j) {int k, L;for (k = 0; i + k < p; ++k)for (L = k+1; j + L < q + 1; ++L)P[r*i + j] += phi[i + k] * _ttheta(j + L) * _rrz(L - k - 1);for (k = 0; j + k < p; ++k)for (L = k+1; i + L < q + 1; ++L)P[r*i + j] += phi[j + k] * _ttheta(i + L) * _rrz(L - k - 1);}} // end if(p > 0)/* Q0 += A2 A2^T */for (i = 0; i < r; ++i)for (j = i; j < r; ++j)for (int k = 0; j + k < q + 1; ++k)P[r*i + j] += _ttheta(i + k) * _ttheta(j + k);/* Symmetrize result */for (i = 0; i < r; ++i)for (j = i+1; j < r; ++j)P[r*j + i] = P[r*i + j];UNPROTECT(1);return res;}SEXP getQ0(SEXP sPhi, SEXP sTheta){SEXP res;int p = LENGTH(sPhi), q = LENGTH(sTheta);double *phi = REAL(sPhi), *theta = REAL(sTheta);/* thetab[np], xnext[np], xrow[np]. rbar[rbar] *//* NB: nrbar could overflow */int r = max(p, q + 1);size_t np = r * (r + 1) / 2, nrbar = np * (np - 1) / 2, npr, npr1;size_t indi, indj, indn, i, j, ithisr, ind, ind1, ind2, im, jm;/* This is the limit using an int index. We could usesize_t and get more on a 64-bit system,but there seems no practical need. */if(r > 350) error(_("maximum supported lag is 350"));double *xnext, *xrow, *rbar, *thetab, *V;xnext = (double *) R_alloc(np, sizeof(double));xrow = (double *) R_alloc(np, sizeof(double));rbar = (double *) R_alloc(nrbar, sizeof(double));thetab = (double *) R_alloc(np, sizeof(double));V = (double *) R_alloc(np, sizeof(double));for (ind = 0, j = 0; j < r; j++) {double vj = 0.0;if (j == 0) vj = 1.0; else if (j - 1 < q) vj = theta[j - 1];for (i = j; i < r; i++) {double vi = 0.0;if (i == 0) vi = 1.0; else if (i - 1 < q) vi = theta[i - 1];V[ind++] = vi * vj;}}PROTECT(res = allocMatrix(REALSXP, r, r));double *P = REAL(res);if (r == 1) {if (p == 0) P[0] = 1.0; // PR#16419else P[0] = 1.0 / (1.0 - phi[0] * phi[0]);UNPROTECT(1);return res;}if (p > 0) {/* The set of equations s * vec(P0) = vec(v) is solved forvec(P0). s is generated row by row in the array xnext. Theorder of elements in P is changed, so as to bring more leadingzeros into the rows of s. */for (i = 0; i < nrbar; i++) rbar[i] = 0.0;for (i = 0; i < np; i++) {P[i] = 0.0;thetab[i] = 0.0;xnext[i] = 0.0;}ind = 0;ind1 = -1;npr = np - r;npr1 = npr + 1;indj = npr;ind2 = npr - 1;for (j = 0; j < r; j++) {double phij = (j < p) ? phi[j] : 0.0;xnext[indj++] = 0.0;indi = npr1 + j;for (i = j; i < r; i++) {double ynext = V[ind++];double phii = (i < p) ? phi[i] : 0.0;if (j != r - 1) {xnext[indj] = -phii;if (i != r - 1) {xnext[indi] -= phij;xnext[++ind1] = -1.0;}}xnext[npr] = -phii * phij;if (++ind2 >= np) ind2 = 0;xnext[ind2] += 1.0;inclu2(np, xnext, xrow, ynext, P, rbar, thetab);xnext[ind2] = 0.0;if (i != r - 1) {xnext[indi++] = 0.0;xnext[ind1] = 0.0;}}}ithisr = nrbar - 1;im = np - 1;for (i = 0; i < np; i++) {double bi = thetab[im];for (jm = np - 1, j = 0; j < i; j++)bi -= rbar[ithisr--] * P[jm--];P[im--] = bi;}/* now re-order p. */ind = npr;for (i = 0; i < r; i++) xnext[i] = P[ind++];ind = np - 1;ind1 = npr - 1;for (i = 0; i < npr; i++) P[ind--] = P[ind1--];for (i = 0; i < r; i++) P[i] = xnext[i];} else {/* P0 is obtained by backsubstitution for a moving average process. */indn = np;ind = np;for (i = 0; i < r; i++)for (j = 0; j <= i; j++) {--ind;P[ind] = V[ind];if (j != 0) P[ind] += P[--indn];}}/* now unpack to a full matrix */for (i = r - 1, ind = np; i > 0; i--)for (j = r - 1; j >= i; j--)P[r * i + j] = P[--ind];for (i = 0; i < r - 1; i++)for (j = i + 1; j < r; j++)P[i + r * j] = P[j + r * i];UNPROTECT(1);return res;}