WASM: Impelment float to string conversion operations
This commit is contained in:
committed by
TeamCityServer
parent
f34a079699
commit
0eba74a9d2
@@ -1758,7 +1758,7 @@ public class Float private constructor(public val value: Float) : Number(), Comp
|
||||
other is Float && this.equals(other)
|
||||
|
||||
public override fun toString(): String =
|
||||
TODO("Wasm: string coercion")
|
||||
dtoa(this.toDouble())
|
||||
|
||||
public override inline fun hashCode(): Int =
|
||||
bits()
|
||||
@@ -2071,7 +2071,7 @@ public class Double private constructor(public val value: Double) : Number(), Co
|
||||
other is Double && this.bits() == other.bits()
|
||||
|
||||
public override fun toString(): String =
|
||||
TODO("Wasm: string coercion")
|
||||
dtoa(this)
|
||||
|
||||
public override inline fun hashCode(): Int = bits().hashCode()
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ package kotlin.wasm.internal
|
||||
|
||||
private enum class CharCodes(val code: Int) {
|
||||
// PERCENT(0x25),
|
||||
// PLUS(0x2B),
|
||||
MINUS(0x2D),
|
||||
// DOT(0x2E),
|
||||
_0(0x30),
|
||||
PLUS(0x2B),
|
||||
MINUS(0x2D),
|
||||
DOT(0x2E),
|
||||
_0(0x30),
|
||||
// _1(0x31),
|
||||
// _2(0x32),
|
||||
// _3(0x33),
|
||||
@@ -29,7 +29,7 @@ private enum class CharCodes(val code: Int) {
|
||||
// Z(0x5A),
|
||||
// a(0x61),
|
||||
// b(0x62),
|
||||
// e(0x65),
|
||||
e(0x65),
|
||||
// n(0x6E),
|
||||
// o(0x6F),
|
||||
// u(0x75),
|
||||
@@ -101,6 +101,7 @@ private fun utoaDecSimple64(buffer: CharArray, numInput: Long, offsetInput: Int)
|
||||
|
||||
|
||||
private fun Boolean.toInt() = if (this) 1 else 0
|
||||
private fun Boolean.toLong() = if (this) 1L else 0L
|
||||
|
||||
private fun decimalCount32(value: Int): Int {
|
||||
if (value < 100000) {
|
||||
@@ -163,3 +164,311 @@ private fun decimalCount64High(value: Long): Int {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val MAX_DOUBLE_LENGTH = 28
|
||||
|
||||
internal fun dtoa(value: Double): String {
|
||||
if (value == 0.0) return "0.0"
|
||||
if (!value.isFinite()) {
|
||||
if (value.isNaN()) return "NaN"
|
||||
return if (value < 0) "-Infinity" else "Infinity"
|
||||
}
|
||||
|
||||
val buf = CharArray(MAX_DOUBLE_LENGTH)
|
||||
val size = dtoaCore(buf, value)
|
||||
val ret = CharArray(size)
|
||||
buf.copyInto(ret, 0, 0, size)
|
||||
return kotlin.String(ret)
|
||||
}
|
||||
|
||||
private fun dtoaCore(buffer: CharArray, valueInp: Double): Int {
|
||||
var value = valueInp
|
||||
|
||||
val sign = (value < 0).toInt()
|
||||
if (sign == 1) {
|
||||
value = -value
|
||||
buffer[0] = CharCodes.MINUS.code.toChar()
|
||||
}
|
||||
|
||||
var len = grisu2(value, buffer, sign)
|
||||
len = prettify(BufferWithOffset(buffer, sign), len - sign, _K)
|
||||
return len + sign
|
||||
}
|
||||
|
||||
// These are needed for grisu2 implementation
|
||||
// TODO: What we are going to do with multiple threads?
|
||||
private var _K: Int = 0
|
||||
private var _exp: Int = 0
|
||||
private var _frc_minus: Long = 0
|
||||
private var _frc_plus: Long = 0
|
||||
private var _frc_pow: Long = 0
|
||||
private var _exp_pow: Int = 0
|
||||
|
||||
private val EXP_POWERS = shortArrayOf(
|
||||
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
|
||||
-954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
|
||||
-688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
|
||||
-422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
|
||||
-157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
|
||||
109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
|
||||
375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
|
||||
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
|
||||
907, 933, 960, 986, 1013, 1039, 1066
|
||||
)
|
||||
|
||||
// 1e-348, 1e-340, ..., 1e340
|
||||
private val FRC_POWERS = longArrayOf(
|
||||
0xFA8FD5A0081C0288UL.toLong(), 0xBAAEE17FA23EBF76UL.toLong(), 0x8B16FB203055AC76UL.toLong(), 0xCF42894A5DCE35EAUL.toLong(),
|
||||
0x9A6BB0AA55653B2DUL.toLong(), 0xE61ACF033D1A45DFUL.toLong(), 0xAB70FE17C79AC6CAUL.toLong(), 0xFF77B1FCBEBCDC4FUL.toLong(),
|
||||
0xBE5691EF416BD60CUL.toLong(), 0x8DD01FAD907FFC3CUL.toLong(), 0xD3515C2831559A83UL.toLong(), 0x9D71AC8FADA6C9B5UL.toLong(),
|
||||
0xEA9C227723EE8BCBUL.toLong(), 0xAECC49914078536DUL.toLong(), 0x823C12795DB6CE57UL.toLong(), 0xC21094364DFB5637UL.toLong(),
|
||||
0x9096EA6F3848984FUL.toLong(), 0xD77485CB25823AC7UL.toLong(), 0xA086CFCD97BF97F4UL.toLong(), 0xEF340A98172AACE5UL.toLong(),
|
||||
0xB23867FB2A35B28EUL.toLong(), 0x84C8D4DFD2C63F3BUL.toLong(), 0xC5DD44271AD3CDBAUL.toLong(), 0x936B9FCEBB25C996UL.toLong(),
|
||||
0xDBAC6C247D62A584UL.toLong(), 0xA3AB66580D5FDAF6UL.toLong(), 0xF3E2F893DEC3F126UL.toLong(), 0xB5B5ADA8AAFF80B8UL.toLong(),
|
||||
0x87625F056C7C4A8BUL.toLong(), 0xC9BCFF6034C13053UL.toLong(), 0x964E858C91BA2655UL.toLong(), 0xDFF9772470297EBDUL.toLong(),
|
||||
0xA6DFBD9FB8E5B88FUL.toLong(), 0xF8A95FCF88747D94UL.toLong(), 0xB94470938FA89BCFUL.toLong(), 0x8A08F0F8BF0F156BUL.toLong(),
|
||||
0xCDB02555653131B6UL.toLong(), 0x993FE2C6D07B7FACUL.toLong(), 0xE45C10C42A2B3B06UL.toLong(), 0xAA242499697392D3UL.toLong(),
|
||||
0xFD87B5F28300CA0EUL.toLong(), 0xBCE5086492111AEBUL.toLong(), 0x8CBCCC096F5088CCUL.toLong(), 0xD1B71758E219652CUL.toLong(),
|
||||
0x9C40000000000000UL.toLong(), 0xE8D4A51000000000UL.toLong(), 0xAD78EBC5AC620000UL.toLong(), 0x813F3978F8940984UL.toLong(),
|
||||
0xC097CE7BC90715B3UL.toLong(), 0x8F7E32CE7BEA5C70UL.toLong(), 0xD5D238A4ABE98068UL.toLong(), 0x9F4F2726179A2245UL.toLong(),
|
||||
0xED63A231D4C4FB27UL.toLong(), 0xB0DE65388CC8ADA8UL.toLong(), 0x83C7088E1AAB65DBUL.toLong(), 0xC45D1DF942711D9AUL.toLong(),
|
||||
0x924D692CA61BE758UL.toLong(), 0xDA01EE641A708DEAUL.toLong(), 0xA26DA3999AEF774AUL.toLong(), 0xF209787BB47D6B85UL.toLong(),
|
||||
0xB454E4A179DD1877UL.toLong(), 0x865B86925B9BC5C2UL.toLong(), 0xC83553C5C8965D3DUL.toLong(), 0x952AB45CFA97A0B3UL.toLong(),
|
||||
0xDE469FBD99A05FE3UL.toLong(), 0xA59BC234DB398C25UL.toLong(), 0xF6C69A72A3989F5CUL.toLong(), 0xB7DCBF5354E9BECEUL.toLong(),
|
||||
0x88FCF317F22241E2UL.toLong(), 0xCC20CE9BD35C78A5UL.toLong(), 0x98165AF37B2153DFUL.toLong(), 0xE2A0B5DC971F303AUL.toLong(),
|
||||
0xA8D9D1535CE3B396UL.toLong(), 0xFB9B7CD9A4A7443CUL.toLong(), 0xBB764C4CA7A44410UL.toLong(), 0x8BAB8EEFB6409C1AUL.toLong(),
|
||||
0xD01FEF10A657842CUL.toLong(), 0x9B10A4E5E9913129UL.toLong(), 0xE7109BFBA19C0C9DUL.toLong(), 0xAC2820D9623BF429UL.toLong(),
|
||||
0x80444B5E7AA7CF85UL.toLong(), 0xBF21E44003ACDD2DUL.toLong(), 0x8E679C2F5E44FF8FUL.toLong(), 0xD433179D9C8CB841UL.toLong(),
|
||||
0x9E19DB92B4E31BA9UL.toLong(), 0xEB96BF6EBADF77D9UL.toLong(), 0xAF87023B9BF0EE6BUL.toLong()
|
||||
)
|
||||
|
||||
private fun grisu2(value: Double, buffer: CharArray, sign: Int): Int {
|
||||
// frexp routine
|
||||
val uv = value.toBits()
|
||||
var exp = ((uv and 0x7FF0000000000000) ushr 52).toInt()
|
||||
val sid = uv and 0x000FFFFFFFFFFFFF
|
||||
var frc = ((exp != 0).toLong() shl 52) + sid
|
||||
exp = (if (exp != 0) exp else 1) - (0x3FF + 52)
|
||||
|
||||
normalizedBoundaries(frc, exp)
|
||||
getCachedPower(_exp)
|
||||
|
||||
// normalize
|
||||
val off = frc.countLeadingZeroBits()
|
||||
frc = frc shl off
|
||||
exp -= off
|
||||
|
||||
var frc_pow = _frc_pow
|
||||
var exp_pow = _exp_pow
|
||||
|
||||
var w_frc = umul64f(frc, frc_pow)
|
||||
var w_exp = umul64e(exp, exp_pow)
|
||||
|
||||
var wp_frc = umul64f(_frc_plus, frc_pow) - 1
|
||||
var wp_exp = umul64e(_exp, exp_pow)
|
||||
|
||||
var wm_frc = umul64f(_frc_minus, frc_pow) + 1
|
||||
var delta = wp_frc - wm_frc
|
||||
|
||||
return genDigits(buffer, w_frc, w_exp, wp_frc, wp_exp, delta, sign);
|
||||
}
|
||||
|
||||
private fun umul64f(u: Long, v: Long): Long {
|
||||
val u0 = u and 0xFFFFFFFF
|
||||
val v0 = v and 0xFFFFFFFF
|
||||
|
||||
val u1 = u ushr 32
|
||||
val v1 = v ushr 32
|
||||
|
||||
val l = u0 * v0
|
||||
var t = u1 * v0 + (l ushr 32)
|
||||
var w = u0 * v1 + (t and 0xFFFFFFFF)
|
||||
|
||||
w += 0x7FFFFFFF // rounding
|
||||
|
||||
t = t ushr 32
|
||||
w = w ushr 32
|
||||
|
||||
return u1 * v1 + t + w
|
||||
}
|
||||
|
||||
private fun umul64e(e1: Int, e2: Int): Int {
|
||||
return e1 + e2 + 64 // where 64 is significand size
|
||||
}
|
||||
|
||||
private fun normalizedBoundaries(f: Long, e: Int) {
|
||||
var frc = (f shl 1) + 1
|
||||
var exp = e - 1
|
||||
val off = frc.countLeadingZeroBits()
|
||||
frc = frc shl off
|
||||
exp -= off
|
||||
|
||||
val m = 1 + (f == 0x0010000000000000).toInt()
|
||||
|
||||
_frc_plus = frc
|
||||
_frc_minus = ((f shl m) - 1) shl e - m - exp
|
||||
_exp = exp
|
||||
}
|
||||
|
||||
private fun getCachedPower(minExp: Int) {
|
||||
val c = Double.fromBits(0x3FD34413509F79FE) // 1 / lg(10) = 0.30102999566398114
|
||||
val dk = (-61 - minExp) * c + 347 // dk must be positive, so can do ceiling in positive
|
||||
var k = dk.toInt()
|
||||
k += (k.toDouble() != dk).toInt() // conversion with ceil
|
||||
|
||||
val index = (k shr 3) + 1
|
||||
_K = 348 - (index shl 3) // decimal exponent no need lookup table
|
||||
_frc_pow = FRC_POWERS[index]
|
||||
_exp_pow = EXP_POWERS[index].toInt()
|
||||
}
|
||||
|
||||
private fun genDigits(buffer: CharArray, w_frc: Long, w_exp: Int, mp_frc: Long, mp_exp: Int, deltaInp: Long, sign: Int): Int {
|
||||
var delta = deltaInp
|
||||
val one_exp = -mp_exp
|
||||
val one_frc = 1L shl one_exp
|
||||
val mask = one_frc - 1
|
||||
|
||||
var wp_w_frc = mp_frc - w_frc
|
||||
|
||||
var p1 = (mp_frc ushr one_exp).toInt()
|
||||
var p2 = mp_frc and mask
|
||||
|
||||
var kappa = decimalCount32(p1)
|
||||
var len = sign
|
||||
|
||||
while (kappa > 0) {
|
||||
var d: Int
|
||||
var pow10: Long
|
||||
when (kappa) {
|
||||
0 -> { d = p1 / 1000000000; p1 %= 1000000000; pow10 = 1000000000; }
|
||||
9 -> { d = p1 / 100000000; p1 %= 100000000; pow10 = 100000000; }
|
||||
8 -> { d = p1 / 10000000; p1 %= 10000000; pow10 = 10000000; }
|
||||
7 -> { d = p1 / 1000000; p1 %= 1000000; pow10 = 1000000; }
|
||||
6 -> { d = p1 / 100000; p1 %= 100000; pow10 = 100000; }
|
||||
5 -> { d = p1 / 10000; p1 %= 10000; pow10 = 10000; }
|
||||
4 -> { d = p1 / 1000; p1 %= 1000; pow10 = 1000; }
|
||||
3 -> { d = p1 / 100; p1 %= 100; pow10 = 100; }
|
||||
2 -> { d = p1 / 10; p1 %= 10; pow10 = 10; }
|
||||
1 -> { d = p1; p1 = 0; pow10 = 1; }
|
||||
else -> { d = 0; pow10 = 1; }
|
||||
}
|
||||
|
||||
if (d or len != 0)
|
||||
buffer[len++] = digitToChar(d)
|
||||
|
||||
--kappa
|
||||
val tmp = (p1.toLong() shl one_exp) + p2
|
||||
if (tmp <= delta) {
|
||||
_K += kappa
|
||||
grisuRound(buffer, len, delta, tmp, pow10 shl one_exp, wp_w_frc)
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
var unit = 1L
|
||||
while (true) {
|
||||
p2 *= 10
|
||||
delta *= 10
|
||||
unit *= 10
|
||||
|
||||
val d = p2 ushr one_exp
|
||||
if (d or len.toLong() != 0L)
|
||||
buffer[len++] = digitToChar(d.toInt())
|
||||
|
||||
p2 = p2 and mask
|
||||
--kappa
|
||||
if (p2 < delta) {
|
||||
_K += kappa
|
||||
grisuRound(buffer, len, delta, p2, one_frc, wp_w_frc * unit)
|
||||
return len
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun grisuRound(buffer: CharArray, len: Int, delta: Long, restInp: Long, ten_kappa: Long, wp_w: Long) {
|
||||
var rest = restInp
|
||||
val lastp = len - 1
|
||||
var digit = buffer[lastp]
|
||||
while (
|
||||
rest < wp_w &&
|
||||
delta - rest >= ten_kappa && (
|
||||
rest + ten_kappa < wp_w ||
|
||||
wp_w - rest > rest + ten_kappa - wp_w
|
||||
)
|
||||
) {
|
||||
--digit
|
||||
rest += ten_kappa;
|
||||
}
|
||||
buffer[lastp] = digit
|
||||
}
|
||||
|
||||
private class BufferWithOffset(val buf: CharArray, val off: Int) {
|
||||
operator fun set(addr: Int, value: Char) {
|
||||
buf[off + addr] = value
|
||||
}
|
||||
|
||||
fun memoryCopy(destAddr: Int, srcAddr: Int, len: Int) {
|
||||
val startIdx = off + srcAddr
|
||||
buf.copyInto(buf, off + destAddr, startIdx, startIdx + len)
|
||||
}
|
||||
|
||||
fun offsetABitMore(anotherOff: Int) = BufferWithOffset(buf, off + anotherOff)
|
||||
}
|
||||
|
||||
private fun prettify(buffer: BufferWithOffset, lengthInp: Int, k: Int): Int {
|
||||
var length = lengthInp
|
||||
if (k == 0) {
|
||||
buffer[length] = CharCodes.DOT.code.toChar()
|
||||
buffer[length + 1] = CharCodes._0.code.toChar()
|
||||
return length + 2
|
||||
}
|
||||
|
||||
var kk = length + k
|
||||
if (length <= kk && kk <= 21) {
|
||||
// 1234e7 -> 12340000000
|
||||
for (i in length until kk) {
|
||||
buffer[i] = CharCodes._0.code.toChar()
|
||||
}
|
||||
buffer[kk] = CharCodes.DOT.code.toChar()
|
||||
buffer[kk + 1] = CharCodes._0.code.toChar()
|
||||
return kk + 2
|
||||
} else if (kk > 0 && kk <= 21) {
|
||||
// 1234e-2 -> 12.34
|
||||
buffer.memoryCopy(kk + 1, kk, -k)
|
||||
buffer[kk] = CharCodes.DOT.code.toChar()
|
||||
return length + 1
|
||||
} else if (-6 < kk && kk <= 0) {
|
||||
// 1234e-6 -> 0.001234
|
||||
val offset = 2 - kk
|
||||
buffer.memoryCopy(offset, 0, length)
|
||||
buffer[0] = CharCodes._0.code.toChar()
|
||||
buffer[1] = CharCodes.DOT.code.toChar()
|
||||
for (i in 2 until offset) {
|
||||
buffer[i] = CharCodes._0.code.toChar()
|
||||
}
|
||||
return length + offset
|
||||
} else if (length == 1) {
|
||||
// 1e30
|
||||
buffer[1] = CharCodes.e.code.toChar()
|
||||
length = genExponent(buffer.offsetABitMore(2), kk - 1)
|
||||
return length + 2
|
||||
} else {
|
||||
val len = length
|
||||
buffer.memoryCopy(2, 1, len - 1)
|
||||
buffer[1] = CharCodes.DOT.code.toChar()
|
||||
buffer[len + 1] = CharCodes.e.code.toChar()
|
||||
length += genExponent(buffer.offsetABitMore(len + 2), kk - 1)
|
||||
return length + 2
|
||||
}
|
||||
}
|
||||
|
||||
private fun genExponent(buffer: BufferWithOffset, kInp: Int): Int {
|
||||
var k = kInp
|
||||
val sign = k < 0
|
||||
if (sign) k = -k
|
||||
val kStr = k.toString()
|
||||
for (i in kStr.indices)
|
||||
buffer[i + 1] = kStr[i]
|
||||
buffer[0] = if (sign) CharCodes.MINUS.code.toChar() else CharCodes.PLUS.code.toChar()
|
||||
return kStr.length + 1
|
||||
}
|
||||
|
||||
@@ -289,11 +289,17 @@ public external fun wasm_f64_convert_i64_s(a: Long): Double
|
||||
@WasmOp(WasmOp.F64_PROMOTE_F32)
|
||||
public external fun wasm_f64_promote_f32(a: Float): Double
|
||||
|
||||
@WasmOp(WasmOp.F32_REINTERPRET_I32)
|
||||
public external fun wasm_f32_reinterpret_i32(a: Int): Float
|
||||
|
||||
@WasmOp(WasmOp.F64_REINTERPRET_I64)
|
||||
public external fun wasm_f64_reinterpret_i64(a: Long): Double
|
||||
|
||||
@WasmOp(WasmOp.I32_REINTERPRET_F32)
|
||||
public external fun wasm_i32_reinterpret_f32(a: Float): Int
|
||||
|
||||
@WasmOp(WasmOp.F32_REINTERPRET_I32)
|
||||
public external fun wasm_f32_reinterpret_i32(a: Int): Float
|
||||
@WasmOp(WasmOp.I64_REINTERPRET_F64)
|
||||
public external fun wasm_i64_reinterpret_f64(a: Double): Long
|
||||
|
||||
@WasmOp(WasmOp.I32_TRUNC_SAT_F32_S)
|
||||
public external fun wasm_i32_trunc_sat_f32_s(a: Float): Int
|
||||
@@ -317,4 +323,10 @@ public external fun wasm_i32_load16_u(x: Int): Int
|
||||
public external fun wasm_i32_store(addr: Int, i: Int): Unit
|
||||
|
||||
@WasmOp(WasmOp.I32_STORE16)
|
||||
public external fun wasm_i32_store16(addr: Int, c: Char): Unit
|
||||
public external fun wasm_i32_store16(addr: Int, c: Char): Unit
|
||||
|
||||
@WasmOp(WasmOp.I32_CLZ)
|
||||
public external fun wasm_i32_clz(a: Int): Int
|
||||
|
||||
@WasmOp(WasmOp.I64_CLZ)
|
||||
public external fun wasm_i64_clz(a: Long): Long
|
||||
|
||||
@@ -7,6 +7,10 @@ package kotlin
|
||||
|
||||
import kotlin.annotation.AnnotationTarget.FIELD
|
||||
import kotlin.annotation.AnnotationTarget.PROPERTY
|
||||
import kotlin.wasm.internal.wasm_f32_reinterpret_i32
|
||||
import kotlin.wasm.internal.wasm_f64_reinterpret_i64
|
||||
import kotlin.wasm.internal.wasm_i32_reinterpret_f32
|
||||
import kotlin.wasm.internal.wasm_i64_reinterpret_f64
|
||||
|
||||
|
||||
/**
|
||||
@@ -27,19 +31,19 @@ public actual fun interface Comparator<T> {
|
||||
|
||||
// From numbers.kt
|
||||
|
||||
actual fun Double.isNaN(): Boolean = TODO("Wasm stdlib: Kotlin")
|
||||
actual fun Float.isNaN(): Boolean = TODO("Wasm stdlib: Kotlin")
|
||||
actual fun Double.isInfinite(): Boolean = TODO("Wasm stdlib: Kotlin")
|
||||
actual fun Float.isInfinite(): Boolean = TODO("Wasm stdlib: Kotlin")
|
||||
actual fun Double.isFinite(): Boolean = TODO("Wasm stdlib: Kotlin")
|
||||
actual fun Float.isFinite(): Boolean = TODO("Wasm stdlib: Kotlin")
|
||||
actual fun Double.isNaN(): Boolean = this != this
|
||||
actual fun Float.isNaN(): Boolean = this != this
|
||||
actual fun Double.isInfinite(): Boolean = (this == Double.POSITIVE_INFINITY) || (this == Double.NEGATIVE_INFINITY)
|
||||
actual fun Float.isInfinite(): Boolean = (this == Float.POSITIVE_INFINITY) || (this == Float.NEGATIVE_INFINITY)
|
||||
actual fun Double.isFinite(): Boolean = !isInfinite() && !isNaN()
|
||||
actual fun Float.isFinite(): Boolean = !isInfinite() && !isNaN()
|
||||
|
||||
/**
|
||||
* Returns a bit representation of the specified floating-point value as [Long]
|
||||
* according to the IEEE 754 floating-point "double format" bit layout.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public actual fun Double.toBits(): Long = TODO("Wasm stdlib: Kotlin")
|
||||
public actual fun Double.toBits(): Long = if (isNaN()) Double.NaN.toRawBits() else toRawBits()
|
||||
|
||||
/**
|
||||
* Returns a bit representation of the specified floating-point value as [Long]
|
||||
@@ -47,20 +51,20 @@ public actual fun Double.toBits(): Long = TODO("Wasm stdlib: Kotlin")
|
||||
* preserving `NaN` values exact layout.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public actual fun Double.toRawBits(): Long = TODO("Wasm stdlib: Kotlin")
|
||||
public actual fun Double.toRawBits(): Long = wasm_i64_reinterpret_f64(this)
|
||||
|
||||
/**
|
||||
* Returns the [Double] value corresponding to a given bit representation.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public actual fun Double.Companion.fromBits(bits: Long): Double = TODO("Wasm stdlib: Kotlin")
|
||||
public actual fun Double.Companion.fromBits(bits: Long): Double = wasm_f64_reinterpret_i64(bits)
|
||||
|
||||
/**
|
||||
* Returns a bit representation of the specified floating-point value as [Int]
|
||||
* according to the IEEE 754 floating-point "single format" bit layout.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public actual fun Float.toBits(): Int = TODO("Wasm stdlib: Kotlin")
|
||||
public actual fun Float.toBits(): Int = if (isNaN()) Float.NaN.toRawBits() else toRawBits()
|
||||
|
||||
/**
|
||||
* Returns a bit representation of the specified floating-point value as [Int]
|
||||
@@ -68,13 +72,13 @@ public actual fun Float.toBits(): Int = TODO("Wasm stdlib: Kotlin")
|
||||
* preserving `NaN` values exact layout.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public actual fun Float.toRawBits(): Int = TODO("Wasm stdlib: Kotlin")
|
||||
public actual fun Float.toRawBits(): Int = wasm_i32_reinterpret_f32(this)
|
||||
|
||||
/**
|
||||
* Returns the [Float] value corresponding to a given bit representation.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public actual fun Float.Companion.fromBits(bits: Int): Float = TODO("Wasm stdlib: Kotlin")
|
||||
public actual fun Float.Companion.fromBits(bits: Int): Float = wasm_f32_reinterpret_i32(bits)
|
||||
|
||||
|
||||
// From concurrent.kt
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
package kotlin
|
||||
|
||||
import kotlin.wasm.internal.*
|
||||
|
||||
/**
|
||||
* Counts the number of set bits in the binary representation of this [Int] number.
|
||||
*/
|
||||
@@ -17,7 +19,7 @@ public actual fun Int.countOneBits(): Int = TODO("Wasm stdlib: Numbers")
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public actual fun Int.countLeadingZeroBits(): Int = TODO("Wasm stdlib: Numbers")
|
||||
public actual fun Int.countLeadingZeroBits(): Int = wasm_i32_clz(this)
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive least significant bits that are zero in the binary representation of this [Int] number.
|
||||
@@ -84,7 +86,7 @@ public actual fun Long.countOneBits(): Int = TODO("Wasm stdlib: Numbers")
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public actual fun Long.countLeadingZeroBits(): Int = TODO("Wasm stdlib: Numbers")
|
||||
public actual fun Long.countLeadingZeroBits(): Int = wasm_i64_clz(this).toInt()
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive least significant bits that are zero in the binary representation of this [Long] number.
|
||||
|
||||
Reference in New Issue
Block a user