From d424a1f1ce4a1517e19dea86544bc80975d1b2d0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Fri, 31 Aug 2018 13:39:32 +0300 Subject: [PATCH] Patch common stdlib to prevent it from using experimental coroutines --- backend.native/build.gradle | 3 + .../kotlin/collections/SlidingWindow.kt | 200 ++ .../kotlin/sequences/SequencesCommon.kt | 634 ++++++ .../kotlin/kotlin/sequences/_Sequences.kt | 1905 +++++++++++++++++ 4 files changed, 2742 insertions(+) create mode 100644 runtime/src/main/kotlin/kotlin/collections/SlidingWindow.kt create mode 100644 runtime/src/main/kotlin/kotlin/sequences/SequencesCommon.kt create mode 100644 runtime/src/main/kotlin/kotlin/sequences/_Sequences.kt diff --git a/backend.native/build.gradle b/backend.native/build.gradle index 649d74f23bd..752c2940a1b 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -150,6 +150,9 @@ def commonSrc = file('build/stdlib') task unzipStdlibSources(type: Copy) { from (zipTree(configurations.kotlin_common_stdlib_src.singleFile)) { + exclude 'generated/_Sequences.kt' + exclude 'kotlin/collections/Sequences.kt' + exclude 'kotlin/collections/SlidingWindow.kt' include 'generated/**/*.kt' include 'kotlin/**/*.kt' } diff --git a/runtime/src/main/kotlin/kotlin/collections/SlidingWindow.kt b/runtime/src/main/kotlin/kotlin/collections/SlidingWindow.kt new file mode 100644 index 00000000000..3beb8ac94ac --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/collections/SlidingWindow.kt @@ -0,0 +1,200 @@ +/* + * Copyright 2010-2018 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. + */ + +package kotlin.collections + +import kotlin.* +import kotlin.sequences.buildIterator + +internal fun checkWindowSizeStep(size: Int, step: Int) { + require(size > 0 && step > 0) { + if (size != step) + "Both size $size and step $step must be greater than zero." + else + "size $size must be greater than zero." + } +} + +internal fun Sequence.windowedSequence(size: Int, step: Int, partialWindows: Boolean, reuseBuffer: Boolean): Sequence> { + checkWindowSizeStep(size, step) + return Sequence { windowedIterator(iterator(), size, step, partialWindows, reuseBuffer) } +} + +internal fun windowedIterator(iterator: Iterator, size: Int, step: Int, partialWindows: Boolean, reuseBuffer: Boolean): Iterator> { + if (!iterator.hasNext()) return EmptyIterator + return buildIterator> { + val gap = step - size + if (gap >= 0) { + var buffer = ArrayList(size) + var skip = 0 + for (e in iterator) { + if (skip > 0) { skip -= 1; continue } + buffer.add(e) + if (buffer.size == size) { + yield(buffer) + if (reuseBuffer) buffer.clear() else buffer = ArrayList(size) + skip = gap + } + } + if (buffer.isNotEmpty()) { + if (partialWindows || buffer.size == size) yield(buffer) + } + } else { + val buffer = RingBuffer(size) + for (e in iterator) { + buffer.add(e) + if (buffer.isFull()) { + yield(if (reuseBuffer) buffer else ArrayList(buffer)) + buffer.removeFirst(step) + } + } + if (partialWindows) { + while (buffer.size > step) { + yield(if (reuseBuffer) buffer else ArrayList(buffer)) + buffer.removeFirst(step) + } + if (buffer.isNotEmpty()) yield(buffer) + } + } + } +} + +internal class MovingSubList(private val list: List) : AbstractList(), RandomAccess { + private var fromIndex: Int = 0 + private var _size: Int = 0 + + fun move(fromIndex: Int, toIndex: Int) { + checkRangeIndexes(fromIndex, toIndex, list.size) + this.fromIndex = fromIndex + this._size = toIndex - fromIndex + } + + override fun get(index: Int): E { + checkElementIndex(index, _size) + + return list[fromIndex + index] + } + + override val size: Int get() = _size +} + + +/** + * Provides ring buffer implementation. + * + * Buffer overflow is not allowed so [add] doesn't overwrite tail but raises an exception. + */ +private class RingBuffer(val capacity: Int) : AbstractList(), RandomAccess { + init { + require(capacity >= 0) { "ring buffer capacity should not be negative but it is $capacity" } + } + + private val buffer = arrayOfNulls(capacity) + private var startIndex: Int = 0 + + override var size: Int = 0 + private set + + override fun get(index: Int): T { + checkElementIndex(index, size) + @Suppress("UNCHECKED_CAST") + return buffer[startIndex.forward(index)] as T + } + + fun isFull() = size == capacity + + override fun iterator(): Iterator = object : AbstractIterator() { + private var count = size + private var index = startIndex + + override fun computeNext() { + if (count == 0) { + done() + } else { + @Suppress("UNCHECKED_CAST") + setNext(buffer[index] as T) + index = index.forward(1) + count-- + } + } + } + + @Suppress("UNCHECKED_CAST") + override fun toArray(array: Array): Array { + val result: Array = + if (array.size < this.size) array.copyOf(this.size) else array as Array + + val size = this.size + + var widx = 0 + var idx = startIndex + + while (widx < size && idx < capacity) { + result[widx] = buffer[idx] as T + widx++ + idx++ + } + + idx = 0 + while (widx < size) { + result[widx] = buffer[idx] as T + widx++ + idx++ + } + if (result.size > this.size) result[this.size] = null + + return result as Array + } + + override fun toArray(): Array { + return toArray(arrayOfNulls(size)) + } + + /** + * Add [element] to the buffer or fail with [IllegalStateException] if no free space available in the buffer + */ + fun add(element: T) { + if (isFull()) { + throw IllegalStateException("ring buffer is full") + } + + buffer[startIndex.forward(size)] = element + size++ + } + + /** + * Removes [n] first elements from the buffer or fails with [IllegalArgumentException] if not enough elements in the buffer to remove + */ + fun removeFirst(n: Int) { + require(n >= 0) { "n shouldn't be negative but it is $n" } + require(n <= size) { "n shouldn't be greater than the buffer size: n = $n, size = $size" } + + if (n > 0) { + val start = startIndex + val end = start.forward(n) + + if (start > end) { + buffer.fill(null, start, capacity) + buffer.fill(null, 0, end) + } else { + buffer.fill(null, start, end) + } + + startIndex = end + size -= n + } + } + + + @Suppress("NOTHING_TO_INLINE") + private inline fun Int.forward(n: Int): Int = (this + n) % capacity + + // TODO: replace with Array.fill from stdlib when available in common + private fun Array.fill(element: T, fromIndex: Int = 0, toIndex: Int = size): Unit { + for (idx in fromIndex until toIndex) { + this[idx] = element + } + } +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/sequences/SequencesCommon.kt b/runtime/src/main/kotlin/kotlin/sequences/SequencesCommon.kt new file mode 100644 index 00000000000..5cc7c35a5cc --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/sequences/SequencesCommon.kt @@ -0,0 +1,634 @@ +/* + * Copyright 2010-2018 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("SequencesKt") + +package kotlin.sequences + +import kotlin.* + +/** + * Given an [iterator] function constructs a [Sequence] that returns values through the [Iterator] + * provided by that function. + * The values are evaluated lazily, and the sequence is potentially infinite. + * + * @sample samples.collections.Sequences.Building.sequenceFromIterator + */ +@kotlin.internal.InlineOnly +public inline fun Sequence(crossinline iterator: () -> Iterator): Sequence = object : Sequence { + override fun iterator(): Iterator = iterator() +} + +/** + * Creates a sequence that returns all elements from this iterator. The sequence is constrained to be iterated only once. + * + * @sample samples.collections.Sequences.Building.sequenceFromIterator + */ +public fun Iterator.asSequence(): Sequence = Sequence { this }.constrainOnce() + +/** + * Creates a sequence that returns the specified values. + * + * @sample samples.collections.Sequences.Building.sequenceOfValues + */ +public fun sequenceOf(vararg elements: T): Sequence = if (elements.isEmpty()) emptySequence() else elements.asSequence() + +/** + * Returns an empty sequence. + */ +public fun emptySequence(): Sequence = EmptySequence + +private object EmptySequence : Sequence, DropTakeSequence { + override fun iterator(): Iterator = EmptyIterator + override fun drop(n: Int) = EmptySequence + override fun take(n: Int) = EmptySequence +} + +/** + * Returns this sequence if it's not `null` and the empty sequence otherwise. + * @sample samples.collections.Sequences.Usage.sequenceOrEmpty + */ +@SinceKotlin("1.3") +@kotlin.internal.InlineOnly +public inline fun Sequence?.orEmpty(): Sequence = this ?: emptySequence() + + +/** + * Returns a sequence that iterates through the elements either of this sequence + * or, if this sequence turns out to be empty, of the sequence returned by [defaultValue] function. + * + * @sample samples.collections.Sequences.Usage.sequenceIfEmpty + */ +@SinceKotlin("1.3") +public fun Sequence.ifEmpty(defaultValue: () -> Sequence): Sequence = buildSequence { + val iterator = this@ifEmpty.iterator() + if (iterator.hasNext()) { + yieldAll(iterator) + } else { + yieldAll(defaultValue()) + } +} + +/** + * Returns a sequence of all elements from all sequences in this sequence. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence>.flatten(): Sequence = flatten { it.iterator() } + +/** + * Returns a sequence of all elements from all iterables in this sequence. + * + * The operation is _intermediate_ and _stateless_. + */ +@kotlin.jvm.JvmName("flattenSequenceOfIterable") +public fun Sequence>.flatten(): Sequence = flatten { it.iterator() } + +private fun Sequence.flatten(iterator: (T) -> Iterator): Sequence { + if (this is TransformingSequence<*, *>) { + return (this as TransformingSequence<*, T>).flatten(iterator) + } + return FlatteningSequence(this, { it }, iterator) +} + +/** + * Returns a pair of lists, where + * *first* list is built from the first values of each pair from this sequence, + * *second* list is built from the second values of each pair from this sequence. + * + * The operation is _terminal_. + */ +public fun Sequence>.unzip(): Pair, List> { + val listT = ArrayList() + val listR = ArrayList() + for (pair in this) { + listT.add(pair.first) + listR.add(pair.second) + } + return listT to listR +} + +/** + * A sequence that returns the values from the underlying [sequence] that either match or do not match + * the specified [predicate]. + * + * @param sendWhen If `true`, values for which the predicate returns `true` are returned. Otherwise, + * values for which the predicate returns `false` are returned + */ +internal class FilteringSequence( + private val sequence: Sequence, + private val sendWhen: Boolean = true, + private val predicate: (T) -> Boolean +) : Sequence { + + override fun iterator(): Iterator = object : Iterator { + val iterator = sequence.iterator() + var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue + var nextItem: T? = null + + private fun calcNext() { + while (iterator.hasNext()) { + val item = iterator.next() + if (predicate(item) == sendWhen) { + nextItem = item + nextState = 1 + return + } + } + nextState = 0 + } + + override fun next(): T { + if (nextState == -1) + calcNext() + if (nextState == 0) + throw NoSuchElementException() + val result = nextItem + nextItem = null + nextState = -1 + @Suppress("UNCHECKED_CAST") + return result as T + } + + override fun hasNext(): Boolean { + if (nextState == -1) + calcNext() + return nextState == 1 + } + } +} + +/** + * A sequence which returns the results of applying the given [transformer] function to the values + * in the underlying [sequence]. + */ + +internal class TransformingSequence +constructor(private val sequence: Sequence, private val transformer: (T) -> R) : Sequence { + override fun iterator(): Iterator = object : Iterator { + val iterator = sequence.iterator() + override fun next(): R { + return transformer(iterator.next()) + } + + override fun hasNext(): Boolean { + return iterator.hasNext() + } + } + + internal fun flatten(iterator: (R) -> Iterator): Sequence { + return FlatteningSequence(sequence, transformer, iterator) + } +} + +/** + * A sequence which returns the results of applying the given [transformer] function to the values + * in the underlying [sequence], where the transformer function takes the index of the value in the underlying + * sequence along with the value itself. + */ +internal class TransformingIndexedSequence +constructor(private val sequence: Sequence, private val transformer: (Int, T) -> R) : Sequence { + override fun iterator(): Iterator = object : Iterator { + val iterator = sequence.iterator() + var index = 0 + override fun next(): R { + return transformer(checkIndexOverflow(index++), iterator.next()) + } + + override fun hasNext(): Boolean { + return iterator.hasNext() + } + } +} + +/** + * A sequence which combines values from the underlying [sequence] with their indices and returns them as + * [IndexedValue] objects. + */ +internal class IndexingSequence +constructor(private val sequence: Sequence) : Sequence> { + override fun iterator(): Iterator> = object : Iterator> { + val iterator = sequence.iterator() + var index = 0 + override fun next(): IndexedValue { + return IndexedValue(checkIndexOverflow(index++), iterator.next()) + } + + override fun hasNext(): Boolean { + return iterator.hasNext() + } + } +} + +/** + * A sequence which takes the values from two parallel underlying sequences, passes them to the given + * [transform] function and returns the values returned by that function. The sequence stops returning + * values as soon as one of the underlying sequences stops returning values. + */ +internal class MergingSequence +constructor( + private val sequence1: Sequence, + private val sequence2: Sequence, + private val transform: (T1, T2) -> V +) : Sequence { + override fun iterator(): Iterator = object : Iterator { + val iterator1 = sequence1.iterator() + val iterator2 = sequence2.iterator() + override fun next(): V { + return transform(iterator1.next(), iterator2.next()) + } + + override fun hasNext(): Boolean { + return iterator1.hasNext() && iterator2.hasNext() + } + } +} + +internal class FlatteningSequence +constructor( + private val sequence: Sequence, + private val transformer: (T) -> R, + private val iterator: (R) -> Iterator +) : Sequence { + override fun iterator(): Iterator = object : Iterator { + val iterator = sequence.iterator() + var itemIterator: Iterator? = null + + override fun next(): E { + if (!ensureItemIterator()) + throw NoSuchElementException() + return itemIterator!!.next() + } + + override fun hasNext(): Boolean { + return ensureItemIterator() + } + + private fun ensureItemIterator(): Boolean { + if (itemIterator?.hasNext() == false) + itemIterator = null + + while (itemIterator == null) { + if (!iterator.hasNext()) { + return false + } else { + val element = iterator.next() + val nextItemIterator = iterator(transformer(element)) + if (nextItemIterator.hasNext()) { + itemIterator = nextItemIterator + return true + } + } + } + return true + } + } +} + +/** + * A sequence that supports drop(n) and take(n) operations + */ +internal interface DropTakeSequence : Sequence { + fun drop(n: Int): Sequence + fun take(n: Int): Sequence +} + +/** + * A sequence that skips [startIndex] values from the underlying [sequence] + * and stops returning values right before [endIndex], i.e. stops at `endIndex - 1` + */ +internal class SubSequence( + private val sequence: Sequence, + private val startIndex: Int, + private val endIndex: Int +) : Sequence, DropTakeSequence { + + init { + require(startIndex >= 0) { "startIndex should be non-negative, but is $startIndex" } + require(endIndex >= 0) { "endIndex should be non-negative, but is $endIndex" } + require(endIndex >= startIndex) { "endIndex should be not less than startIndex, but was $endIndex < $startIndex" } + } + + private val count: Int get() = endIndex - startIndex + + override fun drop(n: Int): Sequence = if (n >= count) emptySequence() else SubSequence(sequence, startIndex + n, endIndex) + override fun take(n: Int): Sequence = if (n >= count) this else SubSequence(sequence, startIndex, startIndex + n) + + override fun iterator() = object : Iterator { + + val iterator = sequence.iterator() + var position = 0 + + // Shouldn't be called from constructor to avoid premature iteration + private fun drop() { + while (position < startIndex && iterator.hasNext()) { + iterator.next() + position++ + } + } + + override fun hasNext(): Boolean { + drop() + return (position < endIndex) && iterator.hasNext() + } + + override fun next(): T { + drop() + if (position >= endIndex) + throw NoSuchElementException() + position++ + return iterator.next() + } + } +} + +/** + * A sequence that returns at most [count] values from the underlying [sequence], and stops returning values + * as soon as that count is reached. + */ +internal class TakeSequence( + private val sequence: Sequence, + private val count: Int +) : Sequence, DropTakeSequence { + + init { + require(count >= 0) { "count must be non-negative, but was $count." } + } + + override fun drop(n: Int): Sequence = if (n >= count) emptySequence() else SubSequence(sequence, n, count) + override fun take(n: Int): Sequence = if (n >= count) this else TakeSequence(sequence, n) + + override fun iterator(): Iterator = object : Iterator { + var left = count + val iterator = sequence.iterator() + + override fun next(): T { + if (left == 0) + throw NoSuchElementException() + left-- + return iterator.next() + } + + override fun hasNext(): Boolean { + return left > 0 && iterator.hasNext() + } + } +} + +/** + * A sequence that returns values from the underlying [sequence] while the [predicate] function returns + * `true`, and stops returning values once the function returns `false` for the next element. + */ +internal class TakeWhileSequence +constructor( + private val sequence: Sequence, + private val predicate: (T) -> Boolean +) : Sequence { + override fun iterator(): Iterator = object : Iterator { + val iterator = sequence.iterator() + var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue + var nextItem: T? = null + + private fun calcNext() { + if (iterator.hasNext()) { + val item = iterator.next() + if (predicate(item)) { + nextState = 1 + nextItem = item + return + } + } + nextState = 0 + } + + override fun next(): T { + if (nextState == -1) + calcNext() // will change nextState + if (nextState == 0) + throw NoSuchElementException() + @Suppress("UNCHECKED_CAST") + val result = nextItem as T + + // Clean next to avoid keeping reference on yielded instance + nextItem = null + nextState = -1 + return result + } + + override fun hasNext(): Boolean { + if (nextState == -1) + calcNext() // will change nextState + return nextState == 1 + } + } +} + +/** + * A sequence that skips the specified number of values from the underlying [sequence] and returns + * all values after that. + */ +internal class DropSequence( + private val sequence: Sequence, + private val count: Int +) : Sequence, DropTakeSequence { + init { + require(count >= 0) { "count must be non-negative, but was $count." } + } + + override fun drop(n: Int): Sequence = (count + n).let { n1 -> if (n1 < 0) DropSequence(this, n) else DropSequence(sequence, n1) } + override fun take(n: Int): Sequence = (count + n).let { n1 -> if (n1 < 0) TakeSequence(this, n) else SubSequence(sequence, count, n1) } + + override fun iterator(): Iterator = object : Iterator { + val iterator = sequence.iterator() + var left = count + + // Shouldn't be called from constructor to avoid premature iteration + private fun drop() { + while (left > 0 && iterator.hasNext()) { + iterator.next() + left-- + } + } + + override fun next(): T { + drop() + return iterator.next() + } + + override fun hasNext(): Boolean { + drop() + return iterator.hasNext() + } + } +} + +/** + * A sequence that skips the values from the underlying [sequence] while the given [predicate] returns `true` and returns + * all values after that. + */ +internal class DropWhileSequence +constructor( + private val sequence: Sequence, + private val predicate: (T) -> Boolean +) : Sequence { + + override fun iterator(): Iterator = object : Iterator { + val iterator = sequence.iterator() + var dropState: Int = -1 // -1 for not dropping, 1 for nextItem, 0 for normal iteration + var nextItem: T? = null + + private fun drop() { + while (iterator.hasNext()) { + val item = iterator.next() + if (!predicate(item)) { + nextItem = item + dropState = 1 + return + } + } + dropState = 0 + } + + override fun next(): T { + if (dropState == -1) + drop() + + if (dropState == 1) { + @Suppress("UNCHECKED_CAST") + val result = nextItem as T + nextItem = null + dropState = 0 + return result + } + return iterator.next() + } + + override fun hasNext(): Boolean { + if (dropState == -1) + drop() + return dropState == 1 || iterator.hasNext() + } + } +} + +internal class DistinctSequence(private val source: Sequence, private val keySelector: (T) -> K) : Sequence { + override fun iterator(): Iterator = DistinctIterator(source.iterator(), keySelector) +} + +private class DistinctIterator(private val source: Iterator, private val keySelector: (T) -> K) : AbstractIterator() { + private val observed = HashSet() + + override fun computeNext() { + while (source.hasNext()) { + val next = source.next() + val key = keySelector(next) + + if (observed.add(key)) { + setNext(next) + return + } + } + + done() + } +} + + +private class GeneratorSequence(private val getInitialValue: () -> T?, private val getNextValue: (T) -> T?) : Sequence { + override fun iterator(): Iterator = object : Iterator { + var nextItem: T? = null + var nextState: Int = -2 // -2 for initial unknown, -1 for next unknown, 0 for done, 1 for continue + + private fun calcNext() { + nextItem = if (nextState == -2) getInitialValue() else getNextValue(nextItem!!) + nextState = if (nextItem == null) 0 else 1 + } + + override fun next(): T { + if (nextState < 0) + calcNext() + + if (nextState == 0) + throw NoSuchElementException() + val result = nextItem as T + // Do not clean nextItem (to avoid keeping reference on yielded instance) -- need to keep state for getNextValue + nextState = -1 + return result + } + + override fun hasNext(): Boolean { + if (nextState < 0) + calcNext() + return nextState == 1 + } + } +} + +/** + * Returns a wrapper sequence that provides values of this sequence, but ensures it can be iterated only one time. + * + * The operation is _intermediate_ and _stateless_. + * + * [IllegalStateException] is thrown on iterating the returned sequence from the second time. + * + */ +public fun Sequence.constrainOnce(): Sequence { + // as? does not work in js + //return this as? ConstrainedOnceSequence ?: ConstrainedOnceSequence(this) + return if (this is ConstrainedOnceSequence) this else ConstrainedOnceSequence(this) +} + + +/** + * Returns a sequence which invokes the function to calculate the next value on each iteration until the function returns `null`. + * + * The returned sequence is constrained to be iterated only once. + * + * @see constrainOnce + * @see buildSequence + * + * @sample samples.collections.Sequences.Building.generateSequence + */ +public fun generateSequence(nextFunction: () -> T?): Sequence { + return GeneratorSequence(nextFunction, { nextFunction() }).constrainOnce() +} + +/** + * Returns a sequence defined by the starting value [seed] and the function [nextFunction], + * which is invoked to calculate the next value based on the previous one on each iteration. + * + * The sequence produces values until it encounters first `null` value. + * If [seed] is `null`, an empty sequence is produced. + * + * The sequence can be iterated multiple times, each time starting with [seed]. + * + * @see buildSequence + * + * @sample samples.collections.Sequences.Building.generateSequenceWithSeed + */ +@kotlin.internal.LowPriorityInOverloadResolution +public fun generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence = + if (seed == null) + EmptySequence + else + GeneratorSequence({ seed }, nextFunction) + +/** + * Returns a sequence defined by the function [seedFunction], which is invoked to produce the starting value, + * and the [nextFunction], which is invoked to calculate the next value based on the previous one on each iteration. + * + * The sequence produces values until it encounters first `null` value. + * If [seedFunction] returns `null`, an empty sequence is produced. + * + * The sequence can be iterated multiple times. + * + * @see buildSequence + * + * @sample samples.collections.Sequences.Building.generateSequenceWithLazySeed + */ +public fun generateSequence(seedFunction: () -> T?, nextFunction: (T) -> T?): Sequence = + GeneratorSequence(seedFunction, nextFunction) + diff --git a/runtime/src/main/kotlin/kotlin/sequences/_Sequences.kt b/runtime/src/main/kotlin/kotlin/sequences/_Sequences.kt new file mode 100644 index 00000000000..4e29a4ec0f0 --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/sequences/_Sequences.kt @@ -0,0 +1,1905 @@ +/* + * Copyright 2010-2018 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("SequencesKt") + +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.* +import kotlin.text.* +import kotlin.comparisons.* +import kotlin.random.* + +/** + * Returns `true` if [element] is found in the sequence. + * + * The operation is _terminal_. + */ +public operator fun <@kotlin.internal.OnlyInputTypes T> Sequence.contains(element: T): Boolean { + return indexOf(element) >= 0 +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this sequence. + * + * The operation is _terminal_. + */ +public fun Sequence.elementAt(index: Int): T { + return elementAtOrElse(index) { throw IndexOutOfBoundsException("Sequence doesn't contain element at index $index.") } +} + +/** + * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this sequence. + * + * The operation is _terminal_. + */ +public fun Sequence.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { + if (index < 0) + return defaultValue(index) + val iterator = iterator() + var count = 0 + while (iterator.hasNext()) { + val element = iterator.next() + if (index == count++) + return element + } + return defaultValue(index) +} + +/** + * Returns an element at the given [index] or `null` if the [index] is out of bounds of this sequence. + * + * The operation is _terminal_. + */ +public fun Sequence.elementAtOrNull(index: Int): T? { + if (index < 0) + return null + val iterator = iterator() + var count = 0 + while (iterator.hasNext()) { + val element = iterator.next() + if (index == count++) + return element + } + return null +} + +/** + * Returns the first element matching the given [predicate], or `null` if no such element was found. + * + * The operation is _terminal_. + */ +@kotlin.internal.InlineOnly +public inline fun Sequence.find(predicate: (T) -> Boolean): T? { + return firstOrNull(predicate) +} + +/** + * Returns the last element matching the given [predicate], or `null` if no such element was found. + * + * The operation is _terminal_. + */ +@kotlin.internal.InlineOnly +public inline fun Sequence.findLast(predicate: (T) -> Boolean): T? { + return lastOrNull(predicate) +} + +/** + * Returns first element. + * @throws [NoSuchElementException] if the sequence is empty. + * + * The operation is _terminal_. + */ +public fun Sequence.first(): T { + val iterator = iterator() + if (!iterator.hasNext()) + throw NoSuchElementException("Sequence is empty.") + return iterator.next() +} + +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + * + * The operation is _terminal_. + */ +public inline fun Sequence.first(predicate: (T) -> Boolean): T { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Sequence contains no element matching the predicate.") +} + +/** + * Returns the first element, or `null` if the sequence is empty. + * + * The operation is _terminal_. + */ +public fun Sequence.firstOrNull(): T? { + val iterator = iterator() + if (!iterator.hasNext()) + return null + return iterator.next() +} + +/** + * Returns the first element matching the given [predicate], or `null` if element was not found. + * + * The operation is _terminal_. + */ +public inline fun Sequence.firstOrNull(predicate: (T) -> Boolean): T? { + for (element in this) if (predicate(element)) return element + return null +} + +/** + * Returns first index of [element], or -1 if the sequence does not contain element. + * + * The operation is _terminal_. + */ +public fun <@kotlin.internal.OnlyInputTypes T> Sequence.indexOf(element: T): Int { + var index = 0 + for (item in this) { + checkIndexOverflow(index) + if (element == item) + return index + index++ + } + return -1 +} + +/** + * Returns index of the first element matching the given [predicate], or -1 if the sequence does not contain such element. + * + * The operation is _terminal_. + */ +public inline fun Sequence.indexOfFirst(predicate: (T) -> Boolean): Int { + var index = 0 + for (item in this) { + checkIndexOverflow(index) + if (predicate(item)) + return index + index++ + } + return -1 +} + +/** + * Returns index of the last element matching the given [predicate], or -1 if the sequence does not contain such element. + * + * The operation is _terminal_. + */ +public inline fun Sequence.indexOfLast(predicate: (T) -> Boolean): Int { + var lastIndex = -1 + var index = 0 + for (item in this) { + checkIndexOverflow(index) + if (predicate(item)) + lastIndex = index + index++ + } + return lastIndex +} + +/** + * Returns the last element. + * @throws [NoSuchElementException] if the sequence is empty. + * + * The operation is _terminal_. + */ +public fun Sequence.last(): T { + val iterator = iterator() + if (!iterator.hasNext()) + throw NoSuchElementException("Sequence is empty.") + var last = iterator.next() + while (iterator.hasNext()) + last = iterator.next() + return last +} + +/** + * Returns the last element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + * + * The operation is _terminal_. + */ +public inline fun Sequence.last(predicate: (T) -> Boolean): T { + var last: T? = null + var found = false + for (element in this) { + if (predicate(element)) { + last = element + found = true + } + } + if (!found) throw NoSuchElementException("Sequence contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return last as T +} + +/** + * Returns last index of [element], or -1 if the sequence does not contain element. + * + * The operation is _terminal_. + */ +public fun <@kotlin.internal.OnlyInputTypes T> Sequence.lastIndexOf(element: T): Int { + var lastIndex = -1 + var index = 0 + for (item in this) { + checkIndexOverflow(index) + if (element == item) + lastIndex = index + index++ + } + return lastIndex +} + +/** + * Returns the last element, or `null` if the sequence is empty. + * + * The operation is _terminal_. + */ +public fun Sequence.lastOrNull(): T? { + val iterator = iterator() + if (!iterator.hasNext()) + return null + var last = iterator.next() + while (iterator.hasNext()) + last = iterator.next() + return last +} + +/** + * Returns the last element matching the given [predicate], or `null` if no such element was found. + * + * The operation is _terminal_. + */ +public inline fun Sequence.lastOrNull(predicate: (T) -> Boolean): T? { + var last: T? = null + for (element in this) { + if (predicate(element)) { + last = element + } + } + return last +} + +/** + * Returns the single element, or throws an exception if the sequence is empty or has more than one element. + * + * The operation is _terminal_. + */ +public fun Sequence.single(): T { + val iterator = iterator() + if (!iterator.hasNext()) + throw NoSuchElementException("Sequence is empty.") + val single = iterator.next() + if (iterator.hasNext()) + throw IllegalArgumentException("Sequence has more than one element.") + return single +} + +/** + * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. + * + * The operation is _terminal_. + */ +public inline fun Sequence.single(predicate: (T) -> Boolean): T { + var single: T? = null + var found = false + for (element in this) { + if (predicate(element)) { + if (found) throw IllegalArgumentException("Sequence contains more than one matching element.") + single = element + found = true + } + } + if (!found) throw NoSuchElementException("Sequence contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as T +} + +/** + * Returns single element, or `null` if the sequence is empty or has more than one element. + * + * The operation is _terminal_. + */ +public fun Sequence.singleOrNull(): T? { + val iterator = iterator() + if (!iterator.hasNext()) + return null + val single = iterator.next() + if (iterator.hasNext()) + return null + return single +} + +/** + * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. + * + * The operation is _terminal_. + */ +public inline fun Sequence.singleOrNull(predicate: (T) -> Boolean): T? { + var single: T? = null + var found = false + for (element in this) { + if (predicate(element)) { + if (found) return null + single = element + found = true + } + } + if (!found) return null + return single +} + +/** + * Returns a sequence containing all elements except first [n] elements. + * + * The operation is _intermediate_ and _stateless_. + * + * @sample samples.collections.Collections.Transformations.drop + */ +public fun Sequence.drop(n: Int): Sequence { + require(n >= 0) { "Requested element count $n is less than zero." } + return when { + n == 0 -> this + this is DropTakeSequence -> this.drop(n) + else -> DropSequence(this, n) + } +} + +/** + * Returns a sequence containing all elements except first elements that satisfy the given [predicate]. + * + * The operation is _intermediate_ and _stateless_. + * + * @sample samples.collections.Collections.Transformations.drop + */ +public fun Sequence.dropWhile(predicate: (T) -> Boolean): Sequence { + return DropWhileSequence(this, predicate) +} + +/** + * Returns a sequence containing only elements matching the given [predicate]. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.filter(predicate: (T) -> Boolean): Sequence { + return FilteringSequence(this, true, predicate) +} + +/** + * Returns a sequence containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself + * and returns the result of predicate evaluation on the element. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.filterIndexed(predicate: (index: Int, T) -> Boolean): Sequence { + // TODO: Rewrite with generalized MapFilterIndexingSequence + return TransformingSequence(FilteringSequence(IndexingSequence(this), true, { predicate(it.index, it.value) }), { it.value }) +} + +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself + * and returns the result of predicate evaluation on the element. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.filterIndexedTo(destination: C, predicate: (index: Int, T) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} + +/** + * Returns a sequence containing all elements that are instances of specified type parameter R. + * + * The operation is _intermediate_ and _stateless_. + */ +public inline fun Sequence<*>.filterIsInstance(): Sequence<@kotlin.internal.NoInfer R> { + @Suppress("UNCHECKED_CAST") + return filter { it is R } as Sequence +} + +/** + * Appends all elements that are instances of specified type parameter R to the given [destination]. + * + * The operation is _terminal_. + */ +public inline fun > Sequence<*>.filterIsInstanceTo(destination: C): C { + for (element in this) if (element is R) destination.add(element) + return destination +} + +/** + * Returns a sequence containing all elements not matching the given [predicate]. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.filterNot(predicate: (T) -> Boolean): Sequence { + return FilteringSequence(this, false, predicate) +} + +/** + * Returns a sequence containing all elements that are not `null`. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.filterNotNull(): Sequence { + @Suppress("UNCHECKED_CAST") + return filterNot { it == null } as Sequence +} + +/** + * Appends all elements that are not `null` to the given [destination]. + * + * The operation is _terminal_. + */ +public fun , T : Any> Sequence.filterNotNullTo(destination: C): C { + for (element in this) if (element != null) destination.add(element) + return destination +} + +/** + * Appends all elements not matching the given [predicate] to the given [destination]. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.filterNotTo(destination: C, predicate: (T) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} + +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.filterTo(destination: C, predicate: (T) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} + +/** + * Returns a sequence containing first [n] elements. + * + * The operation is _intermediate_ and _stateless_. + * + * @sample samples.collections.Collections.Transformations.take + */ +public fun Sequence.take(n: Int): Sequence { + require(n >= 0) { "Requested element count $n is less than zero." } + return when { + n == 0 -> emptySequence() + this is DropTakeSequence -> this.take(n) + else -> TakeSequence(this, n) + } +} + +/** + * Returns a sequence containing first elements satisfying the given [predicate]. + * + * The operation is _intermediate_ and _stateless_. + * + * @sample samples.collections.Collections.Transformations.take + */ +public fun Sequence.takeWhile(predicate: (T) -> Boolean): Sequence { + return TakeWhileSequence(this, predicate) +} + +/** + * Returns a sequence that yields elements of this sequence sorted according to their natural sort order. + * + * The operation is _intermediate_ and _stateful_. + */ +public fun > Sequence.sorted(): Sequence { + return object : Sequence { + override fun iterator(): Iterator { + val sortedList = this@sorted.toMutableList() + sortedList.sort() + return sortedList.iterator() + } + } +} + +/** + * Returns a sequence that yields elements of this sequence sorted according to natural sort order of the value returned by specified [selector] function. + * + * The operation is _intermediate_ and _stateful_. + */ +public inline fun > Sequence.sortedBy(crossinline selector: (T) -> R?): Sequence { + return sortedWith(compareBy(selector)) +} + +/** + * Returns a sequence that yields elements of this sequence sorted descending according to natural sort order of the value returned by specified [selector] function. + * + * The operation is _intermediate_ and _stateful_. + */ +public inline fun > Sequence.sortedByDescending(crossinline selector: (T) -> R?): Sequence { + return sortedWith(compareByDescending(selector)) +} + +/** + * Returns a sequence that yields elements of this sequence sorted descending according to their natural sort order. + * + * The operation is _intermediate_ and _stateful_. + */ +public fun > Sequence.sortedDescending(): Sequence { + return sortedWith(reverseOrder()) +} + +/** + * Returns a sequence that yields elements of this sequence sorted according to the specified [comparator]. + * + * The operation is _intermediate_ and _stateful_. + */ +public fun Sequence.sortedWith(comparator: Comparator): Sequence { + return object : Sequence { + override fun iterator(): Iterator { + val sortedList = this@sortedWith.toMutableList() + sortedList.sortWith(comparator) + return sortedList.iterator() + } + } +} + +/** + * Returns a [Map] containing key-value pairs provided by [transform] function + * applied to elements of the given sequence. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original sequence. + * + * The operation is _terminal_. + */ +public inline fun Sequence.associate(transform: (T) -> Pair): Map { + return associateTo(LinkedHashMap(), transform) +} + +/** + * Returns a [Map] containing the elements from the given sequence indexed by the key + * returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original sequence. + * + * The operation is _terminal_. + */ +public inline fun Sequence.associateBy(keySelector: (T) -> K): Map { + return associateByTo(LinkedHashMap(), keySelector) +} + +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given sequence. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original sequence. + * + * The operation is _terminal_. + */ +public inline fun Sequence.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map { + return associateByTo(LinkedHashMap(), keySelector, valueTransform) +} + +/** + * Populates and returns the [destination] mutable map with key-value pairs, + * where key is provided by the [keySelector] function applied to each element of the given sequence + * and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.associateByTo(destination: M, keySelector: (T) -> K): M { + for (element in this) { + destination.put(keySelector(element), element) + } + return destination +} + +/** + * Populates and returns the [destination] mutable map with key-value pairs, + * where key is provided by the [keySelector] function and + * and value is provided by the [valueTransform] function applied to elements of the given sequence. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.associateByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { + for (element in this) { + destination.put(keySelector(element), valueTransform(element)) + } + return destination +} + +/** + * Populates and returns the [destination] mutable map with key-value pairs + * provided by [transform] function applied to each element of the given sequence. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.associateTo(destination: M, transform: (T) -> Pair): M { + for (element in this) { + destination += transform(element) + } + return destination +} + +/** + * Returns a [Map] where keys are elements from the given sequence and values are + * produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original sequence. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Transformations.associateWith + */ +@SinceKotlin("1.3") +public inline fun Sequence.associateWith(valueSelector: (K) -> V): Map { + val result = LinkedHashMap() + return associateWithTo(result, valueSelector) +} + +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given sequence, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + * + * The operation is _terminal_. + */ +@SinceKotlin("1.3") +public inline fun > Sequence.associateWithTo(destination: M, valueSelector: (K) -> V): M { + for (element in this) { + destination.put(element, valueSelector(element)) + } + return destination +} + +/** + * Appends all elements to the given [destination] collection. + * + * The operation is _terminal_. + */ +public fun > Sequence.toCollection(destination: C): C { + for (item in this) { + destination.add(item) + } + return destination +} + +/** + * Returns a [HashSet] of all elements. + * + * The operation is _terminal_. + */ +public fun Sequence.toHashSet(): HashSet { + return toCollection(HashSet()) +} + +/** + * Returns a [List] containing all elements. + * + * The operation is _terminal_. + */ +public fun Sequence.toList(): List { + return this.toMutableList().optimizeReadOnlyList() +} + +/** + * Returns a [MutableList] filled with all elements of this sequence. + * + * The operation is _terminal_. + */ +public fun Sequence.toMutableList(): MutableList { + return toCollection(ArrayList()) +} + +/** + * Returns a [Set] of all elements. + * + * The returned set preserves the element iteration order of the original sequence. + * + * The operation is _terminal_. + */ +public fun Sequence.toSet(): Set { + return toCollection(LinkedHashSet()).optimizeReadOnlySet() +} + +/** + * Returns a single sequence of all elements from results of [transform] function being invoked on each element of original sequence. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.flatMap(transform: (T) -> Sequence): Sequence { + return FlatteningSequence(this, transform, { it.iterator() }) +} + +/** + * Appends all elements yielded from results of [transform] function being invoked on each element of original sequence, to the given [destination]. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.flatMapTo(destination: C, transform: (T) -> Sequence): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} + +/** + * Groups elements of the original sequence by the key returned by the given [keySelector] function + * applied to each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original sequence. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Transformations.groupBy + */ +public inline fun Sequence.groupBy(keySelector: (T) -> K): Map> { + return groupByTo(LinkedHashMap>(), keySelector) +} + +/** + * Groups values returned by the [valueTransform] function applied to each element of the original sequence + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original sequence. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Transformations.groupByKeysAndValues + */ +public inline fun Sequence.groupBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map> { + return groupByTo(LinkedHashMap>(), keySelector, valueTransform) +} + +/** + * Groups elements of the original sequence by the key returned by the given [keySelector] function + * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Transformations.groupBy + */ +public inline fun >> Sequence.groupByTo(destination: M, keySelector: (T) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} + +/** + * Groups values returned by the [valueTransform] function applied to each element of the original sequence + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Transformations.groupByKeysAndValues + */ +public inline fun >> Sequence.groupByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} + +/** + * Creates a [Grouping] source from a sequence to be used later with one of group-and-fold operations + * using the specified [keySelector] function to extract a key from each element. + * + * The operation is _intermediate_ and _stateless_. + * + * @sample samples.collections.Collections.Transformations.groupingByEachCount + */ +@SinceKotlin("1.1") +public inline fun Sequence.groupingBy(crossinline keySelector: (T) -> K): Grouping { + return object : Grouping { + override fun sourceIterator(): Iterator = this@groupingBy.iterator() + override fun keyOf(element: T): K = keySelector(element) + } +} + +/** + * Returns a sequence containing the results of applying the given [transform] function + * to each element in the original sequence. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.map(transform: (T) -> R): Sequence { + return TransformingSequence(this, transform) +} + +/** + * Returns a sequence containing the results of applying the given [transform] function + * to each element and its index in the original sequence. + * @param [transform] function that takes the index of an element and the element itself + * and returns the result of the transform applied to the element. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.mapIndexed(transform: (index: Int, T) -> R): Sequence { + return TransformingIndexedSequence(this, transform) +} + +/** + * Returns a sequence containing only the non-null results of applying the given [transform] function + * to each element and its index in the original sequence. + * @param [transform] function that takes the index of an element and the element itself + * and returns the result of the transform applied to the element. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.mapIndexedNotNull(transform: (index: Int, T) -> R?): Sequence { + return TransformingIndexedSequence(this, transform).filterNotNull() +} + +/** + * Applies the given [transform] function to each element and its index in the original sequence + * and appends only the non-null results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself + * and returns the result of the transform applied to the element. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.mapIndexedNotNullTo(destination: C, transform: (index: Int, T) -> R?): C { + forEachIndexed { index, element -> transform(index, element)?.let { destination.add(it) } } + return destination +} + +/** + * Applies the given [transform] function to each element and its index in the original sequence + * and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself + * and returns the result of the transform applied to the element. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.mapIndexedTo(destination: C, transform: (index: Int, T) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(checkIndexOverflow(index++), item)) + return destination +} + +/** + * Returns a sequence containing only the non-null results of applying the given [transform] function + * to each element in the original sequence. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.mapNotNull(transform: (T) -> R?): Sequence { + return TransformingSequence(this, transform).filterNotNull() +} + +/** + * Applies the given [transform] function to each element in the original sequence + * and appends only the non-null results to the given [destination]. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.mapNotNullTo(destination: C, transform: (T) -> R?): C { + forEach { element -> transform(element)?.let { destination.add(it) } } + return destination +} + +/** + * Applies the given [transform] function to each element of the original sequence + * and appends the results to the given [destination]. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.mapTo(destination: C, transform: (T) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} + +/** + * Returns a sequence of [IndexedValue] for each element of the original sequence. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.withIndex(): Sequence> { + return IndexingSequence(this) +} + +/** + * Returns a sequence containing only distinct elements from the given sequence. + * + * The elements in the resulting sequence are in the same order as they were in the source sequence. + * + * The operation is _intermediate_ and _stateful_. + */ +public fun Sequence.distinct(): Sequence { + return this.distinctBy { it } +} + +/** + * Returns a sequence containing only elements from the given sequence + * having distinct keys returned by the given [selector] function. + * + * The elements in the resulting sequence are in the same order as they were in the source sequence. + * + * The operation is _intermediate_ and _stateful_. + */ +public fun Sequence.distinctBy(selector: (T) -> K): Sequence { + return DistinctSequence(this, selector) +} + +/** + * Returns a mutable set containing all distinct elements from the given sequence. + * + * The returned set preserves the element iteration order of the original sequence. + * + * The operation is _terminal_. + */ +public fun Sequence.toMutableSet(): MutableSet { + val set = LinkedHashSet() + for (item in this) set.add(item) + return set +} + +/** + * Returns `true` if all elements match the given [predicate]. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Aggregates.all + */ +public inline fun Sequence.all(predicate: (T) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} + +/** + * Returns `true` if sequence has at least one element. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Aggregates.any + */ +public fun Sequence.any(): Boolean { + return iterator().hasNext() +} + +/** + * Returns `true` if at least one element matches the given [predicate]. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Aggregates.anyWithPredicate + */ +public inline fun Sequence.any(predicate: (T) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} + +/** + * Returns the number of elements in this sequence. + * + * The operation is _terminal_. + */ +public fun Sequence.count(): Int { + var count = 0 + for (element in this) checkCountOverflow(++count) + return count +} + +/** + * Returns the number of elements matching the given [predicate]. + * + * The operation is _terminal_. + */ +public inline fun Sequence.count(predicate: (T) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) checkCountOverflow(++count) + return count +} + +/** + * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element. + * + * The operation is _terminal_. + */ +public inline fun Sequence.fold(initial: R, operation: (acc: R, T) -> R): R { + var accumulator = initial + for (element in this) accumulator = operation(accumulator, element) + return accumulator +} + +/** + * Accumulates value starting with [initial] value and applying [operation] from left to right + * to current accumulator value and each element with its index in the original sequence. + * @param [operation] function that takes the index of an element, current accumulator value + * and the element itself, and calculates the next accumulator value. + * + * The operation is _terminal_. + */ +public inline fun Sequence.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R { + var index = 0 + var accumulator = initial + for (element in this) accumulator = operation(checkIndexOverflow(index++), accumulator, element) + return accumulator +} + +/** + * Performs the given [action] on each element. + * + * The operation is _terminal_. + */ +public inline fun Sequence.forEach(action: (T) -> Unit): Unit { + for (element in this) action(element) +} + +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself + * and performs the desired action on the element. + * + * The operation is _terminal_. + */ +public inline fun Sequence.forEachIndexed(action: (index: Int, T) -> Unit): Unit { + var index = 0 + for (item in this) action(checkIndexOverflow(index++), item) +} + +/** + * Returns the largest element or `null` if there are no elements. + * + * If any of elements is `NaN` returns `NaN`. + * + * The operation is _terminal_. + */ +@SinceKotlin("1.1") +public fun Sequence.max(): Double? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var max = iterator.next() + if (max.isNaN()) return max + while (iterator.hasNext()) { + val e = iterator.next() + if (e.isNaN()) return e + if (max < e) max = e + } + return max +} + +/** + * Returns the largest element or `null` if there are no elements. + * + * If any of elements is `NaN` returns `NaN`. + * + * The operation is _terminal_. + */ +@SinceKotlin("1.1") +public fun Sequence.max(): Float? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var max = iterator.next() + if (max.isNaN()) return max + while (iterator.hasNext()) { + val e = iterator.next() + if (e.isNaN()) return e + if (max < e) max = e + } + return max +} + +/** + * Returns the largest element or `null` if there are no elements. + * + * The operation is _terminal_. + */ +public fun > Sequence.max(): T? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var max = iterator.next() + while (iterator.hasNext()) { + val e = iterator.next() + if (max < e) max = e + } + return max +} + +/** + * Returns the first element yielding the largest value of the given function or `null` if there are no elements. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.maxBy(selector: (T) -> R): T? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var maxElem = iterator.next() + var maxValue = selector(maxElem) + while (iterator.hasNext()) { + val e = iterator.next() + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} + +/** + * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. + * + * The operation is _terminal_. + */ +public fun Sequence.maxWith(comparator: Comparator): T? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var max = iterator.next() + while (iterator.hasNext()) { + val e = iterator.next() + if (comparator.compare(max, e) < 0) max = e + } + return max +} + +/** + * Returns the smallest element or `null` if there are no elements. + * + * If any of elements is `NaN` returns `NaN`. + * + * The operation is _terminal_. + */ +@SinceKotlin("1.1") +public fun Sequence.min(): Double? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var min = iterator.next() + if (min.isNaN()) return min + while (iterator.hasNext()) { + val e = iterator.next() + if (e.isNaN()) return e + if (min > e) min = e + } + return min +} + +/** + * Returns the smallest element or `null` if there are no elements. + * + * If any of elements is `NaN` returns `NaN`. + * + * The operation is _terminal_. + */ +@SinceKotlin("1.1") +public fun Sequence.min(): Float? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var min = iterator.next() + if (min.isNaN()) return min + while (iterator.hasNext()) { + val e = iterator.next() + if (e.isNaN()) return e + if (min > e) min = e + } + return min +} + +/** + * Returns the smallest element or `null` if there are no elements. + * + * The operation is _terminal_. + */ +public fun > Sequence.min(): T? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var min = iterator.next() + while (iterator.hasNext()) { + val e = iterator.next() + if (min > e) min = e + } + return min +} + +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * The operation is _terminal_. + */ +public inline fun > Sequence.minBy(selector: (T) -> R): T? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var minElem = iterator.next() + var minValue = selector(minElem) + while (iterator.hasNext()) { + val e = iterator.next() + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} + +/** + * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. + * + * The operation is _terminal_. + */ +public fun Sequence.minWith(comparator: Comparator): T? { + val iterator = iterator() + if (!iterator.hasNext()) return null + var min = iterator.next() + while (iterator.hasNext()) { + val e = iterator.next() + if (comparator.compare(min, e) > 0) min = e + } + return min +} + +/** + * Returns `true` if the sequence has no elements. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Aggregates.none + */ +public fun Sequence.none(): Boolean { + return !iterator().hasNext() +} + +/** + * Returns `true` if no elements match the given [predicate]. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Aggregates.noneWithPredicate + */ +public inline fun Sequence.none(predicate: (T) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} + +/** + * Returns a sequence which performs the given [action] on each element of the original sequence as they pass through it. + * + * The operation is _intermediate_ and _stateless_. + */ +@SinceKotlin("1.1") +public fun Sequence.onEach(action: (T) -> Unit): Sequence { + return map { + action(it) + it + } +} + +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * The operation is _terminal_. + */ +public inline fun Sequence.reduce(operation: (acc: S, T) -> S): S { + val iterator = this.iterator() + if (!iterator.hasNext()) throw UnsupportedOperationException("Empty sequence can't be reduced.") + var accumulator: S = iterator.next() + while (iterator.hasNext()) { + accumulator = operation(accumulator, iterator.next()) + } + return accumulator +} + +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original sequence. + * @param [operation] function that takes the index of an element, current accumulator value + * and the element itself and calculates the next accumulator value. + * + * The operation is _terminal_. + */ +public inline fun Sequence.reduceIndexed(operation: (index: Int, acc: S, T) -> S): S { + val iterator = this.iterator() + if (!iterator.hasNext()) throw UnsupportedOperationException("Empty sequence can't be reduced.") + var index = 1 + var accumulator: S = iterator.next() + while (iterator.hasNext()) { + accumulator = operation(checkIndexOverflow(index++), accumulator, iterator.next()) + } + return accumulator +} + +/** + * Returns the sum of all values produced by [selector] function applied to each element in the sequence. + * + * The operation is _terminal_. + */ +public inline fun Sequence.sumBy(selector: (T) -> Int): Int { + var sum: Int = 0 + for (element in this) { + sum += selector(element) + } + return sum +} + +/** + * Returns the sum of all values produced by [selector] function applied to each element in the sequence. + * + * The operation is _terminal_. + */ +public inline fun Sequence.sumByDouble(selector: (T) -> Double): Double { + var sum: Double = 0.0 + for (element in this) { + sum += selector(element) + } + return sum +} + +/** + * Returns an original collection containing all the non-`null` elements, throwing an [IllegalArgumentException] if there are any `null` elements. + * + * The operation is _intermediate_ and _stateless_. + */ +public fun Sequence.requireNoNulls(): Sequence { + return map { it ?: throw IllegalArgumentException("null element found in $this.") } +} + +/** + * Splits this sequence into a sequence of lists each not exceeding the given [size]. + * + * The last list in the resulting sequence may have less elements than the given [size]. + * + * @param size the number of elements to take in each list, must be positive and can be greater than the number of elements in this sequence. + * + * The operation is _intermediate_ and _stateful_. + * + * @sample samples.collections.Collections.Transformations.chunked + */ +@SinceKotlin("1.2") +public fun Sequence.chunked(size: Int): Sequence> { + return windowed(size, size, partialWindows = true) +} + +/** + * Splits this sequence into several lists each not exceeding the given [size] + * and applies the given [transform] function to an each. + * + * @return sequence of results of the [transform] applied to an each list. + * + * Note that the list passed to the [transform] function is ephemeral and is valid only inside that function. + * You should not store it or allow it to escape in some way, unless you made a snapshot of it. + * The last list may have less elements than the given [size]. + * + * @param size the number of elements to take in each list, must be positive and can be greater than the number of elements in this sequence. + * + * The operation is _intermediate_ and _stateful_. + * + * @sample samples.text.Strings.chunkedTransform + */ +@SinceKotlin("1.2") +public fun Sequence.chunked(size: Int, transform: (List) -> R): Sequence { + return windowed(size, size, partialWindows = true, transform = transform) +} + +/** + * Returns a sequence containing all elements of the original sequence without the first occurrence of the given [element]. + * + * The operation is _intermediate_ and _stateless_. + */ +public operator fun Sequence.minus(element: T): Sequence { + return object: Sequence { + override fun iterator(): Iterator { + var removed = false + return this@minus.filter { if (!removed && it == element) { removed = true; false } else true }.iterator() + } + } +} + +/** + * Returns a sequence containing all elements of original sequence except the elements contained in the given [elements] array. + * + * Note that the source sequence and the array being subtracted are iterated only when an `iterator` is requested from + * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. + * + * The operation is _intermediate_ and _stateful_. + */ +public operator fun Sequence.minus(elements: Array): Sequence { + if (elements.isEmpty()) return this + return object: Sequence { + override fun iterator(): Iterator { + val other = elements.toHashSet() + return this@minus.filterNot { it in other }.iterator() + } + } +} + +/** + * Returns a sequence containing all elements of original sequence except the elements contained in the given [elements] collection. + * + * Note that the source sequence and the collection being subtracted are iterated only when an `iterator` is requested from + * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. + * + * The operation is _intermediate_ and _stateful_. + */ +public operator fun Sequence.minus(elements: Iterable): Sequence { + return object: Sequence { + override fun iterator(): Iterator { + val other = elements.convertToSetForSetOperation() + if (other.isEmpty()) + return this@minus.iterator() + else + return this@minus.filterNot { it in other }.iterator() + } + } +} + +/** + * Returns a sequence containing all elements of original sequence except the elements contained in the given [elements] sequence. + * + * Note that the source sequence and the sequence being subtracted are iterated only when an `iterator` is requested from + * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. + * + * The operation is _intermediate_ for this sequence and _terminal_ and _stateful_ for the [elements] sequence. + */ +public operator fun Sequence.minus(elements: Sequence): Sequence { + return object: Sequence { + override fun iterator(): Iterator { + val other = elements.toHashSet() + if (other.isEmpty()) + return this@minus.iterator() + else + return this@minus.filterNot { it in other }.iterator() + } + } +} + +/** + * Returns a sequence containing all elements of the original sequence without the first occurrence of the given [element]. + * + * The operation is _intermediate_ and _stateless_. + */ +@kotlin.internal.InlineOnly +public inline fun Sequence.minusElement(element: T): Sequence { + return minus(element) +} + +/** + * Splits the original sequence into pair of lists, + * where *first* list contains elements for which [predicate] yielded `true`, + * while *second* list contains elements for which [predicate] yielded `false`. + * + * The operation is _terminal_. + */ +public inline fun Sequence.partition(predicate: (T) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) { + if (predicate(element)) { + first.add(element) + } else { + second.add(element) + } + } + return Pair(first, second) +} + +/** + * Returns a sequence containing all elements of the original sequence and then the given [element]. + * + * The operation is _intermediate_ and _stateless_. + */ +public operator fun Sequence.plus(element: T): Sequence { + return sequenceOf(this, sequenceOf(element)).flatten() +} + +/** + * Returns a sequence containing all elements of original sequence and then all elements of the given [elements] array. + * + * Note that the source sequence and the array being added are iterated only when an `iterator` is requested from + * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. + * + * The operation is _intermediate_ and _stateless_. + */ +public operator fun Sequence.plus(elements: Array): Sequence { + return this.plus(elements.asList()) +} + +/** + * Returns a sequence containing all elements of original sequence and then all elements of the given [elements] collection. + * + * Note that the source sequence and the collection being added are iterated only when an `iterator` is requested from + * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. + * + * The operation is _intermediate_ and _stateless_. + */ +public operator fun Sequence.plus(elements: Iterable): Sequence { + return sequenceOf(this, elements.asSequence()).flatten() +} + +/** + * Returns a sequence containing all elements of original sequence and then all elements of the given [elements] sequence. + * + * Note that the source sequence and the sequence being added are iterated only when an `iterator` is requested from + * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. + * + * The operation is _intermediate_ and _stateless_. + */ +public operator fun Sequence.plus(elements: Sequence): Sequence { + return sequenceOf(this, elements).flatten() +} + +/** + * Returns a sequence containing all elements of the original sequence and then the given [element]. + * + * The operation is _intermediate_ and _stateless_. + */ +@kotlin.internal.InlineOnly +public inline fun Sequence.plusElement(element: T): Sequence { + return plus(element) +} + +/** + * Returns a sequence of snapshots of the window of the given [size] + * sliding along this sequence with the given [step], where each + * snapshot is a list. + * + * Several last lists may have less elements than the given [size]. + * + * Both [size] and [step] must be positive and can be greater than the number of elements in this sequence. + * @param size the number of elements to take in each window + * @param step the number of elements to move the window forward by on an each step, by default 1 + * @param partialWindows controls whether or not to keep partial windows in the end if any, + * by default `false` which means partial windows won't be preserved + * + * @sample samples.collections.Sequences.Transformations.takeWindows + */ +@SinceKotlin("1.2") +public fun Sequence.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false): Sequence> { + return windowedSequence(size, step, partialWindows, reuseBuffer = false) +} + +/** + * Returns a sequence of results of applying the given [transform] function to + * an each list representing a view over the window of the given [size] + * sliding along this sequence with the given [step]. + * + * Note that the list passed to the [transform] function is ephemeral and is valid only inside that function. + * You should not store it or allow it to escape in some way, unless you made a snapshot of it. + * Several last lists may have less elements than the given [size]. + * + * Both [size] and [step] must be positive and can be greater than the number of elements in this sequence. + * @param size the number of elements to take in each window + * @param step the number of elements to move the window forward by on an each step, by default 1 + * @param partialWindows controls whether or not to keep partial windows in the end if any, + * by default `false` which means partial windows won't be preserved + * + * @sample samples.collections.Sequences.Transformations.averageWindows + */ +@SinceKotlin("1.2") +public fun Sequence.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (List) -> R): Sequence { + return windowedSequence(size, step, partialWindows, reuseBuffer = true).map(transform) +} + +/** + * Returns a sequence of values built from the elements of `this` sequence and the [other] sequence with the same index. + * The resulting sequence ends as soon as the shortest input sequence ends. + * + * The operation is _intermediate_ and _stateless_. + * + * @sample samples.collections.Sequences.Transformations.zip + */ +public infix fun Sequence.zip(other: Sequence): Sequence> { + return MergingSequence(this, other) { t1, t2 -> t1 to t2 } +} + +/** + * Returns a sequence of values built from the elements of `this` sequence and the [other] sequence with the same index + * using the provided [transform] function applied to each pair of elements. + * The resulting sequence ends as soon as the shortest input sequence ends. + * + * The operation is _intermediate_ and _stateless_. + * + * @sample samples.collections.Sequences.Transformations.zipWithTransform + */ +public fun Sequence.zip(other: Sequence, transform: (a: T, b: R) -> V): Sequence { + return MergingSequence(this, other, transform) +} + +/** + * Returns a sequence of pairs of each two adjacent elements in this sequence. + * + * The returned sequence is empty if this sequence contains less than two elements. + * + * The operation is _intermediate_ and _stateless_. + * + * @sample samples.collections.Collections.Transformations.zipWithNext + */ +@SinceKotlin("1.2") +public fun Sequence.zipWithNext(): Sequence> { + return zipWithNext { a, b -> a to b } +} + +/** + * Returns a sequence containing the results of applying the given [transform] function + * to an each pair of two adjacent elements in this sequence. + * + * The returned sequence is empty if this sequence contains less than two elements. + * + * The operation is _intermediate_ and _stateless_. + * + * @sample samples.collections.Collections.Transformations.zipWithNextToFindDeltas + */ +@SinceKotlin("1.2") +public fun Sequence.zipWithNext(transform: (a: T, b: T) -> R): Sequence { + return buildSequence result@ { + val iterator = iterator() + if (!iterator.hasNext()) return@result + var current = iterator.next() + while (iterator.hasNext()) { + val next = iterator.next() + yield(transform(current, next)) + current = next + } + } +} + +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Transformations.joinTo + */ +public fun Sequence.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) { + buffer.appendElement(element, transform) + } else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} + +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Transformations.joinToString + */ +public fun Sequence.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +/** + * Creates an [Iterable] instance that wraps the original sequence returning its elements when being iterated. + */ +public fun Sequence.asIterable(): Iterable { + return Iterable { this.iterator() } +} + +/** + * Returns this sequence as a [Sequence]. + */ +@kotlin.internal.InlineOnly +public inline fun Sequence.asSequence(): Sequence { + return this +} + +/** + * Returns an average value of elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("averageOfByte") +public fun Sequence.average(): Double { + var sum: Double = 0.0 + var count: Int = 0 + for (element in this) { + sum += element + checkCountOverflow(++count) + } + return if (count == 0) Double.NaN else sum / count +} + +/** + * Returns an average value of elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("averageOfShort") +public fun Sequence.average(): Double { + var sum: Double = 0.0 + var count: Int = 0 + for (element in this) { + sum += element + checkCountOverflow(++count) + } + return if (count == 0) Double.NaN else sum / count +} + +/** + * Returns an average value of elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("averageOfInt") +public fun Sequence.average(): Double { + var sum: Double = 0.0 + var count: Int = 0 + for (element in this) { + sum += element + checkCountOverflow(++count) + } + return if (count == 0) Double.NaN else sum / count +} + +/** + * Returns an average value of elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("averageOfLong") +public fun Sequence.average(): Double { + var sum: Double = 0.0 + var count: Int = 0 + for (element in this) { + sum += element + checkCountOverflow(++count) + } + return if (count == 0) Double.NaN else sum / count +} + +/** + * Returns an average value of elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("averageOfFloat") +public fun Sequence.average(): Double { + var sum: Double = 0.0 + var count: Int = 0 + for (element in this) { + sum += element + checkCountOverflow(++count) + } + return if (count == 0) Double.NaN else sum / count +} + +/** + * Returns an average value of elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("averageOfDouble") +public fun Sequence.average(): Double { + var sum: Double = 0.0 + var count: Int = 0 + for (element in this) { + sum += element + checkCountOverflow(++count) + } + return if (count == 0) Double.NaN else sum / count +} + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfByte") +public fun Sequence.sum(): Int { + var sum: Int = 0 + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfShort") +public fun Sequence.sum(): Int { + var sum: Int = 0 + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfInt") +public fun Sequence.sum(): Int { + var sum: Int = 0 + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfLong") +public fun Sequence.sum(): Long { + var sum: Long = 0L + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfFloat") +public fun Sequence.sum(): Float { + var sum: Float = 0.0f + for (element in this) { + sum += element + } + return sum +} + +/** + * Returns the sum of all elements in the sequence. + * + * The operation is _terminal_. + */ +@kotlin.jvm.JvmName("sumOfDouble") +public fun Sequence.sum(): Double { + var sum: Double = 0.0 + for (element in this) { + sum += element + } + return sum +} +