[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
@@ -132,13 +132,13 @@ class WasmSymbols(
val voidClass = getIrClass(FqName("kotlin.wasm.internal.Void")) val voidClass = getIrClass(FqName("kotlin.wasm.internal.Void"))
val voidType by lazy { voidClass.defaultType } val voidType by lazy { voidClass.defaultType }
private val consumeAnyIntoVoid = getInternalFunction("consumeAnyIntoVoid")
val uByteType by lazy { getIrClass(FqName("kotlin.UByte")).defaultType } val uByteType by lazy { getIrClass(FqName("kotlin.UByte")).defaultType }
val uShortType by lazy { getIrClass(FqName("kotlin.UShort")).defaultType } val uShortType by lazy { getIrClass(FqName("kotlin.UShort")).defaultType }
val uIntType by lazy { getIrClass(FqName("kotlin.UInt")).defaultType } val uIntType by lazy { getIrClass(FqName("kotlin.UInt")).defaultType }
val uLongType by lazy { getIrClass(FqName("kotlin.ULong")).defaultType } val uLongType by lazy { getIrClass(FqName("kotlin.ULong")).defaultType }
private val consumeAnyIntoVoid = getInternalFunction("consumeAnyIntoVoid")
private val consumePrimitiveIntoVoid = mapOf( private val consumePrimitiveIntoVoid = mapOf(
context.irBuiltIns.booleanType to getInternalFunction("consumeBooleanIntoVoid"), context.irBuiltIns.booleanType to getInternalFunction("consumeBooleanIntoVoid"),
context.irBuiltIns.byteType to getInternalFunction("consumeByteIntoVoid"), context.irBuiltIns.byteType to getInternalFunction("consumeByteIntoVoid"),
@@ -153,14 +153,20 @@ class WasmSymbols(
fun findVoidConsumer(type: IrType): IrSimpleFunctionSymbol = fun findVoidConsumer(type: IrType): IrSimpleFunctionSymbol =
consumePrimitiveIntoVoid[type] ?: consumeAnyIntoVoid consumePrimitiveIntoVoid[type] ?: consumeAnyIntoVoid
val equalityFunctions = mapOf( val equalityFunctions by lazy {
context.irBuiltIns.booleanType to getInternalFunction("wasm_i32_eq"), mapOf(
context.irBuiltIns.byteType to getInternalFunction("wasm_i32_eq"), context.irBuiltIns.booleanType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.shortType to getInternalFunction("wasm_i32_eq"), context.irBuiltIns.byteType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.charType to getInternalFunction("wasm_i32_eq"), context.irBuiltIns.shortType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.intType to getInternalFunction("wasm_i32_eq"), uByteType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.longType to getInternalFunction("wasm_i64_eq") uShortType to getInternalFunction("wasm_i32_eq"),
) context.irBuiltIns.charType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.intType to getInternalFunction("wasm_i32_eq"),
uIntType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.longType to getInternalFunction("wasm_i64_eq"),
uLongType to getInternalFunction("wasm_i64_eq")
)
}
val floatEqualityFunctions = mapOf( val floatEqualityFunctions = mapOf(
context.irBuiltIns.floatType to getInternalFunction("wasm_f32_eq"), context.irBuiltIns.floatType to getInternalFunction("wasm_f32_eq"),
+3 -3
View File
@@ -1,9 +1,9 @@
// TARGET_BACKEND: WASM // TARGET_BACKEND: WASM
// RUN_THIRD_PARTY_OPTIMIZER // RUN_THIRD_PARTY_OPTIMIZER
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 12_814 // WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 12_773
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 4_526 // WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 4_528
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 2_640 // WASM_OPT_EXPECTED_OUTPUT_SIZE: 2_640
// FILE: test.kt // FILE: test.kt
+3 -3
View File
@@ -1,9 +1,9 @@
// TARGET_BACKEND: WASM // TARGET_BACKEND: WASM
// RUN_THIRD_PARTY_OPTIMIZER // RUN_THIRD_PARTY_OPTIMIZER
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 41_349 // WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 35_154
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 4_552 // WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 4_552
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 9_847 // WASM_OPT_EXPECTED_OUTPUT_SIZE: 8_586
fun box(): String { fun box(): String {
println("Hello, World!") println("Hello, World!")
+3 -2
View File
@@ -2,8 +2,9 @@
// TARGET_BACKEND: WASM // TARGET_BACKEND: WASM
// RUN_THIRD_PARTY_OPTIMIZER // RUN_THIRD_PARTY_OPTIMIZER
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 13_362 // WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 13_321
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 3_900 // WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 4_398
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 3_900
interface I { interface I {
fun foo() = "OK" fun foo() = "OK"
+65 -52
View File
@@ -215,67 +215,80 @@ fun box() {
// _ArraysWasm.kt:1700 $kotlin.collections.copyOfUninitializedElements (11, 4) // _ArraysWasm.kt:1700 $kotlin.collections.copyOfUninitializedElements (11, 4)
// StringBuilder.kt:179 $kotlin.text.StringBuilder.append (8, 29, 36, 45, 19, 8, 8) // StringBuilder.kt:179 $kotlin.text.StringBuilder.append (8, 29, 36, 45, 19, 8, 8)
// StringBuilderWasm.kt:52 $kotlin.text.insertInt (22, 28) // StringBuilderWasm.kt:52 $kotlin.text.insertInt (22, 28)
// Primitives.kt:1359 $kotlin.Int__toString-impl (21, 8, 24) // Primitives.kt:1359 $kotlin.Int__toString-impl (8, 20)
// Number2String.kt:199 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:191 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:200 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:192 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:201 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:193 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:202 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:194 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:203 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:195 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:204 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:196 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:206 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:198 $kotlin.wasm.internal.<init properties Number2String.kt>
// Library.kt:93 $kotlin.wasm.internal.<init properties Number2String.kt> (2841, 2841, 2841, 2841, 3432, 3432, 3432, 3432, 3453, 3432, 11556, 11560, 3484, 3463, 11556, 11560, 3515, 3494, 11556, 11560, 3546, 3525, 11556, 11560, 3581, 3560, 11556, 11560, 3612, 3591, 11556, 11560, 3643, 3622, 11556, 11560, 3674, 3653, 11556, 11560, 3709, 3688, 11556, 11560, 3740, 3719, 11556, 11560, 3771, 3750, 11556, 11560, 3802, 3781, 11556, 11560, 3837, 3816, 11556, 11560, 3868, 3847, 11556, 11560, 3899, 3878, 11556, 11560, 3930, 3909, 11556, 11560, 3965, 3944, 11556, 11560, 3996, 3975, 11556, 11560, 4027, 4006, 11556, 11560, 4058, 4037, 11556, 11560, 4093, 4072, 11556, 11560, 4124, 4103, 11556, 11560, 4155, 4134, 11556, 11560, 4186, 4165, 11556, 11560, 4221, 4200, 11556, 11560, 4252, 4231, 11556, 11560, 4283, 4262, 11556, 11560, 4314, 4293, 11556, 11560, 4349, 4328, 11556, 11560, 4380, 4359, 11556, 11560, 4411, 4390, 11556, 11560, 4442, 4421, 11556, 11560, 4477, 4456, 11556, 11560, 4508, 4487, 11556, 11560, 4539, 4518, 11556, 11560, 4570, 4549, 11556, 11560, 4605, 4584, 11556, 11560, 4636, 4615, 11556, 11560, 4667, 4646, 11556, 11560, 4698, 4677, 11556, 11560, 4733, 4712, 11556, 11560, 4764, 4743, 11556, 11560, 4795, 4774, 11556, 11560, 4826, 4805, 11556, 11560, 4861, 4840, 11556, 11560, 4892, 4871, 11556, 11560, 4923, 4902, 11556, 11560, 4954, 4933, 11556, 11560, 4989, 4968, 11556, 11560, 5020, 4999, 11556, 11560, 5051, 5030, 11556, 11560, 5082, 5061, 11556, 11560, 5117, 5096, 11556, 11560, 5148, 5127, 11556, 11560, 5179, 5158, 11556, 11560, 5210, 5189, 11556, 11560, 5245, 5224, 11556, 11560, 5276, 5255, 11556, 11560, 5307, 5286, 11556, 11560, 5338, 5317, 11556, 11560, 5373, 5352, 11556, 11560, 5404, 5383, 11556, 11560, 5435, 5414, 11556, 11560, 5466, 5445, 11556, 11560, 5501, 5480, 11556, 11560, 5532, 5511, 11556, 11560, 5563, 5542, 11556, 11560, 5594, 5573, 11556, 11560, 5629, 5608, 11556, 11560, 5660, 5639, 11556, 11560, 5691, 5670, 11556, 11560, 5722, 5701, 11556, 11560, 5757, 5736, 11556, 11560, 5788, 5767, 11556, 11560, 5819, 5798, 11556, 11560, 5850, 5829, 11556, 11560, 5885, 5864, 11556, 11560, 5916, 5895, 11556, 11560, 5947, 5926, 11556, 11560, 5978, 5957, 11556, 11560, 6013, 5992, 11556, 11560, 6044, 6023, 11556, 11560, 6075, 6054, 11556, 11560, 6106, 6085, 11556, 11560, 6141, 6120, 11556, 11560, 6172, 6151, 11556, 11560, 6203, 6182, 11556, 11560, 3432, 3432) // Library.kt:93 $kotlin.wasm.internal.<init properties Number2String.kt> (2619, 2619, 2619, 2619, 3210, 3210, 3210, 3210, 3231, 3210, 11556, 11560, 3262, 3241, 11556, 11560, 3293, 3272, 11556, 11560, 3324, 3303, 11556, 11560, 3359, 3338, 11556, 11560, 3390, 3369, 11556, 11560, 3421, 3400, 11556, 11560, 3452, 3431, 11556, 11560, 3487, 3466, 11556, 11560, 3518, 3497, 11556, 11560, 3549, 3528, 11556, 11560, 3580, 3559, 11556, 11560, 3615, 3594, 11556, 11560, 3646, 3625, 11556, 11560, 3677, 3656, 11556, 11560, 3708, 3687, 11556, 11560, 3743, 3722, 11556, 11560, 3774, 3753, 11556, 11560, 3805, 3784, 11556, 11560, 3836, 3815, 11556, 11560, 3871, 3850, 11556, 11560, 3902, 3881, 11556, 11560, 3933, 3912, 11556, 11560, 3964, 3943, 11556, 11560, 3999, 3978, 11556, 11560, 4030, 4009, 11556, 11560, 4061, 4040, 11556, 11560, 4092, 4071, 11556, 11560, 4127, 4106, 11556, 11560, 4158, 4137, 11556, 11560, 4189, 4168, 11556, 11560, 4220, 4199, 11556, 11560, 4255, 4234, 11556, 11560, 4286, 4265, 11556, 11560, 4317, 4296, 11556, 11560, 4348, 4327, 11556, 11560, 4383, 4362, 11556, 11560, 4414, 4393, 11556, 11560, 4445, 4424, 11556, 11560, 4476, 4455, 11556, 11560, 4511, 4490, 11556, 11560, 4542, 4521, 11556, 11560, 4573, 4552, 11556, 11560, 4604, 4583, 11556, 11560, 4639, 4618, 11556, 11560, 4670, 4649, 11556, 11560, 4701, 4680, 11556, 11560, 4732, 4711, 11556, 11560, 4767, 4746, 11556, 11560, 4798, 4777, 11556, 11560, 4829, 4808, 11556, 11560, 4860, 4839, 11556, 11560, 4895, 4874, 11556, 11560, 4926, 4905, 11556, 11560, 4957, 4936, 11556, 11560, 4988, 4967, 11556, 11560, 5023, 5002, 11556, 11560, 5054, 5033, 11556, 11560, 5085, 5064, 11556, 11560, 5116, 5095, 11556, 11560, 5151, 5130, 11556, 11560, 5182, 5161, 11556, 11560, 5213, 5192, 11556, 11560, 5244, 5223, 11556, 11560, 5279, 5258, 11556, 11560, 5310, 5289, 11556, 11560, 5341, 5320, 11556, 11560, 5372, 5351, 11556, 11560, 5407, 5386, 11556, 11560, 5438, 5417, 11556, 11560, 5469, 5448, 11556, 11560, 5500, 5479, 11556, 11560, 5535, 5514, 11556, 11560, 5566, 5545, 11556, 11560, 5597, 5576, 11556, 11560, 5628, 5607, 11556, 11560, 5663, 5642, 11556, 11560, 5694, 5673, 11556, 11560, 5725, 5704, 11556, 11560, 5756, 5735, 11556, 11560, 5791, 5770, 11556, 11560, 5822, 5801, 11556, 11560, 5853, 5832, 11556, 11560, 5884, 5863, 11556, 11560, 5919, 5898, 11556, 11560, 5950, 5929, 11556, 11560, 5981, 5960, 11556, 11560, 3210, 3210)
// Library.kt:69 $kotlin.wasm.internal.<init properties Number2String.kt> (69, 77) // Library.kt:69 $kotlin.wasm.internal.<init properties Number2String.kt> (69, 77)
// Number2String.kt:219 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:211 $kotlin.wasm.internal.<init properties Number2String.kt>
// ULong.kt:17 $kotlin.<ULong__<get-data>-impl> (125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125) // ULong.kt:17 $kotlin.<ULong__<get-data>-impl> (125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125)
// Library.kt:54 $kotlin.wasm.internal.<init properties Number2String.kt> (66, 74) // Library.kt:54 $kotlin.wasm.internal.<init properties Number2String.kt> (66, 74)
// Number2String.kt:47 $kotlin.wasm.internal.itoa32 (8, 16, 8, 21, 29, 21) // Number2String.kt:48 $kotlin.wasm.internal.itoa32 (8, 22, 8)
// Number2String.kt:50 $kotlin.wasm.internal.itoa32 (8, 17, 8, 8) // Number2String.kt:50 $kotlin.wasm.internal.itoa32 (21, 34, 21)
// Number2String.kt:53 $kotlin.wasm.internal.itoa32 (8, 22, 8) // Number2String.kt:51 $kotlin.wasm.internal.itoa32 (23, 52, 4)
// Number2String.kt:55 $kotlin.wasm.internal.itoa32 (8, 26, 8) // Number2String.kt:52 $kotlin.wasm.internal.itoa32 (41, 25, 4)
// Number2String.kt:57 $kotlin.wasm.internal.itoa32 (15, 31, 15) // UInt.kt:36 $kotlin.wasm.internal.itoa32
// Number2String.kt:58 $kotlin.wasm.internal.itoa32 (11, 19, 11, 24, 32, 24, 4) // UInt.kt:414 $kotlin.wasm.internal.itoa32 (44, 39, 49)
// Assertions.kt:14 $kotlin.assert (11, 18, 4, 11, 18, 4, 11, 18, 4, 11, 18, 4, 11, 18, 4) // UInt.kt:17 $kotlin.<UInt__<init>-impl>
// Assertions.kt:21 $kotlin.assert (9, 8, 9, 8, 9, 8, 9, 8, 9, 8) // Number2String.kt:58 $kotlin.wasm.internal.utoa32 (8, 22, 8)
// Assertions.kt:25 $kotlin.assert (1, 1, 1, 1, 1) // Number2String.kt:60 $kotlin.wasm.internal.utoa32 (34, 19)
// Assertions.kt:15 $kotlin.assert (1, 1, 1, 1, 1) // Number2String.kt:105 $kotlin.wasm.internal.decimalCount32 (8, 8, 8)
// Number2String.kt:59 $kotlin.wasm.internal.itoa32 (23, 31, 23, 51) // UInt.kt:68 $kotlin.wasm.internal.decimalCount32 (4, 12, 35, 43, 75, 84)
// Number2String.kt:61 $kotlin.wasm.internal.itoa32 (34, 19, 46, 19) // UInt.kt:64 $kotlin.wasm.internal.decimalCount32 (70, 82, 87, 93, 99, 104, 70, 82, 87, 93, 99, 104, 70, 82, 87, 93, 99, 104)
// Number2String.kt:107 $kotlin.wasm.internal.decimalCount32 (8, 16, 8) // UInt.kt:17 $kotlin.<UInt__<get-data>-impl> (124, 124, 124, 124, 124, 124, 124, 124, 124)
// Number2String.kt:108 $kotlin.wasm.internal.decimalCount32 (12, 20, 12) // UInt.kt:31 $kotlin.wasm.internal.decimalCount32 (65, 69, 46, 72, 65, 69, 46, 72, 65, 69, 46, 72)
// Number2String.kt:109 $kotlin.wasm.internal.decimalCount32 (19, 24, 33, 24, 19, 12) // WasmMath.kt:16 $kotlin.wasm.internal.wasm_u32_compareTo (18, 21, 4, 48, 51, 34, 4, 61, 18, 21, 4, 48, 51, 34, 4, 61, 18, 21, 4, 48, 51, 34, 4, 61, 18, 21, 4, 48, 51, 34, 4, 61)
// Number2String.kt:62 $kotlin.wasm.internal.itoa32 (28, 14) // Number2String.kt:106 $kotlin.wasm.internal.decimalCount32 (12, 12, 12)
// Number2String.kt:63 $kotlin.wasm.internal.itoa32 (18, 23, 33, 4) // Number2String.kt:107 $kotlin.wasm.internal.decimalCount32 (19, 24, 24, 24, 19, 12)
// Number2String.kt:71 $kotlin.wasm.internal.utoaDecSimple (11, 23, 11, 11, 4) // Number2String.kt:61 $kotlin.wasm.internal.utoa32 (28, 14)
// Number2String.kt:72 $kotlin.wasm.internal.utoaDecSimple (11, 18, 26, 11, 4) // Number2String.kt:63 $kotlin.wasm.internal.utoa32 (18, 23, 35, 4)
// Number2String.kt:73 $kotlin.wasm.internal.utoaDecSimple (11, 25, 11, 30, 45, 52, 30, 4) // Number2String.kt:69 $kotlin.wasm.internal.utoaDecSimple (11, 23, 11, 11, 4)
// Number2String.kt:75 $kotlin.wasm.internal.utoaDecSimple (14, 4) // Assertions.kt:14 $kotlin.assert (11, 18, 4, 11, 18, 4, 11, 18, 4, 11, 18, 4)
// Number2String.kt:76 $kotlin.wasm.internal.utoaDecSimple (17, 4) // Assertions.kt:21 $kotlin.assert (9, 8, 9, 8, 9, 8, 9, 8)
// Number2String.kt:78 $kotlin.wasm.internal.utoaDecSimple (16, 22, 16, 8) // Assertions.kt:25 $kotlin.assert (1, 1, 1, 1)
// Primitives.kt:1066 $kotlin.Int__div-impl (24, 12, 69, 96) // Assertions.kt:15 $kotlin.assert (1, 1, 1, 1)
// Number2String.kt:79 $kotlin.wasm.internal.utoaDecSimple (16, 22, 16, 8) // Number2String.kt:70 $kotlin.wasm.internal.utoaDecSimple (11, 18, 26, 11, 4)
// Number2String.kt:80 $kotlin.wasm.internal.utoaDecSimple (14, 8) // Number2String.kt:71 $kotlin.wasm.internal.utoaDecSimple (11, 25, 11, 30, 45, 52, 30, 4)
// Number2String.kt:81 $kotlin.wasm.internal.utoaDecSimple // Number2String.kt:73 $kotlin.wasm.internal.utoaDecSimple (14, 4)
// Number2String.kt:74 $kotlin.wasm.internal.utoaDecSimple (17, 4)
// Number2String.kt:76 $kotlin.wasm.internal.utoaDecSimple (16, 8)
// UInt.kt:51 $kotlin.wasm.internal.utoaDecSimple (75, 81, 101, 107)
// UInt.kt:121 $kotlin.wasm.internal.utoaDecSimple (67, 73, 56, 79)
// Number2String.kt:77 $kotlin.wasm.internal.utoaDecSimple (16, 8)
// UInt.kt:146 $kotlin.wasm.internal.utoaDecSimple (70, 76, 56, 82)
// Number2String.kt:78 $kotlin.wasm.internal.utoaDecSimple (14, 8)
// Number2String.kt:79 $kotlin.wasm.internal.utoaDecSimple
// Primitives.kt:1159 $kotlin.Int__dec-impl (15, 8, 16) // Primitives.kt:1159 $kotlin.Int__dec-impl (15, 8, 16)
// Number2String.kt:82 $kotlin.wasm.internal.utoaDecSimple (8, 19, 39, 27, 15) // Number2String.kt:80 $kotlin.wasm.internal.utoaDecSimple (8, 19, 41, 27, 15)
// Number2String.kt:41 $kotlin.wasm.internal.digitToChar (20, 11, 23, 11, 4) // UInt.kt:54 $kotlin.wasm.internal.utoaDecSimple (3, 28)
// Number2String.kt:9 $kotlin.wasm.internal.CharCodes_initEntries // UInt.kt:313 $kotlin.wasm.internal.utoaDecSimple (37, 41)
// Number2String.kt:43 $kotlin.wasm.internal.digitToChar (20, 11, 23, 11, 4)
// Number2String.kt:11 $kotlin.wasm.internal.CharCodes_initEntries
// Enum.kt:9 $kotlin.Enum.<init> (4, 4, 4, 4, 4) // Enum.kt:9 $kotlin.Enum.<init> (4, 4, 4, 4, 4)
// Enum.kt:11 $kotlin.Enum.<init> (4, 4, 4, 4, 4) // Enum.kt:11 $kotlin.Enum.<init> (4, 4, 4, 4, 4)
// Enum.kt:27 $kotlin.Enum.<init> (1, 1, 1, 1, 1) // Enum.kt:27 $kotlin.Enum.<init> (1, 1, 1, 1, 1)
// Number2String.kt:7 $kotlin.wasm.internal.CharCodes.<init> (29, 29, 29, 29, 29) // Number2String.kt:9 $kotlin.wasm.internal.CharCodes.<init> (29, 29, 29, 29, 29)
// Number2String.kt:38 $kotlin.wasm.internal.CharCodes.<init> (1, 1, 1, 1, 1) // Number2String.kt:40 $kotlin.wasm.internal.CharCodes.<init> (1, 1, 1, 1, 1)
// Number2String.kt:10 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:11 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:12 $kotlin.wasm.internal.CharCodes_initEntries // Number2String.kt:12 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:32 $kotlin.wasm.internal.CharCodes_initEntries // Number2String.kt:13 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:42 $kotlin.wasm.internal.digitToChar (25, 32, 12, 39, 4) // Number2String.kt:14 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:34 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:44 $kotlin.wasm.internal.digitToChar (25, 32, 12, 39, 4)
// Primitives.kt:1306 $kotlin.Int__toChar-impl (18, 9, 45) // Primitives.kt:1306 $kotlin.Int__toChar-impl (18, 9, 45)
// Number2String.kt:83 $kotlin.wasm.internal.utoaDecSimple (13, 19, 13, 13) // Number2String.kt:81 $kotlin.wasm.internal.utoaDecSimple (13, 13, 13, 13)
// Number2String.kt:84 $kotlin.wasm.internal.utoaDecSimple // UInt.kt:55 $kotlin.wasm.internal.utoaDecSimple
// Number2String.kt:64 $kotlin.wasm.internal.itoa32 (8, 16, 8) // UInt.kt:64 $kotlin.wasm.internal.utoaDecSimple (70, 82, 87, 93, 99, 104)
// Number2String.kt:67 $kotlin.wasm.internal.itoa32 (15, 4) // UInt.kt:31 $kotlin.wasm.internal.utoaDecSimple (65, 69, 46, 72)
// String.kt:46 $kotlin.wasm.internal.itoa32 // Number2String.kt:82 $kotlin.wasm.internal.utoaDecSimple
// String.kt:138 $kotlin.wasm.internal.itoa32 (4, 4, 4, 4, 11, 17, 22, 29, 4, 34) // Number2String.kt:65 $kotlin.wasm.internal.utoa32 (15, 4)
// String.kt:44 $kotlin.wasm.internal.utoa32
// String.kt:138 $kotlin.wasm.internal.utoa32 (4, 4, 4, 4, 11, 17, 22, 29, 4, 34)
// Number2String.kt:54 $kotlin.wasm.internal.itoa32 (15, 51, 4)
// StringBuilderWasm.kt:53 $kotlin.text.insertInt (17, 29, 4) // StringBuilderWasm.kt:53 $kotlin.text.insertInt (17, 29, 4)
// StringBuilderWasm.kt:54 $kotlin.text.insertInt (17, 24, 31, 44, 47, 4, 4) // StringBuilderWasm.kt:54 $kotlin.text.insertInt (17, 24, 31, 44, 47, 4, 4)
// StringBuilderWasm.kt:55 $kotlin.text.insertInt (11, 4) // StringBuilderWasm.kt:55 $kotlin.text.insertInt (11, 4)
@@ -35,49 +35,59 @@ fun box() {
// test.kt:9 $box (8, 4) // test.kt:9 $box (8, 4)
// test.kt:10 $box (9, 8) // test.kt:10 $box (9, 8)
// test.kt:11 $box (12, 14, 8) // test.kt:11 $box (12, 14, 8)
// Primitives.kt:1359 $kotlin.Int__toString-impl (21, 8, 24) // Primitives.kt:1359 $kotlin.Int__toString-impl (8, 20)
// Number2String.kt:199 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:191 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:200 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:192 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:201 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:193 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:202 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:194 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:203 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:195 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:204 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:196 $kotlin.wasm.internal.<init properties Number2String.kt>
// Number2String.kt:206 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:198 $kotlin.wasm.internal.<init properties Number2String.kt>
// Library.kt:93 $kotlin.wasm.internal.<init properties Number2String.kt> (2841, 2841, 2841, 2841, 3432, 3432, 3432, 3432, 3453, 3432, 11556, 11560, 3484, 3463, 11556, 11560, 3515, 3494, 11556, 11560, 3546, 3525, 11556, 11560, 3581, 3560, 11556, 11560, 3612, 3591, 11556, 11560, 3643, 3622, 11556, 11560, 3674, 3653, 11556, 11560, 3709, 3688, 11556, 11560, 3740, 3719, 11556, 11560, 3771, 3750, 11556, 11560, 3802, 3781, 11556, 11560, 3837, 3816, 11556, 11560, 3868, 3847, 11556, 11560, 3899, 3878, 11556, 11560, 3930, 3909, 11556, 11560, 3965, 3944, 11556, 11560, 3996, 3975, 11556, 11560, 4027, 4006, 11556, 11560, 4058, 4037, 11556, 11560, 4093, 4072, 11556, 11560, 4124, 4103, 11556, 11560, 4155, 4134, 11556, 11560, 4186, 4165, 11556, 11560, 4221, 4200, 11556, 11560, 4252, 4231, 11556, 11560, 4283, 4262, 11556, 11560, 4314, 4293, 11556, 11560, 4349, 4328, 11556, 11560, 4380, 4359, 11556, 11560, 4411, 4390, 11556, 11560, 4442, 4421, 11556, 11560, 4477, 4456, 11556, 11560, 4508, 4487, 11556, 11560, 4539, 4518, 11556, 11560, 4570, 4549, 11556, 11560, 4605, 4584, 11556, 11560, 4636, 4615, 11556, 11560, 4667, 4646, 11556, 11560, 4698, 4677, 11556, 11560, 4733, 4712, 11556, 11560, 4764, 4743, 11556, 11560, 4795, 4774, 11556, 11560, 4826, 4805, 11556, 11560, 4861, 4840, 11556, 11560, 4892, 4871, 11556, 11560, 4923, 4902, 11556, 11560, 4954, 4933, 11556, 11560, 4989, 4968, 11556, 11560, 5020, 4999, 11556, 11560, 5051, 5030, 11556, 11560, 5082, 5061, 11556, 11560, 5117, 5096, 11556, 11560, 5148, 5127, 11556, 11560, 5179, 5158, 11556, 11560, 5210, 5189, 11556, 11560, 5245, 5224, 11556, 11560, 5276, 5255, 11556, 11560, 5307, 5286, 11556, 11560, 5338, 5317, 11556, 11560, 5373, 5352, 11556, 11560, 5404, 5383, 11556, 11560, 5435, 5414, 11556, 11560, 5466, 5445, 11556, 11560, 5501, 5480, 11556, 11560, 5532, 5511, 11556, 11560, 5563, 5542, 11556, 11560, 5594, 5573, 11556, 11560, 5629, 5608, 11556, 11560, 5660, 5639, 11556, 11560, 5691, 5670, 11556, 11560, 5722, 5701, 11556, 11560, 5757, 5736, 11556, 11560, 5788, 5767, 11556, 11560, 5819, 5798, 11556, 11560, 5850, 5829, 11556, 11560, 5885, 5864, 11556, 11560, 5916, 5895, 11556, 11560, 5947, 5926, 11556, 11560, 5978, 5957, 11556, 11560, 6013, 5992, 11556, 11560, 6044, 6023, 11556, 11560, 6075, 6054, 11556, 11560, 6106, 6085, 11556, 11560, 6141, 6120, 11556, 11560, 6172, 6151, 11556, 11560, 6203, 6182, 11556, 11560, 3432, 3432) // Library.kt:93 $kotlin.wasm.internal.<init properties Number2String.kt> (2619, 2619, 2619, 2619, 3210, 3210, 3210, 3210, 3231, 3210, 11556, 11560, 3262, 3241, 11556, 11560, 3293, 3272, 11556, 11560, 3324, 3303, 11556, 11560, 3359, 3338, 11556, 11560, 3390, 3369, 11556, 11560, 3421, 3400, 11556, 11560, 3452, 3431, 11556, 11560, 3487, 3466, 11556, 11560, 3518, 3497, 11556, 11560, 3549, 3528, 11556, 11560, 3580, 3559, 11556, 11560, 3615, 3594, 11556, 11560, 3646, 3625, 11556, 11560, 3677, 3656, 11556, 11560, 3708, 3687, 11556, 11560, 3743, 3722, 11556, 11560, 3774, 3753, 11556, 11560, 3805, 3784, 11556, 11560, 3836, 3815, 11556, 11560, 3871, 3850, 11556, 11560, 3902, 3881, 11556, 11560, 3933, 3912, 11556, 11560, 3964, 3943, 11556, 11560, 3999, 3978, 11556, 11560, 4030, 4009, 11556, 11560, 4061, 4040, 11556, 11560, 4092, 4071, 11556, 11560, 4127, 4106, 11556, 11560, 4158, 4137, 11556, 11560, 4189, 4168, 11556, 11560, 4220, 4199, 11556, 11560, 4255, 4234, 11556, 11560, 4286, 4265, 11556, 11560, 4317, 4296, 11556, 11560, 4348, 4327, 11556, 11560, 4383, 4362, 11556, 11560, 4414, 4393, 11556, 11560, 4445, 4424, 11556, 11560, 4476, 4455, 11556, 11560, 4511, 4490, 11556, 11560, 4542, 4521, 11556, 11560, 4573, 4552, 11556, 11560, 4604, 4583, 11556, 11560, 4639, 4618, 11556, 11560, 4670, 4649, 11556, 11560, 4701, 4680, 11556, 11560, 4732, 4711, 11556, 11560, 4767, 4746, 11556, 11560, 4798, 4777, 11556, 11560, 4829, 4808, 11556, 11560, 4860, 4839, 11556, 11560, 4895, 4874, 11556, 11560, 4926, 4905, 11556, 11560, 4957, 4936, 11556, 11560, 4988, 4967, 11556, 11560, 5023, 5002, 11556, 11560, 5054, 5033, 11556, 11560, 5085, 5064, 11556, 11560, 5116, 5095, 11556, 11560, 5151, 5130, 11556, 11560, 5182, 5161, 11556, 11560, 5213, 5192, 11556, 11560, 5244, 5223, 11556, 11560, 5279, 5258, 11556, 11560, 5310, 5289, 11556, 11560, 5341, 5320, 11556, 11560, 5372, 5351, 11556, 11560, 5407, 5386, 11556, 11560, 5438, 5417, 11556, 11560, 5469, 5448, 11556, 11560, 5500, 5479, 11556, 11560, 5535, 5514, 11556, 11560, 5566, 5545, 11556, 11560, 5597, 5576, 11556, 11560, 5628, 5607, 11556, 11560, 5663, 5642, 11556, 11560, 5694, 5673, 11556, 11560, 5725, 5704, 11556, 11560, 5756, 5735, 11556, 11560, 5791, 5770, 11556, 11560, 5822, 5801, 11556, 11560, 5853, 5832, 11556, 11560, 5884, 5863, 11556, 11560, 5919, 5898, 11556, 11560, 5950, 5929, 11556, 11560, 5981, 5960, 11556, 11560, 3210, 3210)
// Library.kt:69 $kotlin.wasm.internal.<init properties Number2String.kt> (69, 77) // Library.kt:69 $kotlin.wasm.internal.<init properties Number2String.kt> (69, 77)
// Number2String.kt:219 $kotlin.wasm.internal.<init properties Number2String.kt> // Number2String.kt:211 $kotlin.wasm.internal.<init properties Number2String.kt>
// ULong.kt:17 $kotlin.<ULong__<get-data>-impl> (125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125) // ULong.kt:17 $kotlin.<ULong__<get-data>-impl> (125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125)
// Library.kt:54 $kotlin.wasm.internal.<init properties Number2String.kt> (66, 74) // Library.kt:54 $kotlin.wasm.internal.<init properties Number2String.kt> (66, 74)
// Number2String.kt:47 $kotlin.wasm.internal.itoa32 (8, 16, 8, 21, 29, 21) // Number2String.kt:48 $kotlin.wasm.internal.itoa32 (8, 22, 8)
// Number2String.kt:50 $kotlin.wasm.internal.itoa32 (8, 17, 8, 8) // Number2String.kt:50 $kotlin.wasm.internal.itoa32 (21, 34, 21)
// Number2String.kt:53 $kotlin.wasm.internal.itoa32 (8, 22, 8) // Number2String.kt:51 $kotlin.wasm.internal.itoa32 (23, 52, 4)
// Number2String.kt:55 $kotlin.wasm.internal.itoa32 (8, 26, 8) // Number2String.kt:52 $kotlin.wasm.internal.itoa32 (41, 25, 4)
// Number2String.kt:57 $kotlin.wasm.internal.itoa32 (15, 31, 15) // UInt.kt:36 $kotlin.wasm.internal.itoa32
// Number2String.kt:58 $kotlin.wasm.internal.itoa32 (11, 19, 11, 24, 32, 24, 4) // UInt.kt:414 $kotlin.wasm.internal.itoa32 (44, 39, 49)
// Assertions.kt:14 $kotlin.assert (11, 18, 4, 11, 18, 4, 11, 18, 4, 11, 18, 4, 11, 18, 4, 11, 18, 4) // UInt.kt:17 $kotlin.<UInt__<init>-impl>
// Assertions.kt:21 $kotlin.assert (9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8) // Number2String.kt:58 $kotlin.wasm.internal.utoa32 (8, 22, 8)
// Assertions.kt:25 $kotlin.assert (1, 1, 1, 1, 1, 1) // Number2String.kt:60 $kotlin.wasm.internal.utoa32 (34, 19)
// Assertions.kt:15 $kotlin.assert (1, 1, 1, 1, 1, 1) // Number2String.kt:105 $kotlin.wasm.internal.decimalCount32 (8, 8, 8)
// Number2String.kt:59 $kotlin.wasm.internal.itoa32 (23, 31, 23, 51) // UInt.kt:68 $kotlin.wasm.internal.decimalCount32 (4, 12, 35, 43, 75, 84)
// Number2String.kt:61 $kotlin.wasm.internal.itoa32 (34, 19, 46, 19) // UInt.kt:64 $kotlin.wasm.internal.decimalCount32 (70, 82, 87, 93, 99, 104, 70, 82, 87, 93, 99, 104, 70, 82, 87, 93, 99, 104)
// Number2String.kt:107 $kotlin.wasm.internal.decimalCount32 (8, 16, 8) // UInt.kt:17 $kotlin.<UInt__<get-data>-impl> (124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124)
// Number2String.kt:108 $kotlin.wasm.internal.decimalCount32 (12, 20, 12) // UInt.kt:31 $kotlin.wasm.internal.decimalCount32 (65, 69, 46, 72, 65, 69, 46, 72, 65, 69, 46, 72)
// Number2String.kt:109 $kotlin.wasm.internal.decimalCount32 (19, 24, 33, 24, 19, 12) // WasmMath.kt:16 $kotlin.wasm.internal.wasm_u32_compareTo (18, 21, 4, 48, 51, 34, 4, 61, 18, 21, 4, 48, 51, 34, 4, 61, 18, 21, 4, 48, 51, 34, 4, 61, 18, 21, 4, 48, 51, 34, 4, 61, 18, 21, 4, 48, 51, 34, 4, 61)
// Number2String.kt:62 $kotlin.wasm.internal.itoa32 (28, 14) // Number2String.kt:106 $kotlin.wasm.internal.decimalCount32 (12, 12, 12)
// Number2String.kt:63 $kotlin.wasm.internal.itoa32 (18, 23, 33, 4) // Number2String.kt:107 $kotlin.wasm.internal.decimalCount32 (19, 24, 24, 24, 19, 12)
// Number2String.kt:71 $kotlin.wasm.internal.utoaDecSimple (11, 23, 11, 11, 4) // Number2String.kt:61 $kotlin.wasm.internal.utoa32 (28, 14)
// Number2String.kt:72 $kotlin.wasm.internal.utoaDecSimple (11, 18, 26, 11, 4) // Number2String.kt:63 $kotlin.wasm.internal.utoa32 (18, 23, 35, 4)
// Number2String.kt:73 $kotlin.wasm.internal.utoaDecSimple (11, 25, 11, 30, 45, 52, 30, 4) // Number2String.kt:69 $kotlin.wasm.internal.utoaDecSimple (11, 23, 11, 11, 4)
// Number2String.kt:75 $kotlin.wasm.internal.utoaDecSimple (14, 4) // Assertions.kt:14 $kotlin.assert (11, 18, 4, 11, 18, 4, 11, 18, 4, 11, 18, 4, 11, 18, 4)
// Number2String.kt:76 $kotlin.wasm.internal.utoaDecSimple (17, 4) // Assertions.kt:21 $kotlin.assert (9, 8, 9, 8, 9, 8, 9, 8, 9, 8)
// Number2String.kt:78 $kotlin.wasm.internal.utoaDecSimple (16, 22, 16, 8, 16, 22, 16, 8) // Assertions.kt:25 $kotlin.assert (1, 1, 1, 1, 1)
// Primitives.kt:1066 $kotlin.Int__div-impl (24, 12, 69, 96, 24, 12, 69, 96) // Assertions.kt:15 $kotlin.assert (1, 1, 1, 1, 1)
// Number2String.kt:79 $kotlin.wasm.internal.utoaDecSimple (16, 22, 16, 8, 16, 22, 16, 8) // Number2String.kt:70 $kotlin.wasm.internal.utoaDecSimple (11, 18, 26, 11, 4)
// Number2String.kt:80 $kotlin.wasm.internal.utoaDecSimple (14, 8, 14, 8) // Number2String.kt:71 $kotlin.wasm.internal.utoaDecSimple (11, 25, 11, 30, 45, 52, 30, 4)
// Number2String.kt:81 $kotlin.wasm.internal.utoaDecSimple (8, 8) // Number2String.kt:73 $kotlin.wasm.internal.utoaDecSimple (14, 4)
// Number2String.kt:74 $kotlin.wasm.internal.utoaDecSimple (17, 4)
// Number2String.kt:76 $kotlin.wasm.internal.utoaDecSimple (16, 8, 16, 8)
// UInt.kt:51 $kotlin.wasm.internal.utoaDecSimple (75, 81, 101, 107, 75, 81, 101, 107)
// UInt.kt:121 $kotlin.wasm.internal.utoaDecSimple (67, 73, 56, 79, 67, 73, 56, 79)
// Number2String.kt:77 $kotlin.wasm.internal.utoaDecSimple (16, 8, 16, 8)
// UInt.kt:146 $kotlin.wasm.internal.utoaDecSimple (70, 76, 56, 82, 70, 76, 56, 82)
// Number2String.kt:78 $kotlin.wasm.internal.utoaDecSimple (14, 8, 14, 8)
// Number2String.kt:79 $kotlin.wasm.internal.utoaDecSimple (8, 8)
// Primitives.kt:1159 $kotlin.Int__dec-impl (15, 8, 16, 15, 8, 16) // Primitives.kt:1159 $kotlin.Int__dec-impl (15, 8, 16, 15, 8, 16)
// Number2String.kt:82 $kotlin.wasm.internal.utoaDecSimple (8, 19, 39, 27, 15, 8, 19, 39, 27, 15) // Number2String.kt:80 $kotlin.wasm.internal.utoaDecSimple (8, 19, 41, 27, 15, 8, 19, 41, 27, 15)
// Number2String.kt:41 $kotlin.wasm.internal.digitToChar (20, 11, 23, 11, 4, 20, 11, 23, 11, 4) // UInt.kt:54 $kotlin.wasm.internal.utoaDecSimple (3, 28, 3, 28)
// UInt.kt:313 $kotlin.wasm.internal.utoaDecSimple (37, 41, 37, 41)
// Number2String.kt:43 $kotlin.wasm.internal.digitToChar (20, 11, 23, 11, 4, 20, 11, 23, 11, 4)
// String.kt:141 $kotlin.stringLiteral (17, 28, 17, 17, 28, 17, 17, 28, 17, 17, 28, 17, 17, 28, 17) // String.kt:141 $kotlin.stringLiteral (17, 28, 17, 17, 28, 17, 17, 28, 17, 17, 28, 17, 17, 28, 17)
// Array.kt:59 $kotlin.Array.get (19, 26, 34, 8, 19, 26, 34, 8, 19, 26, 34, 8, 19, 26, 34, 8, 19, 26, 34, 8) // Array.kt:59 $kotlin.Array.get (19, 26, 34, 8, 19, 26, 34, 8, 19, 26, 34, 8, 19, 26, 34, 8, 19, 26, 34, 8)
// ThrowHelpers.kt:29 $kotlin.wasm.internal.rangeCheck (6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19) // ThrowHelpers.kt:29 $kotlin.wasm.internal.rangeCheck (6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19, 6, 14, 6, 19, 28, 19)
@@ -91,22 +101,25 @@ fun box() {
// Array.kt:75 $kotlin.Array.set (8, 20, 27, 16, 8, 20, 27, 16, 8, 20, 27, 16, 8, 20, 27, 16, 8, 20, 27, 16) // Array.kt:75 $kotlin.Array.set (8, 20, 27, 16, 8, 20, 27, 16, 8, 20, 27, 16, 8, 20, 27, 16, 8, 20, 27, 16)
// Array.kt:76 $kotlin.Array.set (5, 5, 5, 5, 5) // Array.kt:76 $kotlin.Array.set (5, 5, 5, 5, 5)
// String.kt:149 $kotlin.stringLiteral (11, 4, 11, 4, 11, 4, 11, 4, 11, 4) // String.kt:149 $kotlin.stringLiteral (11, 4, 11, 4, 11, 4, 11, 4, 11, 4)
// Number2String.kt:9 $kotlin.wasm.internal.CharCodes_initEntries // Number2String.kt:11 $kotlin.wasm.internal.CharCodes_initEntries
// Enum.kt:9 $kotlin.Enum.<init> (4, 4, 4, 4, 4) // Enum.kt:9 $kotlin.Enum.<init> (4, 4, 4, 4, 4)
// Enum.kt:11 $kotlin.Enum.<init> (4, 4, 4, 4, 4) // Enum.kt:11 $kotlin.Enum.<init> (4, 4, 4, 4, 4)
// Enum.kt:27 $kotlin.Enum.<init> (1, 1, 1, 1, 1) // Enum.kt:27 $kotlin.Enum.<init> (1, 1, 1, 1, 1)
// Number2String.kt:7 $kotlin.wasm.internal.CharCodes.<init> (29, 29, 29, 29, 29) // Number2String.kt:9 $kotlin.wasm.internal.CharCodes.<init> (29, 29, 29, 29, 29)
// Number2String.kt:38 $kotlin.wasm.internal.CharCodes.<init> (1, 1, 1, 1, 1) // Number2String.kt:40 $kotlin.wasm.internal.CharCodes.<init> (1, 1, 1, 1, 1)
// Number2String.kt:10 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:11 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:12 $kotlin.wasm.internal.CharCodes_initEntries // Number2String.kt:12 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:32 $kotlin.wasm.internal.CharCodes_initEntries // Number2String.kt:13 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:42 $kotlin.wasm.internal.digitToChar (25, 32, 12, 39, 4, 25, 32, 12, 39, 4) // Number2String.kt:14 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:34 $kotlin.wasm.internal.CharCodes_initEntries
// Number2String.kt:44 $kotlin.wasm.internal.digitToChar (25, 32, 12, 39, 4, 25, 32, 12, 39, 4)
// Primitives.kt:1306 $kotlin.Int__toChar-impl (18, 9, 45, 18, 9, 45) // Primitives.kt:1306 $kotlin.Int__toChar-impl (18, 9, 45, 18, 9, 45)
// Number2String.kt:83 $kotlin.wasm.internal.utoaDecSimple (13, 19, 13, 13, 13, 19, 13, 13) // Number2String.kt:81 $kotlin.wasm.internal.utoaDecSimple (13, 13, 13, 13, 13, 13, 13, 13)
// Number2String.kt:84 $kotlin.wasm.internal.utoaDecSimple // UInt.kt:55 $kotlin.wasm.internal.utoaDecSimple (2, 2)
// Number2String.kt:64 $kotlin.wasm.internal.itoa32 (8, 16, 8) // UInt.kt:64 $kotlin.wasm.internal.utoaDecSimple (70, 82, 87, 93, 99, 104, 70, 82, 87, 93, 99, 104)
// Number2String.kt:67 $kotlin.wasm.internal.itoa32 (15, 4) // UInt.kt:31 $kotlin.wasm.internal.utoaDecSimple (65, 69, 46, 72, 65, 69, 46, 72)
// String.kt:46 $kotlin.wasm.internal.itoa32 // Number2String.kt:82 $kotlin.wasm.internal.utoaDecSimple
// String.kt:138 $kotlin.wasm.internal.itoa32 (4, 4, 4, 4, 11, 17, 22, 29, 4, 34) // Number2String.kt:65 $kotlin.wasm.internal.utoa32 (15, 4)
// String.kt:44 $kotlin.wasm.internal.utoa32
// String.kt:138 $kotlin.wasm.internal.utoa32 (4, 4, 4, 4, 11, 17, 22, 29, 4, 34)
// Number2String.kt:54 $kotlin.wasm.internal.itoa32 (15, 51, 4)
// test.kt:13 $box // test.kt:13 $box
@@ -17,7 +17,10 @@ import java.io.File
class IrInterpreterHelpersSourceFilesProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) { class IrInterpreterHelpersSourceFilesProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) {
companion object { companion object {
private const val HELPERS_PATH = "./compiler/testData/ir/interpreter/helpers" private const val HELPERS_PATH = "./compiler/testData/ir/interpreter/helpers"
private const val UNSIGNED_PATH = "./libraries/stdlib/unsigned/src/kotlin" private val UNSIGNED_PATH = arrayOf(
"./libraries/stdlib/unsigned/src/kotlin",
"./libraries/stdlib/jvm/src/kotlin/util/UnsignedJVM.kt"
)
private val RUNTIME_PATHS = arrayOf( private val RUNTIME_PATHS = arrayOf(
"./libraries/stdlib/src/kotlin/ranges/Progressions.kt", "./libraries/stdlib/src/kotlin/ranges/Progressions.kt",
"./libraries/stdlib/src/kotlin/ranges/ProgressionIterators.kt", "./libraries/stdlib/src/kotlin/ranges/ProgressionIterators.kt",
@@ -60,6 +63,12 @@ class IrInterpreterHelpersSourceFilesProvider(testServices: TestServices) : Addi
} }
override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List<TestFile> { override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List<TestFile> {
return getTestFilesForEachDirectory(HELPERS_PATH, UNSIGNED_PATH, *RUNTIME_PATHS, *ANNOTATIONS_PATHS, REFLECT_PATH) return getTestFilesForEachDirectory(
HELPERS_PATH,
*UNSIGNED_PATH,
*RUNTIME_PATHS,
*ANNOTATIONS_PATHS,
REFLECT_PATH
)
} }
} }
@@ -234,7 +234,7 @@ class WasmPrimitivesGenerator(writer: PrintWriter) : BasePrimitivesGenerator(wri
override fun MethodBuilder.modifyGeneratedToString(thisKind: PrimitiveType) { override fun MethodBuilder.modifyGeneratedToString(thisKind: PrimitiveType) {
when (thisKind) { when (thisKind) {
in PrimitiveType.floatingPoint -> "dtoa(this${thisKind.castToIfNecessary(PrimitiveType.DOUBLE)})" in PrimitiveType.floatingPoint -> "dtoa(this${thisKind.castToIfNecessary(PrimitiveType.DOUBLE)})"
PrimitiveType.INT, PrimitiveType.LONG -> "itoa${thisKind.bitSize}(this, 10)" PrimitiveType.INT, PrimitiveType.LONG -> "itoa${thisKind.bitSize}(this)"
else -> "this.toInt().toString()" else -> "this.toInt().toString()"
}.setAsExpressionBody() }.setAsExpressionBody()
} }
+35 -32
View File
@@ -19,7 +19,7 @@ fun generateUnsignedTypes(
targetDir: File, targetDir: File,
generate: (File, (PrintWriter) -> BuiltInsSourceGenerator) -> Unit generate: (File, (PrintWriter) -> BuiltInsSourceGenerator) -> Unit
) { ) {
for (type in UnsignedType.values()) { for (type in UnsignedType.entries) {
generate(File(targetDir, "kotlin/${type.capitalized}.kt")) { UnsignedTypeGenerator(type, it) } generate(File(targetDir, "kotlin/${type.capitalized}.kt")) { UnsignedTypeGenerator(type, it) }
generate(File(targetDir, "kotlin/${type.capitalized}Array.kt")) { UnsignedArrayGenerator(type, it) } generate(File(targetDir, "kotlin/${type.capitalized}Array.kt")) { UnsignedArrayGenerator(type, it) }
} }
@@ -30,8 +30,8 @@ fun generateUnsignedTypes(
} }
class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltInsSourceGenerator(out) { class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltInsSourceGenerator(out) {
val className = type.capitalized private val className = type.capitalized
val storageType = type.asSigned.capitalized private val storageType = type.asSigned.capitalized
internal fun binaryOperatorDoc(operator: String, operand1: UnsignedType, operand2: UnsignedType): String = when (operator) { internal fun binaryOperatorDoc(operator: String, operand1: UnsignedType, operand2: UnsignedType): String = when (operator) {
"floorDiv" -> "floorDiv" ->
@@ -119,7 +119,7 @@ class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltIns
private fun generateCompareTo() { private fun generateCompareTo() {
for (otherType in UnsignedType.values()) { for (otherType in UnsignedType.entries) {
out.println(""" out.println("""
/** /**
* Compares this value with the specified value for order. * Compares this value with the specified value for order.
@@ -155,7 +155,7 @@ class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltIns
} }
private fun generateOperator(name: String) { private fun generateOperator(name: String) {
for (otherType in UnsignedType.values()) { for (otherType in UnsignedType.entries) {
val returnType = getOperatorReturnType(type, otherType) val returnType = getOperatorReturnType(type, otherType)
out.printDoc(binaryOperatorDoc(name, type, otherType), " ") out.printDoc(binaryOperatorDoc(name, type, otherType), " ")
@@ -176,7 +176,7 @@ class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltIns
} }
private fun generateFloorDivMod(name: String) { private fun generateFloorDivMod(name: String) {
for (otherType in UnsignedType.values()) { for (otherType in UnsignedType.entries) {
val operationType = getOperatorReturnType(type, otherType) val operationType = getOperatorReturnType(type, otherType)
val returnType = if (name == "mod") otherType else operationType val returnType = if (name == "mod") otherType else operationType
@@ -299,14 +299,16 @@ class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltIns
out.println(" @kotlin.internal.InlineOnly") out.println(" @kotlin.internal.InlineOnly")
out.print(" public inline fun to$signed(): $signed = ") out.print(" public inline fun to$signed(): $signed = ")
out.println(when { out.println(when {
otherType < type -> "data.to$signed()" type == UnsignedType.UINT && otherType == UnsignedType.ULONG -> "uintToLong(data)"
otherType == type -> "data" otherType < type -> "data.to$signed()"
else -> "data.to$signed() and ${type.mask}" otherType == type -> "data"
}) else -> "data.to$signed() and ${type.mask}"
}
)
} }
out.println() out.println()
for (otherType in UnsignedType.values()) { for (otherType in UnsignedType.entries) {
val name = otherType.capitalized val name = otherType.capitalized
if (type == otherType) if (type == otherType)
@@ -332,11 +334,14 @@ class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltIns
out.println(" @kotlin.internal.InlineOnly") out.println(" @kotlin.internal.InlineOnly")
out.print(" public inline fun to$name(): $name = ") out.print(" public inline fun to$name(): $name = ")
out.println(when { out.println(
otherType > type -> "${otherType.capitalized}(data.to${otherType.asSigned.capitalized}() and ${type.mask})" when {
otherType == type -> "this" type == UnsignedType.UINT && otherType == UnsignedType.ULONG -> "uintToULong(data)"
else -> "data.to${otherType.capitalized}()" otherType > type -> "${otherType.capitalized}(data.to${otherType.asSigned.capitalized}() and ${type.mask})"
}) otherType == type -> "this"
else -> "data.to${otherType.capitalized}()"
}
)
} }
out.println() out.println()
} }
@@ -359,16 +364,16 @@ class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltIns
out.print(" public inline fun to$otherName(): $otherName = ") out.print(" public inline fun to$otherName(): $otherName = ")
when (type) { when (type) {
UnsignedType.UINT, UnsignedType.ULONG -> UnsignedType.UINT, UnsignedType.ULONG ->
out.println(if (otherType == PrimitiveType.FLOAT) "this.toDouble().toFloat()" else className.lowercase() + "ToDouble(data)") out.println(className.lowercase() + "To$otherName(data)")
else -> else ->
out.println("this.toInt().to$otherName()") out.println("uintTo$otherName(this.toInt())")
} }
} }
out.println() out.println()
} }
private fun generateExtensionConversions() { private fun generateExtensionConversions() {
for (otherType in UnsignedType.values()) { for (otherType in UnsignedType.entries) {
val otherSigned = otherType.asSigned.capitalized val otherSigned = otherType.asSigned.capitalized
val thisSigned = type.asSigned.capitalized val thisSigned = type.asSigned.capitalized
@@ -424,18 +429,16 @@ class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltIns
out.println("@WasExperimental(ExperimentalUnsignedTypes::class)") out.println("@WasExperimental(ExperimentalUnsignedTypes::class)")
out.println("@kotlin.internal.InlineOnly") out.println("@kotlin.internal.InlineOnly")
out.print("public inline fun $otherName.to$className(): $className = ") out.print("public inline fun $otherName.to$className(): $className = ")
val conversion = if (otherType == PrimitiveType.DOUBLE) "" else ".toDouble()" out.println("${otherName.lowercase()}To$className(this)")
out.println("doubleTo$className(this$conversion)")
} }
} }
private fun generateToStringHashCode() { private fun generateToStringHashCode() {
out.print(" public override fun toString(): String = ") out.print(" public override fun toString(): String = ")
when (type) { when (type) {
UnsignedType.UBYTE, UnsignedType.USHORT -> out.println("toInt().toString()") UnsignedType.UBYTE, UnsignedType.USHORT -> out.println("toInt().toString()")
UnsignedType.UINT -> out.println("toLong().toString()") UnsignedType.UINT -> out.println("uintToString(data)")
UnsignedType.ULONG -> out.println("ulongToString(data)") UnsignedType.ULONG -> out.println("ulongToString(data)")
} }
@@ -455,11 +458,11 @@ class UnsignedTypeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltIns
class UnsignedArrayGenerator(val type: UnsignedType, out: PrintWriter) : BuiltInsSourceGenerator(out) { class UnsignedArrayGenerator(val type: UnsignedType, out: PrintWriter) : BuiltInsSourceGenerator(out) {
val elementType = type.capitalized private val elementType = type.capitalized
val arrayType = elementType + "Array" private val arrayType = elementType + "Array"
val arrayTypeOf = elementType.lowercase() + "ArrayOf" private val arrayTypeOf = elementType.lowercase() + "ArrayOf"
val storageElementType = type.asSigned.capitalized private val storageElementType = type.asSigned.capitalized
val storageArrayType = storageElementType + "Array" private val storageArrayType = storageElementType + "Array"
override fun generateBody() { override fun generateBody() {
out.println("import kotlin.jvm.*") out.println("import kotlin.jvm.*")
out.println() out.println()
@@ -548,10 +551,10 @@ public inline fun $arrayTypeOf(vararg elements: $elementType): $arrayType = elem
} }
class UnsignedRangeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltInsSourceGenerator(out) { class UnsignedRangeGenerator(val type: UnsignedType, out: PrintWriter) : BuiltInsSourceGenerator(out) {
val elementType = type.capitalized private val elementType = type.capitalized
val signedType = type.asSigned.capitalized private val signedType = type.asSigned.capitalized
val stepType = signedType private val stepType = signedType
val stepMinValue = "$stepType.MIN_VALUE" private val stepMinValue = "$stepType.MIN_VALUE"
override fun getPackage(): String = "kotlin.ranges" override fun getPackage(): String = "kotlin.ranges"
@@ -1,25 +1,24 @@
/* /*
* 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. * 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 package kotlin
@PublishedApi import kotlin.internal.InlineOnly
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)
@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()
// CHANGES IN THIS FILE SHOULD BE SYNCED WITH THE SAME CHANGES IN: UnsignedJVM.kt and UnsignedJs.kt
// Division and remainder are based on Guava's UnsignedLongs implementation // Division and remainder are based on Guava's UnsignedLongs implementation
// Copyright 2011 The Guava Authors // Copyright 2011 The Guava Authors
@PublishedApi @PublishedApi
internal fun ulongDivide(v1: ULong, v2: ULong): ULong { internal actual fun uintRemainder(v1: UInt, v2: UInt): UInt = (v1.toLong() % v2.toLong()).toUInt()
@PublishedApi
internal actual fun uintDivide(v1: UInt, v2: UInt): UInt = (v1.toLong() / v2.toLong()).toUInt()
@PublishedApi
internal actual fun ulongDivide(v1: ULong, v2: ULong): ULong {
val dividend = v1.toLong() val dividend = v1.toLong()
val divisor = v2.toLong() val divisor = v2.toLong()
if (divisor < 0) { // i.e., divisor >= 2^63: if (divisor < 0) { // i.e., divisor >= 2^63:
@@ -39,7 +38,7 @@ internal fun ulongDivide(v1: ULong, v2: ULong): ULong {
} }
@PublishedApi @PublishedApi
internal fun ulongRemainder(v1: ULong, v2: ULong): ULong { internal actual fun ulongRemainder(v1: ULong, v2: ULong): ULong {
val dividend = v1.toLong() val dividend = v1.toLong()
val divisor = v2.toLong() val divisor = v2.toLong()
if (divisor < 0) { // i.e., divisor >= 2^63: if (divisor < 0) { // i.e., divisor >= 2^63:
@@ -62,44 +61,78 @@ internal fun ulongRemainder(v1: ULong, v2: ULong): ULong {
} }
@PublishedApi @PublishedApi
internal fun doubleToUInt(v: Double): UInt = when { internal actual fun uintCompare(v1: Int, v2: Int): Int = (v1 xor Int.MIN_VALUE).compareTo(v2 xor Int.MIN_VALUE)
v.isNaN() -> 0u
v <= UInt.MIN_VALUE.toDouble() -> UInt.MIN_VALUE @PublishedApi
v >= UInt.MAX_VALUE.toDouble() -> UInt.MAX_VALUE internal actual fun ulongCompare(v1: Long, v2: Long): Int = (v1 xor Long.MIN_VALUE).compareTo(v2 xor Long.MIN_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
@InlineOnly
internal actual inline fun uintToULong(value: Int): ULong = ULong(uintToLong(value))
@PublishedApi
@InlineOnly
internal actual inline fun uintToLong(value: Int): Long = value.toLong() and 0xFFFF_FFFF
@PublishedApi
@InlineOnly
internal actual inline fun uintToFloat(value: Int): Float = uintToDouble(value).toFloat()
@PublishedApi
@InlineOnly
internal actual inline fun floatToUInt(value: Float): UInt = doubleToUInt(value.toDouble())
@PublishedApi
internal actual fun uintToDouble(value: Int): Double = (value and Int.MAX_VALUE).toDouble() + (value ushr 31 shl 30).toDouble() * 2
@PublishedApi
internal actual fun doubleToUInt(value: Double): UInt = when {
value.isNaN() -> 0u
value <= UInt.MIN_VALUE.toDouble() -> UInt.MIN_VALUE
value >= UInt.MAX_VALUE.toDouble() -> UInt.MAX_VALUE
value <= Int.MAX_VALUE -> value.toInt().toUInt()
else -> (value - Int.MAX_VALUE).toInt().toUInt() + Int.MAX_VALUE.toUInt() // Int.MAX_VALUE < v < UInt.MAX_VALUE
} }
@PublishedApi @PublishedApi
internal fun doubleToULong(v: Double): ULong = when { @InlineOnly
v.isNaN() -> 0u internal actual inline fun ulongToFloat(value: Long): Float = ulongToDouble(value).toFloat()
v <= ULong.MIN_VALUE.toDouble() -> ULong.MIN_VALUE
v >= ULong.MAX_VALUE.toDouble() -> ULong.MAX_VALUE @PublishedApi
v < Long.MAX_VALUE -> v.toLong().toULong() @InlineOnly
internal actual inline fun floatToULong(value: Float): ULong = doubleToULong(value.toDouble())
@PublishedApi
internal actual fun ulongToDouble(value: Long): Double = (value ushr 11).toDouble() * 2048 + (value and 2047)
@PublishedApi
internal actual fun doubleToULong(value: Double): ULong = when {
value.isNaN() -> 0u
value <= ULong.MIN_VALUE.toDouble() -> ULong.MIN_VALUE
value >= ULong.MAX_VALUE.toDouble() -> ULong.MAX_VALUE
value < Long.MAX_VALUE -> value.toLong().toULong()
// Real values from Long.MAX_VALUE to (Long.MAX_VALUE + 1) are not representable in Double, so don't handle them. // 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 else -> (value - 9223372036854775808.0).toLong().toULong() + 9223372036854775808uL // Long.MAX_VALUE + 1 < v < ULong.MAX_VALUE
} }
@InlineOnly
internal actual inline fun uintToString(value: Int): String = uintToLong(value).toString()
@PublishedApi @InlineOnly
internal fun uintToDouble(v: Int): Double = (v and Int.MAX_VALUE).toDouble() + (v ushr 31 shl 30).toDouble() * 2 internal actual inline fun uintToString(value: Int, base: Int): String = ulongToString(uintToLong(value), base)
@PublishedApi @InlineOnly
internal fun ulongToDouble(v: Long): Double = (v ushr 11).toDouble() * 2048 + (v and 2047) internal actual inline fun ulongToString(value: Long): String = ulongToString(value, 10)
internal actual fun ulongToString(value: Long, base: Int): String {
if (value >= 0) return value.toString(base)
internal fun ulongToString(v: Long): String = ulongToString(v, 10) var quotient = ((value ushr 1) / base) shl 1
var rem = value - quotient * base
internal fun ulongToString(v: Long, base: Int): String {
if (v >= 0) return v.toString(base)
var quotient = ((v ushr 1) / base) shl 1
var rem = v - quotient * base
if (rem >= base) { if (rem >= base) {
rem -= base rem -= base
quotient += 1 quotient += 1
} }
return quotient.toString(base) + rem.toString(base) return quotient.toString(base) + rem.toString(base)
} }
+71 -37
View File
@@ -1,25 +1,25 @@
/* /*
* 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. * 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 package kotlin
@PublishedApi import kotlin.internal.InlineOnly
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)
@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()
// CHANGES IN THIS FILE SHOULD BE SYNCED WITH THE SAME CHANGES IN: UnsignedJVM.kt and kotlin-native/Unsigned.kt
// Division and remainder are based on Guava's UnsignedLongs implementation // Division and remainder are based on Guava's UnsignedLongs implementation
// Copyright 2011 The Guava Authors // Copyright 2011 The Guava Authors
@PublishedApi @PublishedApi
internal fun ulongDivide(v1: ULong, v2: ULong): ULong { internal actual fun uintRemainder(v1: UInt, v2: UInt): UInt = (v1.toLong() % v2.toLong()).toUInt()
@PublishedApi
internal actual fun uintDivide(v1: UInt, v2: UInt): UInt = (v1.toLong() / v2.toLong()).toUInt()
@PublishedApi
internal actual fun ulongDivide(v1: ULong, v2: ULong): ULong {
val dividend = v1.toLong() val dividend = v1.toLong()
val divisor = v2.toLong() val divisor = v2.toLong()
if (divisor < 0) { // i.e., divisor >= 2^63: if (divisor < 0) { // i.e., divisor >= 2^63:
@@ -39,7 +39,7 @@ internal fun ulongDivide(v1: ULong, v2: ULong): ULong {
} }
@PublishedApi @PublishedApi
internal fun ulongRemainder(v1: ULong, v2: ULong): ULong { internal actual fun ulongRemainder(v1: ULong, v2: ULong): ULong {
val dividend = v1.toLong() val dividend = v1.toLong()
val divisor = v2.toLong() val divisor = v2.toLong()
if (divisor < 0) { // i.e., divisor >= 2^63: if (divisor < 0) { // i.e., divisor >= 2^63:
@@ -62,44 +62,78 @@ internal fun ulongRemainder(v1: ULong, v2: ULong): ULong {
} }
@PublishedApi @PublishedApi
internal fun doubleToUInt(v: Double): UInt = when { internal actual fun uintCompare(v1: Int, v2: Int): Int = (v1 xor Int.MIN_VALUE).compareTo(v2 xor Int.MIN_VALUE)
v.isNaN() -> 0u
v <= UInt.MIN_VALUE.toDouble() -> UInt.MIN_VALUE @PublishedApi
v >= UInt.MAX_VALUE.toDouble() -> UInt.MAX_VALUE internal actual fun ulongCompare(v1: Long, v2: Long): Int = (v1 xor Long.MIN_VALUE).compareTo(v2 xor Long.MIN_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
@InlineOnly
internal actual inline fun uintToULong(value: Int): ULong = ULong(uintToLong(value))
@PublishedApi
@InlineOnly
internal actual inline fun uintToLong(value: Int): Long = value.toLong() and 0xFFFF_FFFF
@PublishedApi
@InlineOnly
internal actual inline fun uintToFloat(value: Int): Float = uintToDouble(value).toFloat()
@PublishedApi
@InlineOnly
internal actual inline fun floatToUInt(value: Float): UInt = doubleToUInt(value.toDouble())
@PublishedApi
internal actual fun uintToDouble(value: Int): Double = (value and Int.MAX_VALUE).toDouble() + (value ushr 31 shl 30).toDouble() * 2
@PublishedApi
internal actual fun doubleToUInt(value: Double): UInt = when {
value.isNaN() -> 0u
value <= UInt.MIN_VALUE.toDouble() -> UInt.MIN_VALUE
value >= UInt.MAX_VALUE.toDouble() -> UInt.MAX_VALUE
value <= Int.MAX_VALUE -> value.toInt().toUInt()
else -> (value - Int.MAX_VALUE).toInt().toUInt() + Int.MAX_VALUE.toUInt() // Int.MAX_VALUE < v < UInt.MAX_VALUE
} }
@PublishedApi @PublishedApi
internal fun doubleToULong(v: Double): ULong = when { @InlineOnly
v.isNaN() -> 0u internal actual inline fun ulongToFloat(value: Long): Float = ulongToDouble(value).toFloat()
v <= ULong.MIN_VALUE.toDouble() -> ULong.MIN_VALUE
v >= ULong.MAX_VALUE.toDouble() -> ULong.MAX_VALUE @PublishedApi
v < Long.MAX_VALUE -> v.toLong().toULong() @InlineOnly
internal actual inline fun floatToULong(value: Float): ULong = doubleToULong(value.toDouble())
@PublishedApi
internal actual fun ulongToDouble(value: Long): Double = (value ushr 11).toDouble() * 2048 + (value and 2047)
@PublishedApi
internal actual fun doubleToULong(value: Double): ULong = when {
value.isNaN() -> 0u
value <= ULong.MIN_VALUE.toDouble() -> ULong.MIN_VALUE
value >= ULong.MAX_VALUE.toDouble() -> ULong.MAX_VALUE
value < Long.MAX_VALUE -> value.toLong().toULong()
// Real values from Long.MAX_VALUE to (Long.MAX_VALUE + 1) are not representable in Double, so don't handle them. // 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 else -> (value - 9223372036854775808.0).toLong().toULong() + 9223372036854775808uL // Long.MAX_VALUE + 1 < v < ULong.MAX_VALUE
} }
@InlineOnly
internal actual inline fun uintToString(value: Int): String = uintToLong(value).toString()
@PublishedApi @InlineOnly
internal fun uintToDouble(v: Int): Double = (v and Int.MAX_VALUE).toDouble() + (v ushr 31 shl 30).toDouble() * 2 internal actual inline fun uintToString(value: Int, base: Int): String = ulongToString(uintToLong(value), base)
@PublishedApi @InlineOnly
internal fun ulongToDouble(v: Long): Double = (v ushr 11).toDouble() * 2048 + (v and 2047) internal actual inline fun ulongToString(value: Long): String = ulongToString(value, 10)
internal actual fun ulongToString(value: Long, base: Int): String {
if (value >= 0) return value.toString(base)
internal fun ulongToString(v: Long): String = ulongToString(v, 10) var quotient = ((value ushr 1) / base) shl 1
var rem = value - quotient * base
internal fun ulongToString(v: Long, base: Int): String {
if (v >= 0) return v.toString(base)
var quotient = ((v ushr 1) / base) shl 1
var rem = v - quotient * base
if (rem >= base) { if (rem >= base) {
rem -= base rem -= base
quotient += 1 quotient += 1
} }
return quotient.toString(base) + rem.toString(base) return quotient.toString(base) + rem.toString(base)
} }
@@ -1,25 +1,24 @@
/* /*
* 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. * 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") @file:kotlin.jvm.JvmName("UnsignedKt")
package kotlin package kotlin
@PublishedApi import kotlin.internal.InlineOnly
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)
@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()
// CHANGES IN THIS FILE SHOULD BE SYNCED WITH THE SAME CHANGES IN: UnsignedJs.kt and kotlin-native/Unsigned.kt
// Division and remainder are based on Guava's UnsignedLongs implementation // Division and remainder are based on Guava's UnsignedLongs implementation
// Copyright 2011 The Guava Authors // Copyright 2011 The Guava Authors
@PublishedApi @PublishedApi
internal fun ulongDivide(v1: ULong, v2: ULong): ULong { internal actual fun uintRemainder(v1: UInt, v2: UInt): UInt = (v1.toLong() % v2.toLong()).toUInt()
@PublishedApi
internal actual fun uintDivide(v1: UInt, v2: UInt): UInt = (v1.toLong() / v2.toLong()).toUInt()
@PublishedApi
internal actual fun ulongDivide(v1: ULong, v2: ULong): ULong {
val dividend = v1.toLong() val dividend = v1.toLong()
val divisor = v2.toLong() val divisor = v2.toLong()
if (divisor < 0) { // i.e., divisor >= 2^63: if (divisor < 0) { // i.e., divisor >= 2^63:
@@ -39,7 +38,7 @@ internal fun ulongDivide(v1: ULong, v2: ULong): ULong {
} }
@PublishedApi @PublishedApi
internal fun ulongRemainder(v1: ULong, v2: ULong): ULong { internal actual fun ulongRemainder(v1: ULong, v2: ULong): ULong {
val dividend = v1.toLong() val dividend = v1.toLong()
val divisor = v2.toLong() val divisor = v2.toLong()
if (divisor < 0) { // i.e., divisor >= 2^63: if (divisor < 0) { // i.e., divisor >= 2^63:
@@ -62,44 +61,78 @@ internal fun ulongRemainder(v1: ULong, v2: ULong): ULong {
} }
@PublishedApi @PublishedApi
internal fun doubleToUInt(v: Double): UInt = when { internal actual fun uintCompare(v1: Int, v2: Int): Int = (v1 xor Int.MIN_VALUE).compareTo(v2 xor Int.MIN_VALUE)
v.isNaN() -> 0u
v <= UInt.MIN_VALUE.toDouble() -> UInt.MIN_VALUE @PublishedApi
v >= UInt.MAX_VALUE.toDouble() -> UInt.MAX_VALUE internal actual fun ulongCompare(v1: Long, v2: Long): Int = (v1 xor Long.MIN_VALUE).compareTo(v2 xor Long.MIN_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
@InlineOnly
internal actual inline fun uintToULong(value: Int): ULong = ULong(uintToLong(value))
@PublishedApi
@InlineOnly
internal actual inline fun uintToLong(value: Int): Long = value.toLong() and 0xFFFF_FFFF
@PublishedApi
@InlineOnly
internal actual inline fun uintToFloat(value: Int): Float = uintToDouble(value).toFloat()
@PublishedApi
@InlineOnly
internal actual inline fun floatToUInt(value: Float): UInt = doubleToUInt(value.toDouble())
@PublishedApi
internal actual fun uintToDouble(value: Int): Double = (value and Int.MAX_VALUE).toDouble() + (value ushr 31 shl 30).toDouble() * 2
@PublishedApi
internal actual fun doubleToUInt(value: Double): UInt = when {
value.isNaN() -> 0u
value <= UInt.MIN_VALUE.toDouble() -> UInt.MIN_VALUE
value >= UInt.MAX_VALUE.toDouble() -> UInt.MAX_VALUE
value <= Int.MAX_VALUE -> value.toInt().toUInt()
else -> (value - Int.MAX_VALUE).toInt().toUInt() + Int.MAX_VALUE.toUInt() // Int.MAX_VALUE < v < UInt.MAX_VALUE
} }
@PublishedApi @PublishedApi
internal fun doubleToULong(v: Double): ULong = when { @InlineOnly
v.isNaN() -> 0u internal actual inline fun ulongToFloat(value: Long): Float = ulongToDouble(value).toFloat()
v <= ULong.MIN_VALUE.toDouble() -> ULong.MIN_VALUE
v >= ULong.MAX_VALUE.toDouble() -> ULong.MAX_VALUE @PublishedApi
v < Long.MAX_VALUE -> v.toLong().toULong() @InlineOnly
internal actual inline fun floatToULong(value: Float): ULong = doubleToULong(value.toDouble())
@PublishedApi
internal actual fun ulongToDouble(value: Long): Double = (value ushr 11).toDouble() * 2048 + (value and 2047)
@PublishedApi
internal actual fun doubleToULong(value: Double): ULong = when {
value.isNaN() -> 0u
value <= ULong.MIN_VALUE.toDouble() -> ULong.MIN_VALUE
value >= ULong.MAX_VALUE.toDouble() -> ULong.MAX_VALUE
value < Long.MAX_VALUE -> value.toLong().toULong()
// Real values from Long.MAX_VALUE to (Long.MAX_VALUE + 1) are not representable in Double, so don't handle them. // 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 else -> (value - 9223372036854775808.0).toLong().toULong() + 9223372036854775808uL // Long.MAX_VALUE + 1 < v < ULong.MAX_VALUE
} }
@InlineOnly
internal actual inline fun uintToString(value: Int): String = uintToLong(value).toString()
@PublishedApi @InlineOnly
internal fun uintToDouble(v: Int): Double = (v and Int.MAX_VALUE).toDouble() + (v ushr 31 shl 30).toDouble() * 2 internal actual inline fun uintToString(value: Int, base: Int): String = ulongToString(uintToLong(value), base)
@PublishedApi @InlineOnly
internal fun ulongToDouble(v: Long): Double = (v ushr 11).toDouble() * 2048 + (v and 2047) internal actual inline fun ulongToString(value: Long): String = ulongToString(value, 10)
internal actual fun ulongToString(value: Long, base: Int): String {
if (value >= 0) return value.toString(base)
internal fun ulongToString(v: Long): String = ulongToString(v, 10) var quotient = ((value ushr 1) / base) shl 1
var rem = value - quotient * base
internal fun ulongToString(v: Long, base: Int): String {
if (v >= 0) return v.toString(base)
var quotient = ((v ushr 1) / base) shl 1
var rem = v - quotient * base
if (rem >= base) { if (rem >= base) {
rem -= base rem -= base
quotient += 1 quotient += 1
} }
return quotient.toString(base) + rem.toString(base) return quotient.toString(base) + rem.toString(base)
} }
@@ -342,14 +342,14 @@ public value class UByte @kotlin.internal.IntrinsicConstEvaluation @PublishedApi
* The resulting `Float` value represents the same numerical value as this `UByte`. * The resulting `Float` value represents the same numerical value as this `UByte`.
*/ */
@kotlin.internal.InlineOnly @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]. * Converts this [UByte] value to [Double].
* *
* The resulting `Double` value represents the same numerical value as this `UByte`. * The resulting `Double` value represents the same numerical value as this `UByte`.
*/ */
@kotlin.internal.InlineOnly @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() 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. * whereas the most significant 32 bits are filled with zeros.
*/ */
@kotlin.internal.InlineOnly @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]. * 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. * whereas the most significant 32 bits are filled with zeros.
*/ */
@kotlin.internal.InlineOnly @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]. * 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. * the one with zero at least significant bit of mantissa is selected.
*/ */
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toDouble().toFloat() public inline fun toFloat(): Float = uintToFloat(data)
/** /**
* Converts this [UInt] value to [Double]. * Converts this [UInt] value to [Double].
* *
@@ -373,7 +373,7 @@ public value class UInt @kotlin.internal.IntrinsicConstEvaluation @PublishedApi
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun toDouble(): Double = uintToDouble(data) 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") @SinceKotlin("1.5")
@WasExperimental(ExperimentalUnsignedTypes::class) @WasExperimental(ExperimentalUnsignedTypes::class)
@kotlin.internal.InlineOnly @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]. * 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. * the one with zero at least significant bit of mantissa is selected.
*/ */
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun toFloat(): Float = this.toDouble().toFloat() public inline fun toFloat(): Float = ulongToFloat(data)
/** /**
* Converts this [ULong] value to [Double]. * Converts this [ULong] value to [Double].
* *
@@ -437,7 +437,7 @@ public inline fun Long.toULong(): ULong = ULong(this)
@SinceKotlin("1.5") @SinceKotlin("1.5")
@WasExperimental(ExperimentalUnsignedTypes::class) @WasExperimental(ExperimentalUnsignedTypes::class)
@kotlin.internal.InlineOnly @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]. * 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`. * The resulting `Float` value represents the same numerical value as this `UShort`.
*/ */
@kotlin.internal.InlineOnly @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]. * Converts this [UShort] value to [Double].
* *
* The resulting `Double` value represents the same numerical value as this `UShort`. * The resulting `Double` value represents the same numerical value as this `UShort`.
*/ */
@kotlin.internal.InlineOnly @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() 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") @SinceKotlin("1.5")
@WasExperimental(ExperimentalUnsignedTypes::class) @WasExperimental(ExperimentalUnsignedTypes::class)
//@kotlin.internal.InlineOnly //@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]. * 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. * 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 package kotlin
@PublishedApi @PublishedApi
internal fun uintCompare(v1: Int, v2: Int): Int = (v1 xor Int.MIN_VALUE).compareTo(v2 xor Int.MIN_VALUE) internal expect fun uintRemainder(v1: UInt, v2: UInt): UInt
@PublishedApi
internal fun ulongCompare(v1: Long, v2: Long): Int = (v1 xor Long.MIN_VALUE).compareTo(v2 xor Long.MIN_VALUE)
@PublishedApi @PublishedApi
internal fun uintDivide(v1: UInt, v2: UInt): UInt = (v1.toLong() / v2.toLong()).toUInt() internal expect fun ulongRemainder(v1: ULong, v2: ULong): ULong
@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
@PublishedApi @PublishedApi
internal fun ulongDivide(v1: ULong, v2: ULong): ULong { internal expect fun uintDivide(v1: UInt, v2: UInt): UInt
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)
}
@PublishedApi @PublishedApi
internal fun ulongRemainder(v1: ULong, v2: ULong): ULong { internal expect 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) {
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)
}
@PublishedApi @PublishedApi
internal fun doubleToUInt(v: Double): UInt = when { internal expect fun uintCompare(v1: Int, v2: Int): Int
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 @PublishedApi
internal fun doubleToULong(v: Double): ULong = when { internal expect fun ulongCompare(v1: Long, v2: Long): Int
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 @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 @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 { @PublishedApi
if (v >= 0) return v.toString(base) internal expect fun uintToDouble(value: Int): Double
var quotient = ((v ushr 1) / base) shl 1 @PublishedApi
var rem = v - quotient * base internal expect fun doubleToUInt(value: Double): UInt
if (rem >= base) {
rem -= base
quotient += 1
}
return quotient.toString(base) + rem.toString(base)
}
@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
@@ -1356,7 +1356,7 @@ public class Int private constructor(private val value: Int) : Number(), Compara
@kotlin.internal.IntrinsicConstEvaluation @kotlin.internal.IntrinsicConstEvaluation
public override fun toString(): String = public override fun toString(): String =
itoa32(this, 10) itoa32(this)
@kotlin.internal.IntrinsicConstEvaluation @kotlin.internal.IntrinsicConstEvaluation
public override fun equals(other: Any?): Boolean = public override fun equals(other: Any?): Boolean =
@@ -1865,7 +1865,7 @@ public class Long private constructor(private val value: Long) : Number(), Compa
@kotlin.internal.IntrinsicConstEvaluation @kotlin.internal.IntrinsicConstEvaluation
public override fun toString(): String = public override fun toString(): String =
itoa64(this, 10) itoa64(this)
@kotlin.internal.IntrinsicConstEvaluation @kotlin.internal.IntrinsicConstEvaluation
public override fun equals(other: Any?): Boolean = public override fun equals(other: Any?): Boolean =
@@ -4,6 +4,8 @@
*/ */
package kotlin.wasm.internal package kotlin.wasm.internal
// Based on the AssemblyScript implementation [https://github.com/AssemblyScript/assemblyscript/blob/1e0466ef94fa5cacd0984e4f31a0087de51538a8/std/assembly/util/number.ts]
private enum class CharCodes(val code: Int) { private enum class CharCodes(val code: Int) {
// PERCENT(0x25), // PERCENT(0x25),
PLUS(0x2B), PLUS(0x2B),
@@ -42,125 +44,115 @@ private fun digitToChar(input: Int): Char {
return (CharCodes._0.code + input).toChar() return (CharCodes._0.code + input).toChar()
} }
// Inspired by the AssemblyScript implementation internal fun itoa32(inputValue: Int): String {
internal fun itoa32(inputValue: Int, radix: Int): String {
if (radix < 2 || radix > 36)
throw IllegalArgumentException("Radix argument is unreasonable")
if (radix != 10)
TODO("When we need it")
if (inputValue == 0) return "0" if (inputValue == 0) return "0"
// We can't represent abs(Int.MIN_VALUE), so just hardcode it here
if (inputValue == Int.MIN_VALUE) return "-2147483648"
val sign = inputValue ushr 31 val isNegative = inputValue < 0
assert(sign == 1 || sign == 0) val absValue = if (isNegative) -inputValue else inputValue
val absValue = if (sign == 1) -inputValue else inputValue val absValueString = utoa32(absValue.toUInt())
val decimals = decimalCount32(absValue) + sign return if (isNegative) "-$absValueString" else absValueString
}
internal fun utoa32(inputValue: UInt): String {
if (inputValue == 0U) return "0"
val decimals = decimalCount32(inputValue)
val buf = WasmCharArray(decimals) val buf = WasmCharArray(decimals)
utoaDecSimple(buf, absValue, decimals)
if (sign == 1) utoaDecSimple(buf, inputValue, decimals)
buf.set(0, CharCodes.MINUS.code.toChar())
return buf.createString() return buf.createString()
} }
private fun utoaDecSimple(buffer: WasmCharArray, numInput: Int, offsetInput: Int) { private fun utoaDecSimple(buffer: WasmCharArray, numInput: UInt, offsetInput: Int) {
assert(numInput != 0) assert(numInput != 0U)
assert(buffer.len() > 0) assert(buffer.len() > 0)
assert(offsetInput > 0 && offsetInput <= buffer.len()) assert(offsetInput > 0 && offsetInput <= buffer.len())
var num = numInput var num = numInput
var offset = offsetInput var offset = offsetInput
do { do {
val t = num / 10 val t = num / 10U
val r = num % 10 val r = num % 10U
num = t num = t
offset-- offset--
buffer.set(offset, digitToChar(r)) buffer.set(offset, digitToChar(r.toInt()))
} while (num > 0) } while (num > 0U)
} }
private fun utoaDecSimple64(buffer: WasmCharArray, numInput: Long, offsetInput: Int) { private fun utoaDecSimple64(buffer: WasmCharArray, numInput: ULong, offsetInput: Int) {
assert(numInput != 0L) assert(numInput != 0UL)
assert(buffer.len() > 0) assert(buffer.len() > 0)
assert(offsetInput > 0 && offsetInput <= buffer.len()) assert(offsetInput > 0 && offsetInput <= buffer.len())
var num = numInput var num = numInput
var offset = offsetInput var offset = offsetInput
do { do {
val t = num / 10 val t = num / 10U
val r = (num % 10).toInt() val r = num % 10U
num = t num = t
offset-- offset--
buffer.set(offset, digitToChar(r)) buffer.set(offset, digitToChar(r.toInt()))
} while (num > 0) } while (num > 0U)
} }
private fun Boolean.toInt() = if (this) 1 else 0 private fun Boolean.toInt() = if (this) 1 else 0
private fun Boolean.toLong() = if (this) 1L else 0L private fun Boolean.toLong() = if (this) 1L else 0L
private fun decimalCount32(value: Int): Int { private fun decimalCount32(value: UInt): Int {
if (value < 100000) { if (value < 100000u) {
if (value < 100) { if (value < 100u) {
return 1 + (value >= 10).toInt() return 1 + (value >= 10u).toInt()
} else { } else {
return 3 + (value >= 10000).toInt() + (value >= 1000).toInt() return 3 + (value >= 10000u).toInt() + (value >= 1000u).toInt()
} }
} else { } else {
if (value < 10000000) { if (value < 10000000u) {
return 6 + (value >= 1000000).toInt() return 6 + (value >= 1000000u).toInt()
} else { } else {
return 8 + (value >= 1000000000).toInt() + (value >= 100000000).toInt() return 8 + (value >= 1000000000u).toInt() + (value >= 100000000u).toInt()
} }
} }
} }
internal fun itoa64(inputValue: Long, radix: Int): String { internal fun itoa64(inputValue: Long): String {
if (inputValue in Int.MIN_VALUE..Int.MAX_VALUE) if (inputValue in Int.MIN_VALUE..Int.MAX_VALUE)
return itoa32(inputValue.toInt(), radix) return itoa32(inputValue.toInt())
if (radix < 2 || radix > 36) val isNegative = inputValue < 0
throw IllegalArgumentException("Radix argument is unreasonable") val absValue = if (isNegative) -inputValue else inputValue
val absValueString = utoa64(absValue.toULong())
if (inputValue == 0L) return "0" return if (isNegative) "-$absValueString" else absValueString
// We can't represent abs(Long.MIN_VALUE), so just hardcode it here }
if (inputValue == Long.MIN_VALUE) return "-9223372036854775808"
if (radix != 10) { internal fun utoa64(inputValue: ULong): String {
TODO("When we need it") if (inputValue <= UInt.MAX_VALUE) return utoa32(inputValue.toUInt())
}
val sign = (inputValue ushr 63).toInt() val decimals = decimalCount64High(inputValue)
assert(sign == 1 || sign == 0)
val absValue = if (sign == 1) -inputValue else inputValue
val decimals = decimalCount64High(absValue) + sign
val buf = WasmCharArray(decimals) val buf = WasmCharArray(decimals)
utoaDecSimple64(buf, absValue, decimals)
if (sign == 1) utoaDecSimple64(buf, inputValue, decimals)
buf.set(0, CharCodes.MINUS.code.toChar())
return buf.createString() return buf.createString()
} }
// Count number of decimals for u64 values // Count number of decimals for u64 values
// In our case input value always greater than 2^32-1 so we can skip some parts // In our case input value always greater than 2^32-1 so we can skip some parts
private fun decimalCount64High(value: Long): Int { private fun decimalCount64High(value: ULong): Int {
if (value < 1000000000000000) { if (value < 1000000000000000UL) {
if (value < 1000000000000) { if (value < 1000000000000UL) {
return 10 + (value >= 100000000000).toInt() + (value >= 10000000000).toInt() return 10 + (value >= 100000000000UL).toInt() + (value >= 10000000000UL).toInt()
} else { } else {
return 13 + (value >= 100000000000000).toInt() + (value >= 10000000000000).toInt() return 13 + (value >= 100000000000000UL).toInt() + (value >= 10000000000000UL).toInt()
} }
} else { } else {
if (value < 100000000000000000) { if (value < 100000000000000000UL) {
return 16 + (value >= 10000000000000000).toInt() return 16 + (value >= 10000000000000000UL).toInt()
} else { } else {
return 18 + (value >= 1000000000000000000).toInt() return 18 + (value >= 10000000000000000000UL).toInt() + (value >= 1000000000000000000UL).toInt()
} }
} }
} }
@@ -331,7 +323,7 @@ private fun genDigits(buffer: WasmCharArray, w_frc: Long, mp_frc: Long, mp_exp:
var p1 = (mp_frc ushr one_exp).toInt() var p1 = (mp_frc ushr one_exp).toInt()
var p2 = mp_frc and mask var p2 = mp_frc and mask
var kappa = decimalCount32(p1) var kappa = decimalCount32(p1.toUInt())
var len = sign var len = sign
while (kappa > 0) { while (kappa > 0) {
@@ -11,6 +11,14 @@ package kotlin.wasm.internal
internal fun wasm_i32_compareTo(x: Int, y: Int): Int = internal fun wasm_i32_compareTo(x: Int, y: Int): Int =
wasm_i32_ge_s(x, y).toInt() - wasm_i32_le_s(x, y).toInt() wasm_i32_ge_s(x, y).toInt() - wasm_i32_le_s(x, y).toInt()
@PublishedApi
internal fun wasm_u32_compareTo(x: Int, y: Int): Int =
wasm_i32_ge_u(x, y).toInt() - wasm_i32_le_u(x, y).toInt()
@PublishedApi @PublishedApi
internal fun wasm_i64_compareTo(x: Long, y: Long): Int = internal fun wasm_i64_compareTo(x: Long, y: Long): Int =
wasm_i64_ge_s(x, y).toInt() - wasm_i64_le_s(x, y).toInt() wasm_i64_ge_s(x, y).toInt() - wasm_i64_le_s(x, y).toInt()
@PublishedApi
internal fun wasm_u64_compareTo(x: Long, y: Long): Int =
wasm_i64_ge_u(x, y).toInt() - wasm_i64_le_u(x, y).toInt()
@@ -5,7 +5,6 @@
package kotlin.text package kotlin.text
import kotlin.math.abs
import kotlin.wasm.internal.wasm_f32_demote_f64 import kotlin.wasm.internal.wasm_f32_demote_f64
/** /**
@@ -103,7 +102,7 @@ public actual fun String.toDoubleOrNull(): Double? {
* @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion.
*/ */
@SinceKotlin("1.2") @SinceKotlin("1.2")
public actual fun Byte.toString(radix: Int): String = this.toLong().toString(radix) public actual fun Byte.toString(radix: Int): String = this.toInt().toString(radix)
/** /**
* Returns a string representation of this [Short] value in the specified [radix]. * Returns a string representation of this [Short] value in the specified [radix].
@@ -111,7 +110,7 @@ public actual fun Byte.toString(radix: Int): String = this.toLong().toString(rad
* @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion.
*/ */
@SinceKotlin("1.2") @SinceKotlin("1.2")
public actual fun Short.toString(radix: Int): String = this.toLong().toString(radix) public actual fun Short.toString(radix: Int): String = this.toInt().toString(radix)
/** /**
* Returns a string representation of this [Int] value in the specified [radix]. * Returns a string representation of this [Int] value in the specified [radix].
@@ -119,7 +118,13 @@ public actual fun Short.toString(radix: Int): String = this.toLong().toString(ra
* @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion.
*/ */
@SinceKotlin("1.2") @SinceKotlin("1.2")
public actual fun Int.toString(radix: Int): String = toLong().toString(radix) public actual fun Int.toString(radix: Int): String {
val isNegative = this < 0
val absValue = if (isNegative) -this else this
val absValueString = uintToString(absValue, checkRadix(radix))
return if (isNegative) "-$absValueString" else absValueString
}
/** /**
* Returns a string representation of this [Long] value in the specified [radix]. * Returns a string representation of this [Long] value in the specified [radix].
@@ -128,28 +133,9 @@ public actual fun Int.toString(radix: Int): String = toLong().toString(radix)
*/ */
@SinceKotlin("1.2") @SinceKotlin("1.2")
public actual fun Long.toString(radix: Int): String { public actual fun Long.toString(radix: Int): String {
checkRadix(radix)
fun Long.getChar() = toInt().let { if (it < 10) '0' + it else 'a' + (it - 10) }
if (radix == 10) return toString()
if (this in 0 until radix) return getChar().toString()
val isNegative = this < 0 val isNegative = this < 0
val buffer = CharArray(Long.SIZE_BITS + 1) val absValue = if (isNegative) -this else this
val absValueString = ulongToString(absValue, checkRadix(radix))
var currentBufferIndex = buffer.lastIndex return if (isNegative) "-$absValueString" else absValueString
var current: Long = this }
while(current != 0L) {
buffer[currentBufferIndex] = abs(current % radix).getChar()
current /= radix
currentBufferIndex--
}
if (isNegative) {
buffer[currentBufferIndex] = '-'
currentBufferIndex--
}
return buffer.concatToString(currentBufferIndex + 1)
}
@@ -1,105 +1,134 @@
/* /*
* 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. * 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 package kotlin
@PublishedApi import kotlin.internal.InlineOnly
internal fun uintCompare(v1: Int, v2: Int): Int = (v1 xor Int.MIN_VALUE).compareTo(v2 xor Int.MIN_VALUE) import kotlin.math.abs
@PublishedApi import kotlin.wasm.internal.*
internal fun ulongCompare(v1: Long, v2: Long): Int = (v1 xor Long.MIN_VALUE).compareTo(v2 xor Long.MIN_VALUE) import kotlin.wasm.internal.WasmOp
import kotlin.wasm.internal.implementedAsIntrinsic
import kotlin.wasm.internal.wasm_u32_compareTo
@PublishedApi @PublishedApi
internal fun uintDivide(v1: UInt, v2: UInt): UInt = (v1.toLong() / v2.toLong()).toUInt() @WasmOp(WasmOp.I32_REM_U)
@PublishedApi internal actual fun uintRemainder(v1: UInt, v2: UInt): UInt = implementedAsIntrinsic
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
@PublishedApi @PublishedApi
internal fun ulongDivide(v1: ULong, v2: ULong): ULong { @WasmOp(WasmOp.I32_DIV_U)
val dividend = v1.toLong() internal actual fun uintDivide(v1: UInt, v2: UInt): UInt = implementedAsIntrinsic
val divisor = v2.toLong()
if (divisor < 0) { // i.e., divisor >= 2^63: @PublishedApi
return if (v1 < v2) ULong(0) else ULong(1) @WasmOp(WasmOp.I64_REM_U)
internal actual fun ulongRemainder(v1: ULong, v2: ULong): ULong = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.I64_DIV_U)
internal actual fun ulongDivide(v1: ULong, v2: ULong): ULong = implementedAsIntrinsic
@PublishedApi
@InlineOnly
internal actual inline fun uintCompare(v1: Int, v2: Int): Int = wasm_u32_compareTo(v1, v2)
@PublishedApi
@InlineOnly
internal actual inline fun ulongCompare(v1: Long, v2: Long): Int = wasm_u64_compareTo(v1, v2)
@PublishedApi
@WasmOp(WasmOp.I64_EXTEND_I32_U)
internal actual fun uintToULong(value: Int): ULong = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.I64_EXTEND_I32_U)
internal actual fun uintToLong(value: Int): Long = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.F32_CONVERT_I32_U)
internal actual fun uintToFloat(value: Int): Float = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.I32_TRUNC_SAT_F32_U)
internal actual fun floatToUInt(value: Float): UInt = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.F64_CONVERT_I32_U)
internal actual fun uintToDouble(value: Int): Double = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.I32_TRUNC_SAT_F64_U)
internal actual fun doubleToUInt(value: Double): UInt = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.F32_CONVERT_I64_U)
internal actual fun ulongToFloat(value: Long): Float = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.I64_TRUNC_SAT_F32_U)
internal actual fun floatToULong(value: Float): ULong = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.F64_CONVERT_I64_U)
internal actual fun ulongToDouble(value: Long): Double = implementedAsIntrinsic
@PublishedApi
@WasmOp(WasmOp.I64_TRUNC_SAT_F64_U)
internal actual fun doubleToULong(value: Double): ULong = implementedAsIntrinsic
@InlineOnly
internal actual inline fun uintToString(value: Int): String = utoa32(value.toUInt())
internal actual fun uintToString(value: Int, base: Int): String {
var unsignedValue = value.toUInt()
if (base == 10) return unsignedValue.toString()
if (value in 0 until base) return value.getChar().toString()
val buffer = WasmCharArray(UInt.SIZE_BITS)
val ulongRadix = base.toUInt()
var currentBufferIndex = UInt.SIZE_BITS - 1
while (unsignedValue != 0U) {
buffer.set(currentBufferIndex, (unsignedValue % ulongRadix).toInt().getChar())
unsignedValue /= ulongRadix
currentBufferIndex--
} }
// Optimization - use signed division if both dividend and divisor < 2^63 return buffer.createStringStartingFrom(currentBufferIndex + 1)
if (dividend >= 0) { }
return ULong(dividend / divisor)
@InlineOnly
internal actual inline fun ulongToString(value: Long): String = utoa64(value.toULong())
internal actual fun ulongToString(value: Long, base: Int): String {
var unsignedValue = value.toULong()
if (base == 10) return unsignedValue.toString()
if (value in 0 until base) return value.toInt().getChar().toString()
val buffer = WasmCharArray(ULong.SIZE_BITS)
val ulongRadix = base.toULong()
var currentBufferIndex = ULong.SIZE_BITS - 1
while (unsignedValue != 0UL) {
buffer.set(currentBufferIndex, (unsignedValue % ulongRadix).toInt().getChar())
unsignedValue /= ulongRadix
currentBufferIndex--
} }
// Otherwise, approximate the quotient, check, and correct if necessary. return buffer.createStringStartingFrom(currentBufferIndex + 1)
val quotient = ((dividend ushr 1) / divisor) shl 1
val rem = dividend - quotient * divisor
return ULong(quotient + if (ULong(rem) >= ULong(divisor)) 1 else 0)
} }
@PublishedApi internal fun WasmCharArray.createStringStartingFrom(index: Int): String {
internal fun ulongRemainder(v1: ULong, v2: ULong): ULong { if (index == 0) return createString()
val dividend = v1.toLong() val newLength = this.len() - index
val divisor = v2.toLong() if (newLength == 0) return ""
if (divisor < 0) { // i.e., divisor >= 2^63: val newChars = WasmCharArray(newLength)
return if (v1 < v2) { copyWasmArray(this, newChars, index, 0, newLength)
v1 // dividend < divisor return newChars.createString()
} 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)
}
@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 {
if (v >= 0) return v.toString(base)
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)
} }
private fun Int.getChar() = if (this < 10) '0' + this else 'a' + (this - 10)
+9 -1
View File
@@ -65,7 +65,15 @@ the Kotlin IntelliJ IDEA plugin:
- License: Apache 2 ([license/third_party/gwt_license.txt][gwt]) - License: Apache 2 ([license/third_party/gwt_license.txt][gwt])
- Origin: Derived from GWT, (C) 2007-08 Google Inc. - Origin: Derived from GWT, (C) 2007-08 Google Inc.
- Path: libraries/stdlib/unsigned/src/kotlin/UnsignedUtils.kt - Path: libraries/stdlib/js/src/kotlin/UnsignedJs.kt
- License: Apache 2 ([license/third_party/guava_license.txt][guava])
- Origin: Derived from Guava's UnsignedLongs, (C) 2011 The Guava Authors
- Path: libraries/stdlib/jvm/src/kotlin/util/UnsignedJVM.kt
- License: Apache 2 ([license/third_party/guava_license.txt][guava])
- Origin: Derived from Guava's UnsignedLongs, (C) 2011 The Guava Authors
- Path: kotlin-native/runtime/src/main/kotlin/kotlin/Unsigned.kt
- License: Apache 2 ([license/third_party/guava_license.txt][guava]) - License: Apache 2 ([license/third_party/guava_license.txt][guava])
- Origin: Derived from Guava's UnsignedLongs, (C) 2011 The Guava Authors - Origin: Derived from Guava's UnsignedLongs, (C) 2011 The Guava Authors