Rev 2 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Langage for Statistical Data Analysis* Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka** 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, write to the Free Software* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "Defn.h"/* The following table shows the codes which have been *//* assigned to the type combinations in assignments of *//* the form "x[s] <- y". Here the type of y is given *//* across the top of the table and the type of x at the *//* side. *//*---------------------------------------------------*//* LGL FACT ORD INT REAL CPLX STR EXPR LANG *//* LGL 1010 1011 1012 1013 1014 1015 1016 1020 1006 *//* FACT 1110 1111 1112 1113 1114 1115 1116 1120 1106 *//* ORD 1210 1211 1212 1213 1214 1215 1216 1220 1206 *//* INT 1310 1311 1312 1313 1314 1315 1316 1320 1306 *//* REAL 1410 1411 1412 1413 1414 1415 1416 1420 1406 *//* CPLX 1510 1511 1512 1513 1514 1515 1516 1520 1506 *//* STR 1610 1611 1612 1613 1614 1615 1616 1620 1606 *//* EXPR 2010 2011 2012 2013 2014 2015 2016 2020 2006 *//* LANG 610 611 612 613 614 615 616 620 606 *//*---------------------------------------------------*//* The following table (which is laid out as described *//* above) contains "*" for those combinations where the *//* assignment has been implemented. Some assignments *//* do not make a great deal of sense and we have chosen *//* to leave them unimplemented, although the addition *//* of new assignment combinations represents no great *//* difficulty. *//*--------------------------------------------------*//* LGL FACT ORD INT REAL CPLX STR EXPR LANG *//* LGL * ? ? * * * * * *//* FACT ? * * * *//* ORD ? * * * *//* INT * * * * * * *//* REAL * * * * * * *//* CPLX * * * * * * *//* STR * * * * * * * * *//* EXPR * * *//* LANG *//*--------------------------------------------------*//* The question marks in this table indicate combinations *//* which should probably be implemented, but which as yet *//* have not been. The reason for the LGL row and column *//* are because we want to allow any assignment of the form *//* "x[s] <- NA" (col) and because the interpreted "ifelse" *//* requires assignment into a logical object. */static void CompatibleFactorsCheck(SEXP x, SEXP y){if(!factorsConform(x,y))error("incompatible factors in subset assignment\n");}static void SetArgsforUseMethod(SEXP x){char buf[4];int i=1;if( TAG(x) == R_NilValue)TAG(x) = install("x");for(x=CDR(x); x!=R_NilValue ; x=CDR(x)) {if(TAG(x) == R_NilValue) {if(i<10)sprintf(buf,"..%d",i);elsesprintf(buf,".%d",i);TAG(x)=install(buf);i++;}}}static int R_BoundChecking = 0;SEXP do_checkbounds(SEXP call, SEXP op, SEXP args, SEXP rho){int flag;checkArity(op,args);flag = asLogical(CAR(args));if(flag == NA_LOGICAL)errorcall(call, "invalid argument\n");R_BoundChecking = flag;R_Visible = 0;return R_NilValue;}static SEXP EnlargeVector(SEXP x, int nnew){int i, n;SEXP newx, ap, alist, nap, newalist;if(R_BoundChecking)warning("assignment outside vector/list limits\n");if(isVector(x)) {n = length(x);PROTECT(x);PROTECT(newx = allocVector(TYPEOF(x), nnew));switch(TYPEOF(x)) {case FACTSXP:case ORDSXP:LEVELS(newx) = LEVELS(x);/* drop through here */case LGLSXP:case INTSXP:for(i=0 ; i<n ; i++)INTEGER(newx)[i] = INTEGER(x)[i];for(i=n ; i<nnew ; i++)INTEGER(newx)[i] = NA_INTEGER;break;case REALSXP:for(i=0 ; i<n ; i++)REAL(newx)[i] = REAL(x)[i];for(i=n ; i<nnew ; i++)REAL(newx)[i] = NA_REAL;break;case CPLXSXP:for(i=0 ; i<n ; i++)COMPLEX(newx)[i] = COMPLEX(x)[i];for(i=n ; i<nnew ; i++) {COMPLEX(newx)[i].r = NA_REAL;COMPLEX(newx)[i].i = NA_REAL;}break;case STRSXP:ap = mkChar("");for(i=0 ; i<n ; i++)STRING(newx)[i] = STRING(x)[i];for(i=n ; i<nnew ; i++)STRING(newx)[i] = ap;break;case EXPRSXP:for(i=0 ; i<n ; i++)VECTOR(newx)[i] = VECTOR(x)[i];for(i=n ; i<nnew ; i++)VECTOR(newx)[i] = R_NilValue;break;}ap = alist = ATTRIB(x);PROTECT(nap = newalist = CONS(R_NilValue, R_NilValue));while(ap != R_NilValue) {if(TAG(ap) == R_NamesSymbol) {CDR(nap) = CONS(R_NilValue, R_NilValue);nap = CDR(nap);CAR(nap) = EnlargeVector(CAR(ap), nnew);TAG(nap) = TAG(ap);}else if(TAG(ap) != R_DimSymbol && TAG(ap) != R_DimNamesSymbol) {CDR(nap) = CONS(R_NilValue, R_NilValue);nap = CDR(nap);CAR(nap) = CAR(ap);TAG(nap) = TAG(ap);}ap = CDR(ap);}ATTRIB(newx) = CDR(newalist);OBJECT(newx) = OBJECT(x);UNPROTECT(3);return newx;}else error("attempt to enlarge non-vector\n");}static void SubassignTypeFix(SEXP *x, SEXP *y, int which, int stretch){switch(which) {case 1010: /* logical <- logical */case 1310: /* integer <- logical */case 1410: /* real <- logical */case 1510: /* complex <- logical */case 1313: /* integer <- integer */case 1413: /* real <- integer */case 1513: /* complex <- integer */case 1414: /* real <- real */case 1514: /* complex <- real */case 1515: /* complex <- complex */case 1616: /* character <- character */case 2020: /* character <- character */break;case 1111: /* factor <- factor */case 1212: /* ordered <- ordered */CompatibleFactorsCheck(*x, *y);break;case 1013: /* logical <- integer */*x = coerceVector(*x, INTSXP);break;case 1014: /* logical <- real */case 1314: /* integer <- real */*x = coerceVector(*x, REALSXP);break;case 1015: /* logical <- complex */case 1315: /* integer <- complex */case 1415: /* real <- complex */*x = coerceVector(*x, CPLXSXP);break;case 1610: /* character <- logical */case 1611: /* character <- factor */case 1612: /* character <- ordered */case 1613: /* character <- integer */case 1614: /* character <- real */case 1615: /* character <- complex */*y = coerceVector(*y, STRSXP);break;case 1016: /* logical <- character */case 1116: /* factor <- character */case 1216: /* ordered <- character */case 1316: /* integer <- character */case 1416: /* real <- character */case 1516: /* complex <- character */*x = coerceVector(*x, STRSXP);break;case 2001: /* expression <- symbol */case 2006: /* expression <- language */case 2010: /* expression <- logical */case 2011: /* expression <- factor */case 2012: /* expression <- ordered */case 2013: /* expression <- integer */case 2014: /* expression <- real */case 2015: /* expression <- complex */case 2016: /* expression <- character */*y = coerceVector(*y, EXPRSXP);break;default:error("incompatible types in subset assignment\n");}if(stretch)*x = EnlargeVector(*x, stretch);}static SEXP vectorAssign(SEXP call, SEXP x, SEXP s, SEXP y){SEXP dim, index;int i, ii, iy, n, ny, stretch, which;double ry;/* Check to see if we have special matrix *//* subscripting. If we do, make a real *//* subscript vector. */if(isNull(x) && isNull(y)) {return R_NilValue;}dim = getAttrib(x, R_DimSymbol);if (isMatrix(s) && isArray(x) &&(isInteger(s) || isReal(s)) &&ncols(s) == length(dim)) {s = mat2indsub(dim, s);}PROTECT(s);stretch = 1;PROTECT(index = makeSubscript(x, s, &stretch));n = length(index);#ifndef OLDwhich = 100 * TYPEOF(x) + TYPEOF(y);/* Here we make sure that the LHS has *//* been coerced into a form which can *//* accept elements from the RHS. */SubassignTypeFix(&x, &y, which, stretch);#endifny = length(y);if (n > 0 && ny == 0)errorcall(call, "nothing to replace with\n");if (n > 0 && n % ny)warning("number of items to replace is not a multiple of replacement length\n");#ifdef OLDwhich = 100 * TYPEOF(x) + TYPEOF(y);/* Here we make sure that the LHS has *//* been coerced into a form which can *//* accept elements from the RHS. */SubassignTypeFix(&x, &y, which, stretch);#endifPROTECT(x);/* Nasty bug fixed here. When array elements *//* are being permuted the rhs must be duplicated *//* or the elements get trashed. */if (x == y) PROTECT(y = duplicate(y));else PROTECT(y);/* Note that we are now committed. *//* Since we are mutating existing *//* objects any changes we make now *//* are (likely to be) permanent. *//* Beware! */switch(which) {case 1010: /* logical <- logical */case 1310: /* integer <- logical */case 1111: /* factor <- factor */case 1212: /* ordered <- ordered */case 1013: /* logical <- integer */case 1313: /* integer <- integer */for (i=0; i<n; i++) {ii = INTEGER(index)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;INTEGER(x)[ii] = INTEGER(y)[i % ny];}break;case 1410: /* real <- logical */case 1413: /* real <- integer */for (i=0; i<n; i++) {ii = INTEGER(index)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;iy = INTEGER(y)[i % ny];if(iy == NA_INTEGER)REAL(x)[ii] = NA_REAL;elseREAL(x)[ii] = iy;}break;case 1014: /* logical <- real */case 1314: /* integer <- real */case 1414: /* real <- real */for (i=0; i<n; i++) {ii = INTEGER(index)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;REAL(x)[ii] = REAL(y)[i % ny];}break;case 1510: /* complex <- logical */case 1513: /* complex <- integer */for (i=0; i<n; i++) {ii = INTEGER(index)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;iy = INTEGER(y)[i % ny];if(iy == NA_INTEGER) {COMPLEX(x)[ii].r = NA_REAL;COMPLEX(x)[ii].i = NA_REAL;}else {COMPLEX(x)[ii].r = iy;COMPLEX(x)[ii].i = 0.0;}}break;case 1514: /* complex <- real */for (i=0; i<n; i++) {ii = INTEGER(index)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;ry = REAL(y)[i % ny];if(!FINITE(ry)) {COMPLEX(x)[ii].r = NA_REAL;COMPLEX(x)[ii].i = NA_REAL;}else {COMPLEX(x)[ii].r = ry;COMPLEX(x)[ii].i = 0.0;}}break;case 1015: /* logical <- complex */case 1315: /* integer <- complex */case 1415: /* real <- complex */case 1515: /* complex <- complex */for (i=0; i<n; i++) {ii = INTEGER(index)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;COMPLEX(x)[ii] = COMPLEX(y)[i % ny];}break;case 1610: /* character <- logical */case 1611: /* character <- factor */case 1612: /* character <- ordered */case 1613: /* character <- integer */case 1614: /* character <- real */case 1615: /* character <- complex */case 1616: /* character <- character */case 1016: /* logical <- character */case 1116: /* factor <- character */case 1216: /* ordered <- character */case 1316: /* integer <- character */case 1416: /* real <- character */case 1516: /* complex <- character */for (i=0; i<n; i++) {ii = INTEGER(index)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;STRING(x)[ii] = STRING(y)[i % ny];}break;case 2001:case 2006: /* expression <- language */case 2010: /* expression <- logical */case 2011: /* expression <- factor */case 2012: /* expression <- ordered */case 2013: /* expression <- integer */case 2014: /* expression <- real */case 2015: /* expression <- complex */case 2016: /* expression <- character */case 2020: /* expression <- expression */for (i=0; i<n; i++) {ii = INTEGER(index)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;VECTOR(x)[ii] = VECTOR(y)[i % ny];}break;}UNPROTECT(4);return x;}static SEXP matrixAssign(SEXP call, SEXP x, SEXP s, SEXP y){int i, j, ii, jj, ij, iy, k, which;double ry;int nr, ny;int nrs, ncs;SEXP sr, sc;if (!isMatrix(x))error("incorrect number of subscripts on matrix\n");nr = nrows(x);ny = LENGTH(y);/* s has been protected. *//* No GC problems here. */sr = CAR(s) = arraySubscript(0, CAR(s), x);sc = CADR(s) = arraySubscript(1, CADR(s), x);nrs = LENGTH(sr);ncs = LENGTH(sc);if ((length(sr) * length(sc)) % length(y))error("no of items to replace is not a multiple of replacement length\n");which = 100 * TYPEOF(x) + TYPEOF(y);SubassignTypeFix(&x, &y, which, 0);PROTECT(x);/* Nasty bug fixed here. When array elements *//* are being permuted the rhs must be duplicated *//* or the elements get trashed. */if (x == y) PROTECT(y = duplicate(y));else PROTECT(y);/* Note that we are now committed. *//* Since we are mutating existing *//* objects any changes we make now *//* are (likely to be) permanent. *//* Beware! */k = 0;switch(which) {case 1010: /* logical <- logical */case 1310: /* integer <- logical */case 1111: /* factor <- factor */case 1212: /* ordered <- ordered */case 1013: /* logical <- integer */case 1313: /* integer <- integer */for (j = 0; j < ncs; j++) {jj = INTEGER(sc)[j];if(jj == NA_INTEGER) continue;jj = jj - 1;for (i = 0; i < nrs; i++) {ii = INTEGER(sr)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;ij = ii + jj * nr;INTEGER(x)[ij] = INTEGER(y)[k];k = (k + 1) % ny;}}break;case 1410: /* real <- logical */case 1413: /* real <- integer */for (j = 0; j < ncs; j++) {jj = INTEGER(sc)[j];if(jj == NA_INTEGER) continue;jj = jj - 1;for (i = 0; i < nrs; i++) {ii = INTEGER(sr)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;ij = ii + jj * nr;iy = INTEGER(y)[k];if(iy == NA_INTEGER)REAL(x)[ij] = NA_REAL;elseREAL(x)[ij] = iy;k = (k + 1) % ny;}}break;case 1014: /* logical <- real */case 1314: /* integer <- real */case 1414: /* real <- real */for (j = 0; j < ncs; j++) {jj = INTEGER(sc)[j];if(jj == NA_INTEGER) continue;jj = jj - 1;for (i = 0; i < nrs; i++) {ii = INTEGER(sr)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;ij = ii + jj * nr;REAL(x)[ij] = REAL(y)[k];k = (k + 1) % ny;}}break;case 1510: /* complex <- logical */case 1513: /* complex <- integer */for (j=0; j<ncs ; j++) {jj = INTEGER(sc)[j];if(jj == NA_INTEGER) continue;jj = jj - 1;for (i=0; i<nrs ; i++) {ii = INTEGER(sr)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;ij = ii + jj * nr;iy = INTEGER(y)[k];if(iy == NA_INTEGER) {COMPLEX(x)[ij].r = NA_REAL;COMPLEX(x)[ij].i = NA_REAL;}else {COMPLEX(x)[ij].r = iy;COMPLEX(x)[ij].i = 0.0;}k = (k + 1) % ny;}}break;case 1514: /* complex <- real */for (j=0; j<ncs ; j++) {jj = INTEGER(sc)[j];if(jj == NA_INTEGER) continue;jj = jj - 1;for (i = 0; i < nrs; i++) {ii = INTEGER(sr)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;ij = ii + jj * nr;ry = REAL(y)[k];if(!FINITE(ry)) {COMPLEX(x)[ij].r = NA_REAL;COMPLEX(x)[ij].i = NA_REAL;}else {COMPLEX(x)[ij].r = ry;COMPLEX(x)[ij].i = 0.0;}k = (k + 1) % ny;}}break;case 1015: /* logical <- complex */case 1315: /* integer <- complex */case 1415: /* real <- complex */case 1515: /* complex <- complex */for (j = 0; j < ncs; j++) {jj = INTEGER(sc)[j];if(jj == NA_INTEGER) continue;jj = jj - 1;for (i = 0; i < nrs; i++) {ii = INTEGER(sr)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;ij = ii + jj * nr;COMPLEX(x)[ij] = COMPLEX(y)[k];k = (k + 1) % ny;}}break;case 1610: /* character <- logical */case 1611: /* character <- factor */case 1612: /* character <- ordered */case 1613: /* character <- integer */case 1614: /* character <- real */case 1615: /* character <- complex */case 1616: /* character <- character */case 1016: /* logical <- character */case 1116: /* factor <- character */case 1216: /* ordered <- character */case 1316: /* integer <- character */case 1416: /* real <- character */case 1516: /* complex <- character */for (j = 0; j < ncs; j++) {jj = INTEGER(sc)[j];if(jj == NA_INTEGER) continue;jj = jj - 1;for (i = 0; i < nrs; i++) {ii = INTEGER(sr)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;ij = ii + jj * nr;STRING(x)[ij] = STRING(y)[k];k = (k + 1) % ny;}}break;default:error("incompatible types in subset assignment\n");}UNPROTECT(2);return x;}static SEXP arrayAssign(SEXP call, SEXP x, SEXP s, SEXP y){int i, j, ii, iy, jj, k, n, ny, which;int **subs, *index, *bound, *offset;SEXP dims, tmp;double ry;char *vmax = vmaxget();PROTECT(dims = getAttrib(x, R_DimSymbol));if (dims == R_NilValue || (k = LENGTH(dims)) != length(s))error("incorrect number of subscripts\n");subs = (int**)R_alloc(k, sizeof(int*));index = (int*)R_alloc(k, sizeof(int));bound = (int*)R_alloc(k, sizeof(int));offset = (int*)R_alloc(k, sizeof(int));ny = LENGTH(y);/* Expand the list of subscripts. *//* s is protected, so no GC problems here */tmp = s;for (i = 0; i < k; i++) {CAR(tmp) = arraySubscript(i, CAR(tmp), x);tmp = CDR(tmp);}n = 1;tmp = s;for (i = 0; i < k; i++) {index[i] = 0;subs[i] = INTEGER(CAR(tmp));bound[i] = LENGTH(CAR(tmp));n *= bound[i];tmp = CDR(tmp);}if (n % length(y))error("no of elements to replace is not a multiple of replacement length\n");offset[0] = 1;for (i = 1; i < k; i++)offset[i] = offset[i - 1] * INTEGER(dims)[i - 1];which = 100 * TYPEOF(x) + TYPEOF(y);/* Here we make sure that the LHS has *//* been coerced into a form which can *//* accept elements from the RHS. */SubassignTypeFix(&x, &y, which, 0);PROTECT(x);/* Nasty bug fixed here. When array elements *//* are being permuted the rhs must be duplicated *//* or the elements get trashed. */if (x == y) PROTECT(y = duplicate(y));else PROTECT(y);for (i = 0; i < n; i++) {ii = 0;for (j = 0; j < k; j++) {jj = subs[j][index[j]];if(jj == NA_INTEGER) goto next_i;ii += (jj - 1) * offset[j];}switch (which) {case 1010: /* logical <- logical */case 1310: /* integer <- logical */case 1111: /* factor <- factor */case 1212: /* ordered <- ordered */case 1013: /* logical <- integer */case 1313: /* integer <- integer */INTEGER(x)[ii] = INTEGER(y)[i % ny];break;case 1410: /* real <- logical */case 1413: /* real <- integer */iy = INTEGER(y)[i % ny];if(iy == NA_INTEGER)REAL(x)[ii] = NA_REAL;elseREAL(x)[ii] = iy;break;case 1014: /* logical <- real */case 1314: /* integer <- real */case 1414: /* real <- real */REAL(x)[ii] = REAL(y)[i % ny];break;case 1510: /* complex <- logical */case 1513: /* complex <- integer */iy = INTEGER(y)[i % ny];if(iy == NA_INTEGER) {COMPLEX(x)[ii].r = NA_REAL;COMPLEX(x)[ii].i = NA_REAL;}else {COMPLEX(x)[ii].r = iy;COMPLEX(x)[ii].i = 0.0;}break;case 1514: /* complex <- real */ry = REAL(y)[i % ny];if(!FINITE(ry)) {COMPLEX(x)[ii].r = NA_REAL;COMPLEX(x)[ii].i = NA_REAL;}else {COMPLEX(x)[ii].r = ry;COMPLEX(x)[ii].i = 0.0;}break;case 1015: /* logical <- complex */case 1315: /* integer <- complex */case 1415: /* real <- complex */case 1515: /* complex <- complex */COMPLEX(x)[ii] = COMPLEX(y)[i % ny];break;case 1610: /* character <- logical */case 1611: /* character <- factor */case 1612: /* character <- ordered */case 1613: /* character <- integer */case 1614: /* character <- real */case 1615: /* character <- complex */case 1616: /* character <- character */case 1016: /* logical <- character */case 1116: /* factor <- character */case 1216: /* ordered <- character */case 1316: /* integer <- character */case 1416: /* real <- character */case 1516: /* complex <- character */STRING(x)[ii] = STRING(y)[i % ny];break;}if (n > 1) {j = 0;while (++index[j] >= bound[j]) {index[j] = 0;j = ++j % k;}}next_i:;}UNPROTECT(3);vmaxset(vmax);return x;}static SEXP SimpleListAssign(SEXP call, SEXP x, SEXP s, SEXP y){SEXP index, yi, yp;int i, ii, n, nx, ny, stretch=1;if (length(s) > 1)error("invalid number of subscripts to list assign\n");PROTECT(index = makeSubscript(x, CAR(s), &stretch));n = length(index);/* The shallow copy here is so that *//* permuting a list's elements will work */if(isList(y) || isFrame(y) || isLanguage(y) ) {PROTECT(y);ny = NAMED(y);yi = allocList(length(y));for(yp=yi ; yp!=R_NilValue ; yp=CDR(yp)) {CAR(yp) = CAR(y);NAMED(CAR(yp)) = ny | NAMED(CAR(y));y = CDR(y);}UNPROTECT(1);PROTECT(y = yi);}else PROTECT(y = CONS(y, R_NilValue));ny = length(y);nx = length(x);if (n > 0 && ny == 0)error("nothing to replace with\n");if (n > 0 && n % ny)error("no of items to replace is not a multiple of replacement length\n");if(stretch) {yi = allocList(stretch - nx);PROTECT(x = listAppend(x, yi));nx = stretch;}else PROTECT(x);for (i=0; i<n; i++) {ii = INTEGER(index)[i];if(ii == NA_INTEGER) continue;ii = ii - 1;yi = CAR(nthcdr(y, i % ny));if(NAMED(y) || NAMED(yi)) yi = duplicate(yi);else NAMED(yi) = 1;CAR(nthcdr(x, ii % nx)) = yi;}UNPROTECT(3);return x;}static SEXP listRemove(SEXP x, SEXP s){SEXP a, pa, px;int i, ii, *ind, ns, nx, stretch=0;char *h;h = vmaxget();nx = length(x);PROTECT(s = makeSubscript(x, s, &stretch));ns = length(s);ind = (int*)R_alloc(nx, sizeof(int));for(i=0 ; i<nx ; i++)ind[i] = 1;for(i=0 ; i<ns ; i++) {ii = INTEGER(s)[i];if(ii != NA_INTEGER)ind[ii - 1] = 0;}PROTECT(a = CONS(R_NilValue, R_NilValue));px = x;pa = a;for(i=0 ; i<nx ; i++) {if(ind[i]) {CDR(pa) = px;px = CDR(px);pa = CDR(pa);CDR(pa) = R_NilValue;}else {px = CDR(px);}}UNPROTECT(2);vmaxset(h);return CDR(a);}SEXP listAssign1(SEXP call, SEXP x, SEXP subs, SEXP y){SEXP ax, ay, px, py, dims;int i, nsubs, ny;nsubs = length(subs);switch (nsubs) {case 0:break;case 1:if(y == R_NilValue)x = listRemove(x, CAR(subs));elsex = SimpleListAssign(call, x, subs, y);break;default:dims = getAttrib(x, R_DimSymbol);if (dims == R_NilValue || LENGTH(dims) != length(subs))error("incorrect number of subscripts\n");PROTECT(ax = allocArray(STRSXP, dims));for(px=x, i=0 ; px!=R_NilValue ; px = CDR(px))STRING(ax)[i++] = CAR(px);setAttrib(ax, R_DimNamesSymbol, getAttrib(x, R_DimNamesSymbol));if(isList(y)) {ny = length(y);PROTECT(ay = allocVector(STRSXP, ny));for(py=y, i=0 ; py!=R_NilValue ; py = CDR(py))STRING(ay)[i++] = CAR(py);}else {ny = 1;PROTECT(ay = allocVector(STRSXP, 1));STRING(ay)[0] = y;}if(nsubs == 2) ax = matrixAssign(call, ax, subs, ay);else ax = arrayAssign(call, ax, subs, ay);for(px=x, i=0 ; px!=R_NilValue ; px = CDR(px))CAR(px) = duplicate(STRING(ax)[i++]);UNPROTECT(2);break;}return x;}static SEXP frameAssign(SEXP call, SEXP x, SEXP s, SEXP y){int i, j, ii, jj, ij, k;int nr, nc, ncy;int nrs, ncs;SEXP sr, sc, ss, xp, yp;nr = length(CAR(x));nc = length(x);/* s has been protected. *//* No GC problems here. */if (length(s) == 1) {PROTECT(sr = frameSubscript(0, R_NilValue, x));PROTECT(sc = frameSubscript(1, CAR(s), x));}else if (length(s) == 2) {PROTECT(sr = frameSubscript(0, CAR(s), x));PROTECT(sc = frameSubscript(1, CADR(s), x));}else error("incorrect number of subscripts on data frame\n");nrs = LENGTH(sr);ncs = LENGTH(sc);if(isList(y) || isFrame(y)) PROTECT(y);else PROTECT(y = CONS(y, R_NilValue));ncy = length(y);PROTECT(ss = allocList(2));for(i=0 ; i<ncs ; i++) {ii = INTEGER(sc)[i]-1;xp = nthcdr(x, ii%nc);yp = nthcdr(y, ii%ncy);if ((length(sr) * length(sc)) % length(CAR(yp)))error("no of items to replace is not a multiple of replacement length\n");if(isMatrix(CAR(xp))) {CAR(ss) = sr;CADR(ss) = arraySubscript(1, R_MissingArg, CAR(xp));CAR(xp) = matrixAssign(call, CAR(xp), ss, CAR(yp));}else {CAR(xp) = vectorAssign(call, CAR(xp), sr, CAR(yp));}}UNPROTECT(4);return x;}/* This is a special version of EvalArgs. *//* We don't want to evaluate the last argument *//* It has already been evaluated by applydefine */static SEXP EvalSubassignArgs(SEXP el, SEXP rho){SEXP ans, h, tail;PROTECT(ans = tail = CONS(R_NilValue, R_NilValue));while(CDR(el) != R_NilValue) {/* If we have a ... symbol, we look to see what it *//* is bound to. If its binding is Null (i.e. zero length) *//* we just ignore it and return the cdr with all its *//* expressions evaluated; if it is bound to a ... list *//* of promises, we force all the promises and then splice *//* the list of resulting values into the return value. *//* Anything else bound to a ... symbol is an error */if (CAR(el) == R_DotsSymbol) {h = findVar(CAR(el), rho);if (TYPEOF(h) == DOTSXP || h == R_NilValue) {while(h != R_NilValue) {if(CAR(h) == R_MissingArg)CDR(tail) = CONS(R_MissingArg, R_NilValue);elseCDR(tail) = CONS(eval(CAR(h), rho), R_NilValue);TAG(CDR(tail)) = TAG(h);tail = CDR(tail);h = CDR(h);}}else if(h != R_MissingArg)error("... used in an incorrect context\n");}else if (CAR(el) == R_MissingArg) {CDR(tail) = CONS(R_MissingArg, R_NilValue);tail = CDR(tail);TAG(tail) = TAG(el);}else {CDR(tail) = CONS(eval(CAR(el), rho), R_NilValue);tail = CDR(tail);TAG(tail) = TAG(el);}el = CDR(el);}CDR(tail) = CONS(CAR(el), R_NilValue);UNPROTECT(1);return CDR(ans);}static void SubAssignArgs(SEXP args, SEXP *x, SEXP *s, SEXP *y){SEXP p;*x = CAR(args);*s = p = CDR(args);while(CDDR(p) != R_NilValue)p = CDR(p);*y = CADR(p);CDR(p) = R_NilValue;}/* The [<- operator. x is the vector that is *//* to be assigned into, y is the vector that *//* is going to provide the new values and s is *//* the vector of subscripts that are going to *//* be replaced. On entry (CAR(args)) and the last *//* argument have been evaluated been the remainder *//* of args have not. *//* If this was called directly the CAR(args) and the last *//* arg won't have been. */SEXP do_subassign(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP subs, x, y;int i, nsubs;RCNTXT cntxt;CAR(args) = eval(CAR(args), rho);#ifndef OLDPROTECT(CDR(args) = EvalSubassignArgs(CDR(args), rho));#endifif(isObject(CAR(args)) && CAR(call) != install("[<-.default")) {/*SetArgsforUseMethod(args); */begincontext(&cntxt,CTXT_RETURN, call, rho, rho, args);if(usemethod("[<-", CAR(args), call, args, rho, &y)) {endcontext(&cntxt);UNPROTECT(1);return y;}endcontext(&cntxt);}#ifdef OLDPROTECT(CDR(args) = EvalSubassignArgs(CDR(args), rho));#endifif (NAMED(CAR(args)) == 2) {x = CAR(args) = duplicate(CAR(args));}SubAssignArgs(args, &x, &subs, &y);/* We can't modify an object which is named in *//* another environment. NAMED(x)==2 indicates *//* that x was obtained through a promise evaluation *//* and hence it may be bound to a symbol elsewhere. *//* This will duplicate more often than necessary, *//* but saves over always duplicating. */nsubs = length(subs);if (isVector(x)) {switch (nsubs) {case 0:break;case 1:x = vectorAssign(call, x, CAR(subs), y);break;case 2:x = matrixAssign(call, x, subs, y);break;default:x = arrayAssign(call, x, subs, y);break;}}else if(isList(x) || isLanguage(x)) {x = listAssign1(call, x, subs, y);}else error("type error in subset assignment\n");/* Note the setting of NAMED(x) to zero here. *//* This means that the following assignment will *//* not duplicate the value. This works because *//* at this point, x is guaranteed to have have *//* at most one symbol bound to it. It does mean *//* that there will be multiple reference problems *//* if "[<-" is used in a naked fashion. */UNPROTECT(1);NAMED(x) = 0;return x;}/* The [[<- assignment, it should be fast. *//* args[1] = object being subscripted *//* args[2] = list of subscripts *//* args[3] = replacement values */SEXP do_subassign2(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP dims, index, names, subs, x, y, obj;int i, ndims, nsubs, offset, which;RCNTXT cntxt;CAR(args) = eval(CAR(args), rho);if(isObject(CAR(args)) && CAR(call) != install("[[<-.default") ) {/*SetArgsforUseMethod(args);*/begincontext(&cntxt,CTXT_RETURN, call, rho, rho, args);if(usemethod("[[<-", CAR(args), call, args, rho, &y)) {endcontext(&cntxt);return y;}endcontext(&cntxt);}PROTECT(CDR(args) = EvalSubassignArgs(CDR(args), rho));SubAssignArgs(args, &x, &subs, &y);if(isNull(x) && isNull(y)) {UNPROTECT(1);return R_NilValue;}if (NAMED(x) == 2) {CAR(args) = x = duplicate(x);}dims = getAttrib(x, R_DimSymbol);ndims = length(dims);nsubs = length(subs);#ifdef OLDif (!isList(x) && !isLanguage(x) && length(y) > 1)error("number of elements supplied larger than number of elements to replace\n");#endifif (isVector(x)) {if(!isExpression(x) && length(y) > 1)error("number of elements supplied larger than number of elements to replace\n");if (nsubs == 1) {offset = get1index(CAR(subs), getAttrib(x, R_NamesSymbol));if (offset < 0 || offset >= LENGTH(x))error("[[]] subscript out of bounds\n");}else {if (ndims != nsubs)error("[[]] improper number of subscripts\n");PROTECT(index = allocVector(INTSXP, ndims));names = getAttrib(x, R_DimNamesSymbol);for (i = 0; i < ndims; i++) {INTEGER(index)[i] = get1index(CAR(subs), isList(names) ? CAR(names) : R_NilValue);subs = CDR(subs);if (INTEGER(index)[i] < 0 || INTEGER(index)[i] >= INTEGER(dims)[i])error("[[]] subscript out of bounds\n");}offset = 0;for (i = (ndims - 1); i > 0; i--)offset = (offset + INTEGER(index)[i]) * INTEGER(dims)[i - 1];offset += INTEGER(index)[0];UNPROTECT(1);}which = 100 * TYPEOF(x) + TYPEOF(y);SubassignTypeFix(&x, &y, which, 0);switch (which) {case 1010: /* logical <- logical */case 1310: /* integer <- logical */case 1111: /* factor <- factor */case 1212: /* ordered <- ordered */case 1013: /* logical <- integer */case 1313: /* integer <- integer */INTEGER(x)[offset] = INTEGER(y)[0];break;case 1410: /* real <- logical */case 1413: /* real <- integer */if(INTEGER(y)[0] == NA_INTEGER)REAL(x)[offset] = NA_REAL;elseREAL(x)[offset] = INTEGER(y)[0];break;case 1014: /* logical <- real */case 1314: /* integer <- real */case 1414: /* real <- real */REAL(x)[offset] = REAL(y)[0];break;case 1510: /* complex <- logical */case 1513: /* complex <- integer */if(INTEGER(y)[0] == NA_INTEGER) {COMPLEX(x)[offset].r = NA_REAL;COMPLEX(x)[offset].i = NA_REAL;}else {COMPLEX(x)[offset].r = INTEGER(y)[0];COMPLEX(x)[offset].i = 0.0;}break;case 1514: /* complex <- real */if(!FINITE(REAL(y)[0])) {COMPLEX(x)[offset].r = NA_REAL;COMPLEX(x)[offset].i = NA_REAL;}else {COMPLEX(x)[offset].r = REAL(y)[0];COMPLEX(x)[offset].i = 0.0;}break;case 1015: /* logical <- complex */case 1315: /* integer <- complex */case 1415: /* real <- complex */case 1515: /* complex <- complex */COMPLEX(x)[offset] = COMPLEX(y)[0];break;case 1610: /* character <- logical */case 1611: /* character <- factor */case 1612: /* character <- ordered */case 1613: /* character <- integer */case 1614: /* character <- real */case 1615: /* character <- complex */case 1616: /* character <- character */case 1016: /* logical <- character */case 1116: /* factor <- character */case 1216: /* ordered <- character */case 1316: /* integer <- character */case 1416: /* real <- character */case 1516: /* complex <- character */STRING(x)[offset] = STRING(y)[0];break;case 2001: /* expression <- symbol */case 2006: /* expression <- language */case 2020: /* expression <- expression */case 2010: /* expression <- logical */case 2011: /* expression <- factor */case 2012: /* expression <- ordered */case 2013: /* expression <- integer */case 2014: /* expression <- real */case 2015: /* expression <- complex */case 2016: /* expression <- character */VECTOR(x)[offset] = VECTOR(y)[0];break;default:error("incompatible types in subset assignment\n");}}else if (isList(x) || isLanguage(x) ) {if(NAMED(y)) y = duplicate(y);PROTECT(y);if(nsubs == 1) {if(isNull(y)) {x = listRemove(x, CAR(subs));}else {PROTECT(y = CONS(y, R_NilValue));x = SimpleListAssign(call, x, subs, y);UNPROTECT(1);}}else {if (ndims != nsubs)error("[[]] improper number of subscripts\n");PROTECT(index = allocVector(INTSXP, ndims));names = getAttrib(x, R_DimNamesSymbol);for (i = 0; i < ndims; i++) {INTEGER(index)[i] = get1index(CAR(subs), CAR(names));subs = CDR(subs);if (INTEGER(index)[i] < 0 || INTEGER(index)[i] >= INTEGER(dims)[i])error("[[]] subscript out of bounds\n");}offset = 0;for (i = (ndims - 1); i > 0; i--)offset = (offset + INTEGER(index)[i]) * INTEGER(dims)[i - 1];offset += INTEGER(index)[0];CAR(nthcdr(x, offset)) = duplicate(y);UNPROTECT(1);}UNPROTECT(1);}else error("type error in subset assignment\n");UNPROTECT(1);NAMED(x) = 0;return x;}SEXP do_subassign3(SEXP call, SEXP op, SEXP args, SEXP env){SEXP x, nlist, val, t;checkArity(op, args);PROTECT(x = eval(CAR(args), env));if (!isList(x) && !isLanguage(x))error("$ used on non-list\n");/* Note: rhs is already evaluated by evaluator */val = CADDR(args);if(NAMED(val)) val = duplicate(val);PROTECT(val);nlist = CADR(args);if (isString(nlist))nlist = install(CHAR(STRING(nlist)[0]));if(TAG(x) == nlist ) {if(val == R_NilValue)x= CDR(x);elseCAR(x)= val;}else {for (t = x; t != R_NilValue; t = CDR(t))if (TAG(CDR(t)) == nlist) {if( val == R_NilValue )CDR(t)=CDDR(t);elseCAR(CDR(t)) = val;break;}else if (CDR(t) == R_NilValue && val != R_NilValue) {SETCDR(t, allocSExp(LISTSXP));TAG(CDR(t)) = nlist;CADR(t) = val;break;}}if( x== R_NilValue && val != R_NilValue ) {x=allocList(1);CAR(x) = val;TAG(x) = nlist;}UNPROTECT(2);FrameClassFix(x);NAMED(x) = 0;return x;}/* Data Frame Subsetting Methods */SEXP do_subassigndf(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP subs, x, y;PROTECT(args = EvalArgs(args, rho, 0));SubAssignArgs(args, &x, &subs, &y);switch(length(subs)) {case 1:FrameClassFix(x = listAssign1(call, x, subs, y));break;case 2:x = frameAssign(call, x, subs, y);break;default:errorcall(call, "invalid number of subscripts\n");}UNPROTECT(1);return x;}SEXP do_subassigndf2(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP subs, x, y;PROTECT(args = EvalArgs(args, rho, 0));SubAssignArgs(args, &x, &subs, &y);switch(length(subs)) {case 1:FrameClassFix(x = listAssign1(call, x, subs, y));break;case 2:x = frameAssign(call, x, subs, y);break;default:errorcall(call, "invalid number of subscripts\n");}UNPROTECT(1);return x;}