Rev 39103 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka* Copyright (C) 1999-2006 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*//* this header is always to be included from others.It is only called if COMPILING_R is defined (in util.c) orfrom GNU C systems.There are different comventions for inlining across compilation units.We pro tem only use the GCC one. Seehttp://www.greenend.org.uk/rjk/2003/03/inline.html*/#ifndef R_INLINES_H_#define R_INLINES_H_#ifndef COMPILING_R /* defined only in util.c */# define INLINE_FUN extern R_INLINE#else# define INLINE_FUN#endif/* define inline-able functions *//* from dstruct.c *//* mkChar - make a character (CHARSXP) variable */INLINE_FUN SEXP mkChar(const char *name){SEXP c = allocString(strlen(name));strcpy(CHAR(c), name);return c;}/* length - length of objects */int Rf_envlength(SEXP rho);INLINE_FUN R_len_t length(SEXP s){int i;switch (TYPEOF(s)) {case NILSXP:return 0;case LGLSXP:case INTSXP:case REALSXP:case CPLXSXP:case STRSXP:case CHARSXP:case VECSXP:case EXPRSXP:case RAWSXP:return LENGTH(s);case LISTSXP:case LANGSXP:case DOTSXP:i = 0;while (s != NULL && s != R_NilValue) {i++;s = CDR(s);}return i;case ENVSXP:return Rf_envlength(s);default:return 1;}}/* from list.c *//* Return a dotted pair with the given CAR and CDR. *//* The (R) TAG slot on the cell is set to NULL. *//* Get the i-th element of a list */INLINE_FUN SEXP elt(SEXP list, int i){int j;SEXP result = list;if ((i < 0) || (i > length(list)))return R_NilValue;elsefor (j = 0; j < i; j++)result = CDR(result);return CAR(result);}/* Return the last element of a list */INLINE_FUN SEXP lastElt(SEXP list){SEXP result = R_NilValue;while (list != R_NilValue) {result = list;list = CDR(list);}return result;}/* Shorthands for creating small lists */INLINE_FUN SEXP list1(SEXP s){return CONS(s, R_NilValue);}INLINE_FUN SEXP list2(SEXP s, SEXP t){PROTECT(s);s = CONS(s, list1(t));UNPROTECT(1);return s;}INLINE_FUN SEXP list3(SEXP s, SEXP t, SEXP u){PROTECT(s);s = CONS(s, list2(t, u));UNPROTECT(1);return s;}INLINE_FUN SEXP list4(SEXP s, SEXP t, SEXP u, SEXP v){PROTECT(s);s = CONS(s, list3(t, u, v));UNPROTECT(1);return s;}/* Destructive list append : See also ``append'' */INLINE_FUN SEXP listAppend(SEXP s, SEXP t){SEXP r;if (s == R_NilValue)return t;r = s;while (CDR(r) != R_NilValue)r = CDR(r);SETCDR(r, t);return s;}/* Language based list constructs. These are identical to the list *//* constructs, but the results can be evaluated. *//* Return a (language) dotted pair with the given car and cdr */INLINE_FUN SEXP lcons(SEXP car, SEXP cdr){SEXP e = cons(car, cdr);SET_TYPEOF(e, LANGSXP);return e;}INLINE_FUN SEXP lang1(SEXP s){return LCONS(s, R_NilValue);}INLINE_FUN SEXP lang2(SEXP s, SEXP t){PROTECT(s);s = LCONS(s, list1(t));UNPROTECT(1);return s;}INLINE_FUN SEXP lang3(SEXP s, SEXP t, SEXP u){PROTECT(s);s = LCONS(s, list2(t, u));UNPROTECT(1);return s;}INLINE_FUN SEXP lang4(SEXP s, SEXP t, SEXP u, SEXP v){PROTECT(s);s = LCONS(s, list3(t, u, v));UNPROTECT(1);return s;}/* from util.c *//* Check to see if the arrays "x" and "y" have the identical extents */INLINE_FUN Rboolean conformable(SEXP x, SEXP y){int i, n;PROTECT(x = getAttrib(x, R_DimSymbol));y = getAttrib(y, R_DimSymbol);UNPROTECT(1);if ((n = length(x)) != length(y))return FALSE;for (i = 0; i < n; i++)if (INTEGER(x)[i] != INTEGER(y)[i])return FALSE;return TRUE;}INLINE_FUN Rboolean isString(SEXP s){return (TYPEOF(s) == STRSXP);}INLINE_FUN Rboolean isNull(SEXP s){return (s == R_NilValue);}INLINE_FUN Rboolean isObject(SEXP s){return OBJECT(s);/* really '1-bit unsigned int' */}/* The following should work but as of 06/09/04 it generates warnings aboutundeclared IS_S4_OBJECT, in spite of being apparently identical to the handlingof isObject() above ------INLINE_FUN Rboolean isS4(SEXP s){return IS_S4_OBJECT(s);}INLINE_FUN SEXP asS4(SEXP s, Rboolean flag){if(flag == IS_S4_OBJECT(s))return s;if(NAMED(s) == 2)s = duplicate(s);if(flag) SET_S4_OBJECT(s);else UNSET_S4_OBJECT(s);return s;}*/INLINE_FUN Rboolean inherits(SEXP s, char *name){SEXP class;int i, nclass;if (isObject(s)) {class = getAttrib(s, R_ClassSymbol);nclass = length(class);for (i = 0; i < nclass; i++) {if (!strcmp(CHAR(STRING_ELT(class, i)), name))return TRUE;}}return FALSE;}INLINE_FUN Rboolean isValidString(SEXP x){return isString(x) && LENGTH(x) > 0 && !isNull(STRING_ELT(x, 0));}/* non-empty ("") valid string :*/INLINE_FUN Rboolean isValidStringF(SEXP x){return isValidString(x) && CHAR(STRING_ELT(x, 0))[0];}INLINE_FUN Rboolean isSymbol(SEXP s){return TYPEOF(s) == SYMSXP;}INLINE_FUN Rboolean isUserBinop(SEXP s){if (isSymbol(s)) {char *str = CHAR(PRINTNAME(s));if (strlen(str) >= 2 && str[0] == '%' && str[strlen(str)-1] == '%')return TRUE;}return FALSE;}INLINE_FUN Rboolean isFunction(SEXP s){return (TYPEOF(s) == CLOSXP ||TYPEOF(s) == BUILTINSXP ||TYPEOF(s) == SPECIALSXP);}INLINE_FUN Rboolean isPrimitive(SEXP s){return (TYPEOF(s) == BUILTINSXP ||TYPEOF(s) == SPECIALSXP);}INLINE_FUN Rboolean isList(SEXP s){return (s == R_NilValue || TYPEOF(s) == LISTSXP);}INLINE_FUN Rboolean isNewList(SEXP s){return (s == R_NilValue || TYPEOF(s) == VECSXP);}INLINE_FUN Rboolean isPairList(SEXP s){switch (TYPEOF(s)) {case NILSXP:case LISTSXP:case LANGSXP:return TRUE;default:return FALSE;}}INLINE_FUN Rboolean isVectorList(SEXP s){switch (TYPEOF(s)) {case VECSXP:case EXPRSXP:return TRUE;default:return FALSE;}}INLINE_FUN Rboolean isVectorAtomic(SEXP s){switch (TYPEOF(s)) {case LGLSXP:case INTSXP:case REALSXP:case CPLXSXP:case STRSXP:case RAWSXP:return TRUE;default: /* including NULL */return FALSE;}}INLINE_FUN Rboolean isVector(SEXP s)/* === isVectorList() or isVectorAtomic() */{switch(TYPEOF(s)) {case LGLSXP:case INTSXP:case REALSXP:case CPLXSXP:case STRSXP:case RAWSXP:case VECSXP:case EXPRSXP:return TRUE;default:return FALSE;}}INLINE_FUN Rboolean isFrame(SEXP s){SEXP class;int i;if (isObject(s)) {class = getAttrib(s, R_ClassSymbol);for (i = 0; i < length(class); i++)if (!strcmp(CHAR(STRING_ELT(class, i)), "data.frame")) return TRUE;}return FALSE;}INLINE_FUN Rboolean isExpression(SEXP s){return TYPEOF(s) == EXPRSXP;}INLINE_FUN Rboolean isLanguage(SEXP s){return (s == R_NilValue || TYPEOF(s) == LANGSXP);}INLINE_FUN Rboolean isMatrix(SEXP s){SEXP t;if (isVector(s)) {t = getAttrib(s, R_DimSymbol);if (TYPEOF(t) == INTSXP && LENGTH(t) == 2)return TRUE;}return FALSE;}INLINE_FUN Rboolean isArray(SEXP s){SEXP t;if (isVector(s)) {t = getAttrib(s, R_DimSymbol);if (TYPEOF(t) == INTSXP && LENGTH(t) > 0)return TRUE;}return FALSE;}INLINE_FUN Rboolean isTs(SEXP s){return (isVector(s) && getAttrib(s, R_TspSymbol) != R_NilValue);}INLINE_FUN Rboolean isLogical(SEXP s){return (TYPEOF(s) == LGLSXP);}INLINE_FUN Rboolean isInteger(SEXP s){return (TYPEOF(s) == INTSXP && !inherits(s, "factor"));}INLINE_FUN Rboolean isReal(SEXP s){return (TYPEOF(s) == REALSXP);}INLINE_FUN Rboolean isComplex(SEXP s){return (TYPEOF(s) == CPLXSXP);}INLINE_FUN Rboolean isUnordered(SEXP s){return (TYPEOF(s) == INTSXP&& inherits(s, "factor")&& !inherits(s, "ordered"));}INLINE_FUN Rboolean isOrdered(SEXP s){return (TYPEOF(s) == INTSXP&& inherits(s, "factor")&& inherits(s, "ordered"));}INLINE_FUN Rboolean isFactor(SEXP s){return (TYPEOF(s) == INTSXP && inherits(s, "factor"));}INLINE_FUN Rboolean isEnvironment(SEXP s){return (TYPEOF(s) == ENVSXP);}INLINE_FUN int nlevels(SEXP f){if (!isFactor(f))return 0;return LENGTH(getAttrib(f, R_LevelsSymbol));}/* Is an object of numeric type. *//* FIXME: the LGLSXP case should be excluded here* (really? in many places we affirm they are treated like INTs)*/INLINE_FUN Rboolean isNumeric(SEXP s){switch(TYPEOF(s)) {case INTSXP:if (inherits(s,"factor")) return FALSE;case LGLSXP:case REALSXP:return TRUE;default:return FALSE;}}/* As from R 2.4.0 we check that the value is allowed. */INLINE_FUN SEXP ScalarLogical(int x){SEXP ans = allocVector(LGLSXP, 1);if (x == NA_LOGICAL) LOGICAL(ans)[0] = NA_LOGICAL;else LOGICAL(ans)[0] = (x != 0);return ans;}INLINE_FUN SEXP ScalarInteger(int x){SEXP ans = allocVector(INTSXP, 1);INTEGER(ans)[0] = x;return ans;}INLINE_FUN SEXP ScalarReal(double x){SEXP ans = allocVector(REALSXP, 1);REAL(ans)[0] = x;return ans;}INLINE_FUN SEXP ScalarComplex(Rcomplex x){SEXP ans = allocVector(CPLXSXP, 1);COMPLEX(ans)[0] = x;return ans;}INLINE_FUN SEXP ScalarString(SEXP x){SEXP ans;PROTECT(x);ans = allocVector(STRSXP, 1);SET_STRING_ELT(ans, 0, x);UNPROTECT(1);return ans;}INLINE_FUN SEXP ScalarRaw(Rbyte x){SEXP ans = allocVector(RAWSXP, 1);RAW(ans)[0] = x;return ans;}/* Check to see if a list can be made into a vector. *//* it must have every element being a vector of length 1. *//* BUT it does not exclude 0! */INLINE_FUN Rboolean isVectorizable(SEXP s){if (isNull(s)) return TRUE;else if (isNewList(s)) {int i, n;n = LENGTH(s);for (i = 0 ; i < n; i++)if (!isVector(VECTOR_ELT(s, i)) || LENGTH(VECTOR_ELT(s, i)) > 1)return FALSE;return TRUE;}else if (isList(s)) {for ( ; s != R_NilValue; s = CDR(s))if (!isVector(CAR(s)) || LENGTH(CAR(s)) > 1) return FALSE;return TRUE;}else return FALSE;}/* from gram.y */INLINE_FUN SEXP mkString(const char *s){SEXP t;PROTECT(t = allocVector(STRSXP, 1));SET_STRING_ELT(t, 0, mkChar(s));UNPROTECT(1);return t;}/* from Rmath */#define Rf_fmin2(x, y) fmin2_int(x, y)#define Rf_fmax2(x, y) fmax2_int(x, y)#define Rf_imin2(x, y) imin2_int(x, y)#define Rf_imax2(x, y) imax2_int(x, y)#define Rf_fsign(x, y) fsign_int(x, y)INLINE_FUN double fmin2_int(double x, double y){if (ISNAN(x) || ISNAN(y))return x + y;return (x < y) ? x : y;}INLINE_FUN double fmax2_int(double x, double y){if (ISNAN(x) || ISNAN(y))return x + y;return (x < y) ? y : x;}INLINE_FUN int imin2_int(int x, int y){return (x < y) ? x : y;}INLINE_FUN int imax2_int(int x, int y){return (x < y) ? y : x;}INLINE_FUN double fsign_int(double x, double y){if (ISNAN(x) || ISNAN(y))return x + y;return ((y >= 0) ? fabs(x) : -fabs(x));}#endif /* R_INLINES_H_ */