From ff4c932e67f6073aa500b796ec0717d3f23bad0a Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 21 Jun 2019 05:16:17 +0300 Subject: [PATCH] Actual implementations for bit functions --- runtime/src/main/kotlin/kotlin/Numbers.kt | 151 ++++++++++++++++++ .../src/main/kotlin/kotlin/random/Random.kt | 3 - 2 files changed, 151 insertions(+), 3 deletions(-) diff --git a/runtime/src/main/kotlin/kotlin/Numbers.kt b/runtime/src/main/kotlin/kotlin/Numbers.kt index 32870951547..65043fc7dd6 100644 --- a/runtime/src/main/kotlin/kotlin/Numbers.kt +++ b/runtime/src/main/kotlin/kotlin/Numbers.kt @@ -101,3 +101,154 @@ public actual inline fun Float.Companion.fromBits(bits: Int): Float = kotlin.fro @PublishedApi @TypedIntrinsic(IntrinsicType.REINTERPRET) internal external fun fromBits(bits: Int): Float + + +/** + * Counts the number of set bits in the binary representation of this [Int] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.countOneBits(): Int { + var v = this + v = (v and 0x55555555) + (v.ushr(1) and 0x55555555) + v = (v and 0x33333333) + (v.ushr(2) and 0x33333333) + v = (v and 0x0F0F0F0F) + (v.ushr(4) and 0x0F0F0F0F) + v = (v and 0x00FF00FF) + (v.ushr(8) and 0x00FF00FF) + v = (v and 0x0000FFFF) + (v.ushr(16)) + return v +} + +/** + * Counts the number of consecutive most significant bits that are zero in the binary representation of this [Int] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.countLeadingZeroBits(): Int = TODO() + +/** + * Counts the number of consecutive least significant bits that are zero in the binary representation of this [Int] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.countTrailingZeroBits(): Int = TODO() +// Int.SIZE_BITS - (this or -this).inv().countLeadingZeroBits() + +/** + * Returns a number having a single bit set in the position of the most significant set bit of this [Int] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.takeHighestOneBit(): Int = + if (this == 0) 0 else 1.shl(Int.SIZE_BITS - 1 - countLeadingZeroBits()) + +/** + * Returns a number having a single bit set in the position of the least significant set bit of this [Int] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.takeLowestOneBit(): Int = + this and -this + +/** + * Rotates the binary representation of this [Int] number left by the specified [bitCount] number of bits. + * The most significant bits pushed out from the left side reenter the number as the least significant bits on the right side. + * + * Rotating the number left by a negative bit count is the same as rotating it right by the negated bit count: + * `number.rotateLeft(-n) == number.rotateRight(n)` + * + * Rotating by a multiple of [Int.SIZE_BITS] (32) returns the same number, or more generally + * `number.rotateLeft(n) == number.rotateLeft(n % 32)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.rotateLeft(bitCount: Int): Int = + shl(bitCount) or ushr(Int.SIZE_BITS - bitCount) + + +/** + * Rotates the binary representation of this [Int] number right by the specified [bitCount] number of bits. + * The least significant bits pushed out from the right side reenter the number as the most significant bits on the left side. + * + * Rotating the number right by a negative bit count is the same as rotating it left by the negated bit count: + * `number.rotateRight(-n) == number.rotateLeft(n)` + * + * Rotating by a multiple of [Int.SIZE_BITS] (32) returns the same number, or more generally + * `number.rotateRight(n) == number.rotateRight(n % 32)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.rotateRight(bitCount: Int): Int = + shl(Int.SIZE_BITS - bitCount) or ushr(bitCount) + + +/** + * Counts the number of set bits in the binary representation of this [Long] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.countOneBits(): Int = TODO() +// high.countOneBits() + low.countOneBits() + +/** + * Counts the number of consecutive most significant bits that are zero in the binary representation of this [Long] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.countLeadingZeroBits(): Int = TODO() + +/** + * Counts the number of consecutive least significant bits that are zero in the binary representation of this [Long] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.countTrailingZeroBits(): Int = TODO() + +/** + * Returns a number having a single bit set in the position of the most significant set bit of this [Long] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.takeHighestOneBit(): Long = TODO() + +/** + * Returns a number having a single bit set in the position of the least significant set bit of this [Long] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.takeLowestOneBit(): Long = + this and -this + +/** + * Rotates the binary representation of this [Long] number left by the specified [bitCount] number of bits. + * The most significant bits pushed out from the left side reenter the number as the least significant bits on the right side. + * + * Rotating the number left by a negative bit count is the same as rotating it right by the negated bit count: + * `number.rotateLeft(-n) == number.rotateRight(n)` + * + * Rotating by a multiple of [Long.SIZE_BITS] (64) returns the same number, or more generally + * `number.rotateLeft(n) == number.rotateLeft(n % 64)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.rotateLeft(bitCount: Int): Long = + shl(bitCount) or ushr(Long.SIZE_BITS - bitCount) + +/** + * Rotates the binary representation of this [Long] number right by the specified [bitCount] number of bits. + * The least significant bits pushed out from the right side reenter the number as the most significant bits on the left side. + * + * Rotating the number right by a negative bit count is the same as rotating it left by the negated bit count: + * `number.rotateRight(-n) == number.rotateLeft(n)` + * + * Rotating by a multiple of [Long.SIZE_BITS] (64) returns the same number, or more generally + * `number.rotateRight(n) == number.rotateRight(n % 64)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public actual inline fun Long.rotateRight(bitCount: Int): Long = + shl(Long.SIZE_BITS - bitCount) or ushr(bitCount) diff --git a/runtime/src/main/kotlin/kotlin/random/Random.kt b/runtime/src/main/kotlin/kotlin/random/Random.kt index ee2b4e56cb5..9d1942152f1 100644 --- a/runtime/src/main/kotlin/kotlin/random/Random.kt +++ b/runtime/src/main/kotlin/kotlin/random/Random.kt @@ -36,8 +36,5 @@ internal object NativeRandom : Random() { internal actual fun defaultPlatformRandom(): Random = NativeRandom -internal actual fun fastLog2(value: Int): Int = - 31 - value.numberOfLeadingZeros() - internal actual fun doubleFromParts(hi26: Int, low27: Int): Double = (hi26.toLong().shl(27) + low27) / (1L shl 53).toDouble()