Bit query and bit rotation functions for Int, Long, Short, Byte
#KT-12749
This commit is contained in:
@@ -230,6 +230,17 @@ if (typeof Math.log2 === "undefined") {
|
||||
return Math.log(x) * Math.LOG2E;
|
||||
};
|
||||
}
|
||||
if (typeof Math.clz32 === "undefined") {
|
||||
Math.clz32 = (function(log, LN2) {
|
||||
return function(x) {
|
||||
var asUint = x >>> 0;
|
||||
if (asUint === 0) {
|
||||
return 32;
|
||||
}
|
||||
return 31 - (log(asUint) / LN2 | 0) | 0; // the "| 0" acts like math.floor
|
||||
};
|
||||
})(Math.log, Math.LN2);
|
||||
}
|
||||
|
||||
// For HtmlUnit and PhantomJs
|
||||
if (typeof ArrayBuffer.isView === "undefined") {
|
||||
|
||||
@@ -58,4 +58,9 @@ public actual fun Float.toRawBits(): Int = definedExternally
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Float.Companion.fromBits(bits: Int): Float = js("Kotlin").floatFromBits(bits).unsafeCast<Float>()
|
||||
public actual inline fun Float.Companion.fromBits(bits: Int): Float = js("Kotlin").floatFromBits(bits).unsafeCast<Float>()
|
||||
|
||||
|
||||
internal inline fun Long(low: Int, high: Int) = js("Kotlin").Long.fromBits(low, high).unsafeCast<Long>()
|
||||
internal inline val Long.low: Int get() = this.asDynamic().getLowBits().unsafeCast<Int>()
|
||||
internal inline val Long.high: Int get() = this.asDynamic().getHighBits().unsafeCast<Int>()
|
||||
@@ -87,6 +87,9 @@ public external object Math {
|
||||
internal fun log2(value: Double): Double
|
||||
@PublishedApi
|
||||
internal fun log1p(value: Double): Double
|
||||
|
||||
@PublishedApi
|
||||
internal fun clz32(value: Int): Int
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,4 +35,184 @@ public actual fun Double.isFinite(): Boolean = !isInfinite() && !isNaN()
|
||||
/**
|
||||
* Returns `true` if the argument is a finite floating-point value; returns `false` otherwise (for `NaN` and infinity arguments).
|
||||
*/
|
||||
public actual fun Float.isFinite(): Boolean = !isInfinite() && !isNaN()
|
||||
public actual fun Float.isFinite(): Boolean = !isInfinite() && !isNaN()
|
||||
|
||||
|
||||
/**
|
||||
* Counts the number of set bits in the binary representation of this [Int] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public actual fun Int.countOneBits(): Int {
|
||||
// Hacker's Delight 5-1 algorithm
|
||||
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
|
||||
@Suppress("DEPRECATION")
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Int.countLeadingZeroBits(): Int = kotlin.js.Math.clz32(this)
|
||||
|
||||
/**
|
||||
* 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 =
|
||||
// Hacker's Delight 5-4 algorithm for expressing countTrailingZeroBits with countLeadingZeroBits
|
||||
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 =
|
||||
// Hacker's Delight 2-1 algorithm for isolating rightmost 1-bit
|
||||
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 =
|
||||
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 =
|
||||
when (val high = this.high) {
|
||||
0 -> Int.SIZE_BITS + low.countLeadingZeroBits()
|
||||
else -> high.countLeadingZeroBits()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 =
|
||||
when (val low = this.low) {
|
||||
0 -> Int.SIZE_BITS + high.countTrailingZeroBits()
|
||||
else -> low.countTrailingZeroBits()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 =
|
||||
when (val high = this.high) {
|
||||
0 -> Long(low.takeHighestOneBit(), 0)
|
||||
else -> Long(0, high.takeHighestOneBit())
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 =
|
||||
when (val low = this.low) {
|
||||
0 -> Long(0, high.takeLowestOneBit())
|
||||
else -> Long(low.takeLowestOneBit(), 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
if ((bitCount and 31) != 0) {
|
||||
val low = this.low
|
||||
val high = this.high
|
||||
val newLow = low.shl(bitCount) or high.ushr(-bitCount)
|
||||
val newHigh = high.shl(bitCount) or low.ushr(-bitCount)
|
||||
return if ((bitCount and 32) == 0) Long(newLow, newHigh) else Long(newHigh, newLow)
|
||||
} else {
|
||||
return if ((bitCount and 32) == 0) this else Long(high, low)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 = rotateLeft(-bitCount)
|
||||
|
||||
@@ -92,3 +92,152 @@ public actual inline fun Float.toRawBits(): Int = java.lang.Float.floatToRawIntB
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Float.Companion.fromBits(bits: Int): Float = java.lang.Float.intBitsToFloat(bits)
|
||||
|
||||
|
||||
/**
|
||||
* Counts the number of set bits in the binary representation of this [Int] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Int.countOneBits(): Int = Integer.bitCount(this)
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive most significant bits that are zero in the binary representation of this [Int] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Int.countLeadingZeroBits(): Int = Integer.numberOfLeadingZeros(this)
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive least significant bits that are zero in the binary representation of this [Int] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Int.countTrailingZeroBits(): Int = Integer.numberOfTrailingZeros(this)
|
||||
|
||||
/**
|
||||
* 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
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Int.takeHighestOneBit(): Int = Integer.highestOneBit(this)
|
||||
|
||||
/**
|
||||
* 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
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Int.takeLowestOneBit(): Int = Integer.lowestOneBit(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
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Int.rotateLeft(bitCount: Int): Int = Integer.rotateLeft(this, 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
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Int.rotateRight(bitCount: Int): Int = Integer.rotateRight(this, bitCount)
|
||||
|
||||
|
||||
/**
|
||||
* Counts the number of set bits in the binary representation of this [Long] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Long.countOneBits(): Int = java.lang.Long.bitCount(this)
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive most significant bits that are zero in the binary representation of this [Long] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Long.countLeadingZeroBits(): Int = java.lang.Long.numberOfLeadingZeros(this)
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive least significant bits that are zero in the binary representation of this [Long] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Long.countTrailingZeroBits(): Int = java.lang.Long.numberOfTrailingZeros(this)
|
||||
|
||||
/**
|
||||
* 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
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Long.takeHighestOneBit(): Long = java.lang.Long.highestOneBit(this)
|
||||
|
||||
/**
|
||||
* 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
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Long.takeLowestOneBit(): Long = java.lang.Long.lowestOneBit(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
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun Long.rotateLeft(bitCount: Int): Long = java.lang.Long.rotateLeft(this, 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 = java.lang.Long.rotateRight(this, bitCount)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("NumbersKt")
|
||||
package kotlin
|
||||
|
||||
/**
|
||||
* Counts the number of set bits in the binary representation of this [Int] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public expect fun Int.countOneBits(): Int
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive most significant bits that are zero in the binary representation of this [Int] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public expect fun Int.countLeadingZeroBits(): Int
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive least significant bits that are zero in the binary representation of this [Int] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public expect fun Int.countTrailingZeroBits(): Int
|
||||
|
||||
/**
|
||||
* 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 expect fun Int.takeHighestOneBit(): Int
|
||||
|
||||
/**
|
||||
* 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 expect fun Int.takeLowestOneBit(): Int
|
||||
|
||||
/**
|
||||
* 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 expect fun Int.rotateLeft(bitCount: Int): Int
|
||||
|
||||
|
||||
/**
|
||||
* 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 expect fun Int.rotateRight(bitCount: Int): Int
|
||||
|
||||
|
||||
/**
|
||||
* Counts the number of set bits in the binary representation of this [Long] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public expect fun Long.countOneBits(): Int
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive most significant bits that are zero in the binary representation of this [Long] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public expect fun Long.countLeadingZeroBits(): Int
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive least significant bits that are zero in the binary representation of this [Long] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public expect fun Long.countTrailingZeroBits(): Int
|
||||
|
||||
/**
|
||||
* 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 expect fun Long.takeHighestOneBit(): Long
|
||||
|
||||
/**
|
||||
* 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 expect fun Long.takeLowestOneBit(): Long
|
||||
|
||||
/**
|
||||
* 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 expect fun Long.rotateLeft(bitCount: Int): Long
|
||||
|
||||
/**
|
||||
* 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
|
||||
public expect fun Long.rotateRight(bitCount: Int): Long
|
||||
|
||||
/**
|
||||
* Counts the number of set bits in the binary representation of this [Byte] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Byte.countOneBits(): Int = (toInt() and 0xFF).countOneBits()
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive most significant bits that are zero in the binary representation of this [Byte] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Byte.countLeadingZeroBits(): Int = (toInt() and 0xFF).countLeadingZeroBits() - (Int.SIZE_BITS - Byte.SIZE_BITS)
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive least significant bits that are zero in the binary representation of this [Byte] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Byte.countTrailingZeroBits(): Int = (toInt() or 0x100).countTrailingZeroBits()
|
||||
|
||||
/**
|
||||
* Returns a number having a single bit set in the position of the most significant set bit of this [Byte] number,
|
||||
* or zero, if this number is zero.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Byte.takeHighestOneBit(): Byte = (toInt() and 0xFF).takeHighestOneBit().toByte()
|
||||
|
||||
/**
|
||||
* Returns a number having a single bit set in the position of the least significant set bit of this [Byte] number,
|
||||
* or zero, if this number is zero.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Byte.takeLowestOneBit(): Byte = toInt().takeLowestOneBit().toByte()
|
||||
|
||||
|
||||
/**
|
||||
* Rotates the binary representation of this [Byte] 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 [Byte.SIZE_BITS] (8) returns the same number, or more generally
|
||||
* `number.rotateLeft(n) == number.rotateLeft(n % 8)`
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public fun Byte.rotateLeft(bitCount: Int): Byte =
|
||||
(toInt().shl(bitCount and 7) or (toInt() and 0xFF).ushr(8 - (bitCount and 7))).toByte()
|
||||
|
||||
/**
|
||||
* Rotates the binary representation of this [Byte] 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 [Byte.SIZE_BITS] (8) returns the same number, or more generally
|
||||
* `number.rotateRight(n) == number.rotateRight(n % 8)`
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public fun Byte.rotateRight(bitCount: Int): Byte =
|
||||
(toInt().shl(8 - (bitCount and 7)) or (toInt() and 0xFF).ushr(bitCount and 7)).toByte()
|
||||
|
||||
/**
|
||||
* Counts the number of set bits in the binary representation of this [Short] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Short.countOneBits(): Int = (toInt() and 0xFFFF).countOneBits()
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive most significant bits that are zero in the binary representation of this [Short] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Short.countLeadingZeroBits(): Int =
|
||||
(toInt() and 0xFFFF).countLeadingZeroBits() - (Int.SIZE_BITS - Short.SIZE_BITS)
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive least significant bits that are zero in the binary representation of this [Short] number.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Short.countTrailingZeroBits(): Int = (toInt() or 0x10000).countTrailingZeroBits()
|
||||
|
||||
/**
|
||||
* Returns a number having a single bit set in the position of the most significant set bit of this [Short] number,
|
||||
* or zero, if this number is zero.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Short.takeHighestOneBit(): Short = (toInt() and 0xFFFF).takeHighestOneBit().toShort()
|
||||
|
||||
/**
|
||||
* Returns a number having a single bit set in the position of the least significant set bit of this [Short] number,
|
||||
* or zero, if this number is zero.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Short.takeLowestOneBit(): Short = toInt().takeLowestOneBit().toShort()
|
||||
|
||||
|
||||
/**
|
||||
* Rotates the binary representation of this [Short] 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 [Short.SIZE_BITS] (16) returns the same number, or more generally
|
||||
* `number.rotateLeft(n) == number.rotateLeft(n % 16)`
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public fun Short.rotateLeft(bitCount: Int): Short =
|
||||
(toInt().shl(bitCount and 15) or (toInt() and 0xFFFF).ushr(16 - (bitCount and 15))).toShort()
|
||||
|
||||
/**
|
||||
* Rotates the binary representation of this [Short] 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 [Short.SIZE_BITS] (16) returns the same number, or more generally
|
||||
* `number.rotateRight(n) == number.rotateRight(n % 16)`
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public fun Short.rotateRight(bitCount: Int): Short =
|
||||
(toInt().shl(16 - (bitCount and 15)) or (toInt() and 0xFFFF).ushr(bitCount and 15)).toShort()
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package test.numbers
|
||||
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.*
|
||||
|
||||
object NumbersTestConstants {
|
||||
@@ -199,6 +200,196 @@ class NumbersTest {
|
||||
testSizes(UShort, UShort.SIZE_BYTES, UShort.SIZE_BITS, 2)
|
||||
testSizes(UInt, UInt.SIZE_BYTES, UInt.SIZE_BITS, 4)
|
||||
testSizes(ULong, ULong.SIZE_BYTES, ULong.SIZE_BITS, 8)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun byteBits() {
|
||||
fun test(value: Byte, oneBits: Int, leadingZeroes: Int, trailingZeroes: Int) {
|
||||
assertEquals(oneBits, value.countOneBits())
|
||||
assertEquals(leadingZeroes, value.countLeadingZeroBits())
|
||||
assertEquals(trailingZeroes, value.countTrailingZeroBits())
|
||||
val highestBit = if (leadingZeroes < Byte.SIZE_BITS) 1.shl(Byte.SIZE_BITS - leadingZeroes - 1).toByte() else 0
|
||||
val lowestBit = if (trailingZeroes < Byte.SIZE_BITS) 1.shl(trailingZeroes).toByte() else 0
|
||||
assertEquals(highestBit, value.takeHighestOneBit())
|
||||
assertEquals(lowestBit, value.takeLowestOneBit())
|
||||
}
|
||||
|
||||
test(0, 0, 8, 8)
|
||||
test(1, 1, 7, 0)
|
||||
test(2, 1, 6, 1)
|
||||
test(0x44, 2, 1, 2)
|
||||
test(0x80.toByte(), 1, 0, 7)
|
||||
test(0xF0.toByte(), 4, 0, 4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shortBits() {
|
||||
fun test(value: Short, oneBits: Int, leadingZeroes: Int, trailingZeroes: Int) {
|
||||
assertEquals(oneBits, value.countOneBits())
|
||||
assertEquals(leadingZeroes, value.countLeadingZeroBits())
|
||||
assertEquals(trailingZeroes, value.countTrailingZeroBits())
|
||||
val highestBit = if (leadingZeroes < Short.SIZE_BITS) 1.shl(Short.SIZE_BITS - leadingZeroes - 1).toShort() else 0
|
||||
val lowestBit = if (trailingZeroes < Short.SIZE_BITS) 1.shl(trailingZeroes).toShort() else 0
|
||||
assertEquals(highestBit, value.takeHighestOneBit())
|
||||
assertEquals(lowestBit, value.takeLowestOneBit())
|
||||
}
|
||||
|
||||
test(0, 0, 16, 16)
|
||||
test(1, 1, 15, 0)
|
||||
test(2, 1, 14, 1)
|
||||
test(0xF2, 5, 8, 1)
|
||||
test(0x8000.toShort(), 1, 0, 15)
|
||||
test(0xF200.toShort(), 5, 0, 9)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun intBits() {
|
||||
fun test(value: Int, oneBits: Int, leadingZeroes: Int, trailingZeroes: Int) {
|
||||
assertEquals(oneBits, value.countOneBits())
|
||||
assertEquals(leadingZeroes, value.countLeadingZeroBits())
|
||||
assertEquals(trailingZeroes, value.countTrailingZeroBits())
|
||||
val highestBit = if (leadingZeroes < Int.SIZE_BITS) 1.shl(Int.SIZE_BITS - leadingZeroes - 1) else 0
|
||||
val lowestBit = if (trailingZeroes < Int.SIZE_BITS) 1.shl(trailingZeroes) else 0
|
||||
assertEquals(highestBit, value.takeHighestOneBit())
|
||||
assertEquals(lowestBit, value.takeLowestOneBit())
|
||||
}
|
||||
|
||||
test(0, 0, 32, 32)
|
||||
test(1, 1, 31, 0)
|
||||
test(2, 1, 30, 1)
|
||||
test(0xF002, 5, 16, 1)
|
||||
test(0xF00F0000.toInt(), 8, 0, 16)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun longBits() {
|
||||
fun test(value: Long, oneBits: Int, leadingZeroes: Int, trailingZeroes: Int) {
|
||||
assertEquals(oneBits, value.countOneBits())
|
||||
assertEquals(leadingZeroes, value.countLeadingZeroBits())
|
||||
assertEquals(trailingZeroes, value.countTrailingZeroBits())
|
||||
val highestBit = if (leadingZeroes < Long.SIZE_BITS) 1L.shl(Long.SIZE_BITS - leadingZeroes - 1).toLong() else 0
|
||||
val lowestBit = if (trailingZeroes < Long.SIZE_BITS) 1L.shl(trailingZeroes).toLong() else 0
|
||||
assertEquals(highestBit, value.takeHighestOneBit())
|
||||
assertEquals(lowestBit, value.takeLowestOneBit())
|
||||
}
|
||||
|
||||
test(0, 0, 64, 64)
|
||||
test(1, 1, 63, 0)
|
||||
test(2, 1, 62, 1)
|
||||
test(0xF002, 5, 48, 1)
|
||||
test(0xF00F0000L, 8, 32, 16)
|
||||
test(0x1111_3333_EEEE_0000L, 4 + 8 + 12, 3, 17)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun intRotate() {
|
||||
fun test(value: Int, n: Int, expected: Int) {
|
||||
assertEquals(expected, value.rotateLeft(n))
|
||||
assertEquals(expected, value.rotateRight(-n))
|
||||
}
|
||||
|
||||
fun testCyclic(value: Int) {
|
||||
for (n in -2 * Int.SIZE_BITS..2 * Int.SIZE_BITS) {
|
||||
val rl = value.rotateLeft(n)
|
||||
val rr = value.rotateRight(-n)
|
||||
assertEquals(rl, rr)
|
||||
assertEquals(rl, value.rotateLeft(n % Int.SIZE_BITS))
|
||||
assertEquals(rr, value.rotateRight((-n) % Int.SIZE_BITS))
|
||||
assertEquals(value, value.rotateLeft(n).rotateLeft(-n))
|
||||
assertEquals(value, value.rotateRight(n).rotateRight(-n))
|
||||
}
|
||||
}
|
||||
|
||||
test(0x7_3422345, 4, 0x3422345_7)
|
||||
test(0x7342234_5, -4, 0x5_7342234)
|
||||
test(0x73422345, 1, 0xE684468A.toInt())
|
||||
repeat(100) {
|
||||
testCyclic(Random.nextInt())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun byteRotate() {
|
||||
fun test(value: Byte, n: Int, expected: Byte) {
|
||||
assertEquals(expected, value.rotateLeft(n))
|
||||
assertEquals(expected, value.rotateRight(-n))
|
||||
}
|
||||
|
||||
fun testCyclic(value: Byte) {
|
||||
for (n in -2 * Byte.SIZE_BITS..2 * Byte.SIZE_BITS) {
|
||||
val rl = value.rotateLeft(n)
|
||||
val rr = value.rotateRight(-n)
|
||||
assertEquals(rl, rr)
|
||||
assertEquals(rl, value.rotateLeft(n % Byte.SIZE_BITS))
|
||||
assertEquals(rr, value.rotateRight((-n) % Byte.SIZE_BITS))
|
||||
assertEquals(value, value.rotateLeft(n).rotateLeft(-n))
|
||||
assertEquals(value, value.rotateRight(n).rotateRight(-n))
|
||||
}
|
||||
}
|
||||
|
||||
test(0x73, 4, 0x37)
|
||||
test(0x73, -3, 0x6E)
|
||||
test(0x73, 1, 0xE6.toByte())
|
||||
test(0xE6.toByte(), 1, 0xCD.toByte())
|
||||
repeat(100) {
|
||||
testCyclic(Random.nextInt().toByte())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun longRotate() {
|
||||
fun test(value: Long, n: Int, expected: Long) {
|
||||
assertEquals(expected, value.rotateLeft(n))
|
||||
assertEquals(expected, value.rotateRight(-n))
|
||||
}
|
||||
|
||||
fun testCyclic(value: Long) {
|
||||
for (n in -2 * Long.SIZE_BITS..2 * Long.SIZE_BITS) {
|
||||
val rl = value.rotateLeft(n)
|
||||
val rr = value.rotateRight(-n)
|
||||
assertEquals(rl, rr)
|
||||
assertEquals(rl, value.rotateLeft(n % Long.SIZE_BITS))
|
||||
assertEquals(rr, value.rotateRight((-n) % Long.SIZE_BITS))
|
||||
assertEquals(value, value.rotateLeft(n).rotateLeft(-n))
|
||||
assertEquals(value, value.rotateRight(n).rotateRight(-n))
|
||||
}
|
||||
}
|
||||
|
||||
test(0x7372ABAC_DEEF0123, 4, 0x372ABAC_DEEF01237)
|
||||
test(0x88888888_44444444U.toLong(), -3, 0x91111111_08888888u.toLong())
|
||||
test(0x88888888_44444444U.toLong(), 1, 0x11111110_88888889)
|
||||
repeat(100) {
|
||||
testCyclic(Random.nextLong())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shortRotate() {
|
||||
fun test(value: Short, n: Int, expected: Short) {
|
||||
assertEquals(expected, value.rotateLeft(n))
|
||||
assertEquals(expected, value.rotateRight(-n))
|
||||
}
|
||||
|
||||
fun testCyclic(value: Short) {
|
||||
for (n in -2 * Short.SIZE_BITS..2 * Short.SIZE_BITS) {
|
||||
val rl = value.rotateLeft(n)
|
||||
val rr = value.rotateRight(-n)
|
||||
assertEquals(rl, rr)
|
||||
assertEquals(rl, value.rotateLeft(n % Short.SIZE_BITS))
|
||||
assertEquals(rr, value.rotateRight((-n) % Short.SIZE_BITS))
|
||||
assertEquals(value, value.rotateLeft(n).rotateLeft(-n))
|
||||
assertEquals(value, value.rotateRight(n).rotateRight(-n))
|
||||
}
|
||||
}
|
||||
|
||||
test(0x7361, 4, 0x3617)
|
||||
test(0x7361, -3, 0b001_0111_0011_0110_0)
|
||||
test(0x7361, 1, 0b111_0011_0110_0001_0.toShort())
|
||||
test(0xE6C2.toShort(), 1, 0b11_0011_0110_0001_01.toShort())
|
||||
repeat(100) {
|
||||
testCyclic(Random.nextInt().toShort())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+7
@@ -119,6 +119,13 @@ public final class kotlin/NotImplementedError : java/lang/Error {
|
||||
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class kotlin/NumbersKt {
|
||||
public static final fun rotateLeft (BI)B
|
||||
public static final fun rotateLeft (SI)S
|
||||
public static final fun rotateRight (BI)B
|
||||
public static final fun rotateRight (SI)S
|
||||
}
|
||||
|
||||
public abstract interface annotation class kotlin/OptionalExpectation : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user