예제 #1
0
        /// <summary>
        /// Performs a circular shift on the bits in the current <see cref="BitArray" />.
        /// </summary>
        /// <param name="target">
        /// The current <see cref="BitArray" />.
        /// </param>
        /// <param name="direction">
        /// A direction to shift the bits in the current <see cref="BitArray" />. The default value is
        /// <see cref="BitShiftDirection.Right" />.
        /// </param>
        /// <param name="bitShiftCount">
        /// The number of bits to shift by.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// The value of <paramref name="bitShiftCount" /> is less than zero.
        /// </exception>
        public static BitArray PerformCircularShift(this BitArray target, BitShiftDirection direction, Int32 bitShiftCount)
        {
            var arrayLength = target.Length;

            if (arrayLength < 2)
            {
                return(target);
            }

            Int32 directionalBitShiftCount;

            switch (direction)
            {
            case BitShiftDirection.Left:

                // Sign the shift count negative for left shifts.
                directionalBitShiftCount = (bitShiftCount.RejectIf().IsLessThan(0, nameof(bitShiftCount)) * -1);
                break;

            case BitShiftDirection.Right:

                // Sign the shift count positive for right shifts.
                directionalBitShiftCount = bitShiftCount.RejectIf().IsLessThan(0, nameof(bitShiftCount));
                break;

            default:

                goto case BitShiftDirection.Right;
            }

            var newBitArray = new BitArray(arrayLength, false);

            for (var i = 0; i < arrayLength; i++)
            {
                newBitArray.Set(DetermineNewCircularPosition(i, arrayLength, directionalBitShiftCount), target.Get(i));
            }

            return(newBitArray);
        }
        /// <summary>
        /// Performs a circular shift on the bits in the current <see cref="Byte" /> array.
        /// </summary>
        /// <param name="target">
        /// The current <see cref="Byte" /> array.
        /// </param>
        /// <param name="direction">
        /// A direction to shift the bits in the current <see cref="Byte" /> array. The default value is
        /// <see cref="BitShiftDirection.Right" />.
        /// </param>
        /// <param name="bitShiftCount">
        /// The number of bits to shift by.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// The value of <paramref name="direction" /> is equal to <see cref="BitShiftDirection.Unspecified" /> and/or the value of
        /// <paramref name="bitShiftCount" /> is less than zero.
        /// </exception>
        public static Byte[] PerformCircularBitShift(this Byte[] target, BitShiftDirection direction, Int32 bitShiftCount)
        {
            direction.RejectIf().IsEqualToValue(BitShiftDirection.Unspecified, nameof(direction));

            if (target.Length == 0)
            {
                return(target);
            }

            var collectionByteLength    = target.Length;
            var collectionBitLength     = (collectionByteLength * 8);
            var simplifiedBitShiftCount = (bitShiftCount.RejectIf().IsLessThan(0, nameof(bitShiftCount)) % collectionBitLength);

            if (simplifiedBitShiftCount == 0)
            {
                return(target);
            }

            var   simplifiedByteShiftCount = (simplifiedBitShiftCount / 8);
            var   bitShiftRemainder        = (simplifiedBitShiftCount % 8);
            var   outputBuffer             = new Byte[collectionByteLength];
            Int32 headIndex;
            Int32 readIndex;
            Int32 writeIndex;

            switch (direction)
            {
            case BitShiftDirection.Left:

                headIndex = simplifiedByteShiftCount;

                if (bitShiftRemainder == 0)
                {
                    for (readIndex = headIndex, writeIndex = 0; readIndex < collectionByteLength; readIndex++, writeIndex++)
                    {
                        outputBuffer[writeIndex] = target[readIndex];
                    }

                    for (readIndex = 0; readIndex < headIndex; readIndex++, writeIndex++)
                    {
                        outputBuffer[writeIndex] = target[readIndex];
                    }
                }
                else
                {
                    Byte leftElement;
                    Byte rightElement;

                    for (readIndex = headIndex, writeIndex = 0; readIndex < collectionByteLength; readIndex++, writeIndex++)
                    {
                        leftElement              = target[readIndex];
                        rightElement             = target[readIndex == (collectionByteLength - 1) ? 0 : (readIndex + 1)];
                        outputBuffer[writeIndex] = unchecked ((Byte)(leftElement >> bitShiftRemainder | rightElement << (8 - bitShiftRemainder)));
                    }

                    for (readIndex = 0; readIndex < headIndex; readIndex++, writeIndex++)
                    {
                        leftElement              = target[readIndex];
                        rightElement             = target[readIndex + 1];
                        outputBuffer[writeIndex] = unchecked ((Byte)(leftElement >> bitShiftRemainder | rightElement << (8 - bitShiftRemainder)));
                    }
                }

                break;

            case BitShiftDirection.Right:

                headIndex = (collectionByteLength - simplifiedByteShiftCount);

                if (bitShiftRemainder == 0)
                {
                    for (readIndex = headIndex, writeIndex = 0; readIndex < collectionByteLength; readIndex++, writeIndex++)
                    {
                        outputBuffer[writeIndex] = target[readIndex];
                    }

                    for (readIndex = 0; readIndex < headIndex; readIndex++, writeIndex++)
                    {
                        outputBuffer[writeIndex] = target[readIndex];
                    }
                }
                else
                {
                    Byte leftElement;
                    Byte rightElement;

                    for (readIndex = headIndex, writeIndex = 0; readIndex < collectionByteLength; readIndex++, writeIndex++)
                    {
                        leftElement              = target[readIndex - 1];
                        rightElement             = target[readIndex];
                        outputBuffer[writeIndex] = unchecked ((Byte)(leftElement >> (8 - bitShiftRemainder) | rightElement << bitShiftRemainder));
                    }

                    for (readIndex = 0; readIndex < headIndex; readIndex++, writeIndex++)
                    {
                        leftElement              = target[readIndex == 0 ? (collectionByteLength - 1) : (readIndex - 1)];
                        rightElement             = target[readIndex];
                        outputBuffer[writeIndex] = unchecked ((Byte)(leftElement >> (8 - bitShiftRemainder) | rightElement << bitShiftRemainder));
                    }
                }

                break;

            default:

                throw new ArgumentException($"{direction} is not a supported {nameof(BitShiftDirection)}.", nameof(direction));
            }

            return(outputBuffer);
        }
 /// <summary>
 /// Converts the current <see cref="BitShiftDirection" /> to an array of bytes.
 /// </summary>
 /// <param name="target">
 /// The current instance of the <see cref="BitShiftDirection" />.
 /// </param>
 /// <returns>
 /// An array of bytes representing the current <see cref="BitShiftDirection" />.
 /// </returns>
 public static Byte[] ToByteArray(this BitShiftDirection target) => BitConverter.GetBytes((Int32)target);