Last active
March 5, 2022 22:49
-
-
Save TheNullicorn/41f9a56ad084ee8aac8f2138507b162b to your computer and use it in GitHub Desktop.
Kotlin utility for reversing the order of bits in an Int
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Returns a Byte identical to the current one, but with the positions of the least-significant `n` | |
| * bits reversed, where `n` = [width]. | |
| * | |
| * This means that the bit at position `0` will be replaced with the value of the bit at position | |
| * `width - 1`, and vice-versa. | |
| * | |
| * **Not to be confused with the [invert][Int.inv] function, which toggles all bits in place.** | |
| * | |
| * #### Examples: | |
| * ```text | |
| * 11100101.reversed(width = 4) | |
| * 11101010 | |
| * └──┘ | |
| * | |
| * ======================================================================= | |
| * | |
| * 11100101.reversed() // width = 8 by default | |
| * 10100111 | |
| * └──────┘ | |
| * ``` | |
| * | |
| * @throws[IllegalArgumentException] if [width] exceeds [Byte.SIZE_BITS]. | |
| */ | |
| internal fun Byte.reversed(width: Int = Byte.SIZE_BITS): Byte { | |
| require(width <= Byte.SIZE_BITS) { "width cannot exceed ${Byte.SIZE_BITS}: $width" } | |
| return toInt().reversed(width).toByte() | |
| } | |
| /** | |
| * Returns a Short identical to the current one, but with the positions of the least-significant `n` | |
| * bits reversed, where `n` = [width]. | |
| * | |
| * This means that the bit at position `0` will be replaced with the value of the bit at position | |
| * `width - 1`, and vice-versa. | |
| * | |
| * **Not to be confused with the [invert][Int.inv] function, which toggles all bits in place.** | |
| * | |
| * #### Examples: | |
| * ```text | |
| * 00011101_11000110.reversed(width = 8) | |
| * 00011101_01100011 | |
| * └──────┘ | |
| * | |
| * ======================================================================= | |
| * | |
| * 00011101_11000110.reversed() // width = 16 by default | |
| * 01100011_10111000 | |
| * └───────────────┘ | |
| * ``` | |
| * | |
| * @throws[IllegalArgumentException] if [width] exceeds [Short.SIZE_BITS]. | |
| */ | |
| internal fun Short.reversed(width: Int = Short.SIZE_BITS): Short { | |
| require(width <= Short.SIZE_BITS) { "width cannot exceed ${Short.SIZE_BITS}: $width" } | |
| return toInt().reversed(width).toShort() | |
| } | |
| /** | |
| * Returns an Int identical to the current one, but with the positions of the least-significant `n` | |
| * bits reversed, where `n` = [width]. | |
| * | |
| * This means that the bit at position `0` will be replaced with the value of the bit at position | |
| * `width - 1`, and vice-versa. | |
| * | |
| * **Not to be confused with the [invert][Int.inv] function, which toggles all bits in place.** | |
| * | |
| * #### Examples: | |
| * ```text | |
| * 11100001_00010000_00011101_11000110.reversed(width = 8) | |
| * 11100001_00010000_00011101_01100011 | |
| * └──────┘ | |
| * | |
| * ======================================================================= | |
| * | |
| * 11100001_00010000_00011101_11000110.reversed() // width = 32 by default | |
| * 01100011_10111000_00001000_10000111 | |
| * └─────────────────────────────────┘ | |
| * ``` | |
| * | |
| * @throws[IllegalArgumentException] if [width] exceeds [Int.SIZE_BITS]. | |
| */ | |
| internal fun Int.reversed(width: Int = Int.SIZE_BITS): Int { | |
| require(width <= Int.SIZE_BITS) { "width cannot exceed ${Int.SIZE_BITS}: $width" } | |
| var reverse = this | |
| for (i in 0 until width) { | |
| // The value of the non-reflected bit. | |
| val sourceBit = this shr i and 1 | |
| // A mask with only the bit in the reflected position set. | |
| val targetBit = 1 shl (width - i - 1) | |
| // Set or clear the target bit depending on the source bit's current state. | |
| reverse = if (sourceBit != 0) | |
| reverse or targetBit | |
| else | |
| reverse and targetBit.inv() | |
| } | |
| return reverse | |
| } | |
| /** | |
| * Returns a Long identical to the current one, but with the positions of the least-significant `n` | |
| * bits reversed, where `n` = [width]. | |
| * | |
| * This means that the bit at position `0` will be replaced with the value of the bit at position | |
| * `width - 1`, and vice-versa. | |
| * | |
| * **Not to be confused with the [invert][Long.inv] function, which toggles all bits in place.** | |
| * | |
| * #### Examples: | |
| * ```text | |
| * 00110111_00011101_10100000_00010100_01110011_01100000_00101101_01010001.reversed(width = 16) | |
| * 00110111_00011101_10100000_00010100_01110011_01100000_10001010_10110100 | |
| * └───────────────┘ | |
| * | |
| * ======================================================================= | |
| * | |
| * 00110111_00011101_10100000_00010100_01110011_01100000_00101101_01010001.reversed() // width = 64 by default | |
| * 10001010_10110100_00000110_11001110_00101000_00000101_10111000_11101100 | |
| * └─────────────────────────────────────────────────────────────────────┘ | |
| * ``` | |
| * | |
| * @throws[IllegalArgumentException] if [width] exceeds [Long.SIZE_BITS]. | |
| */ | |
| internal fun Long.reversed(width: Int = Long.SIZE_BITS): Long { | |
| require(width <= Long.SIZE_BITS) { "width cannot exceed ${Long.SIZE_BITS}: $width" } | |
| var reverse = this | |
| for (i in 0 until width) { | |
| // The value of the non-reflected bit. | |
| val sourceBit = this shr i and 1 | |
| // A mask with only the bit in the reflected position set. | |
| val targetBit = 1L shl (width - i - 1) | |
| // Set or clear the target bit depending on the source bit's current state. | |
| reverse = if (sourceBit != 0L) | |
| reverse or targetBit | |
| else | |
| reverse and targetBit.inv() | |
| } | |
| return reverse | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment