/// <inheritdoc/>
        /// <exception cref="NumberIsTooLargeException"> if <c>m</c> is an
        /// <c>OpenMapRealMatrix</c>, and the total number of entries of the product
        /// is larger than <c>Int32.MaxValue</c>.</exception>
        public new RealMatrix multiply(RealMatrix m)
        {
            try
            {
                return(multiply((OpenMapRealMatrix)m));
            }
            catch (InvalidCastException)
            {
                MatrixUtils.checkMultiplicationCompatible(this, m);

                int             outCols = m.getColumnDimension();
                BlockRealMatrix outp    = new BlockRealMatrix(rows, outCols);
                for (OpenIntToDoubleHashMap.Iterator iterator = entries.iterator(); iterator.MoveNext();)
                {
                    double value = iterator.Current.Value;
                    int    key   = iterator.Current.Key;
                    int    i     = key / columns;
                    int    k     = key % columns;
                    for (int j = 0; j < outCols; ++j)
                    {
                        outp.addToEntry(i, j, value * m.getEntry(k, j));
                    }
                }
                return(outp);
            }
        }
        /// <summary>
        /// Subtract <c>m</c> from this matrix.
        /// </summary>
        /// <param name="m">Matrix to be subtracted.</param>
        /// <returns><c>this</c> - <c>m</c>.</returns>
        /// <exception cref="MatrixDimensionMismatchException"> if <c>m</c> is not the same
        /// size as <c>this</c>.</exception>
        public OpenMapRealMatrix subtract(OpenMapRealMatrix m)
        {
            MatrixUtils.checkAdditionCompatible(this, m);

            OpenMapRealMatrix outp = new OpenMapRealMatrix(this);

            for (OpenIntToDoubleHashMap.Iterator iterator = m.entries.iterator(); iterator.MoveNext();)
            {
                int row = iterator.Current.Key / columns;
                int col = iterator.Current.Key - row * columns;
                outp.setEntry(row, col, getEntry(row, col) - iterator.Current.Value);
            }

            return(outp);
        }
        /// <summary>
        /// Postmultiply this matrix by <c>m</c>.
        /// </summary>
        /// <param name="m">Matrix to postmultiply by.</param>
        /// <returns><c>this</c> * <c>m</c>.</returns>
        /// <exception cref="DimensionMismatchException"> if the number of rows of <c>m</c>
        /// differ from the number of columns of <c>this</c> matrix.</exception>
        /// <exception cref="NumberIsTooLargeException"> if the total number of entries of the
        /// product is larger than <c>Int32.MaxValue</c>.</exception>
        public OpenMapRealMatrix multiply(OpenMapRealMatrix m)
        {
            // Safety check.
            MatrixUtils.checkMultiplicationCompatible(this, m);

            int outCols            = m.getColumnDimension();
            OpenMapRealMatrix outp = new OpenMapRealMatrix(rows, outCols);

            for (OpenIntToDoubleHashMap.Iterator iterator = entries.iterator(); iterator.MoveNext();)
            {
                double value = iterator.Current.Value;
                int    key   = iterator.Current.Key;
                int    i     = key / columns;
                int    k     = key % columns;
                for (int j = 0; j < outCols; ++j)
                {
                    int rightKey = m.computeKey(k, j);
                    if (m.entries.containsKey(rightKey))
                    {
                        int    outKey   = outp.computeKey(i, j);
                        double outValue =
                            outp.entries.get(outKey) + value * m.entries.get(rightKey);
                        if (outValue == 0.0)
                        {
                            outp.entries.remove(outKey);
                        }
                        else
                        {
                            outp.entries.put(outKey, outValue);
                        }
                    }
                }
            }

            return(outp);
        }