Implement conversion between floating point numbers and unsigned integers

KT-27108
This commit is contained in:
Abduqodiri Qurbonzoda
2019-01-28 14:49:23 +03:00
committed by Ilya Gorbunov
parent a970de51ab
commit 1b6b44c805
10 changed files with 364 additions and 1 deletions
@@ -176,6 +176,11 @@ public inline class UByte @PublishedApi internal constructor(@PublishedApi inter
@kotlin.internal.InlineOnly
public inline fun toULong(): ULong = ULong(data.toLong() and 0xFF)
@kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toInt().toFloat()
@kotlin.internal.InlineOnly
public inline fun toDouble(): Double = this.toInt().toDouble()
public override fun toString(): String = toInt().toString()
}
@@ -196,3 +201,12 @@ public inline fun Int.toUByte(): UByte = UByte(this.toByte())
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Long.toUByte(): UByte = UByte(this.toByte())
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Float.toUByte(): UByte = doubleToUByte(this.toDouble())
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Double.toUByte(): UByte = doubleToUByte(this)
@@ -182,6 +182,11 @@ public inline class UInt @PublishedApi internal constructor(@PublishedApi intern
@kotlin.internal.InlineOnly
public inline fun toULong(): ULong = ULong(data.toLong() and 0xFFFF_FFFF)
@kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toDouble().toFloat()
@kotlin.internal.InlineOnly
public inline fun toDouble(): Double = uintToDouble(data)
public override fun toString(): String = toLong().toString()
}
@@ -202,3 +207,12 @@ public inline fun Int.toUInt(): UInt = UInt(this)
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Long.toUInt(): UInt = UInt(this.toInt())
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Float.toUInt(): UInt = doubleToUInt(this.toDouble())
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Double.toUInt(): UInt = doubleToUInt(this)
@@ -182,6 +182,11 @@ public inline class ULong @PublishedApi internal constructor(@PublishedApi inter
@kotlin.internal.InlineOnly
public inline fun toULong(): ULong = this
@kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toDouble().toFloat()
@kotlin.internal.InlineOnly
public inline fun toDouble(): Double = ulongToDouble(data)
public override fun toString(): String = ulongToString(data)
}
@@ -202,3 +207,12 @@ public inline fun Int.toULong(): ULong = ULong(this.toLong())
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Long.toULong(): ULong = ULong(this)
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Float.toULong(): ULong = doubleToULong(this.toDouble())
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Double.toULong(): ULong = doubleToULong(this)
@@ -176,6 +176,11 @@ public inline class UShort @PublishedApi internal constructor(@PublishedApi inte
@kotlin.internal.InlineOnly
public inline fun toULong(): ULong = ULong(data.toLong() and 0xFFFF)
@kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toInt().toFloat()
@kotlin.internal.InlineOnly
public inline fun toDouble(): Double = this.toInt().toDouble()
public override fun toString(): String = toInt().toString()
}
@@ -196,3 +201,12 @@ public inline fun Int.toUShort(): UShort = UShort(this.toShort())
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Long.toUShort(): UShort = UShort(this.toShort())
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Float.toUShort(): UShort = doubleToUShort(this.toDouble())
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline fun Double.toUShort(): UShort = doubleToUShort(this)
@@ -63,6 +63,50 @@ internal fun ulongRemainder(v1: ULong, v2: ULong): ULong {
}
@PublishedApi
internal fun doubleToUByte(v: Double): UByte = when {
v.isNaN() -> 0u
v <= UByte.MIN_VALUE.toDouble() -> UByte.MIN_VALUE
v >= UByte.MAX_VALUE.toDouble() -> UByte.MAX_VALUE
else -> v.toInt().toUByte()
}
@PublishedApi
internal fun doubleToUShort(v: Double): UShort = when {
v.isNaN() -> 0u
v <= UShort.MIN_VALUE.toDouble() -> UShort.MIN_VALUE
v >= UShort.MAX_VALUE.toDouble() -> UShort.MAX_VALUE
else -> v.toInt().toUShort()
}
@PublishedApi
internal fun doubleToUInt(v: Double): UInt = when {
v.isNaN() -> 0u
v <= UInt.MIN_VALUE.toDouble() -> UInt.MIN_VALUE
v >= UInt.MAX_VALUE.toDouble() -> UInt.MAX_VALUE
v <= Int.MAX_VALUE -> v.toInt().toUInt()
else -> (v - Int.MAX_VALUE).toInt().toUInt() + Int.MAX_VALUE.toUInt() // Int.MAX_VALUE < v < UInt.MAX_VALUE
}
@PublishedApi
internal fun doubleToULong(v: Double): ULong = when {
v.isNaN() -> 0u
v <= ULong.MIN_VALUE.toDouble() -> ULong.MIN_VALUE
v >= ULong.MAX_VALUE.toDouble() -> ULong.MAX_VALUE
v < Long.MAX_VALUE -> v.toLong().toULong()
// Real values from Long.MAX_VALUE to (Long.MAX_VALUE + 1) are not representable in Double, so don't handle them.
else -> (v - 9223372036854775808.0).toLong().toULong() + 9223372036854775808uL // Long.MAX_VALUE + 1 < v < ULong.MAX_VALUE
}
@PublishedApi
internal fun uintToDouble(v: Int): Double = (v and Int.MAX_VALUE).toDouble() + (v ushr 31 shl 30).toDouble() * 2
@PublishedApi
internal fun ulongToDouble(v: Long): Double = (v ushr 11).toDouble() * 2048 + (v and 2047)
internal fun ulongToString(v: Long): String = ulongToString(v, 10)
internal fun ulongToString(v: Long, base: Int): String {