/**
         * <p>
         * x<sup>T</sup>A<sup>T</sup>y
         * </p>
         *
         * @param x  A vector with n elements. Not modified.
         * @param A  A matrix with n by n elements.  Not modified.
         * @param y  A vector with n elements. Not modified.
         * @return  The results.
         */
        // TODO better name for this
        public static float innerProdTranA(FMatrixD1 x, FMatrixD1 A, FMatrixD1 y)
        {
            int n = A.numRows;

            if (n != A.numCols)
            {
                throw new ArgumentException("A must be square");
            }

            if (x.getNumElements() != n)
            {
                throw new ArgumentException("Unexpected number of elements in x");
            }
            if (y.getNumElements() != n)
            {
                throw new ArgumentException("Unexpected number of elements in y");
            }

            float result = 0;

            for (int i = 0; i < n; i++)
            {
                float total = 0;

                for (int j = 0; j < n; j++)
                {
                    total += x.get(j) * A.unsafe_get(i, j);
                }

                result += total * y.get(i);
            }

            return(result);
        }
Beispiel #2
0
        /**
         * Creates a window visually showing the matrix's state.  Block means an element is zero.
         * Red positive and blue negative.  More intense the color larger the element's absolute value
         * is.
         *
         * @param A A matrix.
         * @param title Name of the window.
         */
        public static void show(FMatrixD1 A, string title)
        {
            // TODO : BRS: Implement for .NET
            throw new NotImplementedException();

            /*
             * JFrame frame = new JFrame(title);
             *
             * int width = 300;
             * int height = 300;
             *
             * if (A.numRows > A.numCols)
             * {
             *  width = width * A.numCols / A.numRows;
             * }
             * else
             * {
             *  height = height * A.numRows / A.numCols;
             * }
             *
             * FMatrixComponent panel = new FMatrixComponent(width, height);
             * panel.setMatrix(A);
             *
             * frame.add(panel, BorderLayout.CENTER);
             *
             * frame.pack();
             * frame.setVisible(true);
             */
        }
        /**
         * <p>
         * Adds to A &isin; &real; <sup>m &times; n</sup> the results of an outer product multiplication
         * of the two vectors.  This is also known as a rank 1 update.<br>
         * <br>
         * A = A + &gamma; x * y<sup>T</sup>
         * where x &isin; &real; <sup>m</sup> and y &isin; &real; <sup>n</sup> are vectors.
         * </p>
         * <p>
         * Which is equivalent to: A<sub>ij</sub> = A<sub>ij</sub> + &gamma; x<sub>i</sub>*y<sub>j</sub>
         * </p>
         *
         * <p>
         * These functions are often used inside of highly optimized code and therefor sanity checks are
         * kept to a minimum.  It is not recommended that any of these functions be used directly.
         * </p>
         *
         * @param gamma A multiplication factor for the outer product.
         * @param x A vector with m elements. Not modified.
         * @param y A vector with n elements. Not modified.
         * @param A A Matrix with m by n elements. Modified.
         */
        public static void addOuterProd(float gamma, FMatrixD1 x, FMatrixD1 y, FMatrix1Row A)
        {
            int m = A.numRows;
            int n = A.numCols;

            int index = 0;

            if (gamma == 1.0f)
            {
                for (int i = 0; i < m; i++)
                {
                    float xdat = x.get(i);
                    for (int j = 0; j < n; j++)
                    {
                        A.plus(index++, xdat * y.get(j));
                    }
                }
            }
            else
            {
                for (int i = 0; i < m; i++)
                {
                    float xdat = x.get(i);
                    for (int j = 0; j < n; j++)
                    {
                        A.plus(index++, gamma * xdat * y.get(j));
                    }
                }
            }
        }
        /**
         * <p>
         * Sets each element in the matrix to a value drawn from an Gaussian distribution with the specified mean and
         * standard deviation
         * </p>
         *
         * @param mat The matrix who is to be randomized. Modified.
         * @param mean Mean value in the distribution
         * @param stdev Standard deviation in the distribution
         * @param rand Random number generator used to fill the matrix.
         */
        public static void fillGaussian(FMatrixD1 mat, float mean, float stdev, IMersenneTwister rand)
        {
            float[] d    = mat.getData();
            int     size = mat.getNumElements();

            for (int i = 0; i < size; i++)
            {
                d[i] = mean + stdev * (float)rand.NextGaussian();
            }
        }
