package water.rapids.ast.prims.reducers;
import water.MRTask;
import water.fvec.Chunk;
import water.fvec.Frame;
import water.fvec.Vec;
import water.rapids.Env;
import water.rapids.vals.ValNum;
import water.rapids.ast.AstPrimitive;
import water.rapids.ast.AstRoot;
/**
*/
public class AstProd extends AstPrimitive {
@Override
public String[] args() {
return new String[]{"ary"};
}
@Override
public int nargs() {
return 1 + 1;
} // (prod x)
@Override
public String str() {
return "prod";
}
@Override
public ValNum apply(Env env, Env.StackHelp stk, AstRoot asts[]) {
Frame fr = stk.track(asts[1].exec(env)).getFrame();
for (Vec v : fr.vecs())
if (v.isCategorical() || v.isUUID() || v.isString())
throw new IllegalArgumentException("`" + str() + "`" + " only defined on a data frame with all numeric variables");
double prod = new AstProd.RedProd().doAll(fr)._d;
return new ValNum(prod);
}
private static class RedProd extends MRTask<AstProd.RedProd> {
double _d;
@Override
public void map(Chunk chks[]) {
int rows = chks[0]._len;
for (Chunk C : chks) {
double prod = 1.;
for (int r = 0; r < rows; r++)
prod *= C.atd(r);
_d = prod;
if (Double.isNaN(prod)) break;
}
}
@Override
public void reduce(AstProd.RedProd s) {
_d *= s._d;
}
}
}