From 4fc54a12b8fc63e34973fa68565e5d13e7fa98ab Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 30 Oct 2015 18:30:25 +0300 Subject: [PATCH] In-place reversing. #KT-9034 --- .../src/core/javautilCollections.kt | 1 + libraries/stdlib/src/generated/_Arrays.kt | 136 ++++++++++++++++++ .../stdlib/src/generated/_Collections.kt | 7 + .../stdlib/test/collections/ArraysTest.kt | 11 ++ .../stdlib/test/collections/CollectionTest.kt | 33 +++-- .../kotlin-stdlib-gen/src/templates/Engine.kt | 5 +- .../src/templates/Ordering.kt | 34 +++-- 7 files changed, 200 insertions(+), 27 deletions(-) diff --git a/js/js.libraries/src/core/javautilCollections.kt b/js/js.libraries/src/core/javautilCollections.kt index 16b25408148..dcd7744840f 100644 --- a/js/js.libraries/src/core/javautilCollections.kt +++ b/js/js.libraries/src/core/javautilCollections.kt @@ -10,6 +10,7 @@ public object Collections { public fun sort(list: MutableList, comparator: java.util.Comparator): Unit = java.util.sort(list, comparator) + @Deprecated("Use list.reverse() instead.", ReplaceWith("list.reverse()")) public fun reverse(list: MutableList): Unit { val size = list.size() for (i in 0..(size / 2) - 1) { diff --git a/libraries/stdlib/src/generated/_Arrays.kt b/libraries/stdlib/src/generated/_Arrays.kt index d65f420b9be..809fb2dc46b 100644 --- a/libraries/stdlib/src/generated/_Arrays.kt +++ b/libraries/stdlib/src/generated/_Arrays.kt @@ -4143,6 +4143,142 @@ public inline fun ShortArray.takeWhile(predicate: (Short) -> Boolean): List Array.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + val _this = this as Array + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = _this[index] + _this[index] = _this[reverseIndex] + _this[reverseIndex] = tmp + reverseIndex-- + } +} + +/** + * Reverses elements in the array in-place. + */ +public fun BooleanArray.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + +/** + * Reverses elements in the array in-place. + */ +public fun ByteArray.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + +/** + * Reverses elements in the array in-place. + */ +public fun CharArray.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + +/** + * Reverses elements in the array in-place. + */ +public fun DoubleArray.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + +/** + * Reverses elements in the array in-place. + */ +public fun FloatArray.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + +/** + * Reverses elements in the array in-place. + */ +public fun IntArray.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + +/** + * Reverses elements in the array in-place. + */ +public fun LongArray.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + +/** + * Reverses elements in the array in-place. + */ +public fun ShortArray.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + /** * Returns a list with elements in reversed order. */ diff --git a/libraries/stdlib/src/generated/_Collections.kt b/libraries/stdlib/src/generated/_Collections.kt index d1ede1bd80a..ecb3d069433 100644 --- a/libraries/stdlib/src/generated/_Collections.kt +++ b/libraries/stdlib/src/generated/_Collections.kt @@ -789,6 +789,13 @@ public inline fun Iterable.takeWhile(predicate: (T) -> Boolean): List return list } +/** + * Reverses elements in the collection in-place. + */ +public fun MutableList.reverse(): Unit { + java.util.Collections.reverse(this) +} + /** * Returns a list with elements in reversed order. */ diff --git a/libraries/stdlib/test/collections/ArraysTest.kt b/libraries/stdlib/test/collections/ArraysTest.kt index f99906a89b3..031f4e2e9ba 100644 --- a/libraries/stdlib/test/collections/ArraysTest.kt +++ b/libraries/stdlib/test/collections/ArraysTest.kt @@ -546,6 +546,17 @@ class ArraysTest { } is UnsupportedOperationException) } + @test fun reverseInPlace() { + assertArrayNotSameButEquals(intArrayOf(3, 2, 1), intArrayOf(1, 2, 3).apply { reverse() }) + assertArrayNotSameButEquals(byteArrayOf(3, 2, 1), byteArrayOf(1, 2, 3).apply { reverse() }) + assertArrayNotSameButEquals(shortArrayOf(3, 2, 1), shortArrayOf(1, 2, 3).apply { reverse() }) + assertArrayNotSameButEquals(longArrayOf(3, 2, 1), longArrayOf(1, 2, 3).apply { reverse() }) + assertArrayNotSameButEquals(floatArrayOf(3F, 2F, 1F), floatArrayOf(1F, 2F, 3F).apply { reverse() }) + assertArrayNotSameButEquals(doubleArrayOf(3.0, 2.0, 1.0), doubleArrayOf(1.0, 2.0, 3.0).apply { reverse() }) + assertArrayNotSameButEquals(charArrayOf('3', '2', '1'), charArrayOf('1', '2', '3').apply { reverse() }) + assertArrayNotSameButEquals(booleanArrayOf(false, false, true), booleanArrayOf(true, false, false).apply { reverse() }) + } + @test fun reversed() { expect(listOf(3, 2, 1)) { intArrayOf(1, 2, 3).reversed() } expect(listOf(3, 2, 1)) { byteArrayOf(1, 2, 3).reversed() } diff --git a/libraries/stdlib/test/collections/CollectionTest.kt b/libraries/stdlib/test/collections/CollectionTest.kt index 5b3c9998728..ae91bcdfbfb 100644 --- a/libraries/stdlib/test/collections/CollectionTest.kt +++ b/libraries/stdlib/test/collections/CollectionTest.kt @@ -310,22 +310,29 @@ class CollectionTest { } } - @test fun reverse() { + @test fun reverseInPlace() { + val data = arrayListOf() + data.reverse() + assertTrue(data.isEmpty()) + + data.add("foo") + data.reverse() + assertEquals(listOf("foo"), data) + + data.add("bar") + data.reverse() + assertEquals(listOf("bar", "foo"), data) + + data.add("zoo") + data.reverse() + assertEquals(listOf("zoo", "foo", "bar"), data) + } + + @test fun reversed() { val data = listOf("foo", "bar") val rev = data.reversed() assertEquals(listOf("bar", "foo"), rev) - } - - @test fun reverseFunctionShouldReturnReversedCopyForList() { - val list: List = listOf(2, 3, 1) - expect(listOf(1, 3, 2)) { list.reversed() } - expect(listOf(2, 3, 1)) { list } - } - - @test fun reverseFunctionShouldReturnReversedCopyForIterable() { - val iterable: Iterable = listOf(2, 3, 1) - expect(listOf(1, 3, 2)) { iterable.reversed() } - expect(listOf(2, 3, 1)) { iterable } + assertNotEquals(data, rev) } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt index c3c3ab2f7ed..8a84c7a237c 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt @@ -106,6 +106,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { val buildPrimitives = LinkedHashSet(defaultPrimitives) val buildFamilyPrimitives = FamilyProperty>() + val customReceiver = FamilyProperty() val customSignature = FamilyProperty() val deprecate = DeprecationProperty() val doc = FamilyProperty() @@ -293,7 +294,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { } val isAsteriskOrT = if (receiverAsterisk[f] == true) "*" else "T" - val receiver = when (f) { + val receiver = (customReceiver[f] ?: when (f) { Iterables -> "Iterable<$isAsteriskOrT>" Collections -> "Collection<$isAsteriskOrT>" Lists -> "List<$isAsteriskOrT>" @@ -310,7 +311,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { ProgressionsOfPrimitives -> primitive?.let { it.name + "Progression" } ?: throw IllegalArgumentException("Primitive progression should specify primitive type") Primitives -> primitive?.let { it.name } ?: throw IllegalArgumentException("Primitive should specify primitive type") Generic -> "T" - }.let { renderType(it, it) } + }).let { renderType(it, it) } fun String.renderType(): String = renderType(this, receiver) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Ordering.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Ordering.kt index 2fb41c324e1..490d96e58fd 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Ordering.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Ordering.kt @@ -6,18 +6,28 @@ import templates.DocExtensions.collection fun ordering(): List { val templates = arrayListOf() -// templates add f("reverse()") { -// deprecate("reverse will change its behavior soon. Use reversed() instead.") -// deprecateReplacement("reversed()") -// doc { "Returns a list with elements in reversed order." } -// returns { "List" } -// body { """return reversed()""" } -// -// include(Strings) -// returns(Strings) { "SELF" } -// -// exclude(Sequences) -// } + templates add f("reverse()") { + doc { f -> "Reverses elements in the ${f.collection} in-place." } + only(Lists, ArraysOfObjects, ArraysOfPrimitives) + customReceiver(Lists) { "MutableList" } + returns { "Unit" } + body { f -> + val _this = if (f == ArraysOfObjects) "_this" else "this" + """ + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + ${if (f == ArraysOfObjects) "val _this = this as Array" else "" } + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = $_this[index] + $_this[index] = $_this[reverseIndex] + $_this[reverseIndex] = tmp + reverseIndex-- + } + """ + } + body(Lists) { """java.util.Collections.reverse(this)""" } + } templates add f("reversed()") { doc { "Returns a list with elements in reversed order." }