Last active
May 25, 2024 10:18
-
-
Save dacr/f5142acec372aeb90010e676292d5142 to your computer and use it in GitHub Desktop.
various binary operations (cheat sheet) / published by https://github.com/dacr/code-examples-manager #5208940e-5e7f-4df2-862d-74c8c5a390bb/f0397129de2575f469409f20061ec2ddd2dae1e6
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
// summary : various binary operations (cheat sheet) | |
// keywords : scala, scalatest, binary, cheatsheet, @testable | |
// publish : gist | |
// authors : David Crosson | |
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2) | |
// id : 5208940e-5e7f-4df2-862d-74c8c5a390bb | |
// created-on : 2020-12-24T10:04:53Z | |
// managed-by : https://github.com/dacr/code-examples-manager | |
// run-with : scala-cli $file | |
// --------------------- | |
//> using scala "3.4.2" | |
//> using dep "org.scalatest::scalatest:3.2.16" | |
//> using objectWrapper | |
// --------------------- | |
import org.scalatest._ | |
import flatspec._ | |
import matchers._ | |
import OptionValues._ | |
// --------------------------------------------------------------------------------------------- | |
val hex2bin = Map( | |
"0" -> "0000", | |
"1" -> "0001", | |
"2" -> "0010", | |
"3" -> "0011", | |
"4" -> "0100", | |
"5" -> "0101", | |
"6" -> "0110", | |
"7" -> "0111", | |
"8" -> "1000", | |
"9" -> "1001", | |
"A" -> "1010", | |
"B" -> "1011", | |
"C" -> "1100", | |
"D" -> "1101", | |
"E" -> "1110", | |
"F" -> "1111" | |
) | |
def hex2bits(input: String): String = input.split("").map(hex2bin).mkString | |
// --------------------------------------------------------------------------------------------- | |
def pow2(p: Int): Int = 1 << p | |
// --------------------------------------------------------------------------------------------- | |
def flipBits(in: Int, bitsCount: Int = 10): Int = { | |
(0 until bitsCount).foldLeft(0) { case (out, n) => out | (((in & pow2(n)) >> n) << (bitsCount - 1 - n)) } | |
} | |
// --------------------------------------------------------------------------------------------- | |
def intToPaddedBin(n: Int, bitsCount: Int): String = { | |
s"%${bitsCount}s" | |
.format(n.toBinaryString) | |
.replaceAll(" ", "0") | |
.takeRight(bitsCount) | |
} | |
// --------------------------------------------------------------------------------------------- | |
def intToBin(n: Int): String = n.toBinaryString | |
def binToInt(in: String): Int = java.lang.Integer.parseInt(in, 2) | |
def bigToBin(n: BigInt): String = n.toString(2) | |
def binToBig(in: String): BigInt = BigInt(in, 2) | |
// --------------------------------------------------------------------------------------------- | |
type BitType = Int | |
def isBitSet(from: BitType, bitPos: Int): Boolean = (from & (1 << bitPos)) != 0 | |
def changeBit(state: Boolean, bitPos: Int): BitType = changeBit(state, bitPos, 0) | |
def changeBit(state: Boolean, bitPos: Int, current: BitType): BitType = { | |
val mask = 1 << bitPos | |
if (state) current | mask | |
else current & ~mask | |
} | |
def decodeSubBinValue(from: BitType, bitPos: Int, sizeMask: BitType): BitType = (from >>> bitPos) & sizeMask | |
def encodeSubBinValue(value: BitType, bitPos: Int, sizeMask: BitType): BitType = encodeSubBinValue(value, bitPos, sizeMask, 0) | |
def encodeSubBinValue(value: BitType, bitPos: Int, sizeMask: BitType, current: BitType): BitType = { | |
(current & (~(sizeMask << bitPos))) | ((value & sizeMask) << bitPos) | |
} | |
// --------------------------------------------------------------------------------------------- | |
def switchBits(base: BitType, numBits: Int): BitType = { | |
val maskRight = (2 << numBits) - 1 | |
val maskLeft = maskRight << numBits | |
((base & maskRight) << numBits) | ((base & maskLeft) >>> numBits) | (base & ~(maskLeft | maskRight)) | |
} | |
// --------------------------------------------------------------------------------------------- | |
class BinaryOperations extends AnyFlatSpec with should.Matchers { | |
override def suiteName = "BinaryOperations" | |
"binToInt" should "convert a binary string to a decimal" in { | |
binToInt("10") shouldBe 2 | |
binToInt("100") shouldBe 4 | |
} | |
"intToPaddedBin" should "convert a decimal to a binary string" in { | |
intToPaddedBin(4, 3) shouldBe "100" | |
intToPaddedBin(4, 4) shouldBe "0100" | |
intToPaddedBin(4, 6) shouldBe "000100" | |
} | |
"intToBin" should "convert a decimal to a binary string" in { | |
intToBin(4) shouldBe "100" | |
intToBin(42) shouldBe "101010" | |
} | |
"flipBits" should "flip the specified number of bits horizontally" in { | |
intToPaddedBin(flipBits(binToInt("00101"), 5), 5) shouldBe "10100" | |
intToPaddedBin(flipBits(binToInt("00001"), 5), 5) shouldBe "10000" | |
intToPaddedBin(flipBits(binToInt("10000"), 5), 5) shouldBe "00001" | |
intToPaddedBin(flipBits(binToInt("01000"), 5), 5) shouldBe "00010" | |
intToPaddedBin(flipBits(binToInt("00100"), 5), 5) shouldBe "00100" | |
flipBits(1, 3) shouldBe 4 | |
flipBits(4, 3) shouldBe 1 | |
} | |
"binToBig" should "convert a binary string to a decimal" in { | |
binToBig("10") shouldBe 2 | |
binToBig("100") shouldBe 4 | |
} | |
"bigToBin" should "convert a decimal to a binary string" in { | |
bigToBin(4) shouldBe "100" | |
bigToBin(42) shouldBe "101010" | |
} | |
"isBitSet" should "check if a bit is set or not" in { | |
isBitSet(0x1, 0) shouldBe true | |
isBitSet(0x1, 1) shouldBe false | |
isBitSet(0xff00, 7) shouldBe false | |
isBitSet(0xff00, 8) shouldBe true | |
isBitSet(0xff00, 15) shouldBe true | |
isBitSet(0xff00, 16) shouldBe false | |
isBitSet(0x80000000, 31) shouldBe true | |
isBitSet(0x80000000, 30) shouldBe false | |
} | |
def encodeDecode(value: BitType, bitPos: Int, sizeMask: Int): BitType = encodeDecode(value, sizeMask, bitPos, 0) | |
def encodeDecode(value: BitType, bitPos: Int, sizeMask: Int, current: Int): BitType = { | |
val encoded = encodeSubBinValue(value, sizeMask, bitPos, current) | |
decodeSubBinValue(encoded, sizeMask, bitPos) | |
} | |
"subBinValue functions" should "encode/decode an int value" in { | |
encodeDecode(0x42, 0, 0xff) shouldBe 0x42 | |
encodeDecode(0x42, 24, 0xff) shouldBe 0x42 | |
encodeDecode(0x142, 0, 0xff) shouldBe 0x42 | |
encodeDecode(0xffff, 0, 0xffff) shouldBe 0xffff | |
encodeDecode(0xffff, 16, 0xffff) shouldBe 0xffff | |
} | |
"switchBits" should "allow to switch sub values" in { | |
switchBits(0xcafebabe, 16) shouldBe 0xbabecafe | |
switchBits(0xcafe, 8) shouldBe 0xfeca | |
switchBits(0x42cafe, 8) shouldBe 0x42feca | |
switchBits(0xff42cafe, 8) shouldBe 0xff42feca | |
switchBits(0x7f42cafe, 8) shouldBe 0x7f42feca | |
} | |
} | |
org.scalatest.tools.Runner.main(Array("-oDF", "-s", classOf[BinaryOperations].getName)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment