@Override
  protected double computeIntermediateMemEstimate(long dim1, long dim2, long nnz) {
    // default: no additional memory required
    double val = 0;

    double sparsity = OptimizerUtils.getSparsity(dim1, dim2, nnz);

    switch (_op) // see MatrixAggLib for runtime operations
    {
      case MAX:
      case MIN:
        // worst-case: column-wise, sparse (temp int count arrays)
        if (_direction == Direction.Col) val = dim2 * OptimizerUtils.INT_SIZE;
        break;
      case SUM:
      case SUM_SQ:
        // worst-case correction LASTROW / LASTCOLUMN
        if (_direction == Direction.Col) // (potentially sparse)
        val = OptimizerUtils.estimateSizeExactSparsity(1, dim2, sparsity);
        else if (_direction == Direction.Row) // (always dense)
        val = OptimizerUtils.estimateSizeExactSparsity(dim1, 1, 1.0);
        break;
      case MEAN:
        // worst-case correction LASTTWOROWS / LASTTWOCOLUMNS
        if (_direction == Direction.Col) // (potentially sparse)
        val = OptimizerUtils.estimateSizeExactSparsity(2, dim2, sparsity);
        else if (_direction == Direction.Row) // (always dense)
        val = OptimizerUtils.estimateSizeExactSparsity(dim1, 2, 1.0);
        break;
      case VAR:
        // worst-case correction LASTFOURROWS / LASTFOURCOLUMNS
        if (_direction == Direction.Col) // (potentially sparse)
        val = OptimizerUtils.estimateSizeExactSparsity(4, dim2, sparsity);
        else if (_direction == Direction.Row) // (always dense)
        val = OptimizerUtils.estimateSizeExactSparsity(dim1, 4, 1.0);
        break;
      case MAXINDEX:
      case MININDEX:
        Hop hop = getInput().get(0);
        if (isUnaryAggregateOuterCPRewriteApplicable())
          val = 3 * OptimizerUtils.estimateSizeExactSparsity(1, hop._dim2, 1.0);
        else
          // worst-case correction LASTCOLUMN
          val = OptimizerUtils.estimateSizeExactSparsity(dim1, 1, 1.0);
        break;
      default:
        // no intermediate memory consumption
        val = 0;
    }

    return val;
  }
 @Override
 protected double computeOutputMemEstimate(long dim1, long dim2, long nnz) {
   double sparsity = OptimizerUtils.getSparsity(dim1, dim2, nnz);
   return OptimizerUtils.estimateSizeExactSparsity(dim1, dim2, sparsity);
 }