
water.rapids.ASTBinOp Maven / Gradle / Ivy
package water.rapids;
import water.H2O;
import water.MRTask;
import water.fvec.Chunk;
import water.fvec.Frame;
import water.fvec.NewChunk;
import water.fvec.Vec;
import water.parser.BufferedString;
import water.util.ArrayUtils;
import water.util.MathUtils;
import water.util.VecUtils;
import java.util.Arrays;
/**
* Subclasses auto-widen between scalars and Frames, and have exactly two arguments
*/
abstract class ASTBinOp extends ASTPrim {
@Override
public String[] args() { return new String[]{"leftArg", "rightArg"}; }
@Override int nargs() { return 1+2; }
@Override
public Val apply(Env env, Env.StackHelp stk, AST asts[]) {
Val left = stk.track(asts[1].exec(env));
Val rite = stk.track(asts[2].exec(env));
return prim_apply(left,rite);
}
Val prim_apply( Val left, Val rite ) {
switch( left.type() ) {
case Val.NUM:
final double dlf = left.getNum();
switch( rite.type() ) {
case Val.NUM: return new ValNum( op (dlf,rite.getNum()));
case Val.NUMS: return new ValNum(op(dlf,rite.getNums()[0]));
case Val.FRM: return scalar_op_frame(dlf,rite.getFrame());
case Val.ROW:
double[] lft = new double[rite.getRow().length];
Arrays.fill(lft,dlf);
return row_op_row(lft,rite.getRow(),((ValRow)rite).getNames());
case Val.STR: throw H2O.unimpl();
case Val.STRS: throw H2O.unimpl();
default: throw H2O.unimpl();
}
case Val.NUMS:
final double ddlf = left.getNums()[0];
switch( rite.type() ) {
case Val.NUM: return new ValNum( op (ddlf,rite.getNum()));
case Val.NUMS: return new ValNum(op(ddlf,rite.getNums()[0]));
case Val.FRM: return scalar_op_frame(ddlf,rite.getFrame());
case Val.ROW:
double[] lft = new double[rite.getRow().length];
Arrays.fill(lft,ddlf);
return row_op_row(lft,rite.getRow(),((ValRow)rite).getNames());
case Val.STR: throw H2O.unimpl();
case Val.STRS: throw H2O.unimpl();
default: throw H2O.unimpl();
}
case Val.FRM:
Frame flf = left.getFrame();
switch( rite.type() ) {
case Val.NUM: return frame_op_scalar(flf,rite.getNum());
case Val.NUMS: return frame_op_scalar(flf,rite.getNums()[0]);
case Val.STR: return frame_op_scalar(flf, rite.getStr());
case Val.STRS: return frame_op_scalar(flf,rite.getStrs()[0]);
case Val.FRM: return frame_op_frame (flf,rite.getFrame());
default: throw H2O.unimpl();
}
case Val.STR:
String slf = left.getStr();
switch( rite.type() ) {
case Val.NUM: throw H2O.unimpl();
case Val.NUMS: throw H2O.unimpl();
case Val.STR: throw H2O.unimpl();
case Val.STRS: throw H2O.unimpl();
case Val.FRM: return scalar_op_frame(slf, rite.getFrame());
default: throw H2O.unimpl();
}
case Val.STRS:
String sslf = left.getStrs()[0];
switch( rite.type() ) {
case Val.NUM: throw H2O.unimpl();
case Val.NUMS: throw H2O.unimpl();
case Val.STR: throw H2O.unimpl();
case Val.STRS: throw H2O.unimpl();
case Val.FRM: return scalar_op_frame(sslf,rite.getFrame());
default: throw H2O.unimpl();
}
case Val.ROW:
double dslf[] = left.getRow();
switch( rite.type() ) {
case Val.NUM:
double[] right = new double[dslf.length];
Arrays.fill(right, rite.getNum());
return row_op_row(dslf,right,((ValRow)left).getNames());
case Val.ROW: return row_op_row(dslf,rite.getRow(),((ValRow)rite).getNames());
case Val.FRM: return row_op_row(dslf,rite.getRow(),rite.getFrame().names());
default: throw H2O.unimpl();
}
default: throw H2O.unimpl();
}
}
/** Override to express a basic math primitive */
abstract double op( double l, double r );
double str_op( BufferedString l, BufferedString r ) { throw H2O.fail(); }
/** Auto-widen the scalar to every element of the frame */
private ValFrame scalar_op_frame( final double d, Frame fr ) {
Frame res = new MRTask() {
@Override public void map( Chunk[] chks, NewChunk[] cress ) {
for( int c=0; c 1 ) return vec_op_frame(lf.vecs()[0],rt);
if( rt.numCols() == 1 && lf.numCols() > 1 ) return frame_op_vec(lf,rt.vecs()[0]);
if( lf.numCols() != rt.numCols() )
throw new IllegalArgumentException("Frames must have same columns, found "+lf.numCols()+" columns and "+rt.numCols()+" columns.");
Frame res = new MRTask() {
@Override public void map( Chunk[] chks, NewChunk[] cress ) {
BufferedString lfstr = new BufferedString();
BufferedString rtstr = new BufferedString();
assert (cress.length<<1) == chks.length;
for( int c=0; c 2.68
if(Double.isNaN(x)) return x;
double sgn = x < 0 ? -1 : 1;
x = Math.abs(x);
if( (int) digits != digits) digits = Math.round(digits);
double power_of_10 = (int)Math.pow(10, (int)digits);
return sgn*(digits == 0
// go to the even digit
?( x % 1 > 0.5 || (x % 1 == 0.5 && !(Math.floor(x)%2==0)))
? Math.ceil(x)
: Math.floor(x)
: Math.floor(x * power_of_10 + 0.5) / power_of_10);
}
}
class ASTSignif extends ASTBinOp {
public String str() { return "signif"; }
double op(double x, double digits) {
if(Double.isNaN(x)) return x;
if(digits < 1) digits = 1; //mimic R's base::signif
if( (int) digits != digits) digits = Math.round(digits);
java.math.BigDecimal bd = new java.math.BigDecimal(x);
bd = bd.round(new java.math.MathContext((int)digits, java.math.RoundingMode.HALF_EVEN));
return bd.doubleValue();
}
}
class ASTGE extends ASTBinOp { public String str() { return ">="; } double op( double l, double r ) { return l>=r?1:0; } }
class ASTGT extends ASTBinOp { public String str() { return ">" ; } double op( double l, double r ) { return l> r?1:0; } }
class ASTLE extends ASTBinOp { public String str() { return "<="; } double op( double l, double r ) { return l<=r?1:0; } }
class ASTLT extends ASTBinOp { public String str() { return "<" ; } double op( double l, double r ) { return l< r?1:0; } }
class ASTEQ extends ASTBinOp { public String str() { return "=="; } double op( double l, double r ) { return MathUtils.equalsWithinOneSmallUlp(l,r)?1:0; }
double str_op( BufferedString l, BufferedString r ) { return (l==null||l.equals("")) ? (r==null||(r.equals(""))?1:0) : (l.equals(r) ? 1 : 0); }
@Override ValFrame frame_op_scalar( Frame fr, final double d ) {
return new ValFrame(new MRTask() {
@Override public void map( Chunk[] chks, NewChunk[] cress ) {
for( int c=0; c 0; truth => 1
fsIntMap[i] = 0;
tsIntMap[i] = 1;
}
} else if( ts!=null ) {
for(int i=0;i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy