From 7695b5e575256c313c31dd7dbf25a893d7cf561b Mon Sep 17 00:00:00 2001 From: Abduqodiri Qurbonzoda Date: Tue, 22 Jan 2019 21:19:38 +0300 Subject: [PATCH] Implement sum extension function for UArrays (KT-28779) --- .../kotlin/js/test/JsIrTestRuntime.kt | 1 + .../stdlib/common/src/generated/_UArrays.kt | 96 +++++++++++++++++++ .../common/src/generated/_UCollections.kt | 56 +++++++++++ .../common/src/generated/_USequences.kt | 81 ++++++++++++++++ .../test/collections/UnsignedArraysTest.kt | 16 ++++ .../kotlin-stdlib-runtime-merged.txt | 15 +++ .../kotlin-stdlib-gen/src/templates/Arrays.kt | 2 +- .../src/templates/Numeric.kt | 54 +++++++++-- .../src/templates/dsl/CommonTypes.kt | 16 ++++ .../src/templates/dsl/MemberBuilder.kt | 15 +-- .../src/templates/dsl/SourceFile.kt | 1 + 11 files changed, 330 insertions(+), 23 deletions(-) create mode 100644 libraries/stdlib/common/src/generated/_USequences.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/JsIrTestRuntime.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/JsIrTestRuntime.kt index 41b58480ad4..d3e32c1df71 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/JsIrTestRuntime.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/JsIrTestRuntime.kt @@ -128,6 +128,7 @@ val reducedRuntimeSources = fullRuntimeSources - listOfKtFilesFrom( "libraries/stdlib/common/src/generated/_UArrays.kt", "libraries/stdlib/common/src/generated/_URanges.kt", "libraries/stdlib/common/src/generated/_UCollections.kt", + "libraries/stdlib/common/src/generated/_USequences.kt", "libraries/stdlib/common/src/kotlin/SequencesH.kt", "libraries/stdlib/common/src/kotlin/TextH.kt", "libraries/stdlib/common/src/kotlin/collections/", diff --git a/libraries/stdlib/common/src/generated/_UArrays.kt b/libraries/stdlib/common/src/generated/_UArrays.kt index 25172ca80f9..04967534502 100644 --- a/libraries/stdlib/common/src/generated/_UArrays.kt +++ b/libraries/stdlib/common/src/generated/_UArrays.kt @@ -3735,3 +3735,99 @@ public inline fun UShortArray.sumByDouble(selector: (UShort) -> Double): Double return sum } +/** + * Returns the sum of all elements in the array. + */ +@kotlin.jvm.JvmName("sumOfUInt") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Array.sum(): UInt { + var sum: UInt = 0u + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the array. + */ +@kotlin.jvm.JvmName("sumOfULong") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Array.sum(): ULong { + var sum: ULong = 0uL + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the array. + */ +@kotlin.jvm.JvmName("sumOfUByte") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Array.sum(): UInt { + var sum: UInt = 0u + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the array. + */ +@kotlin.jvm.JvmName("sumOfUShort") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Array.sum(): UInt { + var sum: UInt = 0u + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UIntArray.sum(): UInt { + return storage.sum().toUInt() +} + +/** + * Returns the sum of all elements in the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun ULongArray.sum(): ULong { + return storage.sum().toULong() +} + +/** + * Returns the sum of all elements in the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UByteArray.sum(): UInt { + return sumBy { it.toUInt() } +} + +/** + * Returns the sum of all elements in the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UShortArray.sum(): UInt { + return sumBy { it.toUInt() } +} + diff --git a/libraries/stdlib/common/src/generated/_UCollections.kt b/libraries/stdlib/common/src/generated/_UCollections.kt index 04fe1df8587..860cf7ddec0 100644 --- a/libraries/stdlib/common/src/generated/_UCollections.kt +++ b/libraries/stdlib/common/src/generated/_UCollections.kt @@ -67,3 +67,59 @@ public fun Collection.toUShortArray(): UShortArray { return result } +/** + * Returns the sum of all elements in the collection. + */ +@kotlin.jvm.JvmName("sumOfUInt") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Iterable.sum(): UInt { + var sum: UInt = 0u + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the collection. + */ +@kotlin.jvm.JvmName("sumOfULong") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Iterable.sum(): ULong { + var sum: ULong = 0uL + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the collection. + */ +@kotlin.jvm.JvmName("sumOfUByte") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Iterable.sum(): UInt { + var sum: UInt = 0u + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the collection. + */ +@kotlin.jvm.JvmName("sumOfUShort") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Iterable.sum(): UInt { + var sum: UInt = 0u + for (element in this) { + sum += element + } + return sum +} + diff --git a/libraries/stdlib/common/src/generated/_USequences.kt b/libraries/stdlib/common/src/generated/_USequences.kt new file mode 100644 index 00000000000..f83e13c93f4 --- /dev/null +++ b/libraries/stdlib/common/src/generated/_USequences.kt @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.JvmMultifileClass +@file:kotlin.jvm.JvmName("USequencesKt") + +package kotlin.sequences + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import kotlin.random.* + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfUInt") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Sequence.sum(): UInt { + var sum: UInt = 0u + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfULong") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Sequence.sum(): ULong { + var sum: ULong = 0uL + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfUByte") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Sequence.sum(): UInt { + var sum: UInt = 0u + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfUShort") +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Sequence.sum(): UInt { + var sum: UInt = 0u + for (element in this) { + sum += element + } + return sum +} + diff --git a/libraries/stdlib/test/collections/UnsignedArraysTest.kt b/libraries/stdlib/test/collections/UnsignedArraysTest.kt index 1b7cc8af9d6..e4505619306 100644 --- a/libraries/stdlib/test/collections/UnsignedArraysTest.kt +++ b/libraries/stdlib/test/collections/UnsignedArraysTest.kt @@ -568,4 +568,20 @@ class UnsignedArraysTest { val a = ubyteArrayOf(3, 2, 1) a.forEachIndexed { index, e -> assertEquals(e, a[index]) } } + + @Test + fun sum() { + expect(14u) { arrayOf(2u, 3u, 9u).asSequence().sum() } + expect(400u) { arrayOf(200u, 200u).asList().sum() } + expect(50000u) { arrayOf(20000u, 30000u).asIterable().sum() } + expect(12_000_000_000_000_000_000uL) { arrayOf(10_000_000_000_000_000_000uL, 2_000_000_000_000_000_000uL).sum() } + } + + @Test + fun sumInUnsignedArrays() { + expect(14u) { uintArrayOf(2u, 3u, 9u).sum() } + expect(400u) { ubyteArrayOf(200u, 200u).sum() } + expect(50000u) { ushortArrayOf(20000u, 30000u).sum() } + expect(12_000_000_000_000_000_000uL) { ulongArrayOf(10_000_000_000_000_000_000uL, 2_000_000_000_000_000_000uL).sum() } + } } \ No newline at end of file diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index 919d16d31ce..091d75a2319 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -2387,6 +2387,10 @@ public final class kotlin/collections/UArraysKt { public static final fun sliceArray-ojwP5H8 ([SLjava/util/Collection;)[S public static final fun sliceArray-tAntMlw ([ILkotlin/ranges/IntRange;)[I public static final fun sliceArray-xo_DsdI ([BLjava/util/Collection;)[B + public static final fun sumOfUByte ([Lkotlin/UByte;)I + public static final fun sumOfUInt ([Lkotlin/UInt;)I + public static final fun sumOfULong ([Lkotlin/ULong;)J + public static final fun sumOfUShort ([Lkotlin/UShort;)I public static final fun toTypedArray--ajY-9A ([I)[Lkotlin/UInt; public static final fun toTypedArray-GBYM_sE ([B)[Lkotlin/UByte; public static final fun toTypedArray-QwZRm1k ([J)[Lkotlin/ULong; @@ -2406,6 +2410,10 @@ public abstract class kotlin/collections/UByteIterator : java/util/Iterator, kot } public final class kotlin/collections/UCollectionsKt { + public static final fun sumOfUByte (Ljava/lang/Iterable;)I + public static final fun sumOfUInt (Ljava/lang/Iterable;)I + public static final fun sumOfULong (Ljava/lang/Iterable;)J + public static final fun sumOfUShort (Ljava/lang/Iterable;)I public static final fun toUByteArray (Ljava/util/Collection;)[B public static final fun toUIntArray (Ljava/util/Collection;)[I public static final fun toULongArray (Ljava/util/Collection;)[J @@ -4566,6 +4574,13 @@ public final class kotlin/sequences/SequencesKt { public static final fun zipWithNext (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence; } +public final class kotlin/sequences/USequencesKt { + public static final fun sumOfUByte (Lkotlin/sequences/Sequence;)I + public static final fun sumOfUInt (Lkotlin/sequences/Sequence;)I + public static final fun sumOfULong (Lkotlin/sequences/Sequence;)J + public static final fun sumOfUShort (Lkotlin/sequences/Sequence;)I +} + public final class kotlin/system/TimingKt { public static final fun measureNanoTime (Lkotlin/jvm/functions/Function0;)J public static final fun measureTimeMillis (Lkotlin/jvm/functions/Function0;)J diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index ffda824e4bb..4b5fb670a1a 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -968,7 +968,7 @@ object ArrayOps : TemplateGroupBase() { PrimitiveType.Char -> body { "return withType(\"CharArray\", fillFrom(this, ${primitive}Array(newSize)))" } PrimitiveType.Long -> - body { "return withType(\"LongArray\", arrayCopyResize(this, newSize, ZERO))" } + body { "return withType(\"LongArray\", arrayCopyResize(this, newSize, ${primitive!!.zero()}))" } else -> body { "return fillFrom(this, ${primitive}Array(newSize))" } } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Numeric.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Numeric.kt index a22e04d11c7..f4d691c5956 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Numeric.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Numeric.kt @@ -5,31 +5,65 @@ package templates +import templates.Family.* + object Numeric : TemplateGroupBase() { init { defaultBuilder { sequenceClassification(SequenceClass.terminal) + specialFor(ArraysOfUnsigned) { + since("1.3") + annotation("@ExperimentalUnsignedTypes") + } } } private val numericPrimitivesDefaultOrder = PrimitiveType.defaultPrimitives intersect PrimitiveType.numericPrimitives + private val summablePrimitives = numericPrimitivesDefaultOrder + PrimitiveType.unsignedPrimitives val f_sum = fn("sum()") { - Family.defaultFamilies.forEach { family -> include(family, numericPrimitivesDefaultOrder) } + listOf(Iterables, Sequences, ArraysOfObjects).forEach { include(it, summablePrimitives) } + include(ArraysOfPrimitives, numericPrimitivesDefaultOrder) + include(ArraysOfUnsigned) } builder { + val p = primitive!! doc { "Returns the sum of all elements in the ${f.collection}." } - returns("SUM") - platformName("sumOf") - body { - """ - var sum: SUM = ZERO - for (element in this) { - sum += element + returns(p.sumType().name) + + specialFor(ArraysOfUnsigned) { + inlineOnly() + + body { + if (p == p.sumType()) + "return storage.sum().to${p.sumType().name}()" + else + "return sumBy { it.to${p.sumType().name}() }" + } + } + specialFor(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives) { + platformName("sumOf") + + if (p.isUnsigned()) { + require(f != ArraysOfPrimitives) { "Arrays of unsigneds are separate from arrays of primitives." } + specialFor(Iterables) { sourceFile(SourceFile.UCollections) } + specialFor(Sequences) { sourceFile(SourceFile.USequences) } + specialFor(ArraysOfObjects) { sourceFile(SourceFile.UArrays) } + + since("1.3") + annotation("@ExperimentalUnsignedTypes") + } + + body { + """ + var sum: ${p.sumType().name} = ${p.sumType().zero()} + for (element in this) { + sum += element + } + return sum + """ } - return sum - """ } } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/CommonTypes.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/CommonTypes.kt index c535305607e..7351f52e7f2 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/CommonTypes.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/CommonTypes.kt @@ -75,6 +75,22 @@ enum class PrimitiveType { fun PrimitiveType.isIntegral(): Boolean = this in PrimitiveType.integralPrimitives fun PrimitiveType.isNumeric(): Boolean = this in PrimitiveType.numericPrimitives fun PrimitiveType.isFloatingPoint(): Boolean = this in PrimitiveType.floatingPointPrimitives +fun PrimitiveType.isUnsigned(): Boolean = this in PrimitiveType.unsignedPrimitives + +fun PrimitiveType.sumType() = when (this) { + PrimitiveType.Byte, PrimitiveType.Short, PrimitiveType.Char -> PrimitiveType.Int + PrimitiveType.UByte, PrimitiveType.UShort -> PrimitiveType.UInt + else -> this +} + +fun PrimitiveType.zero() = when (this) { + PrimitiveType.Double -> "0.0" + PrimitiveType.Float -> "0.0f" + PrimitiveType.Long -> "0L" + PrimitiveType.ULong -> "0uL" + in PrimitiveType.unsignedPrimitives -> "0u" + else -> "0" +} enum class Inline { No, diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/MemberBuilder.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/MemberBuilder.kt index 8cf1b23c4fb..b6ef58efeed 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/MemberBuilder.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/MemberBuilder.kt @@ -194,28 +194,19 @@ class MemberBuilder( "RECEIVER" -> receiver "SELF" -> self "PRIMITIVE" -> primitive?.name ?: token - "SUM" -> { - when (primitive) { - PrimitiveType.Byte, PrimitiveType.Short, PrimitiveType.Char -> "Int" - else -> primitive - } - } - "ZERO" -> when (primitive) { - PrimitiveType.Double -> "0.0" - PrimitiveType.Float -> "0.0f" - PrimitiveType.Long -> "0L" - else -> "0" - } "ONE" -> when (primitive) { PrimitiveType.Double -> "1.0" PrimitiveType.Float -> "1.0f" PrimitiveType.Long -> "1L" + PrimitiveType.ULong -> "1uL" + in PrimitiveType.unsignedPrimitives -> "1u" else -> "1" } "-ONE" -> when (primitive) { PrimitiveType.Double -> "-1.0" PrimitiveType.Float -> "-1.0f" PrimitiveType.Long -> "-1L" + in PrimitiveType.unsignedPrimitives -> error("-ONE is not in the domain of unsigned primitives") else -> "-1" } "TCollection" -> { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/SourceFile.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/SourceFile.kt index 23201c3a587..5610edcb82b 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/SourceFile.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/SourceFile.kt @@ -14,6 +14,7 @@ enum class SourceFile(jvmClassName: String? = null, val multifile: Boolean = tru Sets(packageName = "kotlin.collections"), Maps(packageName = "kotlin.collections"), Sequences(packageName = "kotlin.sequences"), + USequences(packageName = "kotlin.sequences"), Ranges(packageName = "kotlin.ranges"), URanges(packageName = "kotlin.ranges"), Comparisons(packageName = "kotlin.comparisons"),