class BlockFieldMatrix extends AbstractFieldMatrix<T> implements Serializable {

    @Override
    public FieldMatrix<T> add(final FieldMatrix<T> m)
        throws MatrixDimensionMismatchException {
        try {
            return add((BlockFieldMatrix<T>) m);
        } catch (ClassCastException cce) {

            // safety check
            checkAdditionCompatible(m);

            final BlockFieldMatrix<T> out = new BlockFieldMatrix<T>(getField(), rows, columns);

            // perform addition block-wise, to ensure good cache behavior
            int blockIndex = 0;
            for (int iBlock = 0; iBlock < out.blockRows; ++iBlock) {
                for (int jBlock = 0; jBlock < out.blockColumns; ++jBlock) {

                    // perform addition on the current block
                    final T[] outBlock = out.blocks[blockIndex];
                    final T[] tBlock   = blocks[blockIndex];
                    final int      pStart   = iBlock * BLOCK_SIZE;
                    final int      pEnd     = FastMath.min(pStart + BLOCK_SIZE, rows);
                    final int      qStart   = jBlock * BLOCK_SIZE;
                    final int      qEnd     = FastMath.min(qStart + BLOCK_SIZE, columns);
                    int k = 0;
                    for (int p = pStart; p < pEnd; ++p) {
                        for (int q = qStart; q < qEnd; ++q) {
                            outBlock[k] = tBlock[k].add(m.getEntry(p, q));
                            ++k;
                        }
                    }

                    // go to next block
                    ++blockIndex;

                }
            }

            return out;
        }
    }

    public  BlockFieldMatrix(final Field<T> field, final int rows,
                            final int columns);
    public  BlockFieldMatrix(final T[][] rawData);
    public  BlockFieldMatrix(final int rows, final int columns,
                            final T[][] blockData, final boolean copyArray);

}