Beispiel #5
0
        public /* synchronized */ void setMatrix(FMatrixD1 A)
        {
            // TODO : BRS: Implement for .NET
            throw new NotImplementedException();

            /*
             * float maxValue = CommonOps_FDRM.elementMaxAbs(A);
             * renderMatrix(A, image, maxValue);
             * repaint();
             */
        }
        /**
         * <p>
         * Sets each element in the matrix to a value drawn from an uniform distribution from 'min' to 'max' inclusive.
         * </p>
         *
         * @param min The minimum value each element can be.
         * @param max The maximum value each element can be.
         * @param mat The matrix who is to be randomized. Modified.
         * @param rand Random number generator used to fill the matrix.
         */
        public static void fillUniform(FMatrixD1 mat, float min, float max, IMersenneTwister rand)
        {
            float[] d    = mat.getData();
            int     size = mat.getNumElements();

            float r = max - min;

            for (int i = 0; i < size; i++)
            {
                d[i] = r * rand.NextFloat() + min;
            }
        }
Beispiel #7
0
        /**
         * An alternative implementation of {@link #multTransA_small} that performs well on large
         * matrices.  There is a relative performance hit when used on small matrices.
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A Vector that has length m. Not modified.
         * @param C A column vector that has length n. Modified.
         */
        public static void multTransA_reorder(FMatrix1Row A, FMatrixD1 B, FMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numCols)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }
            if (B.numRows == 1)
            {
                if (A.numRows != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numRows != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            if (A.numRows == 0)
            {
                CommonOps_FDRM.fill(C, 0);
                return;
            }

            float B_val = B.get(0);

            for (int i = 0; i < A.numCols; i++)
            {
                C.set(i, A.get(i) * B_val);
            }

            int indexA = A.numCols;

            for (int i = 1; i < A.numRows; i++)
            {
                B_val = B.get(i);
                for (int j = 0; j < A.numCols; j++)
                {
                    C.plus(j, A.get(indexA++) * B_val);
                }
            }
        }
Beispiel #8
0
        /**
         * <p>
         * Performs a matrix vector multiply.<br>
         * <br>
         * c = A * b <br>
         * and<br>
         * c = A * b<sup>T</sup> <br>
         * <br>
         * c<sub>i</sub> = Sum{ j=1:n, a<sub>ij</sub> * b<sub>j</sub>}<br>
         * <br>
         * where A is a matrix, b is a column or transposed row vector, and c is a column vector.
         * </p>
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A vector that has length n. Not modified.
         * @param C A column vector that has length m. Modified.
         */
        public static void mult(FMatrix1Row A, FMatrixD1 B, FMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numRows)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }

            if (B.numRows == 1)
            {
                if (A.numCols != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numCols != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            if (A.numCols == 0)
            {
                CommonOps_FDRM.fill(C, 0);
                return;
            }

            int   indexA = 0;
            int   cIndex = 0;
            float b0     = B.get(0);

            for (int i = 0; i < A.numRows; i++)
            {
                float total = A.get(indexA++) * b0;

                for (int j = 1; j < A.numCols; j++)
                {
                    total += A.get(indexA++) * B.get(j);
                }

                C.set(cIndex++, total);
            }
        }
        /**
         * Checks to see if any element in the matrix is NaN.
         *
         * @param m A matrix. Not modified.
         * @return True if any element in the matrix is NaN.
         */
        public static bool hasNaN(FMatrixD1 m)
        {
            int length = m.getNumElements();

            for (int i = 0; i < length; i++)
            {
                if (float.IsNaN(m.get(i)))
                {
                    return(true);
                }
            }
            return(false);
        }
        /**
         * <p>
         * Computes the inner product of the two vectors.  In geometry this is known as the dot product.<br>
         * <br>
         * &sum;<sub>k=1:n</sub> x<sub>k</sub> * y<sub>k</sub><br>
         * where x and y are vectors with n elements.
         * </p>
         *
         * <p>
         * These functions are often used inside of highly optimized code and therefor sanity checks are
         * kept to a minimum.  It is not recommended that any of these functions be used directly.
         * </p>
         *
         * @param x A vector with n elements. Not modified.
         * @param y A vector with n elements. Not modified.
         * @return The inner product of the two vectors.
         */
        public static float innerProd(FMatrixD1 x, FMatrixD1 y)
        {
            int m = x.getNumElements();

            float total = 0;

            for (int i = 0; i < m; i++)
            {
                total += x.get(i) * y.get(i);
            }

            return(total);
        }
        /**
         * Checks to see all the elements in the matrix are zeros
         *
         * @param m A matrix. Not modified.
         * @return True if all elements are zeros or false if not
         */
        public static bool isZeros(FMatrixD1 m, float tol)
        {
            int length = m.getNumElements();

            for (int i = 0; i < length; i++)
            {
                if (Math.Abs(m.get(i)) > tol)
                {
                    return(false);
                }
            }
            return(true);
        }
Beispiel #12
0
        /**
         * <p>
         * This implementation of the Frobenius norm is a straight forward implementation and can
         * be susceptible for overflow/underflow issues.  A more resilient implementation is
         * {@link #normF}.
         * </p>
         *
         * @param a The matrix whose norm is computed.  Not modified.
         */
        public static float fastNormF(FMatrixD1 a)
        {
            float total = 0;

            int size = a.getNumElements();

            for (int i = 0; i < size; i++)
            {
                float val = a.get(i);
                total += val * val;
            }

            return((float)Math.Sqrt(total));
        }
        /**
         * Checks to see if any element in the matrix is NaN of Infinite.
         *
         * @param m A matrix. Not modified.
         * @return True if any element in the matrix is NaN of Infinite.
         */
        public static bool hasUncountable(FMatrixD1 m)
        {
            int length = m.getNumElements();

            for (int i = 0; i < length; i++)
            {
                float a = m.get(i);
                if (float.IsNaN(a) || float.IsInfinity(a))
                {
                    return(true);
                }
            }
            return(false);
        }
Beispiel #14
0
        /**
         * Sums up the square of each element in the matrix.  This is equivalent to the
         * Frobenius norm squared.
         *
         * @param m Matrix.
         * @return Sum of elements squared.
         */
        public static float elementSumSq(FMatrixD1 m)
        {
            float total = 0;

            int N = m.getNumElements();

            for (int i = 0; i < N; i++)
            {
                float d = m.data[i];
                total += d * d;
            }

            return(total);
        }
Beispiel #15
0
        /**
         * Converts the real matrix into a complex matrix.
         *
         * @param input Real matrix. Not modified.
         * @param output Complex matrix. Modified.
         */
        public static void convert(FMatrixD1 input, CMatrixD1 output)
        {
            if (input.numCols != output.numCols || input.numRows != output.numRows)
            {
                throw new ArgumentException("The matrices are not all the same dimension.");
            }

            Array.Clear(output.data, 0, output.getDataLength());

            int length = output.getDataLength();

            for (int i = 0; i < length; i += 2)
            {
                output.data[i] = input.data[i / 2];
            }
        }
        /**
         * <p>
         * Sets A &isin; &real; <sup>m &times; n</sup> equal to an outer product multiplication of the two
         * vectors.  This is also known as a rank-1 operation.<br>
         * <br>
         * A = x * y'
         * where x &isin; &real; <sup>m</sup> and y &isin; &real; <sup>n</sup> are vectors.
         * </p>
         * <p>
         * Which is equivalent to: A<sub>ij</sub> = x<sub>i</sub>*y<sub>j</sub>
         * </p>
         *
         * <p>
         * These functions are often used inside of highly optimized code and therefor sanity checks are
         * kept to a minimum.  It is not recommended that any of these functions be used directly.
         * </p>
         *
         * @param x A vector with m elements. Not modified.
         * @param y A vector with n elements. Not modified.
         * @param A A Matrix with m by n elements. Modified.
         */
        public static void outerProd(FMatrixD1 x, FMatrixD1 y, FMatrix1Row A)
        {
            int m = A.numRows;
            int n = A.numCols;

            int index = 0;

            for (int i = 0; i < m; i++)
            {
                float xdat = x.get(i);
                for (int j = 0; j < n; j++)
                {
                    A.set(index++, xdat * y.get(j));
                }
            }
        }
Beispiel #17
0
        /**
         * <p>
         * Computes the F norm of the difference between the two Matrices:<br>
         * <br>
         * Sqrt{&sum;<sub>i=1:m</sub> &sum;<sub>j=1:n</sub> ( a<sub>ij</sub> - b<sub>ij</sub>)<sup>2</sup>}
         * </p>
         * <p>
         * This is often used as a cost function.
         * </p>
         *
         * @see NormOps_FDRM#fastNormF
         *
         * @param a m by n matrix. Not modified.
         * @param b m by n matrix. Not modified.
         *
         * @return The F normal of the difference matrix.
         */
        public static float diffNormF(FMatrixD1 a, FMatrixD1 b)
        {
            if (a.numRows != b.numRows || a.numCols != b.numCols)
            {
                throw new ArgumentException("Both matrices must have the same shape.");
            }

            int size = a.getNumElements();

            FMatrixRMaj diff = new FMatrixRMaj(size, 1);

            for (int i = 0; i < size; i++)
            {
                diff.set(i, b.get(i) - a.get(i));
            }
            return(NormOps_FDRM.normF(diff));
        }
Beispiel #18
0
        /**
         * <p>
         * Computes the p=1 p-norm of the difference between the two Matrices:<br>
         * <br>
         * &sum;<sub>i=1:m</sub> &sum;<sub>j=1:n</sub> | a<sub>ij</sub> - b<sub>ij</sub>| <br>
         * <br>
         * where |x| is the absolute value of x.
         * </p>
         * <p>
         * This is often used as a cost function.
         * </p>
         *
         * @param a m by n matrix. Not modified.
         * @param b m by n matrix. Not modified.
         *
         * @return The p=1 p-norm of the difference matrix.
         */
        public static float diffNormP1(FMatrixD1 a, FMatrixD1 b)
        {
            if (a.numRows != b.numRows || a.numCols != b.numCols)
            {
                throw new ArgumentException("Both matrices must have the same shape.");
            }

            int size = a.getNumElements();

            float total = 0;

            for (int i = 0; i < size; i++)
            {
                total += Math.Abs(b.get(i) - a.get(i));
            }
            return(total);
        }
Beispiel #19
0
        /**
         * <p>
         * Returns the absolute value of the digonal element in the matrix that has the largest absolute value.<br>
         * <br>
         * Max{ |a<sub>ij</sub>| } for all i and j<br>
         * </p>
         *
         * @param a A matrix. Not modified.
         * @return The max abs element value of the matrix.
         */
        public static float elementDiagonalMaxAbs(FMatrixD1 a)
        {
            int size = Math.Min(a.numRows, a.numCols);

            float max = 0;

            for (int i = 0; i < size; i++)
            {
                float val = Math.Abs(a.get(i, i));
                if (val > max)
                {
                    max = val;
                }
            }

            return(max);
        }
        /**
         * <p>
         * Multiplies a householder reflection against a vector:<br>
         * <br>
         * y = (I + &gamma; u u<sup>T</sup>)x<br>
         * </p>
         * <p>
         * The Householder reflection is used in some implementations of QR decomposition.
         * </p>
         * @param u A vector. Not modified.
         * @param x a vector. Not modified.
         * @param y Vector where the result are written to.
         */
        public static void householder(float gamma,
                                       FMatrixD1 u,
                                       FMatrixD1 x, FMatrixD1 y)
        {
            int n = u.getNumElements();

            float sum = 0;

            for (int i = 0; i < n; i++)
            {
                sum += u.get(i) * x.get(i);
            }
            for (int i = 0; i < n; i++)
            {
                y.set(i, x.get(i) + gamma * u.get(i) * sum);
            }
        }
Beispiel #21
0
        /**
         * <p>
         * Computes the magnitude of the complex number in the input matrix and stores the results in the output
         * matrix.
         * </p>
         *
         * magnitude = sqrt(real^2 + imaginary^2)
         *
         * @param input Complex matrix. Not modified.
         * @param output real matrix. Modified.
         */
        public static void magnitude(CMatrixD1 input, FMatrixD1 output)
        {
            if (input.numCols != output.numCols || input.numRows != output.numRows)
            {
                throw new ArgumentException("The matrices are not all the same dimension.");
            }

            int length = input.getDataLength();

            for (int i = 0; i < length; i += 2)
            {
                float real      = input.data[i];
                float imaginary = input.data[i + 1];

                output.data[i / 2] = (float)Math.Sqrt(real * real + imaginary * imaginary);
            }
        }
Beispiel #22
0
        /**
         * <p>
         * Performs a matrix vector multiply.<br>
         * <br>
         * C = C + A<sup>T</sup> * B <br>
         * or<br>
         * C = C<sup>T</sup> + A<sup>T</sup> * B<sup>T</sup> <br>
         * <br>
         * c<sub>i</sub> = Sum{ j=1:n, c<sub>i</sub> + a<sub>ji</sub> * b<sub>j</sub>}<br>
         * <br>
         * where A is a matrix, B is a column or transposed row vector, and C is a column vector.
         * </p>
         * <p>
         * This implementation is optimal for small matrices.  There is a huge performance hit when
         * used on large matrices due to CPU cache issues.
         * </p>
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A vector that has length m. Not modified.
         * @param C A column vector that has length n. Modified.
         */
        public static void multAddTransA_small(FMatrix1Row A, FMatrixD1 B, FMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numCols)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }
            if (B.numRows == 1)
            {
                if (A.numRows != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numRows != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            int cIndex = 0;

            for (int i = 0; i < A.numCols; i++)
            {
                float total = 0.0f;

                int indexA = i;
                for (int j = 0; j < A.numRows; j++)
                {
                    total  += A.get(indexA) * B.get(j);
                    indexA += A.numCols;
                }

                C.plus(cIndex++, total);
            }
        }
Beispiel #23
0
        public static float diffNormF_fast(FMatrixD1 a, FMatrixD1 b)
        {
            if (a.numRows != b.numRows || a.numCols != b.numCols)
            {
                throw new ArgumentException("Both matrices must have the same shape.");
            }

            int size = a.getNumElements();

            float total = 0;

            for (int i = 0; i < size; i++)
            {
                float diff = b.get(i) - a.get(i);
                total += diff * diff;
            }
            return((float)Math.Sqrt(total));
        }
        /**
         * <p>
         * Checks to see if the two matrices are the negative of each other:<br>
         * <br>
         * a<sub>ij</sub> = -b<sub>ij</sub>
         * </p>
         *
         * @param a First matrix.  Not modified.
         * @param b Second matrix.  Not modified.
         * @param tol Numerical tolerance.
         * @return True if they are the negative of each other within tolerance.
         */
        public static bool isNegative(FMatrixD1 a, FMatrixD1 b, float tol)
        {
            if (a.numRows != b.numRows || a.numCols != b.numCols)
            {
                throw new ArgumentException("Matrix dimensions must match");
            }

            int length = a.getNumElements();

            for (int i = 0; i < length; i++)
            {
                if (!(Math.Abs(a.get(i) + b.get(i)) <= tol))
                {
                    return(false);
                }
            }

            return(true);
        }
        /**
         * <p>
         * Checks to see if each element in the two matrices are equal:
         * a<sub>ij</sub> == b<sub>ij</sub>
         * <p>
         *
         * <p>
         * NOTE: If any of the elements are NaN then false is returned.  If two corresponding
         * elements are both positive or negative infinity then they are equal.
         * </p>
         *
         * @param a A matrix. Not modified.
         * @param b A matrix. Not modified.
         * @return true if identical and false otherwise.
         */
        public static bool isEquals(FMatrixD1 a, FMatrixD1 b)
        {
            if (a.numRows != b.numRows || a.numCols != b.numCols)
            {
                return(false);
            }

            int length = a.getNumElements();

            for (int i = 0; i < length; i++)
            {
                if (!(a.get(i) == b.get(i)))
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #26
0
        /**
         * <p>
         * Computes the Frobenius matrix norm:<br>
         * <br>
         * normF = Sqrt{  &sum;<sub>i=1:m</sub> &sum;<sub>j=1:n</sub> { a<sub>ij</sub><sup>2</sup>}   }
         * </p>
         * <p>
         * This is equivalent to the element wise p=2 norm.  See {@link #fastNormF} for another implementation
         * that is faster, but more prone to underflow/overflow errors.
         * </p>
         *
         * @param a The matrix whose norm is computed.  Not modified.
         * @return The norm's value.
         */
        public static float normF(FMatrixD1 a)
        {
            float total = 0;

            float scale = CommonOps_FDRM.elementMaxAbs(a);

            if (scale == 0.0f)
            {
                return(0.0f);
            }

            int size = a.getNumElements();

            for (int i = 0; i < size; i++)
            {
                float val = a.get(i) / scale;
                total += val * val;
            }

            return(scale * (float)Math.Sqrt(total));
        }
Beispiel #27
0
        /**
         * Computes the quality of a triangular matrix, where the quality of a matrix
         * is defined in {@link LinearSolverDense#quality()}.  In
         * this situation the quality os the absolute value of the product of
         * each diagonal element divided by the magnitude of the largest diagonal element.
         * If all diagonal elements are zero then zero is returned.
         *
         * @param T A matrix.
         * @return the quality of the system.
         */
        public static float qualityTriangular(FMatrixD1 T)
        {
            int N = Math.Min(T.numRows, T.numCols);

            // TODO make faster by just checking the upper triangular portion
            float max = elementDiagonalMaxAbs(T);

            if (max == 0.0f)
            {
                return(0.0f);
            }

            float quality = 1.0f;

            for (int i = 0; i < N; i++)
            {
                quality *= T.unsafe_get(i, i) / max;
            }

            return(Math.Abs(quality));
        }
Beispiel #28
0
        /**
         * Same as {@link #elementP} but runs faster by not mitigating overflow/underflow related problems.
         *
         * @param A Matrix. Not modified.
         * @param p p value.
         * @return The norm's value.
         */
        public static float fastElementP(FMatrixD1 A, float p)
        {
            if (p == 2)
            {
                return(fastNormF(A));
            }
            else
            {
                float total = 0;

                int size = A.getNumElements();

                for (int i = 0; i < size; i++)
                {
                    float a = A.get(i);

                    total += (float)Math.Pow(Math.Abs(a), p);
                }

                return((float)Math.Pow(total, 1.0f / p));
            }
        }
Beispiel #29
0
        public static void renderMatrix(FMatrixD1 M, Image image, float maxValue)
        {
            // TODO : BRS: Implement for .NET
            throw new NotImplementedException();

            /*
             * int w = image.getWidth();
             * int h = image.getHeight();
             *
             * float widthStep = (float) M.numCols / image.getWidth();
             * float heightStep = (float) M.numRows / image.getHeight();
             *
             * for (int i = 0; i < h; i++)
             * {
             *  for (int j = 0; j < w; j++)
             *  {
             *      float value = M.get((int) (i * heightStep), (int) (j * widthStep));
             *
             *      if (value == 0)
             *      {
             *          image.setRGB(j, i, 255 << 24);
             *      }
             *      else if (value > 0)
             *      {
             *          int p = 255 - (int) (255.0f * (value / maxValue));
             *          int rgb = 255 << 24 | 255 << 16 | p << 8 | p;
             *
             *          image.setRGB(j, i, rgb);
             *      }
             *      else
             *      {
             *          int p = 255 + (int) (255.0f * (value / maxValue));
             *          int rgb = 255 << 24 | p << 16 | p << 8 | 255;
             *
             *          image.setRGB(j, i, rgb);
             *      }
             *  }
             */
        }
        /**
         * <p>
         * Checks to see if each corresponding element in the two matrices are
         * within tolerance of each other or have the some symbolic meaning.  This
         * can handle NaN and Infinite numbers.
         * <p>
         *
         * <p>
         * If both elements are countable then the following equality test is used:<br>
         * |a<sub>ij</sub> - b<sub>ij</sub>| &le; tol.<br>
         * Otherwise both numbers must both be Float.NaN, Float.POSITIVE_INFINITY, or
         * Float.NEGATIVE_INFINITY to be identical.
         * </p>
         *
         * @param a A matrix. Not modified.
         * @param b A matrix. Not modified.
         * @param tol Tolerance for equality.
         * @return true if identical and false otherwise.
         */
        public static bool isIdentical(FMatrixD1 a, FMatrixD1 b, float tol)
        {
            if (a.numRows != b.numRows || a.numCols != b.numCols)
            {
                return(false);
            }
            if (tol < 0)
            {
                throw new ArgumentException("Tolerance must be greater than or equal to zero.");
            }

            int length = a.getNumElements();

            for (int i = 0; i < length; i++)
            {
                if (!isIdentical(a.get(i), b.get(i), tol))
                {
                    return(false);
                }
            }

            return(true);
        }