//Apply SVD on each small piece of the bitmap
        public Image SVD_Fraction(Bitmap bmp, int newRank, ref double RootMeanSquareError)
        {
            int bestRank = (bmp.Height * bmp.Width) / (1 + bmp.Height + bmp.Width);
            if (newRank > bestRank)
                return bmp;

            int FactorRank = (int)Math.Round(BMP_FRAC_SIZE * ((double)newRank / bestRank));
            MatrixFromBitmap(ref bmp);

            int numx = bmp.Width / BMP_FRAC_SIZE;
            int numy = bmp.Height / BMP_FRAC_SIZE;

            MMatrix[] C = new MMatrix[numx];
            MMatrix tmpMat = new MMatrix(BMP_FRAC_SIZE, BMP_FRAC_SIZE);
            int FromRow, ToRow;
            MMatrix Red = new MMatrix(MRed);
            for (int k = 0; k < numx; ++k)
            {
                FromRow = k * BMP_FRAC_SIZE;
                ToRow = (k + 1) * BMP_FRAC_SIZE;
                tmpMat.Copy(Red, FromRow, ToRow, 0, BMP_FRAC_SIZE);
                SVD(ref tmpMat, FactorRank);
                C[k] = tmpMat;
                for (int m = 1; m < numy; ++m)
                {
                    tmpMat.Copy(Red, FromRow, ToRow, m * BMP_FRAC_SIZE, (m + 1) * BMP_FRAC_SIZE);
                    SVD(ref tmpMat, FactorRank);
                    C[k] = MMatrix.Concat_Horizontal(C[k], tmpMat);
                }
            }
            for (int k = 1; k < numx; ++k)
                C[0] = MMatrix.Concat_Vertical(C[0], C[k]);
            MRed = FloorToBitmap(C[0].MArray);
            RootMeanSquareError = MMatrix.RootMeanSquareError(new MMatrix(MRed), C[0]);

            return BitmapFromMatrix(ref MRed, ref MGreen, ref MBlue);
        }