예제 #1
0
        internal void TransposeAndSwapTest()
        {
            var dims = new SubmatrixDims(0, 0, Width, Height);

            TransposeAndSwapNaive(ref dims, ref dims);
            // The result should be the original matrix
        }
예제 #2
0
        private void TransposeAndSwap(ref SubmatrixDims a, ref SubmatrixDims b)
        {
            Debug.Assert(a.Width == b.Height && a.Height == b.Width);

            // 1. Prepare the submatrices
            SubmatrixDims a11, a21, a12, a22;
            SubmatrixDims b11, b21, b12, b22;

            a.SplitDims(out a11, out a21, out a12, out a22);
            b.SplitDims(out b11, out b21, out b12, out b22);

            // 2. If the matrices are small, transpose them naively
            // Check just the first one; because we have a square matrix, the other sizes should be very similar
            if (a11.Width * a11.Height < NaiveThreshold)
            {
                TransposeAndSwapNaive(ref a11, ref b11);
                TransposeAndSwapNaive(ref a21, ref b12);
                TransposeAndSwapNaive(ref a12, ref b21);
                TransposeAndSwapNaive(ref a22, ref b22);
                return;
            }

            // 3. Transpose and swap them
            TransposeAndSwap(ref a11, ref b11);
            TransposeAndSwap(ref a21, ref b12);
            TransposeAndSwap(ref a12, ref b21);
            TransposeAndSwap(ref a22, ref b22);
        }
예제 #3
0
        private void TransposeAndSwapNaive(ref SubmatrixDims a, ref SubmatrixDims b)
        {
#if VERBOSE
            Debug.WriteLine("a: {0}", a);
            Debug.WriteLine(ToString(a));
            Debug.WriteLine("b: {0}", b);
            Debug.WriteLine(ToString(b));
#endif
            Debug.Assert(a.Width == b.Height && a.Height == b.Width);

            int baseOffset      = a.Y * Width + a.X;                                   // Pointer to a's top-left corner
            int baseTransOffset = b.Y * Width + b.X;                                   // Pointer to b's top-left corner

            for (int y = baseTransOffset; y < baseTransOffset + b.Width; y++)          // Iterate over b's columns
            {
                var transOffset = y;                                                   // Reset transOffset to the first line

                for (int offset = baseOffset; offset < baseOffset + a.Width; offset++) // Iterate over a's columns
                {
                    Swap(offset, transOffset);
                    transOffset += Width; // Move by a line
                }

                baseOffset += Width; // Jump to the next line
            }
        }
예제 #4
0
            public void SplitDims(
                out SubmatrixDims a11,
                out SubmatrixDims a21,
                out SubmatrixDims a12,
                out SubmatrixDims a22)
            {
                int halfWidth  = Width >> 1;
                int halfHeight = Height >> 1;

                // Left column
                a11.X     = a12.X = X;
                a11.Width = a12.Width = halfWidth;
                // Right column
                a21.X     = a22.X = X + halfWidth;
                a21.Width = a22.Width = Width - halfWidth;

                // Top row
                a11.Y      = a21.Y = Y;
                a11.Height = a21.Height = halfHeight;
                // Bottom row
                a12.Y      = a22.Y = Y + halfHeight;
                a12.Height = a22.Height = Height - halfHeight;

#if VERBOSE
                Debug.WriteLine("Split: {0},\t\thalf: {1}::{2}", this, halfWidth, halfHeight);
#endif
            }
예제 #5
0
 internal void TransposeInternal()
 {
     if (Width * Height < NaiveThreshold)
     {
         TransposeInternalNaive();
     }
     else
     {
         var dims = new SubmatrixDims(0, 0, Width, Height);
         TransposeInternal(ref dims);
     }
 }
예제 #6
0
        private string ToString(SubmatrixDims dims)
        {
            var sb = new StringBuilder();

            for (int j = dims.Y; j < dims.Y + dims.Height; j++)
            {
                for (int i = dims.X; i < dims.X + dims.Width; i++)
                {
                    sb.Append(this[i, j]);
                    sb.Append('\t');
                }

                sb.AppendLine();
            }

            return(sb.ToString());
        }
예제 #7
0
        // The recursion ends when the split submatrices are small enough. This saves us
        // a lot of work caused by recursion. We do the recursion end check before recursing
        // instead of at the start of the recursive func to reduce the recursion depth by one
        // (it can further save us a lot of recursive calls -- with the tree branching
        // factor of ~4 the number of leaves in the recursion tree is very high compared to
        // the number of internal nodes.
        private void TransposeInternal(ref SubmatrixDims dims)
        {
            // 1. Prepare the submatrices
            SubmatrixDims a11, a21, a12, a22;

            dims.SplitDims(out a11, out a21, out a12, out a22);

            // 2. If the matrices are small enough, transpose them naively
            if (a11.Width * a11.Height <= NaiveThreshold)
            {
                TransposeInternalNaive(ref a11);
                TransposeInternalNaive(ref a22);
                TransposeAndSwapNaive(ref a21, ref a12);
                return;
            }

            // 3. Recurse on the submatrices
            TransposeInternal(ref a11);
            TransposeInternal(ref a22);
            TransposeAndSwap(ref a21, ref a12);
        }
예제 #8
0
        private void TransposeInternalNaive(ref SubmatrixDims dims)
        {
            Debug.Assert(dims.Width == dims.Height);

            int baseOffset      = dims.Y * Width + dims.X;                                               // Pointer to the right half (triangle above the diagonal)
            int baseTransOffset = baseOffset;                                                            // Pointer to the left half (below the diagonal)
            int xSkip           = 0;                                                                     // The amount of columns (rows for the left half) to skip

            for (int y = baseTransOffset + Width; y < baseTransOffset + dims.Height * Width; y += Width) // Iterate over left half's rows
            {
                // baseTransOffset starts with the second row, while baseOffset starts at the first row (second element)
                int transOffset = y + xSkip; // Reset to the next line's beginning; offset the column by on less than the right pointer
                xSkip++;

                for (int offset = baseOffset + xSkip; offset < baseOffset + dims.Width; offset++) // Iterate over right half's columns
                {
                    Swap(offset, transOffset);
                    transOffset += Width; // Move by a line
                }

                baseOffset += Width;
            }
        }
예제 #9
0
        internal void TransposeInternalNaive()
        {
            var dims = new SubmatrixDims(0, 0, Width, Height);

            TransposeInternalNaive(ref dims);
        }