Specialize plus operator for UArrays (KT-28397)
This commit is contained in:
committed by
Ilya Gorbunov
parent
8977d0e26d
commit
6cd9858147
@@ -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))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+4
@@ -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
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user