public static RString substring(RString text, RDouble first, RDouble last, ASTNode ast) { int textSize = text.size(); int firstSize = first.size(); int lastSize = last.size(); int textIndex = 0; int firstIndex = 0; int lastIndex = 0; if (textSize == 0) { return RString.EMPTY; } if (firstSize == 0) { throw RError.getInvalidArgument(ast, "first"); }// not exactly R-warning if (lastSize == 0) { throw RError.getInvalidArgument(ast, "last"); } // not exactly R-warning int n = Math.max(textSize, Math.max(firstSize, lastSize)); String[] content = new String[n]; for (int i = 0; i < n; i++) { double nfirst = first.getDouble(firstIndex++); if (firstIndex == firstSize) { firstIndex = 0; } double nlast = last.getDouble(lastIndex++); if (lastIndex == lastSize) { lastIndex = 0; } String str = text.getString(textIndex++); if (textIndex == textSize) { textIndex = 0; } if (!RDouble.RDoubleUtils.isNAorNaN(nfirst) && !RDouble.RDoubleUtils.isNAorNaN(nlast) && str != RString.NA) { int stp = (int) nlast; int len = str.length(); if (stp > len) { stp = len; } content[i] = str.substring(((int) nfirst) - 1, stp); } else { content[i] = RString.NA; } } return RString.RStringFactory.getFor(content); }
@Override public RNode create(ASTNode call, RSymbol[] names, RNode[] exprs) { ArgumentInfo ia = check(call, names, exprs); boolean product = false; if (ia.provided("FUN")) { RNode fnode = exprs[ia.position("FUN")]; if (fnode instanceof Constant) { RAny value = ((Constant) fnode).execute(null); if (value instanceof RString) { RString str = (RString) value; if (str.size() == 1) { if (str.getString(0).equals("*")) { product = true; } } } } } else { product = true; } if (product) { return new MatrixOperation.OuterProduct(call, exprs[ia.position("X")], exprs[ia.position("Y")]); } int cnArgs = 2 + names.length - 3; // "-2" because both FUN, X, Y RSymbol[] cnNames = new RSymbol[cnArgs]; RNode[] cnExprs = new RNode[cnArgs]; cnNames[0] = null; ValueProvider xArgProvider = new ValueProvider(call); cnExprs[0] = xArgProvider; ValueProvider yArgProvider = new ValueProvider(call); cnExprs[1] = yArgProvider; ValueProvider[] constantArgProviders = new ValueProvider[cnArgs]; int j = 0; for (int i = 0; i < names.length; i++) { if (ia.position("X") == i || ia.position("Y") == i || ia.position("FUN") == i) { continue; } cnNames[2 + j] = names[i]; ValueProvider vp = new ValueProvider(call); cnExprs[2 + j] = vp; constantArgProviders[j] = vp; j++; } RNode funExpr = exprs[ia.position("FUN")]; final CallableProvider callableProvider = new CallableProvider(funExpr.getAST(), funExpr); final RNode callNode = FunctionCall.getFunctionCall(call, callableProvider, cnNames, cnExprs); final int posX = ia.position("X"); final int posY = ia.position("Y"); final int posFUN = ia.position("FUN"); return new OuterBuiltIn(call, names, exprs, callNode, callableProvider, xArgProvider, yArgProvider, constantArgProviders) { @Override public RAny doBuiltIn(Frame frame, RAny[] args) { RAny argx = null; RAny argy = null; RAny argfun = null; int k = 0; for (int i = 0; i < args.length; i++) { if (i == posX) { argx = args[i]; } else if (i == posY) { argy = args[i]; } else if (i == posFUN) { argfun = args[i]; } else { constantArgProviders[k].setValue(args[i]); k++; } } return outer(frame, argx, argy, argfun); } }; }