
water.rapids.ASTAssign Maven / Gradle / Ivy
package water.rapids;
import hex.Model;
import water.*;
import water.fvec.Chunk;
import water.fvec.Frame;
import water.fvec.NewChunk;
import water.fvec.Vec;
/** Assign a whole frame over a global. Copy-On-Write optimizations make this cheap. */
class ASTAssign extends ASTPrim {
@Override public String[] args() { return new String[]{"id", "frame"}; }
@Override int nargs() { return 1+2; } // (assign id frame)
@Override public String str() { return "assign" ; }
@Override
public ValFrame apply(Env env, Env.StackHelp stk, AST asts[]) {
Key id = Key.make( asts[1].str() );
Frame src = stk.track(asts[2].exec(env)).getFrame();
return new ValFrame(env._ses.assign(id,src)); // New global Frame over shared Vecs
}
}
/** Rectangular assign into a row and column slice. The destination must
* already exist. The output is conceptually a new copy of the data, with a
* fresh Frame. Copy-On-Write optimizations lower the cost to be proportional
* to the over-written sections. */
class ASTRectangleAssign extends ASTPrim {
@Override public String[] args() { return new String[]{"dst", "src", "col_expr", "row_expr"}; }
@Override int nargs() { return 5; } // (:= dst src col_expr row_expr)
@Override public String str() { return ":=" ; }
@Override
public Val apply(Env env, Env.StackHelp stk, AST asts[]) {
Frame dst = stk.track(asts[1].exec(env)).getFrame();
Val vsrc = stk.track(asts[2].exec(env));
// Column selection
ASTNumList cols_numlist = new ASTNumList(asts[3].columns(dst.names()));
// Special for ASTAssign: "empty" really means "all"
if( cols_numlist.isEmpty() ) cols_numlist = new ASTNumList(0,dst.numCols());
// Allow R-like number list expansion: negative column numbers mean exclusion
int[] cols = ASTColSlice.col_select(dst.names(),cols_numlist);
// Any COW optimized path changes Vecs in dst._vecs, and so needs a
// defensive copy. Any update-in-place path updates Chunks instead of
// dst._vecs, and does not need a defensive copy. To make life easier,
// just make the copy now.
dst = new Frame(dst._names,dst.vecs().clone());
// Assign over the column slice
if( asts[4] instanceof ASTNum || asts[4] instanceof ASTNumList ) { // Explictly named row assignment
ASTNumList rows = asts[4] instanceof ASTNum ? new ASTNumList(((ASTNum)asts[4])._v.getNum()) : ((ASTNumList)asts[4]);
if( rows.isEmpty() ) rows = new ASTNumList(0,dst.numRows()); // Empty rows is really: all rows
switch( vsrc.type() ) {
case Val.NUM: assign_frame_scalar(dst,cols,rows,vsrc.getNum() ,env._ses); break;
case Val.STR: assign_frame_scalar(dst,cols,rows,vsrc.getStr() ,env._ses); break;
case Val.FRM: assign_frame_frame (dst,cols,rows,vsrc.getFrame(),env._ses); break;
default: throw new IllegalArgumentException("Source must be a Frame or Number, but found a "+vsrc.getClass());
}
} else { // Boolean assignment selection?
Frame rows = stk.track(asts[4].exec(env)).getFrame();
switch( vsrc.type() ) {
case Val.NUM: assign_frame_scalar(dst,cols,rows,vsrc.getNum() ,env._ses); break;
case Val.STR: throw H2O.unimpl();
case Val.FRM: throw H2O.unimpl();
default: throw new IllegalArgumentException("Source must be a Frame or Number, but found a "+vsrc.getClass());
}
}
return new ValFrame(dst);
}
// Rectangular array copy from src into dst
private void assign_frame_frame(Frame dst, int[] cols, ASTNumList rows, Frame src, Session ses) {
// Sanity check
if( cols.length != src.numCols() )
throw new IllegalArgumentException("Source and destination frames must have the same count of columns");
long nrows = rows.cnt();
if( src.numRows() != nrows )
throw new IllegalArgumentException("Requires same count of rows in the number-list ("+nrows+") as in the source ("+src.numRows()+")");
// Whole-column assignment? Directly reuse columns: Copy-On-Write
// optimization happens here on the apply() exit.
if( dst.numRows() == nrows && rows.isDense() ) {
for( int i=0; i end
//3 [ rows ] rows run left: rows.min() < start && rows.max() <= end
//4 [ rows ] rows run in : start <= rows.min() && rows.max() <= end
//5 [ rows ] rows run rite: start <= rows.min() && end < rows.max()
if( !(maxend) ) { // not situation 1 or 2 above
int startOffset = (int) (min > start ? min : start); // situation 4 and 5 => min > start;
for(int i=(int)(startOffset-start);i end
// //3 [ rows ] rows run left: rows.min() < start && rows.max() <= end
// //4 [ rows ] rows run in : start <= rows.min() && rows.max() <= end
// //5 [ rows ] rows run rite: start <= rows.min() && end < rows.max()
// if( !(maxend) ) { // not situation 1 or 2 above
// int startOffset = (int) (min > start ? min : start); // situation 4 and 5 => min > start;
// for(int i=startOffset;iget()); // Remove unshared Vecs
else Keyed.remove(id); // Normal (e.g. Model) remove
return new ValNum(1);
}
}
class ASTRename extends ASTPrim {
@Override public String[] args() { return new String[]{"oldId", "newId"}; }
@Override int nargs() { return 1+2; } // (rename oldId newId)
@Override public String str() { return "rename" ; }
@Override
public ValNum apply(Env env, Env.StackHelp stk, AST asts[]) {
Key oldKey = Key.make(asts[1].exec(env).getStr());
Key newKey = Key.make(asts[2].exec(env).getStr());
Iced o = DKV.remove(oldKey).get();
if( o instanceof Frame ) DKV.put(newKey, new Frame(newKey, ((Frame)o)._names, ((Frame)o).vecs()));
else if( o instanceof Model) {
((Model) o)._key = newKey;
DKV.put(newKey, o);
}
else throw new IllegalArgumentException("Trying to rename Value of type " + o.getClass());
return new ValNum(Double.NaN);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy