@Override
    public Iterable<Tuple2<MatrixIndexes, MatrixBlock>> call(
        Tuple2<MatrixIndexes, MatrixBlock> arg0) throws Exception {
      ArrayList<Tuple2<MatrixIndexes, MatrixBlock>> ret =
          new ArrayList<Tuple2<MatrixIndexes, MatrixBlock>>();

      MatrixIndexes ixIn = arg0._1();
      MatrixBlock blkIn = arg0._2();

      if (_type == CacheType.LEFT) {
        // for all matching left-hand-side blocks
        int len = _pbc.getNumRowBlocks();
        for (int i = 1; i <= len; i++) {
          MatrixBlock left = _pbc.getMatrixBlock(i, (int) ixIn.getRowIndex());
          MatrixIndexes ixOut = new MatrixIndexes();
          MatrixBlock blkOut = new MatrixBlock();

          // execute matrix-vector mult
          OperationsOnMatrixValues.performAggregateBinary(
              new MatrixIndexes(i, ixIn.getRowIndex()), left, ixIn, blkIn, ixOut, blkOut, _op);

          ret.add(new Tuple2<MatrixIndexes, MatrixBlock>(ixOut, blkOut));
        }
      } else // if( _type == CacheType.RIGHT )
      {
        // for all matching right-hand-side blocks
        int len = _pbc.getNumColumnBlocks();
        for (int j = 1; j <= len; j++) {
          // get the right hand side matrix
          MatrixBlock right = _pbc.getMatrixBlock((int) ixIn.getColumnIndex(), j);
          MatrixIndexes ixOut = new MatrixIndexes();
          MatrixBlock blkOut = new MatrixBlock();

          // execute matrix-vector mult
          OperationsOnMatrixValues.performAggregateBinary(
              ixIn, blkIn, new MatrixIndexes(ixIn.getColumnIndex(), j), right, ixOut, blkOut, _op);

          ret.add(new Tuple2<MatrixIndexes, MatrixBlock>(ixOut, blkOut));
        }
      }

      return ret;
    }