[K/Wasm] Generate wasm-specific unsigned implementations ^KT-58039 Fixed

This commit is contained in:
Artem Kobzar
2024-01-23 18:49:06 +01:00
committed by Space Team
parent b59993d88a
commit 8c69ffe8c9
24 changed files with 666 additions and 541 deletions
@@ -342,14 +342,14 @@ public value class UByte @kotlin.internal.IntrinsicConstEvaluation @PublishedApi
* The resulting `Float` value represents the same numerical value as this `UByte`.
*/
@kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toInt().toFloat()
public inline fun toFloat(): Float = uintToFloat(this.toInt())
/**
* Converts this [UByte] value to [Double].
*
* The resulting `Double` value represents the same numerical value as this `UByte`.
*/
@kotlin.internal.InlineOnly
public inline fun toDouble(): Double = this.toInt().toDouble()
public inline fun toDouble(): Double = uintToDouble(this.toInt())
public override fun toString(): String = toInt().toString()
+5 -5
View File
@@ -320,7 +320,7 @@ public value class UInt @kotlin.internal.IntrinsicConstEvaluation @PublishedApi
* whereas the most significant 32 bits are filled with zeros.
*/
@kotlin.internal.InlineOnly
public inline fun toLong(): Long = data.toLong() and 0xFFFF_FFFF
public inline fun toLong(): Long = uintToLong(data)
/**
* Converts this [UInt] value to [UByte].
@@ -354,7 +354,7 @@ public value class UInt @kotlin.internal.IntrinsicConstEvaluation @PublishedApi
* whereas the most significant 32 bits are filled with zeros.
*/
@kotlin.internal.InlineOnly
public inline fun toULong(): ULong = ULong(data.toLong() and 0xFFFF_FFFF)
public inline fun toULong(): ULong = uintToULong(data)
/**
* Converts this [UInt] value to [Float].
@@ -364,7 +364,7 @@ public value class UInt @kotlin.internal.IntrinsicConstEvaluation @PublishedApi
* the one with zero at least significant bit of mantissa is selected.
*/
@kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toDouble().toFloat()
public inline fun toFloat(): Float = uintToFloat(data)
/**
* Converts this [UInt] value to [Double].
*
@@ -373,7 +373,7 @@ public value class UInt @kotlin.internal.IntrinsicConstEvaluation @PublishedApi
@kotlin.internal.InlineOnly
public inline fun toDouble(): Double = uintToDouble(data)
public override fun toString(): String = toLong().toString()
public override fun toString(): String = uintToString(data)
}
@@ -434,7 +434,7 @@ public inline fun Long.toUInt(): UInt = UInt(this.toInt())
@SinceKotlin("1.5")
@WasExperimental(ExperimentalUnsignedTypes::class)
@kotlin.internal.InlineOnly
public inline fun Float.toUInt(): UInt = doubleToUInt(this.toDouble())
public inline fun Float.toUInt(): UInt = floatToUInt(this)
/**
* Converts this [Double] value to [UInt].
*
@@ -365,7 +365,7 @@ public value class ULong @kotlin.internal.IntrinsicConstEvaluation @PublishedApi
* the one with zero at least significant bit of mantissa is selected.
*/
@kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toDouble().toFloat()
public inline fun toFloat(): Float = ulongToFloat(data)
/**
* Converts this [ULong] value to [Double].
*
@@ -437,7 +437,7 @@ public inline fun Long.toULong(): ULong = ULong(this)
@SinceKotlin("1.5")
@WasExperimental(ExperimentalUnsignedTypes::class)
@kotlin.internal.InlineOnly
public inline fun Float.toULong(): ULong = doubleToULong(this.toDouble())
public inline fun Float.toULong(): ULong = floatToULong(this)
/**
* Converts this [Double] value to [ULong].
*
@@ -343,14 +343,14 @@ public value class UShort @kotlin.internal.IntrinsicConstEvaluation @PublishedAp
* The resulting `Float` value represents the same numerical value as this `UShort`.
*/
@kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toInt().toFloat()
public inline fun toFloat(): Float = uintToFloat(this.toInt())
/**
* Converts this [UShort] value to [Double].
*
* The resulting `Double` value represents the same numerical value as this `UShort`.
*/
@kotlin.internal.InlineOnly
public inline fun toDouble(): Double = this.toInt().toDouble()
public inline fun toDouble(): Double = uintToDouble(this.toInt())
public override fun toString(): String = toInt().toString()
@@ -36,7 +36,7 @@ public /*inline*/ fun UShort.toString(radix: Int): String = this.toInt().toStrin
@SinceKotlin("1.5")
@WasExperimental(ExperimentalUnsignedTypes::class)
//@kotlin.internal.InlineOnly
public /*inline*/ fun UInt.toString(radix: Int): String = this.toLong().toString(radix)
public /*inline*/ fun UInt.toString(radix: Int): String = uintToString(this.toInt(), checkRadix(radix))
/**
* Returns a string representation of this [Long] value in the specified [radix].
@@ -1,105 +1,62 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 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.JvmName("UnsignedKt")
package kotlin
@PublishedApi
internal fun uintCompare(v1: Int, v2: Int): Int = (v1 xor Int.MIN_VALUE).compareTo(v2 xor Int.MIN_VALUE)
@PublishedApi
internal fun ulongCompare(v1: Long, v2: Long): Int = (v1 xor Long.MIN_VALUE).compareTo(v2 xor Long.MIN_VALUE)
internal expect fun uintRemainder(v1: UInt, v2: UInt): UInt
@PublishedApi
internal fun uintDivide(v1: UInt, v2: UInt): UInt = (v1.toLong() / v2.toLong()).toUInt()
@PublishedApi
internal fun uintRemainder(v1: UInt, v2: UInt): UInt = (v1.toLong() % v2.toLong()).toUInt()
// Division and remainder are based on Guava's UnsignedLongs implementation
// Copyright 2011 The Guava Authors
internal expect fun ulongRemainder(v1: ULong, v2: ULong): ULong
@PublishedApi
internal fun ulongDivide(v1: ULong, v2: ULong): ULong {
val dividend = v1.toLong()
val divisor = v2.toLong()
if (divisor < 0) { // i.e., divisor >= 2^63:
return if (v1 < v2) ULong(0) else ULong(1)
}
// Optimization - use signed division if both dividend and divisor < 2^63
if (dividend >= 0) {
return ULong(dividend / divisor)
}
// Otherwise, approximate the quotient, check, and correct if necessary.
val quotient = ((dividend ushr 1) / divisor) shl 1
val rem = dividend - quotient * divisor
return ULong(quotient + if (ULong(rem) >= ULong(divisor)) 1 else 0)
}
internal expect fun uintDivide(v1: UInt, v2: UInt): UInt
@PublishedApi
internal fun ulongRemainder(v1: ULong, v2: ULong): ULong {
val dividend = v1.toLong()
val divisor = v2.toLong()
if (divisor < 0) { // i.e., divisor >= 2^63:
return if (v1 < v2) {
v1 // dividend < divisor
} else {
v1 - v2 // dividend >= divisor
}
}
// Optimization - use signed modulus if both dividend and divisor < 2^63
if (dividend >= 0) {
return ULong(dividend % divisor)
}
// Otherwise, approximate the quotient, check, and correct if necessary.
val quotient = ((dividend ushr 1) / divisor) shl 1
val rem = dividend - quotient * divisor
return ULong(rem - if (ULong(rem) >= ULong(divisor)) divisor else 0)
}
internal expect fun ulongDivide(v1: ULong, v2: ULong): ULong
@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
}
internal expect fun uintCompare(v1: Int, v2: Int): Int
@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
}
internal expect fun ulongCompare(v1: Long, v2: Long): Int
@PublishedApi
internal fun uintToDouble(v: Int): Double = (v and Int.MAX_VALUE).toDouble() + (v ushr 31 shl 30).toDouble() * 2
internal expect fun uintToULong(value: Int): ULong
@PublishedApi
internal fun ulongToDouble(v: Long): Double = (v ushr 11).toDouble() * 2048 + (v and 2047)
internal expect fun uintToLong(value: Int): Long
@PublishedApi
internal expect fun uintToFloat(value: Int): Float
internal fun ulongToString(v: Long): String = ulongToString(v, 10)
@PublishedApi
internal expect fun floatToUInt(value: Float): UInt
internal fun ulongToString(v: Long, base: Int): String {
if (v >= 0) return v.toString(base)
@PublishedApi
internal expect fun uintToDouble(value: Int): Double
var quotient = ((v ushr 1) / base) shl 1
var rem = v - quotient * base
if (rem >= base) {
rem -= base
quotient += 1
}
return quotient.toString(base) + rem.toString(base)
}
@PublishedApi
internal expect fun doubleToUInt(value: Double): UInt
@PublishedApi
internal expect fun ulongToFloat(value: Long): Float
@PublishedApi
internal expect fun floatToULong(value: Float): ULong
@PublishedApi
internal expect fun ulongToDouble(value: Long): Double
@PublishedApi
internal expect fun doubleToULong(value: Double): ULong
internal expect fun uintToString(value: Int): String
internal expect fun uintToString(value: Int, base: Int): String
internal expect fun ulongToString(value: Long): String
internal expect fun ulongToString(value: Long, base: Int): String