Switch to side-by-side view

--- a
+++ b/partyMod/src/LinearStatistic.c
@@ -0,0 +1,426 @@
+
+/**
+    Linear statistics for conditional inference based on Strasser & Weber (1999)
+    *\file LinearStatistic.c
+    *\author $Author$
+    *\date $Date$
+*/
+    
+#include "party.h"
+
+
+/**
+    Computes the linear statistic, formula (1) in the paper\n
+    *\param x values of the transformation
+    *\param p dimension of the transformation
+    *\param y values of the influence function
+    *\param q dimension of the influence function
+    *\param weights case weights
+    *\param n number of observations
+    *\param ans return value; a pointer to a REALSXP-vector of length pq
+*/
+  
+void C_LinearStatistic (const double *x, const int p,
+                        const double *y, const int q,
+                        const double *weights, const int n,
+                        double *ans) {
+              
+    int i, j, k, kp, kn;
+    double tmp;
+
+    for (k = 0; k < q; k++) {
+
+        kn = k * n;
+        kp = k * p;
+        for (j = 0; j < p; j++) ans[kp + j] = 0.0;
+            
+        for (i = 0; i < n; i++) {
+                
+            /* optimization: weights are often zero */
+            if (weights[i] == 0.0) continue;
+                
+            tmp = y[kn + i] * weights[i];
+                
+            for (j = 0; j < p; j++)
+                 ans[kp + j] += x[j*n + i] * tmp;
+        }
+    }
+}
+
+
+/**
+    R-interface to C_LinearStatistic \n
+    *\param x values of the transformation
+    *\param y values of the influence function
+    *\param weights case weights
+*/
+
+SEXP R_LinearStatistic(SEXP x, SEXP y, SEXP weights) {
+
+    /* the return value; a vector of type REALSXP */
+    SEXP ans;
+
+    /* dimensions */
+    int n, p, q;
+
+    /* 
+     *    only a basic check: we do not coerce objects since this
+     *    function is for internal use only
+     */
+    
+    if (!isReal(x) || !isReal(y) || !isReal(weights))
+        error("LinStat: arguments are not of type REALSXP");
+    
+    n = nrow(y);
+    if (nrow(x) != n || LENGTH(weights) != n)
+        error("LinStat: dimensions don't match");
+
+    q    = ncol(y);
+    p    = ncol(x);
+           
+    PROTECT(ans = allocVector(REALSXP, p*q));
+ 
+    C_LinearStatistic(REAL(x), p, REAL(y), q, REAL(weights), n, 
+                      REAL(ans));
+
+    UNPROTECT(1);
+    return(ans);
+}
+
+
+/**
+    Conditional expectation and covariance of the influence function\n
+    *\param y values of the influence function
+    *\param q dimension of the influence function
+    *\param weights case weights
+    *\param n number of observations
+    *\param ans return value; an object of class `ExpectCovarInfluence'
+*/
+
+void C_ExpectCovarInfluence(const double* y, const int q,
+                            const double* weights, const int n, 
+                            SEXP ans) {
+
+    int i, j, k, jq;
+    
+    /* pointers to the slots of object ans */
+    double *dExp_y, *dCov_y, *dsweights, tmp;
+    
+    /*  return values: set to zero initially */
+    dExp_y = REAL(GET_SLOT(ans, PL2_expectationSym));
+    for (j = 0; j < q; j++) dExp_y[j] = 0.0;
+    
+    dCov_y = REAL(GET_SLOT(ans, PL2_covarianceSym));
+    for (j = 0; j < q*q; j++) dCov_y[j] = 0.0;
+    
+    dsweights = REAL(GET_SLOT(ans, PL2_sumweightsSym));
+
+    /*  compute the sum of the weights */
+        
+    dsweights[0] = 0;
+    for (i = 0; i < n; i++) dsweights[0] += weights[i];
+    if (dsweights[0] <= 1) 
+        error("C_ExpectCovarInfluence: sum of weights is less than one");
+
+    /*
+     *    Expectation of the influence function
+     */
+
+    for (i = 0; i < n; i++) {
+
+        /*  observations with zero case weights do not contribute */
+    
+        if (weights[i] == 0.0) continue;
+    
+        for (j = 0; j < q; j++)
+            dExp_y[j] += weights[i] * y[j * n + i];
+    }
+
+    for (j = 0; j < q; j++)
+        dExp_y[j] = dExp_y[j] / dsweights[0];
+
+
+    /*
+     *    Covariance of the influence function
+     */
+
+    for (i = 0; i < n; i++) {
+
+        if (weights[i] == 0.0) continue;
+     
+        for (j = 0; j < q; j++) {
+            tmp = weights[i] * (y[j * n + i] - dExp_y[j]);
+            jq = j * q;
+            for (k = 0; k < q; k++)
+                dCov_y[jq + k] += tmp * (y[k * n + i] - dExp_y[k]);
+        }
+    }
+
+    for (j = 0; j < q*q; j++)
+        dCov_y[j] = dCov_y[j] / dsweights[0];
+}
+
+
+/**
+    R-interface to C_ExpectCovarInfluence\n
+    *\param y values of the influence function
+    *\param weights case weights
+*/
+
+SEXP R_ExpectCovarInfluence(SEXP y, SEXP weights) {
+
+    SEXP ans;
+    int q, n;
+    
+    if (!isReal(y) || !isReal(weights))
+        error("R_ExpectCovarInfluence: arguments are not of type REALSXP");
+    
+    n = nrow(y);
+    q = ncol(y);
+    
+    if (LENGTH(weights) != n) 
+        error("R_ExpectCovarInfluence: vector of case weights does not have %d elements", n);
+
+    /*  allocate storage for return values */
+    PROTECT(ans = NEW_OBJECT(MAKE_CLASS("ExpectCovarInfluence")));
+    SET_SLOT(ans, PL2_expectationSym, 
+             PROTECT(allocVector(REALSXP, q)));
+    SET_SLOT(ans, PL2_covarianceSym, 
+             PROTECT(allocMatrix(REALSXP, q, q)));
+    SET_SLOT(ans, PL2_sumweightsSym, 
+             PROTECT(allocVector(REALSXP, 1)));
+
+    C_ExpectCovarInfluence(REAL(y), q, REAL(weights), n, ans);
+    
+    UNPROTECT(4);
+    return(ans);
+}
+
+
+/**
+    Conditional expectation and covariance of the a linear statistic\n
+    *\param x values of the transformation
+    *\param p dimension of the transformation
+    *\param y values of the influence function
+    *\param q dimension of the influence function
+    *\param weights case weights
+    *\param n number of observations
+    *\param expcovinf an object of class `ExpectCovarInfluence'
+    *\param ans return value; an object of class `ExpectCovar'
+*/
+
+void C_ExpectCovarLinearStatistic(const double* x, const int p, 
+                                  const double* y, const int q,
+                                  const double* weights, const int n,
+                                  const SEXP expcovinf, SEXP ans) {
+
+    int i, j, k, pq;
+    double sweights = 0.0, f1, f2, tmp;
+    double *swx, *CT1, *CT2, *Covy_x_swx, 
+           *dExp_y, *dCov_y, *dExp_T, *dCov_T;
+    
+    pq   = p * q;
+    
+    /* the expectation and covariance of the influence function */
+    dExp_y = REAL(GET_SLOT(expcovinf, PL2_expectationSym));
+    dCov_y = REAL(GET_SLOT(expcovinf, PL2_covarianceSym));
+    sweights = REAL(GET_SLOT(expcovinf, PL2_sumweightsSym))[0];
+
+    if (sweights <= 1.0) 
+        error("C_ExpectCovarLinearStatistic: sum of weights is less than one");
+
+    /* prepare for storing the results */
+    dExp_T = REAL(GET_SLOT(ans, PL2_expectationSym));
+    dCov_T = REAL(GET_SLOT(ans, PL2_covarianceSym));
+
+    /* allocate storage: all helpers, initially zero */
+    swx = Calloc(p, double);               /* p x 1  */
+    CT1 = Calloc(p * p, double);           /* p x p  */
+
+    for (i = 0; i < n; i++) {
+
+        /*  observations with zero case weights do not contribute */
+        if (weights[i] == 0.0) continue;
+    
+        for (k = 0; k < p; k++) {
+            tmp = weights[i] * x[k * n + i];
+            swx[k] += tmp;
+
+            /* covariance part */
+            for (j = 0; j < p; j++) {
+                CT1[j * p + k] += tmp * x[j * n + i];
+            }
+        }
+    }
+
+    /*
+    *   dExp_T: expectation of the linear statistic T
+    */
+
+    for (k = 0; k < p; k++) {
+        for (j = 0; j < q; j++)
+            dExp_T[j * p + k] = swx[k] * dExp_y[j];
+    }
+
+    /* 
+    *   dCov_T:  covariance of the linear statistic T
+    */
+
+    f1 = sweights/(sweights - 1);
+    f2 = (1/(sweights - 1));
+
+    if (pq == 1) {
+        dCov_T[0] = f1 * dCov_y[0] * CT1[0];
+        dCov_T[0] -= f2 * dCov_y[0] * swx[0] * swx[0];
+    } else {
+        /* two more helpers needed */
+        CT2 = Calloc(pq * pq, double);            /* pq x pq */
+        Covy_x_swx = Calloc(pq * q, double);      /* pq x q  */
+        
+        C_kronecker(dCov_y, q, q, CT1, p, p, dCov_T);
+        C_kronecker(dCov_y, q, q, swx, p, 1, Covy_x_swx);
+        C_kronecker(Covy_x_swx, pq, q, swx, 1, p, CT2);
+
+        for (k = 0; k < (pq * pq); k++)
+            dCov_T[k] = f1 * dCov_T[k] - f2 * CT2[k];
+
+        /* clean up */
+        Free(CT2); Free(Covy_x_swx);
+    }
+
+    /* clean up */
+    Free(swx); Free(CT1); 
+}
+
+
+/**
+    R-interface to C_ExpectCovarLinearStatistic\n
+    *\param x values of the transformation
+    *\param y values of the influence function
+    *\param weights case weights
+    *\param expcovinf an object of class `ExpectCovarInfluence'
+*/
+
+SEXP R_ExpectCovarLinearStatistic(SEXP x, SEXP y, SEXP weights, 
+                                  SEXP expcovinf) {
+    
+    SEXP ans;
+    int n, p, q, pq;
+
+    /* determine the dimensions and some checks */
+
+    n  = nrow(x);
+    p  = ncol(x);
+    q  = ncol(y);
+    pq = p * q;
+    
+    if (nrow(y) != n)
+        error("y does not have %d rows", n);
+    if (LENGTH(weights) != n) 
+        error("vector of case weights does not have %d elements", n);
+
+    PROTECT(ans = NEW_OBJECT(MAKE_CLASS("ExpectCovar")));
+    SET_SLOT(ans, PL2_expectationSym, 
+             PROTECT(allocVector(REALSXP, pq)));
+    SET_SLOT(ans, PL2_covarianceSym, 
+             PROTECT(allocMatrix(REALSXP, pq, pq)));
+
+    C_ExpectCovarLinearStatistic(REAL(x), p, REAL(y), q, 
+        REAL(weights), n, expcovinf, ans);
+    
+    UNPROTECT(3);
+    return(ans);
+}
+
+
+/**
+    Linear Statistic with permuted indices\n
+    *\param x values of the transformation
+    *\param p dimension of the transformation
+    *\param y values of the influence function
+    *\param q dimension of the influence function
+    *\param n number of observations
+    *\param nperm number of permutations
+    *\param indx indices for the x-part
+    *\param perm (permuted) indices for the y-part
+    *\param ans return value; a pointer to a REALSXP-vector of length pq
+*/
+
+void C_PermutedLinearStatistic(const double *x, const int p,
+                               const double *y, const int q,
+                               const int n, const int nperm,
+                               const int *indx, const int *perm, 
+                               double *ans) {
+
+    int i, j, k, kp, kn, knpi;
+
+    for (k = 0; k < q; k++) {
+
+        kn = k * n;
+        kp = k * p;
+        for (j = 0; j < p; j++) ans[kp + j] = 0.0;
+            
+        for (i = 0; i < nperm; i++) {
+                
+            knpi = kn + perm[i];
+
+            for (j = 0; j < p; j++)
+                ans[kp + j] += x[j*n + indx[i]] * y[knpi];
+        }
+    }
+}
+
+
+/**
+    Linear Statistic with permuted indices\n
+    *\param x values of the transformation
+    *\param y values of the influence function
+    *\param indx indices for the x-part
+    *\param perm (permuted) indices for the y-part
+*/
+
+SEXP R_PermutedLinearStatistic(SEXP x, SEXP y, SEXP indx, SEXP perm) {
+
+    SEXP ans;
+    int n, nperm, p, q, i, *iperm, *iindx;
+
+    /* 
+       only a basic check
+    */
+
+    if (!isReal(x) || !isReal(y))
+        error("R_PermutedLinearStatistic: arguments are not of type REALSXP");
+    
+    if (!isInteger(perm))
+        error("R_PermutedLinearStatistic: perm is not of type INTSXP");
+    if (!isInteger(indx))
+        error("R_PermutedLinearStatistic: indx is not of type INTSXP");
+    
+    n = nrow(y);
+    nperm = LENGTH(perm);
+    iperm = INTEGER(perm);
+    if (LENGTH(indx)  != nperm)
+        error("R_PermutedLinearStatistic: dimensions don't match");
+    iindx = INTEGER(indx);
+
+    if (nrow(x) != n)
+        error("R_PermutedLinearStatistic: dimensions don't match");
+
+    for (i = 0; i < nperm; i++) {
+        if (iperm[i] < 0 || iperm[i] > (n - 1) )
+            error("R_PermutedLinearStatistic: perm is not between 1 and nobs");
+        if (iindx[i] < 0 || iindx[i] > (n - 1) )
+            error("R_PermutedLinearStatistic: indx is not between 1 and nobs");
+    }
+
+    q    = ncol(y);
+    p    = ncol(x);
+           
+    PROTECT(ans = allocVector(REALSXP, p*q));
+    
+    C_PermutedLinearStatistic(REAL(x), p, REAL(y), q, n, nperm,
+                 iindx, iperm, REAL(ans));
+    
+    UNPROTECT(1);
+    return(ans);
+}