@Override
  public void processInstruction(ExecutionContext ec) throws DMLRuntimeException {
    // obtain and pin input frame
    FrameBlock fin = ec.getFrameInput(input1.getName());
    String spec =
        ec.getScalarInput(input2.getName(), input2.getValueType(), input2.isLiteral())
            .getStringValue();
    String[] colnames = fin.getColumnNames();

    // execute block transform encode
    Encoder encoder = EncoderFactory.createEncoder(spec, colnames, fin.getNumColumns(), null);
    MatrixBlock data =
        encoder.encode(
            fin, new MatrixBlock(fin.getNumRows(), fin.getNumColumns(), false)); // build and apply
    FrameBlock meta = encoder.getMetaData(new FrameBlock(fin.getNumColumns(), ValueType.STRING));
    meta.setColumnNames(colnames);

    // release input and outputs
    ec.releaseFrameInput(input1.getName());
    ec.setMatrixOutput(getOutput(0).getName(), data);
    ec.setFrameOutput(getOutput(1).getName(), meta);
  }
  @Override
  public void processInstruction(ExecutionContext ec) throws DMLRuntimeException {
    // get inputs
    MatrixBlock matBlock1 = ec.getMatrixInput(input1.getName());
    MatrixBlock matBlock2 = ec.getMatrixInput(input2.getName());

    // check input dimensions
    if (_type == AppendType.CBIND && matBlock1.getNumRows() != matBlock2.getNumRows()) {
      throw new DMLRuntimeException(
          "Append-cbind is not possible for input matrices "
              + input1.getName()
              + " and "
              + input2.getName()
              + " with different number of rows: "
              + matBlock1.getNumRows()
              + " vs "
              + matBlock2.getNumRows());
    } else if (_type == AppendType.RBIND
        && matBlock1.getNumColumns() != matBlock2.getNumColumns()) {
      throw new DMLRuntimeException(
          "Append-rbind is not possible for input matrices "
              + input1.getName()
              + " and "
              + input2.getName()
              + " with different number of columns: "
              + matBlock1.getNumColumns()
              + " vs "
              + matBlock2.getNumColumns());
    }

    // execute append operations (append both inputs to initially empty output)
    MatrixBlock ret =
        matBlock1.appendOperations(matBlock2, new MatrixBlock(), _type == AppendType.CBIND);

    // set output and release inputs
    ec.setMatrixOutput(output.getName(), ret);
    ec.releaseMatrixInput(input1.getName());
    ec.releaseMatrixInput(input2.getName());
  }
  @Override
  public void processInstruction(ExecutionContext ec) throws DMLRuntimeException {
    CPOperand mat = (input1.getDataType() == DataType.MATRIX) ? input1 : input2;
    CPOperand scalar = (input1.getDataType() == DataType.MATRIX) ? input2 : input1;

    MatrixBlock inBlock = ec.getMatrixInput(mat.getName());
    ScalarObject constant =
        (ScalarObject)
            ec.getScalarInput(scalar.getName(), scalar.getValueType(), scalar.isLiteral());

    ScalarOperator sc_op = (ScalarOperator) _optr;
    sc_op.setConstant(constant.getDoubleValue());

    MatrixBlock retBlock = (MatrixBlock) inBlock.scalarOperations(sc_op, new MatrixBlock());

    ec.releaseMatrixInput(mat.getName());

    // Ensure right dense/sparse output representation (guarded by released input memory)
    if (checkGuardedRepresentationChange(inBlock, retBlock)) {
      retBlock.examSparsity();
    }

    ec.setMatrixOutput(output.getName(), retBlock);
  }