/// <summary>
        /// concatenate submatrices column-wise into one matrix, i.e., the number of rows for the output matrix
        /// is equal to the number of rows of each of the frequency band matrices.
        /// </summary>
        public static double[,] ConcatFreqBandMatrices(List <double[, ]> submatrices)
        {
            // The assumption here is all frequency band matrices have the same number of columns.
            int columnSize = submatrices.Count * submatrices[0].GetLength(1);
            int rowSize    = submatrices[0].GetLength(0);

            double[,] matrix = new double[rowSize, columnSize];
            int count = 0;

            while (count < submatrices.Count)
            {
                matrix.AddToArray(submatrices[count], DoubleSquareArrayExtensions.MergingDirection.Column, submatrices[count].GetLength(1) * count);
                count++;
            }

            // If we have frequency band matrices with different number of columns,
            // Then the below commented code need to be used.

            /*
             * double[][,] submatrix = submatrices.ToArray();
             * int colSize = 0;
             * for (int i = 0; i < submatrix.Length; i++)
             * {
             *  colSize = colSize + submatrix[i].GetLength(1);
             * }
             *
             * // storing the number of rows of each submatrice in an array
             * int[] noRows = new int[submatrix.Length];
             * for (int i = 0; i < submatrix.Length; i++)
             * {
             *  noRows[i] = submatrix[i].GetLength(0);
             * }
             *
             * // find the max number of rows from noRows array
             * int maxRows = noRows.Max();
             *
             * double[,] matrix = new double[maxRows, colSize];
             *
             * // might be better way to do this
             * AddToArray(matrix, submatrix[0], "column");
             * AddToArray(matrix, submatrix[1], "column", submatrix[0].GetLength(1));
             * AddToArray(matrix, submatrix[2], "column", submatrix[0].GetLength(1) + submatrix[1].GetLength(1));
             */

            return(matrix);
        }
        /// <summary>
        /// convert a list of patch matrices to one matrix by row
        /// patch matrices can have different row numbers but must have the same column number
        /// </summary>
        public static double[,] ListOf2DArrayToOne2DArray(List <double[, ]> listOfPatchMatrices)
        {
            int sumNumberOfPatches = 0;

            foreach (var matrix in listOfPatchMatrices)
            {
                sumNumberOfPatches = matrix.GetLength(0) + sumNumberOfPatches;
            }

            double[,] allPatchesMatrix = new double[sumNumberOfPatches, listOfPatchMatrices[0].GetLength(1)];
            int start = 0;

            for (int i = 0; i < listOfPatchMatrices.Count; i++)
            {
                var m = listOfPatchMatrices[i];
                allPatchesMatrix.AddToArray(m, DoubleSquareArrayExtensions.MergingDirection.Row, start);
                start = m.GetLength(0) + start;
            }

            return(allPatchesMatrix);
        }