Rev 9615 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* Copyright (C) 1995-2000 Robert Gentleman, Ross Ihaka and the* R Development 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, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "Defn.h"/*-- Maybe modularize into own Coerce.h ..*/#include "Mathlib.h"#include "Print.h"/* This section of code handles type conversion for elements *//* of data vectors. Type coercion throughout R should use these *//* routines to ensure consistency. */static char *truenames[] = {"T","True","TRUE","true",(char *) 0,};static char *falsenames[] = {"F","False","FALSE","false",(char *) 0,};#define WARN_NA 1#define WARN_INACC 2#define WARN_IMAG 4void CoercionWarning(int warn){if (warn & WARN_NA)warning("NAs introduced by coercion");if (warn & WARN_INACC)warning("inaccurate integer conversion in coercion");if (warn & WARN_IMAG)warning("imaginary parts discarded in coercion");}double R_strtod(char *c, char **end){double x;if (strncmp(c, "NA", 2) == 0){x = NA_REAL; *end = c + 2;}else if (strncmp(c, "NaN", 3) == 0) {x = R_NaN; *end = c + 3;}else if (strncmp(c, "Inf", 3) == 0) {x = R_PosInf; *end = c + 3;}else if (strncmp(c, "-Inf", 4) == 0) {x = R_NegInf; *end = c + 4;}elsex = strtod(c, end);return x;}int LogicalFromInteger(int x, int *warn){return (x == NA_INTEGER) ?NA_LOGICAL : (x != 0);}int LogicalFromReal(double x, int *warn){return ISNAN(x) ?NA_LOGICAL : (x != 0);}int LogicalFromComplex(Rcomplex x, int *warn){return (ISNAN(x.r) || ISNAN(x.i)) ?NA_LOGICAL : (x.r != 0 || x.i != 0);}int LogicalFromString(SEXP x, int *warn){if (x != R_NaString) {int i;for (i = 0; truenames[i]; i++)if (!strcmp(CHAR(x), truenames[i]))return 1;for (i = 0; falsenames[i]; i++)if (!strcmp(CHAR(x), falsenames[i]))return 0;}return NA_LOGICAL;}int IntegerFromLogical(int x, int *warn){return (x == NA_LOGICAL) ?NA_INTEGER : x;}int IntegerFromReal(double x, int *warn){if (ISNAN(x))return NA_INTEGER;else if (x > INT_MAX) {*warn |= WARN_INACC;return INT_MAX;}else if (x <= INT_MIN) {*warn |= WARN_INACC;return INT_MIN+1;}return x;}int IntegerFromComplex(Rcomplex x, int *warn){if (ISNAN(x.r) || ISNAN(x.i))return NA_INTEGER;else if (x.r > INT_MAX) {*warn |= WARN_INACC;return INT_MAX;}else if (x.r <= INT_MIN) {*warn |= WARN_INACC;return INT_MIN+1;}if (x.i != 0)*warn |= WARN_IMAG;return x.r;}int IntegerFromString(SEXP x, int *warn){double xdouble;char *endp;if (x != R_NaString) {xdouble = strtod(CHAR(x), &endp);if (isBlankString(endp)) {if (xdouble > INT_MAX) {*warn |= WARN_INACC;return INT_MAX;}else if(xdouble < INT_MIN+1) {*warn |= WARN_INACC;return INT_MIN;}elsereturn xdouble;}else *warn |= WARN_NA;}return NA_INTEGER;}double RealFromLogical(int x, int *warn){return (x == NA_LOGICAL) ?NA_REAL : x;}double RealFromInteger(int x, int *warn){if (x == NA_INTEGER)return NA_REAL;elsereturn x;}double RealFromComplex(Rcomplex x, int *warn){if (ISNAN(x.r) || ISNAN(x.i))return NA_INTEGER;if (x.i != 0)*warn |= WARN_IMAG;return x.r;}double RealFromString(SEXP x, int *warn){double xdouble;char *endp;if (x != R_NaString) {xdouble = strtod(CHAR(x), &endp);if (isBlankString(endp))return xdouble;else*warn |= WARN_NA;}return NA_REAL;}Rcomplex ComplexFromLogical(int x, int *warn){Rcomplex z;if (x == NA_LOGICAL) {z.r = NA_REAL;z.i = NA_REAL;}else {z.r = x;z.i = 0;}return z;}Rcomplex ComplexFromInteger(int x, int *warn){Rcomplex z;if (x == NA_INTEGER) {z.r = NA_REAL;z.i = NA_REAL;}else {z.r = x;z.i = 0;}return z;}Rcomplex ComplexFromReal(double x, int *warn){Rcomplex z;if (ISNAN(x)) {z.r = NA_REAL;z.i = NA_REAL;}else {z.r = x;z.i = 0;}return z;}Rcomplex ComplexFromString(SEXP x, int *warn){double xr, xi;Rcomplex z;char *endp = CHAR(x);;z.r = z.i = NA_REAL;if (x != R_NaString) {xr = strtod(endp, &endp);if (isBlankString(endp)) {z.r = xr;z.i = 0.0;}else if (*endp == '+' || *endp == '-') {xi = strtod(endp, &endp);if (*endp++ == 'i' && isBlankString(endp)) {z.r = xr;z.i = xi;}else *warn |= WARN_NA;}else *warn |= WARN_NA;}return z;}SEXP StringFromLogical(int x, int *warn){int w;formatLogical(&x, 1, &w);return mkChar(EncodeLogical(x, w));}SEXP StringFromInteger(int x, int *warn){int w;formatInteger(&x, 1, &w);return mkChar(EncodeInteger(x, w));}SEXP StringFromReal(double x, int *warn){int w, d, e;formatReal(&x, 1, &w, &d, &e);return mkChar(EncodeReal(x, w, d, e));}SEXP StringFromComplex(Rcomplex x, int *warn){int wr, dr, er, wi, di, ei;formatComplex(&x, 1, &wr, &dr, &er, &wi, &di, &ei);return mkChar(EncodeComplex(x, wr, dr, er, wi, di, ei));}/* Conversion between the two list types (LISTSXP and VECSXP). */SEXP PairToVectorList(SEXP x){SEXP xptr, xnew, xnames;int i, len = 0, named = 0;for (xptr = x ; xptr != R_NilValue ; xptr = CDR(xptr)) {named = named | (TAG(xptr) != R_NilValue);len++;}PROTECT(x);PROTECT(xnew = allocVector(VECSXP, len));for (i = 0, xptr = x; i < len; i++, xptr = CDR(xptr))SET_VECTOR_ELT(xnew, i, CAR(xptr));if (named) {PROTECT(xnames = allocVector(STRSXP, len));xptr = x;for (i = 0, xptr = x; i < len; i++, xptr = CDR(xptr)) {if(TAG(xptr) == R_NilValue)SET_STRING_ELT(xnames, i, R_BlankString);elseSET_STRING_ELT(xnames, i, PRINTNAME(TAG(xptr)));}setAttrib(xnew, R_NamesSymbol, xnames);UNPROTECT(1);}copyMostAttrib(x, xnew);UNPROTECT(2);return xnew;}SEXP VectorToPairList(SEXP x){SEXP xptr, xnew, xnames;int i, len, named;len = length(x);PROTECT(x);PROTECT(xnew = allocList(len));PROTECT(xnames = getAttrib(x, R_NamesSymbol));named = (xnames != R_NilValue);xptr = xnew;for (i = 0; i < len; i++) {SETCAR(xptr, VECTOR_ELT(x, i));if (named && CHAR(STRING_ELT(xnames, i))[0] != '\0')SET_TAG(xptr, install(CHAR(STRING_ELT(xnames, i))));xptr = CDR(xptr);}copyMostAttrib(x, xnew);UNPROTECT(3);return xnew;}static SEXP coerceToSymbol(SEXP v){SEXP ans = R_NilValue;int warn;if (length(v) <= 0)error("Invalid data of mode \"%s\" (too short)",CHAR(type2str(TYPEOF(v))));PROTECT(v);switch(TYPEOF(v)) {case LGLSXP:ans = StringFromLogical(LOGICAL(v)[0], &warn);break;case INTSXP:ans = StringFromInteger(INTEGER(v)[0], &warn);break;case REALSXP:ans = StringFromReal(REAL(v)[0], &warn);break;case CPLXSXP:ans = StringFromComplex(COMPLEX(v)[0], &warn);break;case STRSXP:ans = STRING_ELT(v, 0);break;}ans = install(CHAR(ans));UNPROTECT(1);return ans;}static SEXP coerceToLogical(SEXP v){SEXP ans;int i, n, warn = 0;PROTECT(ans = allocVector(LGLSXP, n = length(v)));SET_ATTRIB(ans, duplicate(ATTRIB(v)));switch (TYPEOF(v)) {case INTSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = LogicalFromInteger(INTEGER(v)[i], &warn);break;case REALSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = LogicalFromReal(REAL(v)[i], &warn);break;case CPLXSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = LogicalFromComplex(COMPLEX(v)[i], &warn);break;case STRSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = LogicalFromString(STRING_ELT(v, i), &warn);break;}if (warn) CoercionWarning(warn);UNPROTECT(1);return ans;}static SEXP coerceToInteger(SEXP v){SEXP ans;int i, n, warn = 0;PROTECT(ans = allocVector(INTSXP, n = LENGTH(v)));SET_ATTRIB(ans, duplicate(ATTRIB(v)));switch (TYPEOF(v)) {case LGLSXP:for (i = 0; i < n; i++)INTEGER(ans)[i] = IntegerFromLogical(LOGICAL(v)[i], &warn);break;case REALSXP:for (i = 0; i < n; i++)INTEGER(ans)[i] = IntegerFromReal(REAL(v)[i], &warn);break;case CPLXSXP:for (i = 0; i < n; i++)INTEGER(ans)[i] = IntegerFromComplex(COMPLEX(v)[i], &warn);break;case STRSXP:for (i = 0; i < n; i++)INTEGER(ans)[i] = IntegerFromString(STRING_ELT(v, i), &warn);break;}if (warn) CoercionWarning(warn);UNPROTECT(1);return ans;}static SEXP coerceToReal(SEXP v){SEXP ans;int i, n, warn = 0;PROTECT(ans = allocVector(REALSXP, n = LENGTH(v)));SET_ATTRIB(ans, duplicate(ATTRIB(v)));switch (TYPEOF(v)) {case LGLSXP:for (i = 0; i < n; i++)REAL(ans)[i] = RealFromLogical(LOGICAL(v)[i], &warn);break;case INTSXP:for (i = 0; i < n; i++)REAL(ans)[i] = RealFromInteger(INTEGER(v)[i], &warn);break;case CPLXSXP:for (i = 0; i < n; i++)REAL(ans)[i] = RealFromComplex(COMPLEX(v)[i], &warn);break;case STRSXP:for (i = 0; i < n; i++)REAL(ans)[i] = RealFromString(STRING_ELT(v, i), &warn);break;}if (warn) CoercionWarning(warn);UNPROTECT(1);return ans;}static SEXP coerceToComplex(SEXP v){SEXP ans;int i, n, warn = 0;PROTECT(ans = allocVector(CPLXSXP, n = LENGTH(v)));SET_ATTRIB(ans, duplicate(ATTRIB(v)));switch (TYPEOF(v)) {case LGLSXP:for (i = 0; i < n; i++)COMPLEX(ans)[i] = ComplexFromLogical(LOGICAL(v)[i], &warn);break;case INTSXP:for (i = 0; i < n; i++)COMPLEX(ans)[i] = ComplexFromInteger(INTEGER(v)[i], &warn);break;case REALSXP:for (i = 0; i < n; i++)COMPLEX(ans)[i] = ComplexFromReal(REAL(v)[i], &warn);break;case STRSXP:for (i = 0; i < n; i++)COMPLEX(ans)[i] = ComplexFromString(STRING_ELT(v, i), &warn);break;}if (warn) CoercionWarning(warn);UNPROTECT(1);return ans;}static SEXP coerceToString(SEXP v){SEXP ans;int i, n, savedigits, warn = 0;PROTECT(ans = allocVector(STRSXP, n = LENGTH(v)));SET_ATTRIB(ans, duplicate(ATTRIB(v)));switch (TYPEOF(v)) {case LGLSXP:for (i = 0; i < n; i++)SET_STRING_ELT(ans, i, StringFromLogical(LOGICAL(v)[i], &warn));break;case INTSXP:for (i = 0; i < n; i++)SET_STRING_ELT(ans, i, StringFromInteger(INTEGER(v)[i], &warn));break;case REALSXP:PrintDefaults(R_NilValue);savedigits = R_print.digits; R_print.digits = DBL_DIG;/* MAX precision */for (i = 0; i < n; i++)SET_STRING_ELT(ans, i, StringFromReal(REAL(v)[i], &warn));break;R_print.digits = savedigits;case CPLXSXP:PrintDefaults(R_NilValue);savedigits = R_print.digits; R_print.digits = DBL_DIG;/* MAX precision */for (i = 0; i < n; i++)SET_STRING_ELT(ans, i, StringFromComplex(COMPLEX(v)[i], &warn));break;R_print.digits = savedigits;}UNPROTECT(1);return (ans);}static SEXP coerceToExpression(SEXP v){SEXP ans;int i, n;if (isVectorAtomic(v)) {n = LENGTH(v);PROTECT(ans = allocVector(EXPRSXP, n));switch (TYPEOF(v)) {case LGLSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, ScalarLogical(LOGICAL(v)[i]));break;case INTSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, ScalarInteger(INTEGER(v)[i]));break;case REALSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, ScalarReal(REAL(v)[i]));break;case CPLXSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, ScalarComplex(COMPLEX(v)[i]));break;case STRSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, ScalarString(STRING_ELT(v, i)));break;#ifdef never_usedcase VECSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, VECTOR_ELT(v, i));break;#endif}}else {/* not used either */PROTECT(ans = allocVector(EXPRSXP, 1));SET_VECTOR_ELT(ans, 0, duplicate(v));}UNPROTECT(1);return ans;}static SEXP coerceToVectorList(SEXP v){SEXP ans, tmp;int i, n;n = length(v);PROTECT(ans = allocVector(VECSXP, n));switch (TYPEOF(v)) {case LGLSXP:case INTSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, ScalarInteger(INTEGER(v)[i]));break;case REALSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, ScalarReal(REAL(v)[i]));break;case CPLXSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, ScalarComplex(COMPLEX(v)[i]));break;case STRSXP:for (i = 0; i < n; i++)SET_VECTOR_ELT(ans, i, ScalarString(STRING_ELT(v, i)));break;case LISTSXP:case LANGSXP:tmp = v;for (i = 0; i < n; i++) {SET_VECTOR_ELT(ans, i, CAR(tmp));tmp = CDR(tmp);}break;default:UNIMPLEMENTED("coerceToVectorList");}tmp = getAttrib(v, R_NamesSymbol);if (tmp != R_NilValue)setAttrib(ans, R_NamesSymbol, tmp);UNPROTECT(1);return (ans);}static SEXP coerceToPairList(SEXP v){SEXP ans, ansp;int i, n;n = LENGTH(v);PROTECT(ansp = ans = allocList(n));for (i = 0; i < n; i++) {switch (TYPEOF(v)) {case LGLSXP:SETCAR(ansp, allocVector(LGLSXP, 1));INTEGER(CAR(ansp))[0] = INTEGER(v)[i];break;case INTSXP:SETCAR(ansp, allocVector(INTSXP, 1));INTEGER(CAR(ansp))[0] = INTEGER(v)[i];break;case REALSXP:SETCAR(ansp, allocVector(REALSXP, 1));REAL(CAR(ansp))[0] = REAL(v)[i];break;case CPLXSXP:SETCAR(ansp, allocVector(CPLXSXP, 1));COMPLEX(CAR(ansp))[0] = COMPLEX(v)[i];break;case STRSXP:SETCAR(ansp, allocVector(STRSXP, 1));SET_STRING_ELT(CAR(ansp), 0, STRING_ELT(v, i));break;case VECSXP:SETCAR(ansp, VECTOR_ELT(v, i));break;case EXPRSXP:SETCAR(ansp, VECTOR_ELT(v, i));break;default:UNIMPLEMENTED("coerceToPairList");}ansp = CDR(ansp);}ansp = getAttrib(v, R_NamesSymbol);if (ansp != R_NilValue)setAttrib(ans, R_NamesSymbol, ansp);UNPROTECT(1);return (ans);}/* Coerce a list to the given type */static SEXP coercePairList(SEXP v, SEXPTYPE type){int i, n=0;SEXP rval= R_NilValue, vp, names;if(type == LISTSXP) return v;/* IS pairlist */names = v;if (type == EXPRSXP) {PROTECT(rval = allocVector(type, 1));SET_VECTOR_ELT(rval, 0, v);UNPROTECT(1);return rval;}else if (type == STRSXP) {n = length(v);PROTECT(rval = allocVector(type, n));for (vp = v, i = 0; vp != R_NilValue; vp = CDR(vp), i++) {if (isString(CAR(vp)) && length(CAR(vp)) == 1)SET_STRING_ELT(rval, i, STRING_ELT(CAR(vp), 0));elseSET_STRING_ELT(rval, i, STRING_ELT(deparse1(CAR(vp), 0), 0));}}else if (type == VECSXP) {rval = PairToVectorList(v);return rval;}else if (isVectorizable(v)) {n = length(v);PROTECT(rval = allocVector(type, n));switch (type) {case LGLSXP:for (i = 0, vp = v; i < n; i++, vp = CDR(vp))LOGICAL(rval)[i] = asLogical(CAR(vp));break;case INTSXP:for (i = 0, vp = v; i < n; i++, vp = CDR(vp))INTEGER(rval)[i] = asInteger(CAR(vp));break;case REALSXP:for (i = 0, vp = v; i < n; i++, vp = CDR(vp))REAL(rval)[i] = asReal(CAR(vp));break;case CPLXSXP:for (i = 0, vp = v; i < n; i++, vp = CDR(vp))COMPLEX(rval)[i] = asComplex(CAR(vp));break;default:UNIMPLEMENTED("coercePairList");}}elseerror("pairlist object cannot be coerced to vector type [%d]",type);/* If any tags are non-null then we *//* need to add a names attribute. */for (vp = v, i = 0; vp != R_NilValue; vp = CDR(vp))if (TAG(vp) != R_NilValue)i = 1;if (i) {i = 0;names = allocVector(STRSXP, n);for (vp = v; vp != R_NilValue; vp = CDR(vp), i++)if (TAG(vp) != R_NilValue)SET_STRING_ELT(names, i, PRINTNAME(TAG(vp)));setAttrib(rval, R_NamesSymbol, names);}UNPROTECT(1);return rval;}static SEXP coerceVectorList(SEXP v, SEXPTYPE type){int i, n;SEXP rval, names;names = v;rval = R_NilValue; /* -Wall */if (type == EXPRSXP) {PROTECT(rval = allocVector(type, 1));SET_VECTOR_ELT(rval, 0, v);UNPROTECT(1);return rval;}else if (type == STRSXP) {n = length(v);PROTECT(rval = allocVector(type, n));for (i = 0; i < n; i++) {if (isString(VECTOR_ELT(v, i)) && length(VECTOR_ELT(v, i)) == 1)SET_STRING_ELT(rval, i, STRING_ELT(VECTOR_ELT(v, i), 0));elseSET_STRING_ELT(rval, i,STRING_ELT(deparse1(VECTOR_ELT(v, i), 0), 0));}}else if (type == LISTSXP) {rval = VectorToPairList(v);return rval;}else if (isVectorizable(v)) {n = length(v);PROTECT(rval = allocVector(type, n));switch (type) {case LGLSXP:for (i = 0; i < n; i++)LOGICAL(rval)[i] = asLogical(VECTOR_ELT(v, i));break;case INTSXP:for (i = 0; i < n; i++)INTEGER(rval)[i] = asInteger(VECTOR_ELT(v, i));break;case REALSXP:for (i = 0; i < n; i++)REAL(rval)[i] = asReal(VECTOR_ELT(v, i));break;case CPLXSXP:for (i = 0; i < n; i++)COMPLEX(rval)[i] = asComplex(VECTOR_ELT(v, i));break;default:UNIMPLEMENTED("coerceVectorList");}}elseerror("(list) object cannot be coerced to vector type %d",type);names = getAttrib(v, R_NamesSymbol);if (names != R_NilValue)setAttrib(rval, R_NamesSymbol, names);UNPROTECT(1);return rval;}SEXP coerceVector(SEXP v, SEXPTYPE type){SEXP ans = R_NilValue; /* -Wall */if (TYPEOF(v) == type)return v;switch (TYPEOF(v)) {#ifdef NOTYETcase NILSXP:ans = coerceNull(v, type);break;case SYMSXP:ans = coerceSymbol(v, type);break;#endifcase NILSXP:case LISTSXP:case LANGSXP:ans = coercePairList(v, type);break;case VECSXP:case EXPRSXP:ans = coerceVectorList(v, type);break;case ENVSXP:error("environments cannot be coerced to other types");break;case LGLSXP:case INTSXP:case REALSXP:case CPLXSXP:case STRSXP:switch (type) {case SYMSXP:ans = coerceToSymbol(v);break;case LGLSXP:ans = coerceToLogical(v);break;case INTSXP:ans = coerceToInteger(v);break;case REALSXP:ans = coerceToReal(v);break;case CPLXSXP:ans = coerceToComplex(v);break;case STRSXP:ans = coerceToString(v);break;case EXPRSXP:ans = coerceToExpression(v);break;case VECSXP:ans = coerceToVectorList(v);break;case LISTSXP:ans = coerceToPairList(v);break;}}return ans;}SEXP CreateTag(SEXP x){if (isNull(x) || isSymbol(x))return x;if (isString(x)&& length(x) >= 1&& length(STRING_ELT(x, 0)) >= 1)x = install(CHAR(STRING_ELT(x, 0)));elsex = install(CHAR(STRING_ELT(deparse1(x, 1), 0)));return x;}static SEXP asFunction(SEXP x){SEXP f, pf;int n;if (isFunction(x)) return x;PROTECT(f = allocSExp(CLOSXP));SET_CLOENV(f, R_GlobalEnv);if (NAMED(x)) PROTECT(x = duplicate(x));else PROTECT(x);if (isNull(x) || !isList(x)) {SET_FORMALS(f, R_NilValue);SET_BODY(f, x);}else {n = length(x);pf = allocList(n - 1);SET_FORMALS(f, pf);while(--n) {if (TAG(x) == R_NilValue) {SET_TAG(pf, CreateTag(CAR(x)));SETCAR(pf, R_MissingArg);}else {SETCAR(pf, CAR(x));SET_TAG(pf, TAG(x));}pf = CDR(pf);x = CDR(x);}SET_BODY(f, CAR(x));}UNPROTECT(2);return f;}static SEXP ascommon(SEXP call, SEXP u, int type){/* -> as.vector(..) or as.XXX(.) : coerce 'u' to 'type' : */SEXP v;#ifdef OLDif (type == SYMSXP) {if (TYPEOF(u) == SYMSXP)return u;if (!isString(u) || LENGTH(u) < 0 || CHAR(STRING_ELT(u, 0))[0] == '\0')errorcall(call, "character argument required");return install(CHAR(STRING_ELT(u, 0)));}else#endifif (type == CLOSXP) {return asFunction(u);}else if (isVector(u) || isList(u) || isLanguage(u)) {if (NAMED(u))v = duplicate(u);else v = u;if (type != ANYSXP) {PROTECT(v);v = coerceVector(v, type);UNPROTECT(1);}/* drop attributes() and class() in some cases: */if ((type == LISTSXP/* already loses 'names' where it shouldn't:|| type == VECSXP) */) &&!(TYPEOF(u) == LANGSXP || TYPEOF(u) == LISTSXP ||TYPEOF(u) == EXPRSXP || TYPEOF(u) == VECSXP)) {SET_ATTRIB(v, R_NilValue);SET_OBJECT(v, 0);}return v;}else if (isSymbol(u) && type == STRSXP) {v = allocVector(STRSXP, 1);SET_STRING_ELT(v, 0, PRINTNAME(u));return v;}else if (isSymbol(u) && type == SYMSXP)return u;else errorcall(call, "cannot coerce to vector");return u;/* -Wall */}SEXP do_asvector(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP ans;int type;if (DispatchOrEval(call, op, args, rho, &ans, 1))return(ans);/* Method dispatch has failed, we now just *//* run the generic internal code */PROTECT(args = ans);checkArity(op, args);if (!isString(CADR(args)) || LENGTH(CADR(args)) < 1)errorcall_return(call, R_MSG_mode);if (!strcmp("function", (CHAR(STRING_ELT(CADR(args), 0)))))type = CLOSXP;elsetype = str2type(CHAR(STRING_ELT(CADR(args), 0)));switch(type) {/* only those are valid : */case SYMSXP:case LGLSXP:case INTSXP:case REALSXP:case CPLXSXP:case STRSXP:case EXPRSXP:case VECSXP: /* list */case LISTSXP:/* pairlist */case CLOSXP: /* non-primitive function */case ANYSXP: /* any */break;default:errorcall_return(call, R_MSG_mode);}ans = ascommon(call, CAR(args), type);switch(TYPEOF(ans)) {/* keep attributes for these:*/case NILSXP:case VECSXP:case EXPRSXP:case LISTSXP:case LANGSXP:break;default:SET_ATTRIB(ans, R_NilValue);break;}UNPROTECT(1);return ans;}SEXP do_asfunction(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP arglist, envir, names, pargs;int i, n;checkArity(op, args);/* Check the arguments; we need a list and environment. */arglist = CAR(args);if (length(arglist) > 1 && !isNewList(arglist))errorcall(call, "list argument expected");envir = CADR(args);if (!isNull(envir) && !isEnvironment(envir))errorcall(call, "invalid environment");n = length(arglist);if (n < 1)errorcall(call, "argument must have length at least 1");names = getAttrib(arglist, R_NamesSymbol);PROTECT(pargs = args = allocList(n - 1));for (i = 0; i < n - 1; i++) {SETCAR(pargs, VECTOR_ELT(arglist, i));if (names != R_NilValue && *CHAR(STRING_ELT(names, i)) != '\0')SET_TAG(pargs, install(CHAR(STRING_ELT(names, i))));elseSET_TAG(pargs, R_NilValue);pargs = CDR(pargs);}CheckFormals(args);if( n == 1 )args = mkCLOSXP(args, arglist, envir);elseargs = mkCLOSXP(args, VECTOR_ELT(arglist, n - 1), envir);UNPROTECT(1);return args;}SEXP do_ascall(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP ap, ans, names;int i, n;checkArity(op, args);args = CAR(args);switch (TYPEOF(args)) {case LANGSXP:ans = args;break;case VECSXP:case EXPRSXP:if(0 == (n = length(args)))errorcall(call,"illegal length 0 argument");names = getAttrib(args, R_NamesSymbol);PROTECT(ap = ans = allocList(n));for (i = 0; i < n; i++) {SETCAR(ap, VECTOR_ELT(args, i));if (names != R_NilValue && !StringBlank(STRING_ELT(names, i)))SET_TAG(ap, install(CHAR(STRING_ELT(names, i))));ap = CDR(ap);}UNPROTECT(1);break;case LISTSXP:ans = duplicate(args);break;default:errorcall(call, "invalid argument list");ans = R_NilValue;}SET_TYPEOF(ans, LANGSXP);SET_TAG(ans, R_NilValue);return ans;}/* return the type (= "detailed mode") of the SEXP */SEXP do_typeof(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP ans;checkArity(op, args);PROTECT(ans = allocVector(STRSXP, 1));SET_STRING_ELT(ans,0, type2str(TYPEOF(CAR(args))));UNPROTECT(1);return ans;}/* Define many of the <primitive> "is.xxx" functions :Note that isNull, isNumeric, etc are defined in ./util.c*/SEXP do_is(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP ans;checkArity(op, args);PROTECT(ans = allocVector(LGLSXP, 1));switch (PRIMVAL(op)) {case NILSXP: /* is.null */LOGICAL(ans)[0] = isNull(CAR(args));break;case LGLSXP: /* is.logical */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == LGLSXP);break;case INTSXP: /* is.integer */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == INTSXP);break;case REALSXP: /* is.double */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == REALSXP);break;case CPLXSXP: /* is.complex */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == CPLXSXP);break;case STRSXP: /* is.character */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == STRSXP);break;case SYMSXP: /* is.symbol === is.name */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == SYMSXP);break;case ENVSXP: /* is.environment */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == ENVSXP);break;case VECSXP: /* is.list */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == VECSXP ||TYPEOF(CAR(args)) == LISTSXP);break;case LISTSXP: /* is.pairlist */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == LISTSXP ||TYPEOF(CAR(args)) == NILSXP);/* pairlist() -> NULL */break;case EXPRSXP: /* is.expression */LOGICAL(ans)[0] = TYPEOF(CAR(args)) == EXPRSXP;break;case 50: /* is.object */LOGICAL(ans)[0] = OBJECT(CAR(args));break;case 75: /* is.factor */LOGICAL(ans)[0] = isFactor(CAR(args));break;case 80:LOGICAL(ans)[0] = isFrame(CAR(args));break;case 100: /* is.numeric */LOGICAL(ans)[0] = (isNumeric(CAR(args)) &&!isLogical(CAR(args)));break;case 101: /* is.matrix */LOGICAL(ans)[0] = isMatrix(CAR(args));break;case 102: /* is.array */LOGICAL(ans)[0] = isArray(CAR(args));break;case 103: /* is.ts */LOGICAL(ans)[0] = isTs(CAR(args));break;case 200: /* is.atomic */switch(TYPEOF(CAR(args))) {case NILSXP:case CHARSXP:case LGLSXP:case INTSXP:case REALSXP:case CPLXSXP:case STRSXP:LOGICAL(ans)[0] = 1;break;default:LOGICAL(ans)[0] = 0;break;}break;case 201: /* is.recursive */switch(TYPEOF(CAR(args))) {case VECSXP:case LISTSXP:case CLOSXP:case ENVSXP:case PROMSXP:case LANGSXP:case SPECIALSXP:case BUILTINSXP:case DOTSXP:case ANYSXP:case EXPRSXP:LOGICAL(ans)[0] = 1;break;default:LOGICAL(ans)[0] = 0;break;}break;case 300: /* is.call */LOGICAL(ans)[0] = TYPEOF(CAR(args)) == LANGSXP;break;case 301: /* is.language */LOGICAL(ans)[0] = (TYPEOF(CAR(args)) == SYMSXP ||TYPEOF(CAR(args)) == LANGSXP ||TYPEOF(CAR(args)) == EXPRSXP);break;case 302: /* is.function */LOGICAL(ans)[0] = isFunction(CAR(args));break;case 999: /* is.single */errorcall(call, "type \"single\" unimplemented in R");default:errorcall(call, "unimplemented predicate");}UNPROTECT(1);return (ans);}/* What should is.vector do ?* In S, if an object has no attributes it is a vector, otherwise it isn't.* It seems to make more sense to check for a dim attribute.*/SEXP do_isvector(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP ans, a;checkArity(op, args);if (!isString(CADR(args)) || LENGTH(CADR(args)) <= 0)errorcall_return(call, R_MSG_mode);PROTECT(ans = allocVector(LGLSXP, 1));if (streql(CHAR(STRING_ELT(CADR(args), 0)), "any")) {LOGICAL(ans)[0] = isVector(CAR(args));/* from ./util.c */}else if (streql(CHAR(STRING_ELT(CADR(args), 0)), "numeric")) {LOGICAL(ans)[0] = (isNumeric(CAR(args)) &&!isLogical(CAR(args)));}else if (streql(CHAR(STRING_ELT(CADR(args), 0)),CHAR(type2str(TYPEOF(CAR(args)))))) {LOGICAL(ans)[0] = 1;}elseLOGICAL(ans)[0] = 0;/* We allow a "names" attribute on any vector. */if (LOGICAL(ans)[0] && ATTRIB(CAR(args)) != R_NilValue) {a = ATTRIB(CAR(args));while(a != R_NilValue) {if (TAG(a) != R_NamesSymbol) {LOGICAL(ans)[0] = 0;break;}a = CDR(a);}}UNPROTECT(1);return (ans);}SEXP do_isna(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP ans, dims, names, x;int i, n;if (DispatchOrEval(call, op, args, rho, &ans, 1))return(ans);PROTECT(args = ans);checkArity(op, args);#ifdef stringent_isif (!isList(CAR(args)) && !isVector(CAR(args)))errorcall_return(call, "is.na " R_MSG_list_vec);#endifx = CAR(args);n = length(x);ans = allocVector(LGLSXP, n);if (isVector(x)) {PROTECT(dims = getAttrib(x, R_DimSymbol));if (isArray(x))PROTECT(names = getAttrib(x, R_DimNamesSymbol));elsePROTECT(names = getAttrib(x, R_NamesSymbol));}else dims = names = R_NilValue;switch (TYPEOF(x)) {case LGLSXP:case INTSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = (INTEGER(x)[i] == NA_INTEGER);break;case REALSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = ISNAN(REAL(x)[i]);break;case CPLXSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = (ISNAN(COMPLEX(x)[i].r) ||ISNAN(COMPLEX(x)[i].i));break;case STRSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = (STRING_ELT(x, i) == NA_STRING);break;/* Same code for LISTSXP and VECSXP : */#define LIST_VEC_NA(s) \if (!isVector(s) || length(s) > 1) \LOGICAL(ans)[i] = 0; \else { \switch (TYPEOF(s)) { \case LGLSXP: \case INTSXP: \LOGICAL(ans)[i] = (INTEGER(s)[0] == NA_INTEGER); \break; \case REALSXP: \LOGICAL(ans)[i] = ISNAN(REAL(s)[0]); \break; \case STRSXP: \LOGICAL(ans)[i] = (STRING_ELT(s, 0) == NA_STRING); \break; \case CPLXSXP: \LOGICAL(ans)[i] = (ISNAN(COMPLEX(s)[0].r) \|| ISNAN(COMPLEX(s)[0].i)); \break; \} \}case LISTSXP:for (i = 0; i < n; i++) {LIST_VEC_NA(CAR(x));x = CDR(x);}break;case VECSXP:for (i = 0; i < n; i++) {SEXP s = VECTOR_ELT(x, i);LIST_VEC_NA(s);}break;default:warningcall(call, "is.na" R_MSG_list_vec2);for (i = 0; i < n; i++)LOGICAL(ans)[i] = 0;}if (dims != R_NilValue)setAttrib(ans, R_DimSymbol, dims);if (names != R_NilValue) {if (isArray(x))setAttrib(ans, R_DimNamesSymbol, names);elsesetAttrib(ans, R_NamesSymbol, names);}if (isVector(x))UNPROTECT(2);UNPROTECT(1);return ans;}SEXP do_isnan(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP ans, dims, names, x;int i, n;if (DispatchOrEval(call, op, args, rho, &ans, 1))return(ans);PROTECT(args = ans);checkArity(op, args);#ifdef stringent_isif (!isList(CAR(args)) && !isVector(CAR(args)))errorcall_return(call, "is.nan " R_MSG_list_vec);#endifx = CAR(args);n = length(x);ans = allocVector(LGLSXP, n);if (isVector(x)) {PROTECT(dims = getAttrib(x, R_DimSymbol));if (isArray(x))PROTECT(names = getAttrib(x, R_DimNamesSymbol));elsePROTECT(names = getAttrib(x, R_NamesSymbol));}else dims = names = R_NilValue;switch (TYPEOF(x)) {case LGLSXP:case INTSXP:case STRSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = 0;break;case REALSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = R_IsNaN(REAL(x)[i]);break;case CPLXSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = (R_IsNaN(COMPLEX(x)[i].r) ||R_IsNaN(COMPLEX(x)[i].i));break;/* Same code for LISTSXP and VECSXP : */#define LIST_VEC_NAN(s) \if (!isVector(s) || length(s) > 1) \LOGICAL(ans)[i] = 0; \else { \switch (TYPEOF(s)) { \case LGLSXP: \case INTSXP: \case STRSXP: \LOGICAL(ans)[i] = 0; \break; \case REALSXP: \LOGICAL(ans)[i] = R_IsNaN(REAL(s)[0]); \break; \case CPLXSXP: \LOGICAL(ans)[i] = (R_IsNaN(COMPLEX(s)[0].r) || \R_IsNaN(COMPLEX(s)[0].i)); \break; \} \}case LISTSXP:for (i = 0; i < n; i++) {LIST_VEC_NAN(CAR(x));x = CDR(x);}break;case VECSXP:for (i = 0; i < n; i++) {SEXP s = VECTOR_ELT(x, i);LIST_VEC_NAN(s);}break;default:warningcall(call, "is.nan" R_MSG_list_vec2);for (i = 0; i < n; i++)LOGICAL(ans)[i] = 0;}if (dims != R_NilValue)setAttrib(ans, R_DimSymbol, dims);if (names != R_NilValue) {if (isArray(x))setAttrib(ans, R_DimNamesSymbol, names);elsesetAttrib(ans, R_NamesSymbol, names);}if (isVector(x))UNPROTECT(2);UNPROTECT(1);return ans;}SEXP do_isfinite(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP ans, x, names, dims;int i, n;checkArity(op, args);#ifdef stringent_isif (!isList(CAR(args)) && !isVector(CAR(args)))errorcall_return(call, "is.finite " R_MSG_list_vec);#endifx = CAR(args);n = length(x);ans = allocVector(LGLSXP, n);if (isVector(x)) {dims = getAttrib(x, R_DimSymbol);if (isArray(x))names = getAttrib(x, R_DimNamesSymbol);elsenames = getAttrib(x, R_NamesSymbol);}else dims = names = R_NilValue;switch (TYPEOF(x)) {case LGLSXP:case INTSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = (INTEGER(x)[i] != NA_INTEGER);break;case REALSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = R_FINITE(REAL(x)[i]);break;case CPLXSXP:for (i = 0; i < n; i++)LOGICAL(ans)[i] = (R_FINITE(COMPLEX(x)[i].r) && R_FINITE(COMPLEX(x)[i].i));break;default:for (i = 0; i < n; i++)LOGICAL(ans)[i] = 0;}if (dims != R_NilValue)setAttrib(ans, R_DimSymbol, dims);if (names != R_NilValue) {if (isArray(x))setAttrib(ans, R_DimNamesSymbol, names);elsesetAttrib(ans, R_NamesSymbol, names);}return ans;}SEXP do_isinfinite(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP ans, x, names, dims;double xr, xi;int i, n;checkArity(op, args);#ifdef stringent_isif (!isList(CAR(args)) && !isVector(CAR(args)))errorcall_return(call, "is.infinite " R_MSG_list_vec);#endifx = CAR(args);n = length(x);ans = allocVector(LGLSXP, n);if (isVector(x)) {dims = getAttrib(x, R_DimSymbol);if (isArray(x))names = getAttrib(x, R_DimNamesSymbol);elsenames = getAttrib(x, R_NamesSymbol);}else dims = names = R_NilValue;switch (TYPEOF(x)) {case REALSXP:for (i = 0; i < n; i++) {xr = REAL(x)[i];if (ISNAN(xr) || R_FINITE(xr))LOGICAL(ans)[i] = 0;elseLOGICAL(ans)[i] = 1;}break;case CPLXSXP:for (i = 0; i < n; i++) {xr = COMPLEX(x)[i].r;xi = COMPLEX(x)[i].i;if ((ISNAN(xr) || R_FINITE(xr)) && (ISNAN(xi) || R_FINITE(xi)))LOGICAL(ans)[i] = 0;elseLOGICAL(ans)[i] = 1;}break;default:for (i = 0; i < n; i++)LOGICAL(ans)[i] = 0;}if (!isNull(dims))setAttrib(ans, R_DimSymbol, dims);if (!isNull(names)) {if (isArray(x))setAttrib(ans, R_DimNamesSymbol, names);elsesetAttrib(ans, R_NamesSymbol, names);}return ans;}SEXP do_call(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP rest, evargs, rfun;PROTECT(rfun = eval(CAR(args), rho));if (!isString(rfun) || length(rfun) <= 0 ||streql(CHAR(STRING_ELT(rfun, 0)), ""))errorcall_return(call, R_MSG_A1_char);PROTECT(rfun = install(CHAR(STRING_ELT(rfun, 0))));PROTECT(evargs = duplicate(CDR(args)));for (rest = evargs; rest != R_NilValue; rest = CDR(rest))SETCAR(rest, eval(CAR(rest), rho));rfun = LCONS(rfun, evargs);UNPROTECT(3);return (rfun);}SEXP do_docall(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP c, fun, names;int i, n;checkArity(op, args);fun = CAR(args);args = CADR(args);if (!isString(fun) || length(fun) <= 0 || CHAR(STRING_ELT(fun, 0)) == '\0')errorcall_return(call, R_MSG_A1_char);if (!isNull(args) && !isNewList(args))errorcall_return(call, R_MSG_A2_list);n = length(args);names = getAttrib(args, R_NamesSymbol);PROTECT(c = call = allocList(n + 1));SET_TYPEOF(c, LANGSXP);SETCAR(c, install(CHAR(STRING_ELT(fun, 0))));c = CDR(c);for (i = 0; i < n; i++) {#ifndef NEWSETCAR(c, VECTOR_ELT(args, i));#elseSETCAR(c, mkPROMISE(VECTOR_ELT(args, i), rho));SET_PRVALUE(CAR(c), VECTOR_ELT(args, i));#endifif (ItemName(names, i) != R_NilValue)SET_TAG(c, install(CHAR(ItemName(names, i))));c = CDR(c);}call = eval(call, rho);UNPROTECT(1);return call;}/* do_substitute has two arguments, an expression and an environment *//* (optional). Symbols found in the expression are substituted with their *//* values as found in the environment. There is no inheritance so only *//* the supplied environment is searched. If no environment is specified *//* the environment in which substitute was called is used. If the *//* specified environment is R_NilValue then R_GlobalEnv is used. *//* Arguments to do_substitute should not be evaluated. */SEXP substitute(SEXP lang, SEXP rho){SEXP t;switch (TYPEOF(lang)) {case PROMSXP:return substitute(PREXPR(lang), rho);case SYMSXP:t = findVarInFrame( rho, lang);if (t != R_UnboundValue) {if (TYPEOF(t) == PROMSXP) {do {t = PREXPR(t);}while(TYPEOF(t) == PROMSXP);return t;#ifdef OLDreturn substitute(PREXPR(t), rho);return PREXPR(t);#endif}else if (TYPEOF(t) == DOTSXP) {error("... used in an incorrect context");}if (rho != R_GlobalEnv)return t;}return (lang);case LANGSXP:return substituteList(lang, rho);default:return (lang);}}/* Work through a list doing substitute on the *//* elements taking particular care to handle ... */SEXP substituteList(SEXP el, SEXP rho){SEXP h, t;if (isNull(el))return el;if (CAR(el) == R_DotsSymbol) {h = findVar(CAR(el), rho);if (h == R_NilValue)return substituteList(CDR(el), rho);if (TYPEOF(h) != DOTSXP) {if (h == R_MissingArg)return substituteList(CDR(el), rho);error("... used in an incorrect context");}PROTECT(h = substituteList(h, R_NilValue));PROTECT(t = substituteList(CDR(el), rho));t = listAppend(h, t);UNPROTECT(2);return t;}#ifdef OLDelse if (CAR(el) == R_MissingArg) {return substituteList(CDR(el), rho);}#endifelse {PROTECT(h = substitute(CAR(el), rho));PROTECT(t = substituteList(CDR(el), rho));if (isLanguage(el))t = LCONS(h, t);elset = CONS(h, t);SET_TAG(t, TAG(el));UNPROTECT(2);return t;}}SEXP do_substitute(SEXP call, SEXP op, SEXP args, SEXP rho){SEXP env, s, t;/* set up the environment for substitution */if (length(args) == 1)env = rho;elseenv = eval(CADR(args), rho);if (env == R_NilValue)env = R_GlobalEnv;if (TYPEOF(env) == VECSXP)env = VectorToPairList(env);if (TYPEOF(env) == LISTSXP) {PROTECT(s = duplicate(env));PROTECT(env = allocSExp(ENVSXP));SET_FRAME(env, s);UNPROTECT(2);}if (TYPEOF(env) != ENVSXP)errorcall(call, "invalid environment specified");PROTECT(env);PROTECT(t = duplicate(args));SETCDR(t, R_NilValue);s = substituteList(t, env);UNPROTECT(2);return CAR(s);}