From 97c688057dac1d6f40caa2dec13a8ce10092bd83 Mon Sep 17 00:00:00 2001 From: Abduqodiri Qurbonzoda Date: Fri, 27 Mar 2020 06:09:12 +0300 Subject: [PATCH] Compare floating point values asList elements in total order #KT-28753 --- .../stdlib/jvm/src/generated/_ArraysJvm.kt | 12 ++++---- .../stdlib/test/collections/ArraysTest.kt | 20 +++++++++++++ .../kotlin-stdlib-gen/src/templates/Arrays.kt | 30 ++++++++++++------- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/libraries/stdlib/jvm/src/generated/_ArraysJvm.kt b/libraries/stdlib/jvm/src/generated/_ArraysJvm.kt index f2c60bc2486..37ea03415f0 100644 --- a/libraries/stdlib/jvm/src/generated/_ArraysJvm.kt +++ b/libraries/stdlib/jvm/src/generated/_ArraysJvm.kt @@ -192,10 +192,10 @@ public actual fun FloatArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() - override fun contains(element: Float): Boolean = this@asList.contains(element) + override fun contains(element: Float): Boolean = this@asList.any { it.toBits() == element.toBits() } override fun get(index: Int): Float = this@asList[index] - override fun indexOf(element: Float): Int = this@asList.indexOf(element) - override fun lastIndexOf(element: Float): Int = this@asList.lastIndexOf(element) + override fun indexOf(element: Float): Int = this@asList.indexOfFirst { it.toBits() == element.toBits() } + override fun lastIndexOf(element: Float): Int = this@asList.indexOfLast { it.toBits() == element.toBits() } } } @@ -206,10 +206,10 @@ public actual fun DoubleArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() - override fun contains(element: Double): Boolean = this@asList.contains(element) + override fun contains(element: Double): Boolean = this@asList.any { it.toBits() == element.toBits() } override fun get(index: Int): Double = this@asList[index] - override fun indexOf(element: Double): Int = this@asList.indexOf(element) - override fun lastIndexOf(element: Double): Int = this@asList.lastIndexOf(element) + override fun indexOf(element: Double): Int = this@asList.indexOfFirst { it.toBits() == element.toBits() } + override fun lastIndexOf(element: Double): Int = this@asList.indexOfLast { it.toBits() == element.toBits() } } } diff --git a/libraries/stdlib/test/collections/ArraysTest.kt b/libraries/stdlib/test/collections/ArraysTest.kt index 0e0b5d6bb68..ff6b4aca7da 100644 --- a/libraries/stdlib/test/collections/ArraysTest.kt +++ b/libraries/stdlib/test/collections/ArraysTest.kt @@ -824,6 +824,26 @@ class ArraysTest { assertEquals(10, intsAsList[1], "Should reflect changes in original array") } + @Test fun asListInFloatingPrimitiveArrays() { + fun testTotalOrder(expected: List, actual: List, element: T) = compare(expected, actual) { + propertyEquals { contains(element) } + propertyEquals { indexOf(element) } + propertyEquals { lastIndexOf(element) } + } + + testTotalOrder(listOf(Float.NaN), floatArrayOf(Float.NaN).asList(), Float.NaN) + testTotalOrder(listOf(-0.0f), floatArrayOf(-0.0f).asList(), -0.0f) + testTotalOrder(listOf(-0.0f), floatArrayOf(-0.0f).asList(), 0.0f) + testTotalOrder(listOf(0.0f), floatArrayOf(0.0f).asList(), 0.0f) + testTotalOrder(listOf(0.0f), floatArrayOf(0.0f).asList(), -0.0f) + + testTotalOrder(listOf(Double.NaN), doubleArrayOf(Double.NaN).asList(), Double.NaN) + testTotalOrder(listOf(-0.0), doubleArrayOf(-0.0).asList(), -0.0) + testTotalOrder(listOf(-0.0), doubleArrayOf(-0.0).asList(), 0.0) + testTotalOrder(listOf(0.0), doubleArrayOf(0.0).asList(), 0.0) + testTotalOrder(listOf(0.0), doubleArrayOf(0.0).asList(), -0.0) + } + @Test fun toPrimitiveArray() { val genericArray: Array = arrayOf(1, 2, 3) val primitiveArray: IntArray = genericArray.toIntArray() diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index 3a313b4e80a..d380fb01eea 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -1467,16 +1467,26 @@ object ArrayOps : TemplateGroupBase() { body { """return ArrayList(this.unsafeCast>())""" } } - val objectLiteralImpl = """ - return object : AbstractList(), RandomAccess { - override val size: Int get() = this@asList.size - override fun isEmpty(): Boolean = this@asList.isEmpty() - override fun contains(element: T): Boolean = this@asList.contains(element) - override fun get(index: Int): T = this@asList[index] - override fun indexOf(element: T): Int = this@asList.indexOf(element) - override fun lastIndexOf(element: T): Int = this@asList.lastIndexOf(element) - } - """ + val objectLiteralImpl = if (primitive in PrimitiveType.floatingPointPrimitives) """ + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: T): Boolean = this@asList.any { it.toBits() == element.toBits() } + override fun get(index: Int): T = this@asList[index] + override fun indexOf(element: T): Int = this@asList.indexOfFirst { it.toBits() == element.toBits() } + override fun lastIndexOf(element: T): Int = this@asList.indexOfLast { it.toBits() == element.toBits() } + } + """ + else """ + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: T): Boolean = this@asList.contains(element) + override fun get(index: Int): T = this@asList[index] + override fun indexOf(element: T): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: T): Int = this@asList.lastIndexOf(element) + } + """ specialFor(ArraysOfPrimitives, ArraysOfUnsigned) { on(Platform.JVM) { body { objectLiteralImpl }