/// <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);