@Override public Object execute(Frame frame) { RAny lhsVal = (RAny) lhs.execute(frame); RAny rowVal = (RAny) rowExpr.execute(frame); boolean dropVal = dropExpr.executeLogical(frame) != RLogical.FALSE; // FIXME: what is the correct execution order of these args? int exactVal = exactExpr.executeLogical(frame); if (!(lhsVal instanceof RArray)) { throw RError.getObjectNotSubsettable(ast, lhsVal.typeOf()); } RArray array = (RArray) lhsVal; int[] dim = array.dimensions(); if (dim == null || dim.length != 2) { throw RError.getIncorrectDimensions(getAST()); } int m = dim[0]; int n = dim[1]; try { int row; if (rowVal instanceof ScalarIntImpl) { row = ((ScalarIntImpl) rowVal).getInt(); } else if (rowVal instanceof ScalarDoubleImpl) { row = Convert.double2int(((ScalarDoubleImpl) rowVal).getDouble()); } else { throw new UnexpectedResultException(null); } if (row > n || row <= 0) { throw new UnexpectedResultException(null); } int[] ndim; if (dropVal) { ndim = null; } else { ndim = new int[] {1, n}; } // note: also could be lazy here RArray res = Utils.createArray(array, n, ndim, null, null); // drop attributes int offset = row - 1; for (int i = 0; i < n; i++) { res.set(i, array.getRef(offset)); offset += m; } return res; } catch (UnexpectedResultException e) { SelectorNode selIExpr = Selector.createSelectorNode(ast, true, rowExpr); SelectorNode selJExpr = Selector.createSelectorNode(ast, true, null); MatrixRead nn = new MatrixRead(ast, true, lhs, selIExpr, selJExpr, dropExpr, exactExpr); replace(nn, "install MatrixRead from MatrixRowSubset"); Selector selI = selIExpr.executeSelector(rowVal); Selector selJ = selJExpr.executeSelector(frame); return nn.executeLoop(array, selI, selJ, dropVal, exactVal); } }
@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); } }; }
public RAny outer(Frame frame, RAny xarg, RAny yarg, RAny farg) { // LICENSE: transcribed code from GNU R, which is licensed under GPL if (!(xarg instanceof RArray && yarg instanceof RArray)) { Utils.nyi("unsupported type"); return null; } RArray x = (RArray) xarg; RArray y = (RArray) yarg; int xsize = x.size(); int ysize = y.size(); RArray expy; RArray expx; if (EAGER) { x = x.materialize(); // FIXME: probably unnecessary (both x and y), could be done on-the-fly in the expansion methods y = y.materialize(); if (y instanceof DoubleImpl) { expy = expandYVector((DoubleImpl) y, ysize, xsize); } else if (y instanceof IntImpl) { expy = expandYVector((IntImpl) y, ysize, xsize); } else { expy = expandYVector(y, ysize, xsize); } if (xsize > 0) { if (x instanceof DoubleImpl) { expx = expandXVector((DoubleImpl) x, xsize, ysize); } else if (x instanceof IntImpl) { expx = expandXVector((IntImpl) x, xsize, ysize); } else { expx = expandXVector(x, xsize, ysize); } } else { expx = x; } } else { if (y instanceof RInt) { expy = lazyExpandYVector((RInt) y, ysize, xsize); } else { throw Utils.nyi(); } if (xsize > 0) { if (x instanceof RInt) { expx = lazyExpandXVector((RInt) x, xsize, ysize); } else { throw Utils.nyi(); } } else { expx = x; } } xArgProvider.setValue(expx); yArgProvider.setValue(expy); callableProvider.matchAndSet(frame, farg); RArray res = (RArray) callNode.execute(frame); int[] dimx = x.dimensions(); int[] dimy = y.dimensions(); int[] dim; if (dimx == null) { if (dimy == null) { dim = new int[]{xsize, ysize}; } else { dim = new int[1 + dimy.length]; dim[0] = xsize; System.arraycopy(dimy, 0, dim, 1, dimy.length); } } else { if (dimy == null) { dim = new int[dimx.length + 1]; System.arraycopy(dimx, 0, dim, 0, dimx.length); dim[dimx.length] = ysize; } else { dim = new int[dimx.length + dimy.length]; System.arraycopy(dimx, 0, dim, 0, dimx.length); System.arraycopy(dimy, 0, dim, dimx.length, dimy.length); } } return res.setDimensions(dim); // triggers materialization of the result }
@Override public Object execute(Frame frame) { RAny lhsVal = (RAny) lhs.execute(frame); Object rowFromVal = rowFromExpr.execute(frame); Object rowToVal = rowToExpr.execute(frame); Object colFromVal = colFromExpr.execute(frame); Object colToVal = colToExpr.execute(frame); boolean dropVal = dropExpr.executeLogical(frame) != RLogical.FALSE; // FIXME: what is the correct execution order of these args? int exactVal = exactExpr.executeLogical(frame); if (!(lhsVal instanceof RArray)) { throw RError.getObjectNotSubsettable(ast, lhsVal.typeOf()); } RArray array = (RArray) lhsVal; try { int rowFrom = extractLimit(rowFromVal); // zero-based int rowTo = extractLimit(rowToVal); int colFrom = extractLimit(colFromVal); int colTo = extractLimit(colToVal); int[] dim = array.dimensions(); if (dim == null || dim.length != 2) { throw RError.getIncorrectDimensions(getAST()); } int m = dim[0]; int n = dim[1]; int rowStep; int rowSize; if (rowFrom <= rowTo) { rowStep = 1; if (rowTo > m) { throw new UnexpectedResultException(null); } rowSize = rowTo - rowFrom + 1; } else { rowStep = -1; if (rowFrom > m) { throw new UnexpectedResultException(null); } rowSize = rowFrom - rowTo + 1; } int colStep; int colSize; if (colFrom <= colTo) { colStep = 1; if (colTo > n) { throw new UnexpectedResultException(null); } colSize = colTo - colFrom + 1; } else { colStep = -1; if (colFrom > n) { throw new UnexpectedResultException(null); } colSize = colFrom - colTo + 1; } int[] ndim; if (!dropVal || (rowSize > 1 && colSize > 1)) { ndim = new int[] {rowSize, colSize}; } else { ndim = null; } int size = rowSize * colSize; RArray res = Utils.createArray(array, size, ndim, null, null); // drop attributes if (colStep == 1 && rowStep == 1) { int j = colFrom * m + rowFrom; // j - index to source matrix int jmax = j + rowSize; int jadvance = m - rowSize; for (int i = 0; i < size; i++) { res.set(i, array.getRef(j++)); // i - index to target matrix if (j == jmax) { j += jadvance; jmax += m; } } } else { int i = 0; // NOTE: here we know that colFrom != colTo and rowFrom != rowTo for (int col = colFrom; col != colTo + colStep; col += colStep) { for (int row = rowFrom; row != rowTo + rowStep; row += rowStep) { res.set(i++, array.getRef(col * m + row)); } } } return res; } catch (UnexpectedResultException e) { // FIXME: clean this up; does Colon need to be package-private? ASTNode rowAST = rowFromExpr.getAST().getParent(); Builtin rowColon = (Builtin) Primitives.getCallFactory(RSymbol.getSymbol(":"), null) .create(rowAST, rowFromExpr, rowToExpr); SelectorNode selIExpr = Selector.createSelectorNode(rowAST, true, rowColon); ASTNode colAST = colFromExpr.getAST().getParent(); Builtin colColon = (Builtin) Primitives.getCallFactory(RSymbol.getSymbol(":"), null) .create(colAST, colFromExpr, colToExpr); SelectorNode selJExpr = Selector.createSelectorNode(ast, true, colColon); MatrixRead nn = new MatrixRead(ast, true, lhs, selIExpr, selJExpr, dropExpr, exactExpr); replace(nn, "install MatrixRead from MatrixSequenceSubset"); Selector selI = selIExpr.executeSelector( rowColon.doBuiltIn(frame, new RAny[] {(RAny) rowFromVal, (RAny) rowToVal})); Selector selJ = selJExpr.executeSelector( colColon.doBuiltIn(frame, new RAny[] {(RAny) colFromVal, (RAny) colToVal})); return nn.executeLoop(array, selI, selJ, dropVal, exactVal); } }
@Override public Object execute(Frame frame) { RAny lhsVal = (RAny) lhs.execute(frame); RAny colVal = (RAny) columnExpr.execute(frame); boolean dropVal = dropExpr.executeLogical(frame) != RLogical.FALSE; // FIXME: what is the correct execution order of these args? int exactVal = exactExpr.executeLogical(frame); // TODO: GNU-R has different behavior when selecting from arrays that have some dimension zero if (!(lhsVal instanceof RArray)) { throw RError.getObjectNotSubsettable(ast, lhsVal.typeOf()); } RArray array = (RArray) lhsVal; int[] dim = array.dimensions(); if (dim == null || dim.length != nSelectors) { throw RError.getIncorrectDimensions(getAST()); } int n = dim[nSelectors - 1]; // limit for the column (last dimension) try { int col; if (colVal instanceof ScalarIntImpl) { col = ((ScalarIntImpl) colVal).getInt(); } else if (colVal instanceof ScalarDoubleImpl) { col = Convert.double2int(((ScalarDoubleImpl) colVal).getDouble()); } else { throw new UnexpectedResultException(null); } if (col > n || col <= 0) { throw new UnexpectedResultException(null); } int[] ndim; int m; // size of the result if (dropVal) { boolean hasNonTrivialDimension = false; boolean resultIsVector = true; m = 1; for (int i = 0; i < nSelectors - 1; i++) { int d = dim[i]; if (d != 1) { if (hasNonTrivialDimension) { resultIsVector = false; } else { hasNonTrivialDimension = true; } } m *= d; } if (resultIsVector) { ndim = null; } else { ndim = new int[nSelectors - 1]; System.arraycopy(dim, 0, ndim, 0, ndim.length); } } else { ndim = new int[nSelectors]; ndim[nSelectors - 1] = 1; m = 1; for (int i = 0; i < ndim.length - 1; i++) { int d = dim[i]; ndim[i] = d; m *= d; } } // note: also could be lazy here RArray res = Utils.createArray(array, m, ndim, null, null); // drop attributes int offset = (col - 1) * m; // note: col is 1-based for (int i = 0; i < m; i++) { res.set(i, array.getRef(offset + i)); } return res; } catch (UnexpectedResultException e) { SelectorNode[] selectorExprs = new SelectorNode[nSelectors]; for (int i = 0; i < nSelectors - 1; i++) { selectorExprs[i] = Selector.createSelectorNode(ast, true, null); } selectorExprs[nSelectors - 1] = Selector.createSelectorNode(ast, true, columnExpr); GenericRead gr = new GenericRead(ast, true, lhs, selectorExprs, dropExpr, exactExpr); replace(gr, "install GenericRead from ArrayColumnSubset"); for (int i = 0; i < nSelectors - 1; i++) { gr.selectorVals[i] = selectorExprs[i].executeSelector(frame); } gr.selectorVals[nSelectors - 1] = selectorExprs[nSelectors - 1].executeSelector(colVal); return gr.executeLoop(array, dropVal, exactVal); } }
@Override public final Object execute(Frame frame) { RAny leftValue = (RAny) left.execute(frame); RAny rightValue = (RAny) right.execute(frame); return execute(leftValue, rightValue); }