/** * Returns the selection array or vector. * * <p>The selSizes array contains sizes of the selectors (number of elements that will be * returned by it). The idx array contains the indices returned by the selectors (that is the * indices used to compute the source offset). * * <p>The selIdx array contains the position in the selector (when this is equal to the selector * size the selector has overflown). */ public Object execute(RArray source, boolean drop, int exact) throws UnexpectedResultException { int[] sourceDim = source.dimensions(); boolean mayHaveNA = Selector.initialize(offsets, selectorVals, sourceDim, selSizes, ast); int[] destDim = Selector.calculateDestinationDimensions(selSizes, !subset || drop); int destSize = Selector.calculateSizeFromSelectorSizes(selSizes); RArray dest = Utils.createArray(source, destSize, destDim, null, null); // drop attributes if (destSize == 0) { return dest; } int offset = 0; for (; ; ) { int sourceOffset = offsets[0]; if (sourceOffset == RInt.NA) { Utils.setNA(dest, offset); } else { dest.set(offset, source.getRef(sourceOffset)); } offset++; if (offset < destSize) { if (!mayHaveNA) { Selector.advanceNoNA(offsets, sourceDim, selectorVals, ast); } else { Selector.advance(offsets, sourceDim, selectorVals, ast); } } else { break; } } return dest; }
@Override protected <N extends RNode> N replaceChild(RNode oldNode, N newNode) { assert oldNode != null; if (callNode == oldNode) { callNode = newNode; return adoptInternal(newNode); } assert Utils.check(oldNode != callableProvider); // this not must not be rewritten assert Utils.check(oldNode != xArgProvider); assert Utils.check(oldNode != yArgProvider); return super.replaceChild(oldNode, newNode); }
public static <T extends RArray> T trace(RArray orig) { if (VIEW_TRACING) { RArray res; if (orig instanceof RList) { res = new RListTracingView((RList) orig); } else if (orig instanceof RString) { res = new RStringTracingView((RString) orig); } else if (orig instanceof RComplex) { res = new RComplexTracingView((RComplex) orig); } else if (orig instanceof RDouble) { res = new RDoubleTracingView((RDouble) orig); } else if (orig instanceof RInt) { res = new RIntTracingView((RInt) orig); } else if (orig instanceof RLogical) { res = new RLogicalTracingView((RLogical) orig); } else if (orig instanceof RRaw) { res = new RRawTracingView((RRaw) orig); } else { assert Utils.check(false, "missed view type"); res = orig; } return (T) res; } else { return (T) orig; } }
@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); } }
private static Field[] getAllFields(Class cls) { ArrayList<Field> res = new ArrayList<>(); Class c = cls; while (c != View.class) { assert Utils.check(c != null); res.addAll(Arrays.asList(c.getDeclaredFields())); c = c.getSuperclass(); } return res.toArray(new Field[res.size()]); }
public Site(StackTraceElement[] site) { this.site = site; int i = 0; while (!THIS_FILE_NAME.equals(site[i].getFileName())) { i++; } while (THIS_FILE_NAME.equals(site[i].getFileName())) { i++; } assert Utils.check(i < site.length - 1); this.offset = i; }
public static RArray expandXVector(RArray x, int xsize, int count) { int nsize = xsize * count; RArray res = Utils.createArray(x, nsize); int offset = 0; for (int rep = 0; rep < count; rep++) { for (int i = 0; i < xsize; i++) { res.set(offset + i, x.get(i)); } offset += xsize; } return res; }
public static RArray expandYVector(RArray y, int ysize, int count) { int size = ysize; int nsize = size * count; RArray res = Utils.createArray(y, nsize); int offset = 0; for (int elem = 0; elem < size; elem++) { Object v = y.get(elem); for (int i = 0; i < count; i++) { res.set(offset + i, v); } offset += count; } return res; }
@Override public Object execute( RArray base, Selector selectorI, Selector selectorJ, boolean drop, int exact) throws UnexpectedResultException { int[] ndim = base.dimensions(); int m = ndim[0]; int n = ndim[1]; selectorI.start(m, ast); selectorJ.start(n, ast); int i = selectorI.nextIndex(ast); int j = selectorJ.nextIndex(ast); assert Utils.check(i != RInt.NA && j != RInt.NA); // ensured by subscript selectors int offset = j * m + i; if (!(base instanceof RList)) { return base.boxedGet(offset); } else { return ((RList) base).getRAny(offset); } }
private static void linkChildren(RArray parentRealView, ViewTrace parentTrace) { Class viewClass = parentRealView.getClass(); Field[] fields = getAllFields(viewClass); for (Field f : fields) { if (f.isSynthetic()) { continue; } Class fieldClass = f.getType(); if (RArray.class.isAssignableFrom(fieldClass)) { try { f.setAccessible(true); Object o = f.get(parentRealView); if (o instanceof TracingView) { ((TracingView) o).getTrace().parentView = parentTrace; } } catch (IllegalAccessException e) { assert Utils.check(false, "can't read a view field " + e); } } } }
public static ASTNode create(boolean isSuper, ASTNode lhs, ASTNode rhs) { if (lhs instanceof SimpleAccessVariable) { return writeVariable(isSuper, ((SimpleAccessVariable) lhs).symbol, rhs); } else if (lhs instanceof AccessVector) { return writeVector(isSuper, (AccessVector) lhs, rhs); } else if (lhs instanceof FieldAccess) { return writeField(isSuper, (FieldAccess) lhs, rhs); } else if (lhs instanceof FunctionCall) { return writeFunction(isSuper, (FunctionCall) lhs, rhs); } else if (lhs instanceof Constant) { // TODO: move this to the parser? RAny value = ((Constant) lhs).getValue(); if (value instanceof RString) { RString svalue = (RString) value; if (svalue.size() == 1) { String name = svalue.getString(0); return writeVariable(isSuper, RSymbol.getSymbol(name), rhs); } } throw RError.getUnknownObject(rhs); // TODO it's own exception } Utils.nyi(); return null; }
public class RContext { public static final boolean DEBUG = Utils.getProperty("RConsole.debug.gui", false); private static boolean debuggingFormat = false; private static boolean usesTruffleOptimizer = Truffle.getRuntime().equals("Default Truffle Runtime"); private static ManageError errorManager = new ManageError(System.err); private static Truffleize truffleize = new Truffleize(); private static final int NCONNECTIONS = 128; private static final Connection[] connections = new Connection[NCONNECTIONS]; static { Arrays.fill(connections, null); } public static boolean usesTruffleOptimizer() { return usesTruffleOptimizer; } public static boolean debuggingFormat() { return debuggingFormat; } public static boolean debuggingFormat(boolean useDebuggingFormat) { boolean previous = debuggingFormat; debuggingFormat = useDebuggingFormat; return previous; } public static RAny eval(ASTNode expr, boolean useDebuggingFormat) { debuggingFormat(useDebuggingFormat); return eval(expr); // NOTE: cannot reset to the original value of debuggingFormat here, because usually the pretty // printer is // invoked on the results afterwards by the caller of eval; the pretty printer still depends on // the correct // setting of debugging format } public static RAny eval(ASTNode expr) { try { return (RAny) truffleize.createLazyRootTree(expr).execute(null); // null means top-level } catch (RError e) { if (DEBUG) { e.printStackTrace(); } error(e); // throws an error } throw new Error("Never reached"); } public static RNode createNode(ASTNode expr) { return truffleize.createTree(expr); } public static RNode createRootNode(ASTNode expr, final RFunction rootEnclosingFunction) { return new BaseR(expr) { @Child RNode node = adoptChild(truffleize.createTree(ast, rootEnclosingFunction)); @Override public Object execute(Frame frame) { return node.execute(frame); } }; } public static void warning(ASTNode expr, String msg, Object... args) { errorManager.warning(expr, String.format(msg, args)); } public static void warning(ASTNode expr, String msg) { errorManager.warning(expr, msg); } public static void warning(RError err) { errorManager.warning(err); } public static void error(ASTNode expr, String msg) { errorManager.error(expr, msg); } public static void error(RError err) { errorManager.error(err); } public static int allocateConnection(Connection connection) { for (int i = 0; i < NCONNECTIONS; i++) { if (connections[i] == null) { connections[i] = connection; return i; } } return -1; } /** Release a connection currently in use. */ public static void freeConnection(int i) { assert Utils.check(connections[i] != null); connections[i] = null; } /** Return a connection or null. */ public static Connection getConnection(int i) { return i >= 0 && i < NCONNECTIONS ? connections[i] : null; } // note: GNUR currently means not only the GNU-R library, but also some other native code, under // licenses compatible with GPL private static int hasGNUR = -1; public static boolean hasGNUR() { if (hasGNUR == -1) { try { System.loadLibrary("gnurglue"); hasGNUR = 1; } catch (Throwable t) { hasGNUR = 0; } } return hasGNUR == 1; } public static ASTNode parseFile(ANTLRStringStream inputStream) { CommonTokenStream tokens = new CommonTokenStream(); RLexer lexer = new RLexer(inputStream); tokens.setTokenSource(lexer); RParser parser = new RParser(tokens); try { return parser.script(); } catch (RecognitionException e) { Console.parseError(parser, e); return null; } } }
/** Release a connection currently in use. */ public static void freeConnection(int i) { assert Utils.check(connections[i] != null); connections[i] = null; }
private static void dumpView(int depth, ViewTrace trace) { printedIndividualViews.add(trace); ps.println(trace.realView + " size = " + trace.realView.size()); if (TRACE_ALLOCATION_SITE) { indent(depth); ps.print(" allocationSite ="); Site.printSite(trace.allocationSite); ps.println(); } int unused = trace.unusedElements(); int redundant = trace.redundantGets(); boolean singleUse; Site[] useSites; if (TRACE_USE_SITES) { useSites = trace.useSites.toArray(new Site[trace.useSites.size()]); singleUse = (useSites.length == 1); } else if (TRACE_SINGLE_USE_SITE) { useSites = null; singleUse = !trace.multipleUseSites; } else { useSites = null; singleUse = false; } if (singleUse) { indent(depth); ps.print(" singleUseSite = US"); Site.printSite(useSites != null ? useSites[0] : trace.singleUseSite); if (trace.getCount > 0) { ps.println(" (get)"); } else if (trace.sumCount > 0) { ps.println(" (sum)"); } else { ps.println(" (materialize)"); } } else if (trace.getCount > 0) { if (TRACE_FIRST_GET_SITE) { indent(depth); ps.print(" firstGetSite ="); Site.printSite(trace.firstGetSite); ps.println(); } if (trace.materializeCount == 0 && trace.sumCount == 0) { if (unused > 0) { indent(depth); ps.println(" unusedElements = " + unused); } if (redundant > 0) { indent(depth); ps.println(" redundantGets = " + redundant + " (no materialize, sum)"); } } } else { if (trace.materializeCount == 0 && trace.sumCount == 0) { indent(depth); ps.println(" UNUSED"); } else { indent(depth); ps.println( " materializeCount = " + trace.materializeCount + " sumCount = " + trace.sumCount + " getCount = " + trace.getCount); } } if (TRACE_FIRST_MATERIALIZE_SITE && trace.materializeCount > 0 && !singleUse) { indent(depth); ps.print(" firstMaterializeSite ="); Site.printSite(trace.firstMaterializeSite); ps.println(); } if (TRACE_FIRST_SUM_SITE && trace.sumCount > 0 && !singleUse) { indent(depth); ps.print(" firstSumSite ="); Site.printSite(trace.firstSumSite); ps.println(); } if (TRACE_USE_SITES) { if (useSites.length != 1) { indent(depth); ps.println(" useSites (" + useSites.length + "):"); for (Site s : useSites) { indent(depth); ps.print(" US"); Site.printSite(s); ps.println(); } } } ps.println(); RArray view = trace.realView; Class viewClass = view.getClass(); Field[] fields = getAllFields(viewClass); boolean printedField = false; for (Field f : fields) { if (f.isSynthetic()) { continue; } Class fieldClass = f.getType(); if (RArray.class.isAssignableFrom(fieldClass)) { continue; // these later } indent(depth); ps.print(" " + f.getName() + " "); try { f.setAccessible(true); ps.println(f.get(view)); printedField = true; } catch (IllegalAccessException e) { assert Utils.check(false, "can't read a view field " + e); } } boolean printNewline = printedField; for (Field f : fields) { if (f.isSynthetic()) { continue; } Class fieldClass = f.getType(); if (!RArray.class.isAssignableFrom(fieldClass)) { continue; } if (printNewline) { ps.println(); printNewline = false; } indent(depth); ps.print(" " + f.getName() + " "); try { f.setAccessible(true); Object o = f.get(view); if (o instanceof TracingView) { ps.print("VIEW "); TracingView child = (TracingView) o; dumpView(depth + 2, child.getTrace()); } else { ps.print("ARRAY " + o + " size = " + ((RArray) o).size()); if (o instanceof View) { ps.println("MISSED VIEW " + o); } } ps.println(); } catch (IllegalAccessException e) { assert Utils.check(false, "can't read a view field " + e); } } }
private static void extractViewPattern(int depth, ViewTrace trace, StringBuilder p) { if (!processedViewsForPatterns.add(trace)) { p.append("(ALIASED) "); } p.append(trace.realView.getClass() + " size = " + trace.realView.size() + "\n"); indent(depth, p); p.append(" use:"); if (trace.materializeCount == 0 && trace.sumCount == 0 && trace.getCount == 0) { p.append(" UNUSED"); } else { if (trace.getCount > 0) { p.append(" get"); } if (trace.materializeCount > 0) { p.append(" materialize"); } if (trace.sumCount > 0) { p.append(" sum"); } } p.append("\n"); if (false) { p.append(" allocationSite ="); Site.printSite(trace.allocationSite, p); p.append("\n"); indent(depth, p); } RArray view = trace.realView; Class viewClass = view.getClass(); Field[] fields = getAllFields(viewClass); boolean printedField = false; for (Field f : fields) { if (f.isSynthetic()) { continue; } Class fieldClass = f.getType(); if (RArray.class.isAssignableFrom(fieldClass)) { continue; // these later } indent(depth, p); p.append(" " + f.getName() + " "); try { f.setAccessible(true); Object o = f.get(view); p.append(o == null ? "null (" + fieldClass + ")" : o.getClass()); p.append("\n"); printedField = true; } catch (IllegalAccessException e) { assert Utils.check(false, "can't read a view field " + e); } } boolean printNewline = printedField; for (Field f : fields) { if (f.isSynthetic()) { continue; } Class fieldClass = f.getType(); if (!RArray.class.isAssignableFrom(fieldClass)) { continue; } if (printNewline) { p.append("\n"); printNewline = false; } indent(depth, p); p.append(" " + f.getName() + " "); try { f.setAccessible(true); Object o = f.get(view); if (o instanceof TracingView) { p.append("VIEW "); TracingView child = (TracingView) o; extractViewPattern(depth + 2, child.getTrace(), p); } else { p.append("ARRAY " + o.getClass() + " size = " + ((RArray) o).size()); if (o instanceof View) { ps.println("MISSED VIEW " + o); } } p.append("\n"); } catch (IllegalAccessException e) { assert Utils.check(false, "can't read a view field " + e); } } }
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 RNode create(ASTNode call, RSymbol[] names, RNode[] exprs) { /*ArgumentInfo ia = */ check(call, names, exprs); if (names.length == 1) { return new Builtin.Builtin1(call, names, exprs) { @Override public RAny doBuiltIn(Frame frame, RAny xarg) { // x must be matrix-like // method is pearson // use is everything RDouble xd; if (xarg instanceof RDouble || xarg instanceof RInt || xarg instanceof RLogical) { xd = xarg.asDouble().materialize(); } else { if (xarg instanceof RArray) { throw RError.getXNumeric(ast); } else { throw RError.getSupplyXYMatrix(ast); } } int[] dim = xd.dimensions(); if (dim == null || dim.length != 2) { throw RError.getSupplyXYMatrix(ast); } int nrow = dim[0]; int ncol = dim[1]; double[] res = new double[ncol * ncol]; double[] x = xd.getContent(); boolean[] hasNA = new boolean[ncol]; boolean anyNA = columnsNAMap(x, nrow, ncol, hasNA); int n1 = nrow - 1; boolean sdZero = false; if (!anyNA) { double[] colMeans = columnMeansNoNA(x, nrow, ncol); for (int i = 0; i < ncol ; i++) { double imean = colMeans[i]; int ioffset = i * nrow; for (int j = 0; j <= i; j++) { double jmean = colMeans[j]; int joffset = j * nrow; double sum = 0; for (int k = 0; k < nrow; k++) { sum += (x[ioffset + k] - imean) * (x[joffset + k] - jmean); } double tmp = sum / n1; res[j * ncol + i] = tmp; res[i * ncol + j] = tmp; } } double[] srcov = colMeans; // colMeans no longer needed for (int i = 0; i < ncol; i++) { srcov[i] = Math.sqrt(res[i * ncol + i]); } for (int i = 0; i < ncol; i++) { for (int j = 0; j < i; j++) { if (srcov[i] == 0 || srcov[j] == 0) { sdZero = true; res[j * ncol + i] = RDouble.NA; res[i * ncol + j] = RDouble.NA; } else { double tmp = res[i * ncol + j] / (srcov[i] * srcov[j]); if (tmp > 1) { tmp = 1; } res[j * ncol + i] = tmp; res[i * ncol + j] = tmp; } } res[i * ncol + i] = 1; } } else { double[] colMeans = columnMeans(x, nrow, ncol, hasNA); for (int i = 0; i < ncol ; i++) { if (hasNA[i]) { for (int j = 0; j <= i; j++ ) { res[j * ncol + i] = RDouble.NA; // FIXME: break this into two loops? res[i * ncol + j] = RDouble.NA; } continue; } double imean = colMeans[i]; int ioffset = i * nrow; for (int j = 0; j <= i; j++) { if (hasNA[j]) { res[j * ncol + i] = RDouble.NA; res[i * ncol + j] = RDouble.NA; continue; } double jmean = colMeans[j]; int joffset = j * nrow; double sum = 0; for (int k = 0; k < nrow; k++) { sum += (x[ioffset + k] - imean) * (x[joffset + k] - jmean); } double tmp = sum / n1; res[j * ncol + i] = tmp; res[i * ncol + j] = tmp; } } double[] srcov = colMeans; // colMeans no longer needed for (int i = 0; i < ncol; i++) { if (!hasNA[i]) { srcov[i] = Math.sqrt(res[i * ncol + i]); } } for (int i = 0; i < ncol; i++) { if (!hasNA[i]) { for (int j = 0; j < i; j++) { if (srcov[i] == 0 || srcov[j] == 0) { sdZero = true; res[j * ncol + i] = RDouble.NA; res[i * ncol + j] = RDouble.NA; } else { double tmp = res[i * ncol + j] / (srcov[i] * srcov[j]); if (tmp > 1) { tmp = 1; } res[j * ncol + i] = tmp; res[i * ncol + j] = tmp; } } } res[i * ncol + i] = 1; } } if (sdZero) { RContext.warning(ast, RError.SD_ZERO); } return RDouble.RDoubleFactory.getFor(res, new int[] {ncol, ncol}, null); } }; } // final int xPosition = ia.position("x"); // final int yPosition = ia.position("y"); // final int usePosition = ia.position("use"); // final int methodPosition = ia.position("method"); Utils.nyi("finish cor"); return null; }
@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); } }
public Object execute( RArray source, Selector selectorI, Selector selectorJ, boolean drop, int exact) throws UnexpectedResultException { assert Utils.check(subset); int[] ndim = source.dimensions(); int m = ndim[0]; int n = ndim[1]; selectorI.start(m, ast); selectorJ.start(n, ast); int nm = selectorI.size(); int nn = selectorJ.size(); boolean mayHaveNA = selectorI.mayHaveNA() || selectorJ.mayHaveNA(); int nsize = nm * nn; if ((nm != 1 && nn != 1) || !drop) { ndim = new int[] {nm, nn}; } else { ndim = null; } RArray res = Utils.createArray(source, nsize, ndim, null, null); // drop attributes if (!mayHaveNA) { int resoffset = 0; for (int nj = 0; nj < nn; nj++) { int j = selectorJ.nextIndex(ast); int srcoffset = j * m; for (int ni = 0; ni < nm; ni++) { int i = selectorI.nextIndex(ast); Object value = source.getRef( srcoffset + i); // FIXME: check overflow? (the same is at many locations, whenever // indexing a matrix) res.set(resoffset++, value); } selectorI.restart(); } } else { for (int nj = 0; nj < nn; nj++) { int j = selectorJ.nextIndex(ast); if (j != RInt.NA) { selectorI.restart(); for (int ni = 0; ni < nm; ni++) { int offset = nj * nm + ni; int i = selectorI.nextIndex(ast); if (i != RInt.NA) { Object value; value = source.getRef( j * m + i); // FIXME: check overflow? (the same is at many locations, whenever // indexing a matrix) res.set(offset, value); } else { Utils.setNA(res, offset); } } } else { for (int ni = 0; ni < nm; ni++) { Utils.setNA(res, nj * nm + ni); } } } } return res; }