Specialize plus operator for UArrays (KT-28397)

This commit is contained in:
Abduqodiri Qurbonzoda
2019-01-23 00:15:39 +03:00
committed by Ilya Gorbunov
parent 8977d0e26d
commit 6cd9858147
5 changed files with 292 additions and 117 deletions
@@ -575,6 +575,134 @@ public inline fun UShortArray.copyOfRange(fromIndex: Int, toIndex: Int): UShortA
return UShortArray(storage.copyOfRange(fromIndex, toIndex)) return UShortArray(storage.copyOfRange(fromIndex, toIndex))
} }
/**
* Returns an array containing all elements of the original array and then the given [element].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline operator fun UIntArray.plus(element: UInt): UIntArray {
return UIntArray(storage + element.toInt())
}
/**
* Returns an array containing all elements of the original array and then the given [element].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline operator fun ULongArray.plus(element: ULong): ULongArray {
return ULongArray(storage + element.toLong())
}
/**
* Returns an array containing all elements of the original array and then the given [element].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline operator fun UByteArray.plus(element: UByte): UByteArray {
return UByteArray(storage + element.toByte())
}
/**
* Returns an array containing all elements of the original array and then the given [element].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline operator fun UShortArray.plus(element: UShort): UShortArray {
return UShortArray(storage + element.toShort())
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public operator fun UIntArray.plus(elements: Collection<UInt>): UIntArray {
var index = size
val result = storage.copyOf(size + elements.size)
for (element in elements) result[index++] = element.toInt()
return UIntArray(result)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public operator fun ULongArray.plus(elements: Collection<ULong>): ULongArray {
var index = size
val result = storage.copyOf(size + elements.size)
for (element in elements) result[index++] = element.toLong()
return ULongArray(result)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public operator fun UByteArray.plus(elements: Collection<UByte>): UByteArray {
var index = size
val result = storage.copyOf(size + elements.size)
for (element in elements) result[index++] = element.toByte()
return UByteArray(result)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public operator fun UShortArray.plus(elements: Collection<UShort>): UShortArray {
var index = size
val result = storage.copyOf(size + elements.size)
for (element in elements) result[index++] = element.toShort()
return UShortArray(result)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] array.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline operator fun UIntArray.plus(elements: UIntArray): UIntArray {
return UIntArray(storage + elements.storage)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] array.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline operator fun ULongArray.plus(elements: ULongArray): ULongArray {
return ULongArray(storage + elements.storage)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] array.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline operator fun UByteArray.plus(elements: UByteArray): UByteArray {
return UByteArray(storage + elements.storage)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] array.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
@kotlin.internal.InlineOnly
public inline operator fun UShortArray.plus(elements: UShortArray): UShortArray {
return UShortArray(storage + elements.storage)
}
/** /**
* Returns an array of type [ByteArray], which is a copy of this array where each element is a signed reinterpretation * Returns an array of type [ByteArray], which is a copy of this array where each element is a signed reinterpretation
* of the corresponding element of this array. * of the corresponding element of this array.
@@ -9,6 +9,9 @@ package test.collections
import test.collections.behaviors.collectionBehavior import test.collections.behaviors.collectionBehavior
import kotlin.test.* import kotlin.test.*
fun assertArrayContentEquals(expected: UIntArray, actual: UIntArray, message: String = "") { assertTrue(expected contentEquals actual, message) }
class UnsignedArraysTest { class UnsignedArraysTest {
@Test @Test
@@ -228,4 +231,11 @@ class UnsignedArraysTest {
} }
} }
@Test
fun plus() {
assertArrayContentEquals(uintArrayOf(1u, 2u, 3u), uintArrayOf(1u, 2u) + 3u)
assertArrayContentEquals(uintArrayOf(1u, 2u, 3u, 4u), uintArrayOf(1u, 2u) + listOf(3u, 4u))
assertArrayContentEquals(uintArrayOf(1u, 2u, 3u, 4u), uintArrayOf(1u, 2u) + uintArrayOf(3u, 4u))
}
} }
@@ -2299,6 +2299,10 @@ public final class kotlin/collections/UArraysKt {
public static final fun contentToString-GBYM_sE ([B)Ljava/lang/String; public static final fun contentToString-GBYM_sE ([B)Ljava/lang/String;
public static final fun contentToString-QwZRm1k ([J)Ljava/lang/String; public static final fun contentToString-QwZRm1k ([J)Ljava/lang/String;
public static final fun contentToString-rL5Bavg ([S)Ljava/lang/String; public static final fun contentToString-rL5Bavg ([S)Ljava/lang/String;
public static final fun plus-CFIt9YE ([ILjava/util/Collection;)[I
public static final fun plus-kzHmqpY ([JLjava/util/Collection;)[J
public static final fun plus-ojwP5H8 ([SLjava/util/Collection;)[S
public static final fun plus-xo_DsdI ([BLjava/util/Collection;)[B
public static final fun random-2D5oskM ([ILkotlin/random/Random;)I public static final fun random-2D5oskM ([ILkotlin/random/Random;)I
public static final fun random-JzugnMA ([JLkotlin/random/Random;)J public static final fun random-JzugnMA ([JLkotlin/random/Random;)J
public static final fun random-oSF2wD8 ([BLkotlin/random/Random;)B public static final fun random-oSF2wD8 ([BLkotlin/random/Random;)B
@@ -454,171 +454,204 @@ object ArrayOps : TemplateGroupBase() {
} }
val f_plus = fn("plus(element: T)") { val f_plus = fn("plus(element: T)") {
include(InvariantArraysOfObjects, ArraysOfPrimitives) include(InvariantArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned)
} builderWith { primitive -> } builderWith { primitive ->
doc { "Returns an array containing all elements of the original array and then the given [element]." } doc { "Returns an array containing all elements of the original array and then the given [element]." }
operator() operator()
returns("SELF") returns("SELF")
on(Platform.JVM) { specialFor(ArraysOfUnsigned) {
inlineOnly()
val signedPrimitiveName = primitive!!.name.drop(1)
body { body {
""" """
val index = size return SELF(storage + element.to$signedPrimitiveName())
val result = java.util.Arrays.copyOf(this, index + 1)
result[index] = element
return result
""" """
} }
} }
on(Platform.JS) { specialFor(InvariantArraysOfObjects, ArraysOfPrimitives) {
inline(suppressWarning = true) on(Platform.JVM) {
specialFor(InvariantArraysOfObjects) { body {
family = ArraysOfObjects """
suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937 val index = size
returns("Array<T>") val result = java.util.Arrays.copyOf(this, index + 1)
result[index] = element
return result
"""
}
} }
body { on(Platform.JS) {
if (primitive == null) inline(suppressWarning = true)
"return this.asDynamic().concat(arrayOf(element))" specialFor(InvariantArraysOfObjects) {
else family = ArraysOfObjects
"return plus(${primitive.name.toLowerCase()}ArrayOf(element))" suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937
returns("Array<T>")
}
body {
if (primitive == null)
"return this.asDynamic().concat(arrayOf(element))"
else
"return plus(${primitive.name.toLowerCase()}ArrayOf(element))"
}
} }
} on(Platform.Native) {
on(Platform.Native) { body {
body { """
""" val index = size
val index = size val result = copyOfUninitializedElements(index + 1)
val result = copyOfUninitializedElements(index + 1) result[index] = element
result[index] = element return result
return result """
""" }
} }
} on(Platform.Common) {
on(Platform.Common) { specialFor(InvariantArraysOfObjects) {
specialFor(InvariantArraysOfObjects) { suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937
suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 }
} }
} }
} }
val f_plus_collection = fn("plus(elements: Collection<T>)") { val f_plus_collection = fn("plus(elements: Collection<T>)") {
include(InvariantArraysOfObjects, ArraysOfPrimitives) include(InvariantArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned)
} builder { } builder {
operator() operator()
returns("SELF") returns("SELF")
doc { "Returns an array containing all elements of the original array and then all elements of the given [elements] collection." } doc { "Returns an array containing all elements of the original array and then all elements of the given [elements] collection." }
on(Platform.JVM) {
specialFor(ArraysOfUnsigned) {
val signedPrimitiveName = primitive!!.name.drop(1)
body { body {
""" """
var index = size var index = size
val result = java.util.Arrays.copyOf(this, index + elements.size) val result = storage.copyOf(size + elements.size)
for (element in elements) result[index++] = element for (element in elements) result[index++] = element.to$signedPrimitiveName()
return result return SELF(result)
""" """
} }
} }
on(Platform.JS) { specialFor(InvariantArraysOfObjects, ArraysOfPrimitives) {
// TODO: inline arrayPlusCollection when @PublishedAPI is available on(Platform.JVM) {
// inline(Platform.JS, Inline.Yes) body {
// annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""") """
specialFor(InvariantArraysOfObjects) { var index = size
family = ArraysOfObjects val result = java.util.Arrays.copyOf(this, index + elements.size)
suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937 for (element in elements) result[index++] = element
returns("Array<T>") return result
"""
}
} }
when (primitive) { on(Platform.JS) {
null, PrimitiveType.Boolean, PrimitiveType.Long -> // TODO: inline arrayPlusCollection when @PublishedAPI is available
body { "return arrayPlusCollection(this, elements)" } // inline(Platform.JS, Inline.Yes)
else -> { // annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""")
on(Backend.Legacy) { specialFor(InvariantArraysOfObjects) {
body { family = ArraysOfObjects
"return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)" suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937
returns("Array<T>")
}
when (primitive) {
null, PrimitiveType.Boolean, PrimitiveType.Long ->
body { "return arrayPlusCollection(this, elements)" }
else -> {
on(Backend.Legacy) {
body {
"return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)"
}
} }
} on(Backend.IR) {
on(Backend.IR) { // Don't use fillFromCollection because it treats arrays
// Don't use fillFromCollection because it treats arrays // as `dynamic` but we need to concrete types to perform
// as `dynamic` but we need to concrete types to perform // unboxing of collections elements
// unboxing of collections elements body {
body { """
""" var index = size
var index = size val result = this.copyOf(size + elements.size)
val result = this.copyOf(size + elements.size) for (element in elements) result[index++] = element
for (element in elements) result[index++] = element return result
return result """
""" }
} }
} }
} }
} }
} on(Platform.Native) {
on(Platform.Native) { body {
body { """
""" var index = size
var index = size val result = copyOfUninitializedElements(index + elements.size)
val result = copyOfUninitializedElements(index + elements.size) for (element in elements) result[index++] = element
for (element in elements) result[index++] = element return result
return result """
""" }
} }
} on(Platform.Common) {
on(Platform.Common) { specialFor(InvariantArraysOfObjects) {
specialFor(InvariantArraysOfObjects) { suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937
suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 }
} }
} }
} }
val f_plus_array = fn("plus(elements: SELF)") { val f_plus_array = fn("plus(elements: SELF)") {
include(InvariantArraysOfObjects, ArraysOfPrimitives) include(InvariantArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned)
} builder { } builder {
operator(true) operator(true)
doc { "Returns an array containing all elements of the original array and then all elements of the given [elements] array." } doc { "Returns an array containing all elements of the original array and then all elements of the given [elements] array." }
returns("SELF") returns("SELF")
specialFor(InvariantArraysOfObjects) {
signature("plus(elements: Array<out T>)", notForSorting = true)
}
on(Platform.JVM) { specialFor(ArraysOfUnsigned) {
body { inlineOnly()
""" body { "return SELF(storage + elements.storage)" }
val thisSize = size }
val arraySize = elements.size specialFor(InvariantArraysOfObjects, ArraysOfPrimitives) {
val result = java.util.Arrays.copyOf(this, thisSize + arraySize) specialFor(InvariantArraysOfObjects) {
System.arraycopy(elements, 0, result, thisSize, arraySize) signature("plus(elements: Array<out T>)", notForSorting = true)
return result
"""
} }
} on(Platform.JVM) {
on(Platform.JS) { body {
inline(suppressWarning = true) """
specialFor(InvariantArraysOfObjects) { val thisSize = size
family = ArraysOfObjects val arraySize = elements.size
suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937 val result = java.util.Arrays.copyOf(this, thisSize + arraySize)
returns("Array<T>") System.arraycopy(elements, 0, result, thisSize, arraySize)
body { """return this.asDynamic().concat(elements)""" } return result
"""
}
} }
specialFor(ArraysOfPrimitives) { on(Platform.JS) {
body { """return primitiveArrayConcat(this, elements)""" } inline(suppressWarning = true)
specialFor(InvariantArraysOfObjects) {
family = ArraysOfObjects
suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937
returns("Array<T>")
body { """return this.asDynamic().concat(elements)""" }
}
specialFor(ArraysOfPrimitives) {
body { """return primitiveArrayConcat(this, elements)""" }
}
} }
} on(Platform.Native) {
on(Platform.Native) { body {
body { """
""" val thisSize = size
val thisSize = size val arraySize = elements.size
val arraySize = elements.size val result = copyOfUninitializedElements(thisSize + arraySize)
val result = copyOfUninitializedElements(thisSize + arraySize) elements.copyInto(result, thisSize)
elements.copyInto(result, thisSize) return result
return result """
""" }
} }
} on(Platform.Common) {
on(Platform.Common) { specialFor(InvariantArraysOfObjects) {
specialFor(InvariantArraysOfObjects) { suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937
suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 }
} }
} }
} }