use of org.apache.sysml.hops.UnaryOp in project incubator-systemml by apache.
the class DMLTranslator method constructHops.
public void constructHops(StatementBlock sb) {
if (sb instanceof WhileStatementBlock) {
constructHopsForWhileControlBlock((WhileStatementBlock) sb);
return;
}
if (sb instanceof IfStatementBlock) {
constructHopsForIfControlBlock((IfStatementBlock) sb);
return;
}
if (sb instanceof ForStatementBlock) {
// incl ParForStatementBlock
constructHopsForForControlBlock((ForStatementBlock) sb);
return;
}
if (sb instanceof FunctionStatementBlock) {
constructHopsForFunctionControlBlock((FunctionStatementBlock) sb);
return;
}
HashMap<String, Hop> ids = new HashMap<>();
ArrayList<Hop> output = new ArrayList<>();
VariableSet liveIn = sb.liveIn();
VariableSet liveOut = sb.liveOut();
VariableSet updated = sb._updated;
VariableSet gen = sb._gen;
VariableSet updatedLiveOut = new VariableSet();
// handle liveout variables that are updated --> target identifiers for Assignment
HashMap<String, Integer> liveOutToTemp = new HashMap<>();
for (int i = 0; i < sb.getNumStatements(); i++) {
Statement current = sb.getStatement(i);
if (current instanceof AssignmentStatement) {
AssignmentStatement as = (AssignmentStatement) current;
DataIdentifier target = as.getTarget();
if (target != null) {
if (liveOut.containsVariable(target.getName())) {
liveOutToTemp.put(target.getName(), Integer.valueOf(i));
}
}
}
if (current instanceof MultiAssignmentStatement) {
MultiAssignmentStatement mas = (MultiAssignmentStatement) current;
for (DataIdentifier target : mas.getTargetList()) {
if (liveOut.containsVariable(target.getName())) {
liveOutToTemp.put(target.getName(), Integer.valueOf(i));
}
}
}
}
// (i.e., from LV analysis, updated and gen sets)
if (!liveIn.getVariables().values().isEmpty()) {
for (String varName : liveIn.getVariables().keySet()) {
if (updated.containsVariable(varName) || gen.containsVariable(varName)) {
DataIdentifier var = liveIn.getVariables().get(varName);
long actualDim1 = (var instanceof IndexedIdentifier) ? ((IndexedIdentifier) var).getOrigDim1() : var.getDim1();
long actualDim2 = (var instanceof IndexedIdentifier) ? ((IndexedIdentifier) var).getOrigDim2() : var.getDim2();
DataOp read = new DataOp(var.getName(), var.getDataType(), var.getValueType(), DataOpTypes.TRANSIENTREAD, null, actualDim1, actualDim2, var.getNnz(), var.getRowsInBlock(), var.getColumnsInBlock());
read.setParseInfo(var);
ids.put(varName, read);
}
}
}
for (int i = 0; i < sb.getNumStatements(); i++) {
Statement current = sb.getStatement(i);
if (current instanceof OutputStatement) {
OutputStatement os = (OutputStatement) current;
DataExpression source = os.getSource();
DataIdentifier target = os.getIdentifier();
// error handling unsupported indexing expression in write statement
if (target instanceof IndexedIdentifier) {
throw new LanguageException(source.printErrorLocation() + ": Unsupported indexing expression in write statement. " + "Please, assign the right indexing result to a variable and write this variable.");
}
DataOp ae = (DataOp) processExpression(source, target, ids);
String formatName = os.getExprParam(DataExpression.FORMAT_TYPE).toString();
ae.setInputFormatType(Expression.convertFormatType(formatName));
if (ae.getDataType() == DataType.SCALAR) {
ae.setOutputParams(ae.getDim1(), ae.getDim2(), ae.getNnz(), ae.getUpdateType(), -1, -1);
} else {
switch(ae.getInputFormatType()) {
case TEXT:
case MM:
case CSV:
// write output in textcell format
ae.setOutputParams(ae.getDim1(), ae.getDim2(), ae.getNnz(), ae.getUpdateType(), -1, -1);
break;
case BINARY:
// write output in binary block format
ae.setOutputParams(ae.getDim1(), ae.getDim2(), ae.getNnz(), ae.getUpdateType(), ConfigurationManager.getBlocksize(), ConfigurationManager.getBlocksize());
break;
default:
throw new LanguageException("Unrecognized file format: " + ae.getInputFormatType());
}
}
output.add(ae);
}
if (current instanceof PrintStatement) {
DataIdentifier target = createTarget();
target.setDataType(DataType.SCALAR);
target.setValueType(ValueType.STRING);
target.setParseInfo(current);
PrintStatement ps = (PrintStatement) current;
PRINTTYPE ptype = ps.getType();
try {
if (ptype == PRINTTYPE.PRINT) {
Hop.OpOp1 op = Hop.OpOp1.PRINT;
Expression source = ps.getExpressions().get(0);
Hop ae = processExpression(source, target, ids);
Hop printHop = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), op, ae);
printHop.setParseInfo(current);
output.add(printHop);
} else if (ptype == PRINTTYPE.ASSERT) {
Hop.OpOp1 op = Hop.OpOp1.ASSERT;
Expression source = ps.getExpressions().get(0);
Hop ae = processExpression(source, target, ids);
Hop printHop = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), op, ae);
printHop.setParseInfo(current);
output.add(printHop);
} else if (ptype == PRINTTYPE.STOP) {
Hop.OpOp1 op = Hop.OpOp1.STOP;
Expression source = ps.getExpressions().get(0);
Hop ae = processExpression(source, target, ids);
Hop stopHop = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), op, ae);
stopHop.setParseInfo(current);
output.add(stopHop);
// avoid merge
sb.setSplitDag(true);
} else if (ptype == PRINTTYPE.PRINTF) {
List<Expression> expressions = ps.getExpressions();
Hop[] inHops = new Hop[expressions.size()];
// Hop (ie, MultipleOp) as input Hops
for (int j = 0; j < expressions.size(); j++) {
Hop inHop = processExpression(expressions.get(j), target, ids);
inHops[j] = inHop;
}
target.setValueType(ValueType.STRING);
Hop printfHop = new NaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOpN.PRINTF, inHops);
output.add(printfHop);
}
} catch (HopsException e) {
throw new LanguageException(e);
}
}
if (current instanceof AssignmentStatement) {
AssignmentStatement as = (AssignmentStatement) current;
DataIdentifier target = as.getTarget();
Expression source = as.getSource();
// CASE: regular assignment statement -- source is DML expression that is NOT user-defined or external function
if (!(source instanceof FunctionCallIdentifier)) {
// CASE: target is regular data identifier
if (!(target instanceof IndexedIdentifier)) {
// process right hand side and accumulation
Hop ae = processExpression(source, target, ids);
if (((AssignmentStatement) current).isAccumulator()) {
DataIdentifier accum = liveIn.getVariable(target.getName());
if (accum == null)
throw new LanguageException("Invalid accumulator assignment " + "to non-existing variable " + target.getName() + ".");
ae = HopRewriteUtils.createBinary(ids.get(target.getName()), ae, OpOp2.PLUS);
target.setProperties(accum.getOutput());
} else
target.setProperties(source.getOutput());
ids.put(target.getName(), ae);
// add transient write if needed
Integer statementId = liveOutToTemp.get(target.getName());
if ((statementId != null) && (statementId.intValue() == i)) {
DataOp transientwrite = new DataOp(target.getName(), target.getDataType(), target.getValueType(), ae, DataOpTypes.TRANSIENTWRITE, null);
transientwrite.setOutputParams(ae.getDim1(), ae.getDim2(), ae.getNnz(), ae.getUpdateType(), ae.getRowsInBlock(), ae.getColsInBlock());
transientwrite.setParseInfo(target);
updatedLiveOut.addVariable(target.getName(), target);
output.add(transientwrite);
}
} else // CASE: target is indexed identifier (left-hand side indexed expression)
{
Hop ae = processLeftIndexedExpression(source, (IndexedIdentifier) target, ids);
ids.put(target.getName(), ae);
// obtain origDim values BEFORE they are potentially updated during setProperties call
// (this is incorrect for LHS Indexing)
long origDim1 = ((IndexedIdentifier) target).getOrigDim1();
long origDim2 = ((IndexedIdentifier) target).getOrigDim2();
target.setProperties(source.getOutput());
((IndexedIdentifier) target).setOriginalDimensions(origDim1, origDim2);
// (required for scalar input to left indexing)
if (target.getDataType() != DataType.MATRIX) {
target.setDataType(DataType.MATRIX);
target.setValueType(ValueType.DOUBLE);
target.setBlockDimensions(ConfigurationManager.getBlocksize(), ConfigurationManager.getBlocksize());
}
Integer statementId = liveOutToTemp.get(target.getName());
if ((statementId != null) && (statementId.intValue() == i)) {
DataOp transientwrite = new DataOp(target.getName(), target.getDataType(), target.getValueType(), ae, DataOpTypes.TRANSIENTWRITE, null);
transientwrite.setOutputParams(origDim1, origDim2, ae.getNnz(), ae.getUpdateType(), ae.getRowsInBlock(), ae.getColsInBlock());
transientwrite.setParseInfo(target);
updatedLiveOut.addVariable(target.getName(), target);
output.add(transientwrite);
}
}
} else {
// assignment, function call
FunctionCallIdentifier fci = (FunctionCallIdentifier) source;
FunctionStatementBlock fsb = this._dmlProg.getFunctionStatementBlock(fci.getNamespace(), fci.getName());
// error handling missing function
if (fsb == null) {
String error = source.printErrorLocation() + "function " + fci.getName() + " is undefined in namespace " + fci.getNamespace();
LOG.error(error);
throw new LanguageException(error);
}
// error handling unsupported function call in indexing expression
if (target instanceof IndexedIdentifier) {
String fkey = DMLProgram.constructFunctionKey(fci.getNamespace(), fci.getName());
throw new LanguageException("Unsupported function call to '" + fkey + "' in left indexing expression. " + "Please, assign the function output to a variable.");
}
ArrayList<Hop> finputs = new ArrayList<>();
for (ParameterExpression paramName : fci.getParamExprs()) {
Hop in = processExpression(paramName.getExpr(), null, ids);
finputs.add(in);
}
// create function op
FunctionType ftype = fsb.getFunctionOpType();
FunctionOp fcall = (target == null) ? new FunctionOp(ftype, fci.getNamespace(), fci.getName(), finputs, new String[] {}, false) : new FunctionOp(ftype, fci.getNamespace(), fci.getName(), finputs, new String[] { target.getName() }, false);
output.add(fcall);
// TODO function output dataops (phase 3)
// DataOp trFoutput = new DataOp(target.getName(), target.getDataType(), target.getValueType(), fcall, DataOpTypes.FUNCTIONOUTPUT, null);
// DataOp twFoutput = new DataOp(target.getName(), target.getDataType(), target.getValueType(), trFoutput, DataOpTypes.TRANSIENTWRITE, null);
}
} else if (current instanceof MultiAssignmentStatement) {
// multi-assignment, by definition a function call
MultiAssignmentStatement mas = (MultiAssignmentStatement) current;
Expression source = mas.getSource();
if (source instanceof FunctionCallIdentifier) {
FunctionCallIdentifier fci = (FunctionCallIdentifier) source;
FunctionStatementBlock fsb = this._dmlProg.getFunctionStatementBlock(fci.getNamespace(), fci.getName());
FunctionStatement fstmt = (FunctionStatement) fsb.getStatement(0);
if (fstmt == null) {
LOG.error(source.printErrorLocation() + "function " + fci.getName() + " is undefined in namespace " + fci.getNamespace());
throw new LanguageException(source.printErrorLocation() + "function " + fci.getName() + " is undefined in namespace " + fci.getNamespace());
}
ArrayList<Hop> finputs = new ArrayList<>();
for (ParameterExpression paramName : fci.getParamExprs()) {
Hop in = processExpression(paramName.getExpr(), null, ids);
finputs.add(in);
}
// create function op
String[] foutputs = mas.getTargetList().stream().map(d -> d.getName()).toArray(String[]::new);
FunctionType ftype = fsb.getFunctionOpType();
FunctionOp fcall = new FunctionOp(ftype, fci.getNamespace(), fci.getName(), finputs, foutputs, false);
output.add(fcall);
// TODO function output dataops (phase 3)
/*for ( DataIdentifier paramName : mas.getTargetList() ){
DataOp twFoutput = new DataOp(paramName.getName(), paramName.getDataType(), paramName.getValueType(), fcall, DataOpTypes.TRANSIENTWRITE, null);
output.add(twFoutput);
}*/
} else if (source instanceof BuiltinFunctionExpression && ((BuiltinFunctionExpression) source).multipleReturns()) {
// construct input hops
Hop fcall = processMultipleReturnBuiltinFunctionExpression((BuiltinFunctionExpression) source, mas.getTargetList(), ids);
output.add(fcall);
} else if (source instanceof ParameterizedBuiltinFunctionExpression && ((ParameterizedBuiltinFunctionExpression) source).multipleReturns()) {
// construct input hops
Hop fcall = processMultipleReturnParameterizedBuiltinFunctionExpression((ParameterizedBuiltinFunctionExpression) source, mas.getTargetList(), ids);
output.add(fcall);
} else
throw new LanguageException("Class \"" + source.getClass() + "\" is not supported in Multiple Assignment statements");
}
}
sb.updateLiveVariablesOut(updatedLiveOut);
sb.setHops(output);
}
use of org.apache.sysml.hops.UnaryOp in project incubator-systemml by apache.
the class DMLTranslator method processBooleanExpression.
private Hop processBooleanExpression(BooleanExpression source, DataIdentifier target, HashMap<String, Hop> hops) {
// Boolean Not has a single parameter
boolean constLeft = (source.getLeft().getOutput() instanceof ConstIdentifier);
boolean constRight = false;
if (source.getRight() != null) {
constRight = (source.getRight().getOutput() instanceof ConstIdentifier);
}
if (constLeft || constRight) {
LOG.error(source.printErrorLocation() + "Boolean expression with constant unsupported");
throw new RuntimeException(source.printErrorLocation() + "Boolean expression with constant unsupported");
}
Hop left = processExpression(source.getLeft(), null, hops);
Hop right = null;
if (source.getRight() != null) {
right = processExpression(source.getRight(), null, hops);
}
// (type should not be determined by target (e.g., string for print)
if (target == null)
target = createTarget(source);
if (target.getDataType().isScalar())
target.setValueType(ValueType.BOOLEAN);
if (source.getRight() == null) {
Hop currUop = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.NOT, left);
currUop.setParseInfo(source);
return currUop;
} else {
Hop currBop = null;
OpOp2 op = null;
if (source.getOpCode() == Expression.BooleanOp.LOGICALAND) {
op = OpOp2.AND;
} else if (source.getOpCode() == Expression.BooleanOp.LOGICALOR) {
op = OpOp2.OR;
} else {
LOG.error(source.printErrorLocation() + "Unknown boolean operation " + source.getOpCode());
throw new RuntimeException(source.printErrorLocation() + "Unknown boolean operation " + source.getOpCode());
}
currBop = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), op, left, right);
currBop.setParseInfo(source);
// setIdentifierParams(currBop,source.getOutput());
return currBop;
}
}
use of org.apache.sysml.hops.UnaryOp in project incubator-systemml by apache.
the class DMLTranslator method processIndexingExpression.
private Hop processIndexingExpression(IndexedIdentifier source, DataIdentifier target, HashMap<String, Hop> hops) {
// process Hops for indexes (for source)
Hop rowLowerHops = null, rowUpperHops = null, colLowerHops = null, colUpperHops = null;
if (source.getRowLowerBound() != null)
rowLowerHops = processExpression(source.getRowLowerBound(), null, hops);
else
rowLowerHops = new LiteralOp(1);
if (source.getRowUpperBound() != null)
rowUpperHops = processExpression(source.getRowUpperBound(), null, hops);
else {
if (source.getOrigDim1() != -1)
rowUpperHops = new LiteralOp(source.getOrigDim1());
else {
rowUpperHops = new UnaryOp(source.getName(), DataType.SCALAR, ValueType.INT, Hop.OpOp1.NROW, hops.get(source.getName()));
rowUpperHops.setParseInfo(source);
}
}
if (source.getColLowerBound() != null)
colLowerHops = processExpression(source.getColLowerBound(), null, hops);
else
colLowerHops = new LiteralOp(1);
if (source.getColUpperBound() != null)
colUpperHops = processExpression(source.getColUpperBound(), null, hops);
else {
if (source.getOrigDim2() != -1)
colUpperHops = new LiteralOp(source.getOrigDim2());
else
colUpperHops = new UnaryOp(source.getName(), DataType.SCALAR, ValueType.INT, Hop.OpOp1.NCOL, hops.get(source.getName()));
}
if (target == null) {
target = createTarget(source);
}
// unknown nnz after range indexing (applies to indexing op but also
// data dependent operations)
target.setNnz(-1);
Hop indexOp = new IndexingOp(target.getName(), target.getDataType(), target.getValueType(), hops.get(source.getName()), rowLowerHops, rowUpperHops, colLowerHops, colUpperHops, source.getRowLowerEqualsUpper(), source.getColLowerEqualsUpper());
indexOp.setParseInfo(target);
setIdentifierParams(indexOp, target);
return indexOp;
}
use of org.apache.sysml.hops.UnaryOp in project incubator-systemml by apache.
the class PlanSelectionFuseCostBased method rGetComputeCosts.
private static void rGetComputeCosts(Hop current, HashSet<Long> partition, HashMap<Long, Double> computeCosts) {
if (computeCosts.containsKey(current.getHopID()))
return;
// recursively process children
for (Hop c : current.getInput()) rGetComputeCosts(c, partition, computeCosts);
// get costs for given hop
double costs = 1;
if (current instanceof UnaryOp) {
switch(((UnaryOp) current).getOp()) {
case ABS:
case ROUND:
case CEIL:
case FLOOR:
case SIGN:
costs = 1;
break;
case SPROP:
case SQRT:
costs = 2;
break;
case EXP:
costs = 18;
break;
case SIGMOID:
costs = 21;
break;
case LOG:
case LOG_NZ:
costs = 32;
break;
case NCOL:
case NROW:
case PRINT:
case ASSERT:
case CAST_AS_BOOLEAN:
case CAST_AS_DOUBLE:
case CAST_AS_INT:
case CAST_AS_MATRIX:
case CAST_AS_SCALAR:
costs = 1;
break;
case SIN:
costs = 18;
break;
case COS:
costs = 22;
break;
case TAN:
costs = 42;
break;
case ASIN:
costs = 93;
break;
case ACOS:
costs = 103;
break;
case ATAN:
costs = 40;
break;
// TODO:
case SINH:
costs = 93;
break;
case COSH:
costs = 103;
break;
case TANH:
costs = 40;
break;
case CUMSUM:
case CUMMIN:
case CUMMAX:
case CUMPROD:
costs = 1;
break;
default:
LOG.warn("Cost model not " + "implemented yet for: " + ((UnaryOp) current).getOp());
}
} else if (current instanceof BinaryOp) {
switch(((BinaryOp) current).getOp()) {
case MULT:
case PLUS:
case MINUS:
case MIN:
case MAX:
case AND:
case OR:
case EQUAL:
case NOTEQUAL:
case LESS:
case LESSEQUAL:
case GREATER:
case GREATEREQUAL:
case CBIND:
case RBIND:
costs = 1;
break;
case INTDIV:
costs = 6;
break;
case MODULUS:
costs = 8;
break;
case DIV:
costs = 22;
break;
case LOG:
case LOG_NZ:
costs = 32;
break;
case POW:
costs = (HopRewriteUtils.isLiteralOfValue(current.getInput().get(1), 2) ? 1 : 16);
break;
case MINUS_NZ:
case MINUS1_MULT:
costs = 2;
break;
case CENTRALMOMENT:
int type = (int) (current.getInput().get(1) instanceof LiteralOp ? HopRewriteUtils.getIntValueSafe((LiteralOp) current.getInput().get(1)) : 2);
switch(type) {
// count
case 0:
costs = 1;
break;
// mean
case 1:
costs = 8;
break;
// cm2
case 2:
costs = 16;
break;
// cm3
case 3:
costs = 31;
break;
// cm4
case 4:
costs = 51;
break;
// variance
case 5:
costs = 16;
break;
}
break;
case COVARIANCE:
costs = 23;
break;
default:
LOG.warn("Cost model not " + "implemented yet for: " + ((BinaryOp) current).getOp());
}
} else if (current instanceof TernaryOp) {
switch(((TernaryOp) current).getOp()) {
case PLUS_MULT:
case MINUS_MULT:
costs = 2;
break;
case CTABLE:
costs = 3;
break;
case CENTRALMOMENT:
int type = (int) (current.getInput().get(1) instanceof LiteralOp ? HopRewriteUtils.getIntValueSafe((LiteralOp) current.getInput().get(1)) : 2);
switch(type) {
// count
case 0:
costs = 2;
break;
// mean
case 1:
costs = 9;
break;
// cm2
case 2:
costs = 17;
break;
// cm3
case 3:
costs = 32;
break;
// cm4
case 4:
costs = 52;
break;
// variance
case 5:
costs = 17;
break;
}
break;
case COVARIANCE:
costs = 23;
break;
default:
LOG.warn("Cost model not " + "implemented yet for: " + ((TernaryOp) current).getOp());
}
} else if (current instanceof ParameterizedBuiltinOp) {
costs = 1;
} else if (current instanceof IndexingOp) {
costs = 1;
} else if (current instanceof ReorgOp) {
costs = 1;
} else if (current instanceof AggBinaryOp) {
// matrix vector
costs = 2;
} else if (current instanceof AggUnaryOp) {
switch(((AggUnaryOp) current).getOp()) {
case SUM:
costs = 4;
break;
case SUM_SQ:
costs = 5;
break;
case MIN:
case MAX:
costs = 1;
break;
default:
LOG.warn("Cost model not " + "implemented yet for: " + ((AggUnaryOp) current).getOp());
}
}
computeCosts.put(current.getHopID(), costs);
}
use of org.apache.sysml.hops.UnaryOp in project incubator-systemml by apache.
the class TemplateRow method rConstructCplan.
private void rConstructCplan(Hop hop, CPlanMemoTable memo, HashMap<Long, CNode> tmp, HashSet<Hop> inHops, HashMap<String, Hop> inHops2, boolean compileLiterals) {
// memoization for common subexpression elimination and to avoid redundant work
if (tmp.containsKey(hop.getHopID()))
return;
// recursively process required childs
MemoTableEntry me = memo.getBest(hop.getHopID(), TemplateType.ROW, TemplateType.CELL);
for (int i = 0; i < hop.getInput().size(); i++) {
Hop c = hop.getInput().get(i);
if (me != null && me.isPlanRef(i))
rConstructCplan(c, memo, tmp, inHops, inHops2, compileLiterals);
else {
CNodeData cdata = TemplateUtils.createCNodeData(c, compileLiterals);
tmp.put(c.getHopID(), cdata);
inHops.add(c);
}
}
// construct cnode for current hop
CNode out = null;
if (hop instanceof AggUnaryOp) {
CNode cdata1 = tmp.get(hop.getInput().get(0).getHopID());
if (((AggUnaryOp) hop).getDirection() == Direction.Row && HopRewriteUtils.isAggUnaryOp(hop, SUPPORTED_ROW_AGG)) {
if (hop.getInput().get(0).getDim2() == 1)
out = (cdata1.getDataType() == DataType.SCALAR) ? cdata1 : new CNodeUnary(cdata1, UnaryType.LOOKUP_R);
else {
String opcode = "ROW_" + ((AggUnaryOp) hop).getOp().name().toUpperCase() + "S";
out = new CNodeUnary(cdata1, UnaryType.valueOf(opcode));
if (cdata1 instanceof CNodeData && !inHops2.containsKey("X"))
inHops2.put("X", hop.getInput().get(0));
}
} else if (((AggUnaryOp) hop).getDirection() == Direction.Col && ((AggUnaryOp) hop).getOp() == AggOp.SUM) {
// vector add without temporary copy
if (cdata1 instanceof CNodeBinary && ((CNodeBinary) cdata1).getType().isVectorScalarPrimitive())
out = new CNodeBinary(cdata1.getInput().get(0), cdata1.getInput().get(1), ((CNodeBinary) cdata1).getType().getVectorAddPrimitive());
else
out = cdata1;
} else if (((AggUnaryOp) hop).getDirection() == Direction.RowCol && ((AggUnaryOp) hop).getOp() == AggOp.SUM) {
out = (cdata1.getDataType().isMatrix()) ? new CNodeUnary(cdata1, UnaryType.ROW_SUMS) : cdata1;
}
} else if (hop instanceof AggBinaryOp) {
CNode cdata1 = tmp.get(hop.getInput().get(0).getHopID());
CNode cdata2 = tmp.get(hop.getInput().get(1).getHopID());
if (HopRewriteUtils.isTransposeOperation(hop.getInput().get(0))) {
// correct input under transpose
cdata1 = TemplateUtils.skipTranspose(cdata1, hop.getInput().get(0), tmp, compileLiterals);
inHops.remove(hop.getInput().get(0));
if (cdata1 instanceof CNodeData)
inHops.add(hop.getInput().get(0).getInput().get(0));
// note: vectorMultAdd applicable to vector-scalar, and vector-vector
if (hop.getInput().get(1).getDim2() == 1)
out = new CNodeBinary(cdata1, cdata2, BinType.VECT_MULT_ADD);
else {
out = new CNodeBinary(cdata1, cdata2, BinType.VECT_OUTERMULT_ADD);
if (!inHops2.containsKey("B1")) {
// incl modification of X for consistency
if (cdata1 instanceof CNodeData)
inHops2.put("X", hop.getInput().get(0).getInput().get(0));
inHops2.put("B1", hop.getInput().get(1));
}
}
if (!inHops2.containsKey("X"))
inHops2.put("X", hop.getInput().get(0).getInput().get(0));
} else {
if (hop.getInput().get(0).getDim2() == 1 && hop.getInput().get(1).getDim2() == 1)
out = new CNodeBinary((cdata1.getDataType() == DataType.SCALAR) ? cdata1 : new CNodeUnary(cdata1, UnaryType.LOOKUP0), (cdata2.getDataType() == DataType.SCALAR) ? cdata2 : new CNodeUnary(cdata2, UnaryType.LOOKUP0), BinType.MULT);
else if (hop.getInput().get(1).getDim2() == 1) {
out = new CNodeBinary(cdata1, cdata2, BinType.DOT_PRODUCT);
inHops2.put("X", hop.getInput().get(0));
} else {
out = new CNodeBinary(cdata1, cdata2, BinType.VECT_MATRIXMULT);
inHops2.put("X", hop.getInput().get(0));
inHops2.put("B1", hop.getInput().get(1));
}
}
} else if (HopRewriteUtils.isTransposeOperation(hop)) {
out = TemplateUtils.skipTranspose(tmp.get(hop.getHopID()), hop, tmp, compileLiterals);
if (out instanceof CNodeData && !inHops.contains(hop.getInput().get(0)))
inHops.add(hop.getInput().get(0));
} else if (hop instanceof UnaryOp) {
CNode cdata1 = tmp.get(hop.getInput().get(0).getHopID());
// if one input is a matrix then we need to do vector by scalar operations
if (hop.getInput().get(0).getDim1() >= 1 && hop.getInput().get(0).getDim2() > 1 || (!hop.dimsKnown() && cdata1.getDataType() == DataType.MATRIX)) {
if (HopRewriteUtils.isUnary(hop, SUPPORTED_VECT_UNARY)) {
String opname = "VECT_" + ((UnaryOp) hop).getOp().name();
out = new CNodeUnary(cdata1, UnaryType.valueOf(opname));
if (cdata1 instanceof CNodeData && !inHops2.containsKey("X"))
inHops2.put("X", hop.getInput().get(0));
} else
throw new RuntimeException("Unsupported unary matrix " + "operation: " + ((UnaryOp) hop).getOp().name());
} else // general scalar case
{
cdata1 = TemplateUtils.wrapLookupIfNecessary(cdata1, hop.getInput().get(0));
String primitiveOpName = ((UnaryOp) hop).getOp().toString();
out = new CNodeUnary(cdata1, UnaryType.valueOf(primitiveOpName));
}
} else if (HopRewriteUtils.isBinary(hop, OpOp2.CBIND)) {
// special case for cbind with zeros
CNode cdata1 = tmp.get(hop.getInput().get(0).getHopID());
CNode cdata2 = null;
if (HopRewriteUtils.isDataGenOpWithConstantValue(hop.getInput().get(1))) {
cdata2 = TemplateUtils.createCNodeData(HopRewriteUtils.getDataGenOpConstantValue(hop.getInput().get(1)), true);
// rm 0-matrix
inHops.remove(hop.getInput().get(1));
} else {
cdata2 = tmp.get(hop.getInput().get(1).getHopID());
cdata2 = TemplateUtils.wrapLookupIfNecessary(cdata2, hop.getInput().get(1));
}
out = new CNodeBinary(cdata1, cdata2, BinType.VECT_CBIND);
if (cdata1 instanceof CNodeData && !inHops2.containsKey("X"))
inHops2.put("X", hop.getInput().get(0));
} else if (hop instanceof BinaryOp) {
CNode cdata1 = tmp.get(hop.getInput().get(0).getHopID());
CNode cdata2 = tmp.get(hop.getInput().get(1).getHopID());
// if one input is a matrix then we need to do vector by scalar operations
if ((hop.getInput().get(0).getDim1() >= 1 && hop.getInput().get(0).getDim2() > 1) || (hop.getInput().get(1).getDim1() >= 1 && hop.getInput().get(1).getDim2() > 1) || (!(hop.dimsKnown() && hop.getInput().get(0).dimsKnown() && hop.getInput().get(1).dimsKnown()) && // not a known vector output
(hop.getDim2() != 1) && (cdata1.getDataType().isMatrix() || cdata2.getDataType().isMatrix()))) {
if (HopRewriteUtils.isBinary(hop, SUPPORTED_VECT_BINARY)) {
if (TemplateUtils.isMatrix(cdata1) && (TemplateUtils.isMatrix(cdata2) || TemplateUtils.isRowVector(cdata2))) {
String opname = "VECT_" + ((BinaryOp) hop).getOp().name();
out = new CNodeBinary(cdata1, cdata2, BinType.valueOf(opname));
} else {
String opname = "VECT_" + ((BinaryOp) hop).getOp().name() + "_SCALAR";
if (TemplateUtils.isColVector(cdata1))
cdata1 = new CNodeUnary(cdata1, UnaryType.LOOKUP_R);
if (TemplateUtils.isColVector(cdata2))
cdata2 = new CNodeUnary(cdata2, UnaryType.LOOKUP_R);
out = new CNodeBinary(cdata1, cdata2, BinType.valueOf(opname));
}
if (cdata1 instanceof CNodeData && !inHops2.containsKey("X") && !(cdata1.getDataType() == DataType.SCALAR)) {
inHops2.put("X", hop.getInput().get(0));
}
} else
throw new RuntimeException("Unsupported binary matrix " + "operation: " + ((BinaryOp) hop).getOp().name());
} else // one input is a vector/scalar other is a scalar
{
String primitiveOpName = ((BinaryOp) hop).getOp().toString();
if (TemplateUtils.isColVector(cdata1))
cdata1 = new CNodeUnary(cdata1, UnaryType.LOOKUP_R);
if (// vector or vector can be inferred from lhs
TemplateUtils.isColVector(cdata2) || (TemplateUtils.isColVector(hop.getInput().get(0)) && cdata2 instanceof CNodeData && hop.getInput().get(1).getDataType().isMatrix()))
cdata2 = new CNodeUnary(cdata2, UnaryType.LOOKUP_R);
out = new CNodeBinary(cdata1, cdata2, BinType.valueOf(primitiveOpName));
}
} else if (hop instanceof TernaryOp) {
TernaryOp top = (TernaryOp) hop;
CNode cdata1 = tmp.get(hop.getInput().get(0).getHopID());
CNode cdata2 = tmp.get(hop.getInput().get(1).getHopID());
CNode cdata3 = tmp.get(hop.getInput().get(2).getHopID());
// add lookups if required
cdata1 = TemplateUtils.wrapLookupIfNecessary(cdata1, hop.getInput().get(0));
cdata3 = TemplateUtils.wrapLookupIfNecessary(cdata3, hop.getInput().get(2));
// construct ternary cnode, primitive operation derived from OpOp3
out = new CNodeTernary(cdata1, cdata2, cdata3, TernaryType.valueOf(top.getOp().toString()));
} else if (HopRewriteUtils.isNary(hop, OpOpN.CBIND)) {
CNode[] inputs = new CNode[hop.getInput().size()];
for (int i = 0; i < hop.getInput().size(); i++) {
Hop c = hop.getInput().get(i);
CNode cdata = tmp.get(c.getHopID());
if (TemplateUtils.isColVector(cdata) || TemplateUtils.isRowVector(cdata))
cdata = TemplateUtils.wrapLookupIfNecessary(cdata, c);
inputs[i] = cdata;
if (i == 0 && cdata instanceof CNodeData && !inHops2.containsKey("X"))
inHops2.put("X", c);
}
out = new CNodeNary(inputs, NaryType.VECT_CBIND);
} else if (hop instanceof ParameterizedBuiltinOp) {
CNode cdata1 = tmp.get(((ParameterizedBuiltinOp) hop).getTargetHop().getHopID());
cdata1 = TemplateUtils.wrapLookupIfNecessary(cdata1, hop.getInput().get(0));
CNode cdata2 = tmp.get(((ParameterizedBuiltinOp) hop).getParameterHop("pattern").getHopID());
CNode cdata3 = tmp.get(((ParameterizedBuiltinOp) hop).getParameterHop("replacement").getHopID());
TernaryType ttype = (cdata2.isLiteral() && cdata2.getVarname().equals("Double.NaN")) ? TernaryType.REPLACE_NAN : TernaryType.REPLACE;
out = new CNodeTernary(cdata1, cdata2, cdata3, ttype);
} else if (hop instanceof IndexingOp) {
CNode cdata1 = tmp.get(hop.getInput().get(0).getHopID());
out = new CNodeTernary(cdata1, TemplateUtils.createCNodeData(new LiteralOp(hop.getInput().get(0).getDim2()), true), TemplateUtils.createCNodeData(hop.getInput().get(4), true), (hop.getDim2() != 1) ? TernaryType.LOOKUP_RVECT1 : TernaryType.LOOKUP_RC1);
}
if (out == null) {
throw new RuntimeException(hop.getHopID() + " " + hop.getOpString());
}
if (out.getDataType().isMatrix()) {
out.setNumRows(hop.getDim1());
out.setNumCols(hop.getDim2());
}
tmp.put(hop.getHopID(), out);
}
Aggregations