Rev 81076 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* Copyright (C) 1997--2021 The R Core Team* 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, a copy is available at* https://www.R-project.org/Licenses/*/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <Defn.h>#include <Internal.h>#include <Rmath.h>#include <errno.h>#include <R_ext/Itermacros.h>/* interval at which to check interrupts, a guess */#define NINTERRUPT 10000000static SEXP numeric_relop(RELOP_TYPE code, SEXP s1, SEXP s2);static SEXP complex_relop(RELOP_TYPE code, SEXP s1, SEXP s2, SEXP call);static SEXP string_relop (RELOP_TYPE code, SEXP s1, SEXP s2);static SEXP raw_relop (RELOP_TYPE code, SEXP s1, SEXP s2);#define DO_SCALAR_RELOP(oper, x, y) do { \switch (oper) { \case EQOP: return ScalarLogical((x) == (y)); \case NEOP: return ScalarLogical((x) != (y)); \case LTOP: return ScalarLogical((x) < (y)); \case GTOP: return ScalarLogical((x) > (y)); \case LEOP: return ScalarLogical((x) <= (y)); \case GEOP: return ScalarLogical((x) >= (y)); \} \} while (0)SEXP attribute_hidden do_relop(SEXP call, SEXP op, SEXP args, SEXP env){SEXP ans, arg1, arg2;int argc;if (args != R_NilValue &&CDR(args) != R_NilValue &&CDDR(args) == R_NilValue)argc = 2;elseargc = length(args);arg1 = CAR(args);arg2 = CADR(args);if (ATTRIB(arg1) != R_NilValue || ATTRIB(arg2) != R_NilValue) {if (DispatchGroup("Ops", call, op, args, env, &ans))return ans;}if (argc != 2)error("operator needs two arguments");return do_relop_dflt(call, op, arg1, arg2);}// also called from cmp_relop() in eval.c :SEXP attribute_hidden do_relop_dflt(SEXP call, SEXP op, SEXP x, SEXP y){/* handle the REALSXP/INTSXP simple scalar case quickly */if (IS_SIMPLE_SCALAR(x, INTSXP)) {int ix = SCALAR_IVAL(x);if (IS_SIMPLE_SCALAR(y, INTSXP)) {int iy = SCALAR_IVAL(y);if (ix == NA_INTEGER || iy == NA_INTEGER)return ScalarLogical(NA_LOGICAL);DO_SCALAR_RELOP(PRIMVAL(op), ix, iy);}else if (IS_SIMPLE_SCALAR(y, REALSXP)) {double dy = SCALAR_DVAL(y);if (ix == NA_INTEGER || ISNAN(dy))return ScalarLogical(NA_LOGICAL);DO_SCALAR_RELOP(PRIMVAL(op), ix, dy);}}else if (IS_SIMPLE_SCALAR(x, REALSXP)) {double dx = SCALAR_DVAL(x);if (IS_SIMPLE_SCALAR(y, INTSXP)) {int iy = SCALAR_IVAL(y);if (ISNAN(dx) || iy == NA_INTEGER)return ScalarLogical(NA_LOGICAL);DO_SCALAR_RELOP(PRIMVAL(op), dx, iy);}else if (IS_SIMPLE_SCALAR(y, REALSXP)) {double dy = SCALAR_DVAL(y);if (ISNAN(dx) || ISNAN(dy))return ScalarLogical(NA_LOGICAL);DO_SCALAR_RELOP(PRIMVAL(op), dx, dy);}}R_xlen_tnx = xlength(x),ny = xlength(y);SEXPTYPEtypex = TYPEOF(x),typey = TYPEOF(y);/* handle the REALSXP/INTSXP simple vector/scalar case quickly. */if (ATTRIB(x) == R_NilValue && ATTRIB(y) == R_NilValue &&(typex == REALSXP || typex == INTSXP) &&(typey == REALSXP || typey == INTSXP) &&nx > 0 && ny > 0 && (nx == 1 || ny == 1)) {PROTECT(x);PROTECT(y);SEXP ans;ans = numeric_relop(PRIMVAL(op), x, y);UNPROTECT(2);return ans;}/* handle the general case */PROTECT_INDEX xpi, ypi;PROTECT_WITH_INDEX(x, &xpi);PROTECT_WITH_INDEX(y, &ypi);Rboolean iS;/* That symbols and calls were allowed was undocumented prior toR 2.5.0. We deparse them as deparse() would, minus attributes */if ((iS = isSymbol(x)) || TYPEOF(x) == LANGSXP) {SEXP tmp = allocVector(STRSXP, 1);PROTECT(tmp);SET_STRING_ELT(tmp, 0, (iS) ? PRINTNAME(x) :STRING_ELT(deparse1(x, 0, DEFAULTDEPARSE), 0));REPROTECT(x = tmp, xpi);nx = xlength(x);UNPROTECT(1);}if ((iS = isSymbol(y)) || TYPEOF(y) == LANGSXP) {SEXP tmp = allocVector(STRSXP, 1);PROTECT(tmp);SET_STRING_ELT(tmp, 0, (iS) ? PRINTNAME(y) :STRING_ELT(deparse1(y, 0, DEFAULTDEPARSE), 0));REPROTECT(y = tmp, ypi);ny = xlength(y);UNPROTECT(1);}if (isNull(x)) REPROTECT(x = allocVector(INTSXP,0), xpi);if (isNull(y)) REPROTECT(y = allocVector(INTSXP,0), ypi);if (!isVector(x) || !isVector(y))errorcall(call,_("comparison (%d) is possible only for atomic and list types"),PRIMVAL(op));if (TYPEOF(x) == EXPRSXP || TYPEOF(y) == EXPRSXP)errorcall(call, _("comparison is not allowed for expressions"));/* ELSE : x and y are both atomic or list */Rbooleanxarray = isArray(x),yarray = isArray(y),xts = isTs(x),yts = isTs(y);SEXP dims, xnames, ynames;if (xarray || yarray) {if (xarray && yarray) {if (!conformable(x, y))errorcall(call, _("non-conformable arrays"));PROTECT(dims = getAttrib(x, R_DimSymbol));}else if (xarray && (ny != 0 || nx == 0)) {PROTECT(dims = getAttrib(x, R_DimSymbol));}else if (yarray && (nx != 0 || ny == 0)) {PROTECT(dims = getAttrib(y, R_DimSymbol));} elsePROTECT(dims = R_NilValue);PROTECT(xnames = getAttrib(x, R_DimNamesSymbol));PROTECT(ynames = getAttrib(y, R_DimNamesSymbol));}else {PROTECT(dims = R_NilValue);PROTECT(xnames = getAttrib(x, R_NamesSymbol));PROTECT(ynames = getAttrib(y, R_NamesSymbol));}SEXP klass = NULL, tsp = NULL; // -Wallif (xts || yts) {if (xts && yts) {/* could check ts conformance here */PROTECT(tsp = getAttrib(x, R_TspSymbol));PROTECT(klass = getAttrib(x, R_ClassSymbol));}else if (xts) {if (xlength(x) < xlength(y))ErrorMessage(call, ERROR_TSVEC_MISMATCH);PROTECT(tsp = getAttrib(x, R_TspSymbol));PROTECT(klass = getAttrib(x, R_ClassSymbol));}else /*(yts)*/ {if (xlength(y) < xlength(x))ErrorMessage(call, ERROR_TSVEC_MISMATCH);PROTECT(tsp = getAttrib(y, R_TspSymbol));PROTECT(klass = getAttrib(y, R_ClassSymbol));}}if (nx > 0 && ny > 0) {if(((nx > ny) ? nx % ny : ny % nx) != 0) // mismatchwarningcall(call, _("longer object length is not a multiple of shorter object length"));if (isString(x) || isString(y)) {REPROTECT(x = coerceVector(x, STRSXP), xpi);REPROTECT(y = coerceVector(y, STRSXP), ypi);x = string_relop((RELOP_TYPE) PRIMVAL(op), x, y);}else if (isComplex(x) || isComplex(y)) {REPROTECT(x = coerceVector(x, CPLXSXP), xpi);REPROTECT(y = coerceVector(y, CPLXSXP), ypi);x = complex_relop((RELOP_TYPE) PRIMVAL(op), x, y, call);}else if ((isNumeric(x) || isLogical(x)) && (isNumeric(y) || isLogical(y))) {x = numeric_relop((RELOP_TYPE) PRIMVAL(op), x, y);} // rest of cases only apply when 'x' or 'y' is rawelse if (isReal(x) || isReal(y)) {REPROTECT(x = coerceVector(x, REALSXP), xpi);REPROTECT(y = coerceVector(y, REALSXP), ypi);x = numeric_relop((RELOP_TYPE) PRIMVAL(op), x, y);}else if (isInteger(x) || isInteger(y)) {REPROTECT(x = coerceVector(x, INTSXP), xpi);REPROTECT(y = coerceVector(y, INTSXP), ypi);x = numeric_relop((RELOP_TYPE) PRIMVAL(op), x, y);}else if (isLogical(x) || isLogical(y)) {REPROTECT(x = coerceVector(x, LGLSXP), xpi);REPROTECT(y = coerceVector(y, LGLSXP), ypi);x = numeric_relop((RELOP_TYPE) PRIMVAL(op), x, y);}else if (TYPEOF(x) == RAWSXP || TYPEOF(y) == RAWSXP) {REPROTECT(x = coerceVector(x, RAWSXP), xpi);REPROTECT(y = coerceVector(y, RAWSXP), ypi);x = raw_relop((RELOP_TYPE) PRIMVAL(op), x, y);} else errorcall(call, _("comparison of these types is not implemented"));} else { // nx == 0 || ny == 0x = allocVector(LGLSXP, 0);}PROTECT(x);if (dims != R_NilValue) {setAttrib(x, R_DimSymbol, dims);if (xnames != R_NilValue)setAttrib(x, R_DimNamesSymbol, xnames);else if (ynames != R_NilValue)setAttrib(x, R_DimNamesSymbol, ynames);}else {if (xnames != R_NilValue && xlength(x) == xlength(xnames))setAttrib(x, R_NamesSymbol, xnames);else if (ynames != R_NilValue && xlength(x) == xlength(ynames))setAttrib(x, R_NamesSymbol, ynames);}if (xts || yts) {setAttrib(x, R_TspSymbol, tsp);setAttrib(x, R_ClassSymbol, klass);UNPROTECT(2);}UNPROTECT(6);return x;}#define ISNA_INT(x) x == NA_INTEGER#define NR_HELPER(OP, type1, ACCESSOR1, ISNA1, type2, ACCESSOR2, ISNA2) do { \type1 x1, *px1 = ACCESSOR1(s1); \type2 x2, *px2 = ACCESSOR2(s2); \int *pa = LOGICAL(ans); \MOD_ITERATE2(n, n1, n2, i, i1, i2, { \x1 = px1[i1]; \x2 = px2[i2]; \if (ISNA1(x1) || ISNA2(x2)) \pa[i] = NA_LOGICAL; \else \pa[i] = (x1 OP x2); \}); \} while (0)#define NUMERIC_RELOP(type1, ACCESSOR1, ISNA1, type2, ACCESSOR2, ISNA2) do { \switch (code) { \case EQOP: \NR_HELPER(==, type1, ACCESSOR1, ISNA1, type2, ACCESSOR2, ISNA2); \break; \case NEOP: \NR_HELPER(!=, type1, ACCESSOR1, ISNA1, type2, ACCESSOR2, ISNA2); \break; \case LTOP: \NR_HELPER(<, type1, ACCESSOR1, ISNA1, type2, ACCESSOR2, ISNA2); \break; \case GTOP: \NR_HELPER(>, type1, ACCESSOR1, ISNA1, type2, ACCESSOR2, ISNA2); \break; \case LEOP: \NR_HELPER(<=, type1, ACCESSOR1, ISNA1, type2, ACCESSOR2, ISNA2); \break; \case GEOP: \NR_HELPER(>=, type1, ACCESSOR1, ISNA1, type2, ACCESSOR2, ISNA2); \break; \} \} while(0)static SEXP numeric_relop(RELOP_TYPE code, SEXP s1, SEXP s2){R_xlen_t i, i1, i2, n, n1, n2;SEXP ans;n1 = XLENGTH(s1);n2 = XLENGTH(s2);n = (n1 > n2) ? n1 : n2;PROTECT(s1);PROTECT(s2);ans = allocVector(LGLSXP, n);if (isInteger(s1) || isLogical(s1)) {if (isInteger(s2) || isLogical(s2)) {NUMERIC_RELOP(int, INTEGER, ISNA_INT, int, INTEGER, ISNA_INT);} else {NUMERIC_RELOP(int, INTEGER, ISNA_INT, double, REAL, ISNAN);}} else if (isInteger(s2) || isLogical(s2)) {NUMERIC_RELOP(double, REAL, ISNAN, int, INTEGER, ISNA_INT);} else {NUMERIC_RELOP(double, REAL, ISNAN, double, REAL, ISNAN);}UNPROTECT(2);return ans;}static SEXP complex_relop(RELOP_TYPE code, SEXP s1, SEXP s2, SEXP call){R_xlen_t i, i1, i2, n, n1, n2;Rcomplex x1, x2;SEXP ans;if (code != EQOP && code != NEOP) {errorcall(call, _("invalid comparison with complex values"));}n1 = XLENGTH(s1);n2 = XLENGTH(s2);n = (n1 > n2) ? n1 : n2;PROTECT(s1);PROTECT(s2);ans = allocVector(LGLSXP, n);const Rcomplex *px1 = COMPLEX_RO(s1);const Rcomplex *px2 = COMPLEX_RO(s2);int *pa = LOGICAL(ans);switch (code) {case EQOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();x1 = px1[i1];x2 = px2[i2];if (ISNAN(x1.r) || ISNAN(x1.i) ||ISNAN(x2.r) || ISNAN(x2.i))pa[i] = NA_LOGICAL;elsepa[i] = (x1.r == x2.r && x1.i == x2.i);});break;case NEOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();x1 = px1[i1];x2 = px2[i2];if (ISNAN(x1.r) || ISNAN(x1.i) ||ISNAN(x2.r) || ISNAN(x2.i))pa[i] = NA_LOGICAL;elsepa[i] = (x1.r != x2.r || x1.i != x2.i);});break;default:/* never happens (-Wall) */break;}UNPROTECT(2);return ans;}/* POSIX allows EINVAL when one of the strings contains charactersoutside the collation domain. */static SEXP string_relop(RELOP_TYPE code, SEXP s1, SEXP s2){R_xlen_t i, n, n1, n2, res, i1, i2;SEXP ans, c1, c2;const void *vmax = vmaxget(); // for Scollaten1 = XLENGTH(s1);n2 = XLENGTH(s2);n = (n1 > n2) ? n1 : n2;PROTECT(s1);PROTECT(s2);PROTECT(ans = allocVector(LGLSXP, n));int *pa = LOGICAL(ans);switch (code) {case EQOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();c1 = STRING_ELT(s1, i1);c2 = STRING_ELT(s2, i2);if (c1 == NA_STRING || c2 == NA_STRING)pa[i] = NA_LOGICAL;elsepa[i] = Seql(c1, c2) ? 1 : 0;});break;case NEOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();c1 = STRING_ELT(s1, i1);c2 = STRING_ELT(s2, i2);if (c1 == NA_STRING || c2 == NA_STRING)pa[i] = NA_LOGICAL;elsepa[i] = Seql(c1, c2) ? 0 : 1;});break;case LTOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();c1 = STRING_ELT(s1, i1);c2 = STRING_ELT(s2, i2);if (c1 == NA_STRING || c2 == NA_STRING)pa[i] = NA_LOGICAL;else if (c1 == c2)pa[i] = 0;else {errno = 0;res = Scollate(c1, c2);if(errno)pa[i] = NA_LOGICAL;elsepa[i] = (res < 0) ? 1 : 0;}});break;case GTOP:MOD_ITERATE2(n, n1, n2, i ,i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();c1 = STRING_ELT(s1, i1);c2 = STRING_ELT(s2, i2);if (c1 == NA_STRING || c2 == NA_STRING)pa[i] = NA_LOGICAL;else if (c1 == c2)pa[i] = 0;else {errno = 0;res = Scollate(c1, c2);if(errno)pa[i] = NA_LOGICAL;elsepa[i] = (res > 0) ? 1 : 0;}});break;case LEOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();c1 = STRING_ELT(s1, i1);c2 = STRING_ELT(s2, i2);if (c1 == NA_STRING || c2 == NA_STRING)pa[i] = NA_LOGICAL;else if (c1 == c2)pa[i] = 1;else {errno = 0;res = Scollate(c1, c2);if(errno)pa[i] = NA_LOGICAL;elsepa[i] = (res <= 0) ? 1 : 0;}});break;case GEOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();c1 = STRING_ELT(s1, i1);c2 = STRING_ELT(s2, i2);if (c1 == NA_STRING || c2 == NA_STRING)pa[i] = NA_LOGICAL;else if (c1 == c2)pa[i] = 1;else {errno = 0;res = Scollate(c1, c2);if(errno)pa[i] = NA_LOGICAL;elsepa[i] = (res >= 0) ? 1 : 0;}});break;}UNPROTECT(3);vmaxset(vmax);return ans;}static SEXP raw_relop(RELOP_TYPE code, SEXP s1, SEXP s2){R_xlen_t i, i1, i2, n, n1, n2;Rbyte x1, x2;SEXP ans;n1 = XLENGTH(s1);n2 = XLENGTH(s2);n = (n1 > n2) ? n1 : n2;PROTECT(s1);PROTECT(s2);ans = allocVector(LGLSXP, n);const Rbyte *px1 = RAW_RO(s1);const Rbyte *px2 = RAW_RO(s2);int *pa = LOGICAL(ans);switch (code) {case EQOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();x1 = px1[i1];x2 = px2[i2];pa[i] = (x1 == x2);});break;case NEOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();x1 = px1[i1];x2 = px2[i2];pa[i] = (x1 != x2);});break;case LTOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();x1 = px1[i1];x2 = px2[i2];pa[i] = (x1 < x2);});break;case GTOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();x1 = px1[i1];x2 = px2[i2];pa[i] = (x1 > x2);});break;case LEOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();x1 = px1[i1];x2 = px2[i2];pa[i] = (x1 <= x2);});break;case GEOP:MOD_ITERATE2(n, n1, n2, i, i1, i2, {// if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();x1 = px1[i1];x2 = px2[i2];pa[i] = (x1 >= x2);});break;}UNPROTECT(2);return ans;}static SEXP bitwiseNot(SEXP a){SEXP ans;int np = 0;if(isReal(a)) {a = PROTECT(coerceVector(a, INTSXP)); np++;}switch(TYPEOF(a)) {case INTSXP:{R_xlen_t m = XLENGTH(a);ans = allocVector(INTSXP, m);int *pans = INTEGER(ans);const int *pa = INTEGER_RO(a);for(R_xlen_t i = 0; i < m; i++) {int aa = pa[i];pans[i] = (aa == NA_INTEGER) ? aa : ~aa;}}break;default:UNIMPLEMENTED_TYPE("bitwNot", a);}if(np) UNPROTECT(np);return ans;}#define mymax(x, y) ((x >= y) ? x : y)#define BIT(op, name) \SEXP ans; \int np = 0; \if(isReal(a)) {a = PROTECT(coerceVector(a, INTSXP)); np++;} \if(isReal(b)) {b = PROTECT(coerceVector(b, INTSXP)); np++;} \if (TYPEOF(a) != TYPEOF(b)) \error(_("'a' and 'b' must have the same type")); \switch(TYPEOF(a)) { \case INTSXP: \{ \R_xlen_t i, ia, ib; \R_xlen_t m = XLENGTH(a), n = XLENGTH(b), \mn = (m && n) ? mymax(m, n) : 0; \ans = allocVector(INTSXP, mn); \int *pans = INTEGER(ans); \const int *pa = INTEGER_RO(a), *pb = INTEGER_RO(b); \MOD_ITERATE2(mn, m, n, i, ia, ib, { \int aa = pa[ia]; int bb = pb[ib]; \pans[i] = (aa == NA_INTEGER || bb == NA_INTEGER) ? \NA_INTEGER : aa op bb; \}); \} \break; \default: \UNIMPLEMENTED_TYPE(name, a); \} \if(np) UNPROTECT(np); \return ansstatic SEXP bitwiseAnd(SEXP a, SEXP b){BIT(&, "bitwAnd");}static SEXP bitwiseOr(SEXP a, SEXP b){BIT(|, "bitwOr");}static SEXP bitwiseXor(SEXP a, SEXP b){BIT(^, "bitwXor");}static SEXP bitwiseShiftL(SEXP a, SEXP b){SEXP ans;int np = 0;if(isReal(a)) {a = PROTECT(coerceVector(a, INTSXP)); np++;}if(!isInteger(b)) {b = PROTECT(coerceVector(b, INTSXP)); np++;}if (TYPEOF(a) != TYPEOF(b))error(_("'a' and 'b' must have the same type"));switch(TYPEOF(a)) {case INTSXP:{R_xlen_t i, ia, ib;R_xlen_t m = XLENGTH(a), n = XLENGTH(b),mn = (m && n) ? mymax(m, n) : 0;ans = allocVector(INTSXP, mn);int *pans = INTEGER(ans);const int *pa = INTEGER_RO(a), *pb = INTEGER_RO(b);MOD_ITERATE2(mn, m, n, i, ia, ib, {int aa = pa[ia]; int bb = pb[ib];pans[i] =(aa == NA_INTEGER || bb == NA_INTEGER ||bb < 0 || bb > 31) ?NA_INTEGER : ((unsigned int)aa << bb);});}break;default:UNIMPLEMENTED_TYPE("bitShiftL", a);}if(np) UNPROTECT(np);return ans;}static SEXP bitwiseShiftR(SEXP a, SEXP b){SEXP ans;int np = 0;if(isReal(a)) {a = PROTECT(coerceVector(a, INTSXP)); np++;}if(!isInteger(b)) {b = PROTECT(coerceVector(b, INTSXP)); np++;}if (TYPEOF(a) != TYPEOF(b))error(_("'a' and 'b' must have the same type"));switch(TYPEOF(a)) {case INTSXP:{R_xlen_t i, ia, ib;R_xlen_t m = XLENGTH(a), n = XLENGTH(b),mn = (m && n) ? mymax(m, n) : 0;ans = allocVector(TYPEOF(a), mn);int *pans = INTEGER(ans);const int *pa = INTEGER_RO(a), *pb = INTEGER_RO(b);MOD_ITERATE2(mn, m, n, i, ia, ib, {int aa = pa[ia]; int bb = pb[ib];pans[i] =(aa == NA_INTEGER || bb == NA_INTEGER ||bb < 0 || bb > 31) ?NA_INTEGER : ((unsigned int)aa >> bb);});}break;default:UNIMPLEMENTED_TYPE("bitShiftR", a);}if(np) UNPROTECT(np);return ans;}SEXP attribute_hidden do_bitwise(SEXP call, SEXP op, SEXP args, SEXP env){checkArity(op, args);SEXP ans = R_NilValue; /* -Wall */switch(PRIMVAL(op)) {case 1: ans = bitwiseAnd(CAR(args), CADR(args)); break;case 2: ans = bitwiseNot(CAR(args)); break;case 3: ans = bitwiseOr(CAR(args), CADR(args)); break;case 4: ans = bitwiseXor(CAR(args), CADR(args)); break;case 5: ans = bitwiseShiftL(CAR(args), CADR(args)); break;case 6: ans = bitwiseShiftR(CAR(args), CADR(args)); break;}return ans;}