package water.rapids.ast.prims.repeaters;
import water.Futures;
import water.fvec.AppendableVec;
import water.fvec.Frame;
import water.fvec.NewChunk;
import water.fvec.Vec;
import water.rapids.Env;
import water.rapids.Val;
import water.rapids.vals.ValFrame;
import water.rapids.ast.AstPrimitive;
import water.rapids.ast.AstRoot;
/**
* Same logic as R's generic seq method
*/
public class AstSeq extends AstPrimitive {
@Override
public String[] args() {
return new String[]{"from", "to", "by"};
}
/* (seq from to by) */
@Override
public int nargs() {
return 1 + 3;
}
@Override
public String str() {
return "seq";
}
@Override
public ValFrame apply(Env env, Env.StackHelp stk, AstRoot asts[]) {
double from = asts[1].exec(env).getNum();
double to = asts[2].exec(env).getNum();
double by = asts[3].exec(env).getNum();
double delta = to - from;
if (delta == 0 && to == 0)
throw new IllegalArgumentException("Expected `to` and `from` to have nonzero difference.");
else {
double n = delta / by;
if (n < 0) throw new IllegalArgumentException("wrong sign in 'by' argument");
else if (n > Double.MAX_VALUE) throw new IllegalArgumentException("'by' argument is much too small");
Futures fs = new Futures();
AppendableVec av = new AppendableVec(Vec.newKey(), Vec.T_NUM);
NewChunk nc = new NewChunk(av, 0);
int len = (int) n + 1;
for (int r = 0; r < len; r++) nc.addNum(from + r * by);
// May need to adjust values = by > 0 ? min(values, to) : max(values, to)
nc.close(0, fs);
Vec vec = av.layout_and_close(fs);
fs.blockForPending();
return new ValFrame(new Frame(vec));
}
}
}