示例#1
0
        public static void Reverse(ref int buf, nuint length)
        {
            if (Avx2.IsSupported && (nuint)Vector256 <int> .Count * 2 <= length)
            {
                nuint           numElements = (nuint)Vector256 <int> .Count;
                nuint           numIters    = (length / numElements) / 2;
                Vector256 <int> reverseMask = Vector256.Create(7, 6, 5, 4, 3, 2, 1, 0);
                for (nuint i = 0; i < numIters; i++)
                {
                    nuint firstOffset = i * numElements;
                    nuint lastOffset  = length - ((1 + i) * numElements);

                    // Load the values into vectors
                    Vector256 <int> tempFirst = Vector256.LoadUnsafe(ref buf, firstOffset);
                    Vector256 <int> tempLast  = Vector256.LoadUnsafe(ref buf, lastOffset);

                    // Permute to reverse each vector:
                    //     +-------------------------------+
                    //     | A | B | C | D | E | F | G | H |
                    //     +-------------------------------+
                    //         --->
                    //     +-------------------------------+
                    //     | H | G | F | E | D | C | B | A |
                    //     +-------------------------------+
                    tempFirst = Avx2.PermuteVar8x32(tempFirst, reverseMask);
                    tempLast  = Avx2.PermuteVar8x32(tempLast, reverseMask);

                    // Store the values into final location
                    tempLast.StoreUnsafe(ref buf, firstOffset);
                    tempFirst.StoreUnsafe(ref buf, lastOffset);
                }
                buf     = ref Unsafe.Add(ref buf, numIters * numElements);
                length -= numIters * numElements * 2;
            }
            else if (Sse2.IsSupported && (nuint)Vector128 <int> .Count * 2 <= length)
            {
                nuint numElements = (nuint)Vector128 <int> .Count;
                nuint numIters    = (length / numElements) / 2;
                for (nuint i = 0; i < numIters; i++)
                {
                    nuint firstOffset = i * numElements;
                    nuint lastOffset  = length - ((1 + i) * numElements);

                    // Load the values into vectors
                    Vector128 <int> tempFirst = Vector128.LoadUnsafe(ref buf, firstOffset);
                    Vector128 <int> tempLast  = Vector128.LoadUnsafe(ref buf, lastOffset);

                    // Shuffle to reverse each vector:
                    //     +---------------+
                    //     | A | B | C | D |
                    //     +---------------+
                    //          --->
                    //     +---------------+
                    //     | D | C | B | A |
                    //     +---------------+
                    tempFirst = Sse2.Shuffle(tempFirst, 0b00_01_10_11);
                    tempLast  = Sse2.Shuffle(tempLast, 0b00_01_10_11);

                    // Store the values into final location
                    tempLast.StoreUnsafe(ref buf, firstOffset);
                    tempFirst.StoreUnsafe(ref buf, lastOffset);
                }
                buf     = ref Unsafe.Add(ref buf, numIters * numElements);
                length -= numIters * numElements * 2;
            }

            // Store any remaining values one-by-one
            for (nuint i = 0; i < (length / 2); i++)
            {
                ref int firstInt = ref Unsafe.Add(ref buf, i);
                ref int lastInt  = ref Unsafe.Add(ref buf, length - 1 - i);
示例#2
0
        public static void Reverse(ref long buf, nuint length)
        {
            if (Avx2.IsSupported && (nuint)Vector256 <long> .Count * 2 <= length)
            {
                nuint numElements = (nuint)Vector256 <long> .Count;
                nuint numIters    = (length / numElements) / 2;
                for (nuint i = 0; i < numIters; i++)
                {
                    nuint firstOffset = i * numElements;
                    nuint lastOffset  = length - ((1 + i) * numElements);
                    // Load the values into vectors
                    Vector256 <long> tempFirst = Vector256.LoadUnsafe(ref buf, firstOffset);
                    Vector256 <long> tempLast  = Vector256.LoadUnsafe(ref buf, lastOffset);

                    // Permute to reverse each vector:
                    //     +---------------+
                    //     | A | B | C | D |
                    //     +---------------+
                    //         --->
                    //     +---------------+
                    //     | D | C | B | A |
                    //     +---------------+
                    tempFirst = Avx2.Permute4x64(tempFirst, 0b00_01_10_11);
                    tempLast  = Avx2.Permute4x64(tempLast, 0b00_01_10_11);

                    // Store the values into final location
                    tempLast.StoreUnsafe(ref buf, firstOffset);
                    tempFirst.StoreUnsafe(ref buf, lastOffset);
                }
                buf     = ref Unsafe.Add(ref buf, numIters * numElements);
                length -= numIters * numElements * 2;
            }
            else if (Vector128.IsHardwareAccelerated && (nuint)Vector128 <long> .Count * 2 <= length)
            {
                nuint numElements = (nuint)Vector128 <long> .Count;
                nuint numIters    = (length / numElements) / 2;
                for (nuint i = 0; i < numIters; i++)
                {
                    nuint firstOffset = i * numElements;
                    nuint lastOffset  = length - ((1 + i) * numElements);
                    // Load the values into vectors
                    Vector128 <long> tempFirst = Vector128.LoadUnsafe(ref buf, firstOffset);
                    Vector128 <long> tempLast  = Vector128.LoadUnsafe(ref buf, lastOffset);

                    // Shuffle to reverse each vector:
                    //     +-------+
                    //     | A | B |
                    //     +-------+
                    //          --->
                    //     +-------+
                    //     | B | A |
                    //     +-------+
                    tempFirst = Vector128.Shuffle(tempFirst, Vector128.Create(1, 0));
                    tempLast  = Vector128.Shuffle(tempLast, Vector128.Create(1, 0));

                    // Store the values into final location
                    tempLast.StoreUnsafe(ref buf, firstOffset);
                    tempFirst.StoreUnsafe(ref buf, lastOffset);
                }
                buf     = ref Unsafe.Add(ref buf, numIters * numElements);
                length -= numIters * (nuint)Vector128 <long> .Count * 2;
            }

            // Store any remaining values one-by-one
            ReverseInner(ref buf, length);
        }
示例#3
0
        public static void Reverse(ref long buf, nuint length)
        {
            if (Avx2.IsSupported && (nuint)Vector256 <long> .Count * 2 <= length)
            {
                nuint numElements = (nuint)Vector256 <long> .Count;
                nuint numIters    = (length / numElements) / 2;
                for (nuint i = 0; i < numIters; i++)
                {
                    nuint firstOffset = i * numElements;
                    nuint lastOffset  = length - ((1 + i) * numElements);
                    // Load the values into vectors
                    Vector256 <long> tempFirst = Vector256.LoadUnsafe(ref buf, firstOffset);
                    Vector256 <long> tempLast  = Vector256.LoadUnsafe(ref buf, lastOffset);

                    // Permute to reverse each vector:
                    //     +---------------+
                    //     | A | B | C | D |
                    //     +---------------+
                    //         --->
                    //     +---------------+
                    //     | D | C | B | A |
                    //     +---------------+
                    tempFirst = Avx2.Permute4x64(tempFirst, 0b00_01_10_11);
                    tempLast  = Avx2.Permute4x64(tempLast, 0b00_01_10_11);

                    // Store the values into final location
                    tempLast.StoreUnsafe(ref buf, firstOffset);
                    tempFirst.StoreUnsafe(ref buf, lastOffset);
                }
                buf     = ref Unsafe.Add(ref buf, numIters * numElements);
                length -= numIters * numElements * 2;
            }
            else if (Sse2.IsSupported && (nuint)Vector128 <long> .Count * 2 <= length)
            {
                ref int bufInt      = ref Unsafe.As <long, int>(ref buf);
                nuint   intLength   = length * (sizeof(long) / sizeof(int));
                nuint   numElements = (nuint)Vector128 <int> .Count;
                nuint   numIters    = (intLength / numElements) / 2;
                for (nuint i = 0; i < numIters; i++)
                {
                    nuint firstOffset = i * numElements;
                    nuint lastOffset  = intLength - ((1 + i) * numElements);
                    // Load the values into vectors
                    Vector128 <int> tempFirst = Vector128.LoadUnsafe(ref bufInt, firstOffset);
                    Vector128 <int> tempLast  = Vector128.LoadUnsafe(ref bufInt, lastOffset);

                    // Shuffle to reverse each vector:
                    //     +-------+
                    //     | A | B |
                    //     +-------+
                    //          --->
                    //     +-------+
                    //     | B | A |
                    //     +-------+
                    tempFirst = Sse2.Shuffle(tempFirst, 0b0100_1110);
                    tempLast  = Sse2.Shuffle(tempLast, 0b0100_1110);

                    // Store the values into final location
                    tempLast.StoreUnsafe(ref bufInt, firstOffset);
                    tempFirst.StoreUnsafe(ref bufInt, lastOffset);
                }
                bufInt  = ref Unsafe.Add(ref bufInt, numIters * numElements);
                buf     = ref Unsafe.As <int, long>(ref bufInt);
                length -= numIters * (nuint)Vector128 <long> .Count * 2;
            }
示例#4
0
        public static void Reverse(ref int buf, nuint length)
        {
            if (Avx2.IsSupported && (nuint)Vector256 <int> .Count * 2 <= length)
            {
                nuint           numElements = (nuint)Vector256 <int> .Count;
                nuint           numIters    = (length / numElements) / 2;
                Vector256 <int> reverseMask = Vector256.Create(7, 6, 5, 4, 3, 2, 1, 0);
                for (nuint i = 0; i < numIters; i++)
                {
                    nuint firstOffset = i * numElements;
                    nuint lastOffset  = length - ((1 + i) * numElements);

                    // Load the values into vectors
                    Vector256 <int> tempFirst = Vector256.LoadUnsafe(ref buf, firstOffset);
                    Vector256 <int> tempLast  = Vector256.LoadUnsafe(ref buf, lastOffset);

                    // Permute to reverse each vector:
                    //     +-------------------------------+
                    //     | A | B | C | D | E | F | G | H |
                    //     +-------------------------------+
                    //         --->
                    //     +-------------------------------+
                    //     | H | G | F | E | D | C | B | A |
                    //     +-------------------------------+
                    tempFirst = Avx2.PermuteVar8x32(tempFirst, reverseMask);
                    tempLast  = Avx2.PermuteVar8x32(tempLast, reverseMask);

                    // Store the values into final location
                    tempLast.StoreUnsafe(ref buf, firstOffset);
                    tempFirst.StoreUnsafe(ref buf, lastOffset);
                }
                buf     = ref Unsafe.Add(ref buf, numIters * numElements);
                length -= numIters * numElements * 2;
            }
            else if (Vector128.IsHardwareAccelerated && (nuint)Vector128 <int> .Count * 2 <= length)
            {
                nuint numElements = (nuint)Vector128 <int> .Count;
                nuint numIters    = (length / numElements) / 2;
                for (nuint i = 0; i < numIters; i++)
                {
                    nuint firstOffset = i * numElements;
                    nuint lastOffset  = length - ((1 + i) * numElements);

                    // Load the values into vectors
                    Vector128 <int> tempFirst = Vector128.LoadUnsafe(ref buf, firstOffset);
                    Vector128 <int> tempLast  = Vector128.LoadUnsafe(ref buf, lastOffset);

                    // Shuffle to reverse each vector:
                    //     +---------------+
                    //     | A | B | C | D |
                    //     +---------------+
                    //          --->
                    //     +---------------+
                    //     | D | C | B | A |
                    //     +---------------+
                    tempFirst = Vector128.Shuffle(tempFirst, Vector128.Create(3, 2, 1, 0));
                    tempLast  = Vector128.Shuffle(tempLast, Vector128.Create(3, 2, 1, 0));

                    // Store the values into final location
                    tempLast.StoreUnsafe(ref buf, firstOffset);
                    tempFirst.StoreUnsafe(ref buf, lastOffset);
                }
                buf     = ref Unsafe.Add(ref buf, numIters * numElements);
                length -= numIters * numElements * 2;
            }

            ReverseInner(ref buf, length);
        }