Generate ranges, progressions and progressioniterators for UInt and ULong

This commit is contained in:
Ilya Gorbunov
2018-05-03 21:37:48 +03:00
parent 5c6719b1e6
commit f2c01a9d9b
8 changed files with 465 additions and 1 deletions
@@ -101,6 +101,9 @@ public inline class UByte internal constructor(private val data: Byte) : Compara
/** Decrements this value. */
public operator fun dec(): UByte = TODO()
/** Creates a range from this value to the specified [other] value. */
public operator fun rangeTo(other: UByte): UIntRange = UIntRange(this.toUInt(), other.toUInt())
/** Performs a bitwise AND operation between the two values. */
public infix fun and(other: UByte): UByte = UByte(this.data and other.data)
/** Performs a bitwise OR operation between the two values. */
@@ -101,6 +101,9 @@ public inline class UInt internal constructor(private val data: Int) : Comparabl
/** Decrements this value. */
public operator fun dec(): UInt = TODO()
/** Creates a range from this value to the specified [other] value. */
public operator fun rangeTo(other: UInt): UIntRange = UIntRange(this, other)
/** Shifts this value left by the [bitCount] number of bits. */
public infix fun shl(bitCount: Int): UInt = UInt(data shl bitCount)
/** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with zeros. */
@@ -0,0 +1,117 @@
/*
* 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.
*/
// Auto-generated file. DO NOT EDIT!
package kotlin.ranges
import kotlin.internal.*
/**
* A range of values of type `UInt`.
*/
public class UIntRange(start: UInt, endInclusive: UInt) : UIntProgression(start, endInclusive, 1), ClosedRange<UInt> {
override val start: UInt get() = first
override val endInclusive: UInt get() = last
override fun contains(value: UInt): Boolean = first <= value && value <= last
override fun isEmpty(): Boolean = first > last
override fun equals(other: Any?): Boolean =
other is UIntRange && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last)
override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * first.toInt() + last.toInt())
override fun toString(): String = "$first..$last"
companion object {
/** An empty range of values of type UInt. */
public val EMPTY: UIntRange = UIntRange(UInt.MAX_VALUE, UInt.MIN_VALUE)
}
}
/**
* A progression of values of type `UInt`.
*/
public open class UIntProgression
internal constructor(
start: UInt,
endInclusive: UInt,
step: Int
) : Iterable<UInt> {
init {
if (step == 0.toInt()) throw kotlin.IllegalArgumentException("Step must be non-zero")
}
/**
* The first element in the progression.
*/
public val first: UInt = start
/**
* The last element in the progression.
*/
public val last: UInt = getProgressionLastElement(start, endInclusive, step)
/**
* The step of the progression.
*/
public val step: Int = step
override fun iterator(): UIntIterator = UIntProgressionIterator(first, last, step)
/** Checks if the progression is empty. */
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
override fun equals(other: Any?): Boolean =
other is UIntProgression && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last && step == other.step)
override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * (31 * first.toInt() + last.toInt()) + step.toInt())
override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}"
companion object {
/**
* Creates UIntProgression within the specified bounds of a closed range.
* The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step].
* In order to go backwards the [step] must be negative.
*/
public fun fromClosedRange(rangeStart: UInt, rangeEnd: UInt, step: Int): UIntProgression = UIntProgression(rangeStart, rangeEnd, step)
}
}
/**
* An iterator over a progression of values of type `UInt`.
* @property step the number by which the value is incremented on each step.
*/
private class UIntProgressionIterator(first: UInt, last: UInt, step: Int) : UIntIterator() {
private val finalElement = last
private var hasNext: Boolean = if (step > 0) first <= last else first >= last
private val step = step.toUInt() // use 2-complement math for negative steps
private var next = if (hasNext) first else finalElement
override fun hasNext(): Boolean = hasNext
override fun nextUInt(): UInt {
val value = next
if (value == finalElement) {
if (!hasNext) throw kotlin.NoSuchElementException()
hasNext = false
} else {
next += step
}
return value
}
}
@@ -101,6 +101,9 @@ public inline class ULong internal constructor(private val data: Long) : Compara
/** Decrements this value. */
public operator fun dec(): ULong = TODO()
/** Creates a range from this value to the specified [other] value. */
public operator fun rangeTo(other: ULong): ULongRange = ULongRange(this, other)
/** Shifts this value left by the [bitCount] number of bits. */
public infix fun shl(bitCount: Int): ULong = ULong(data shl bitCount)
/** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with zeros. */
@@ -0,0 +1,117 @@
/*
* 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.
*/
// Auto-generated file. DO NOT EDIT!
package kotlin.ranges
import kotlin.internal.*
/**
* A range of values of type `ULong`.
*/
public class ULongRange(start: ULong, endInclusive: ULong) : ULongProgression(start, endInclusive, 1), ClosedRange<ULong> {
override val start: ULong get() = first
override val endInclusive: ULong get() = last
override fun contains(value: ULong): Boolean = first <= value && value <= last
override fun isEmpty(): Boolean = first > last
override fun equals(other: Any?): Boolean =
other is ULongRange && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last)
override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * (first xor (first shr 32)).toInt() + (last xor (last shr 32)).toInt())
override fun toString(): String = "$first..$last"
companion object {
/** An empty range of values of type ULong. */
public val EMPTY: ULongRange = ULongRange(ULong.MAX_VALUE, ULong.MIN_VALUE)
}
}
/**
* A progression of values of type `ULong`.
*/
public open class ULongProgression
internal constructor(
start: ULong,
endInclusive: ULong,
step: Long
) : Iterable<ULong> {
init {
if (step == 0.toLong()) throw kotlin.IllegalArgumentException("Step must be non-zero")
}
/**
* The first element in the progression.
*/
public val first: ULong = start
/**
* The last element in the progression.
*/
public val last: ULong = getProgressionLastElement(start, endInclusive, step)
/**
* The step of the progression.
*/
public val step: Long = step
override fun iterator(): ULongIterator = ULongProgressionIterator(first, last, step)
/** Checks if the progression is empty. */
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
override fun equals(other: Any?): Boolean =
other is ULongProgression && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last && step == other.step)
override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * (31 * (first xor (first shr 32)).toInt() + (last xor (last shr 32)).toInt()) + (step xor (step ushr 32)).toInt())
override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}"
companion object {
/**
* Creates ULongProgression within the specified bounds of a closed range.
* The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step].
* In order to go backwards the [step] must be negative.
*/
public fun fromClosedRange(rangeStart: ULong, rangeEnd: ULong, step: Long): ULongProgression = ULongProgression(rangeStart, rangeEnd, step)
}
}
/**
* An iterator over a progression of values of type `ULong`.
* @property step the number by which the value is incremented on each step.
*/
private class ULongProgressionIterator(first: ULong, last: ULong, step: Long) : ULongIterator() {
private val finalElement = last
private var hasNext: Boolean = if (step > 0) first <= last else first >= last
private val step = step.toULong() // use 2-complement math for negative steps
private var next = if (hasNext) first else finalElement
override fun hasNext(): Boolean = hasNext
override fun nextULong(): ULong {
val value = next
if (value == finalElement) {
if (!hasNext) throw kotlin.NoSuchElementException()
hasNext = false
} else {
next += step
}
return value
}
}
@@ -0,0 +1,84 @@
/*
* 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.internal
import kotlin.jvm.JvmName
// a mod b (in arithmetical sense)
@JvmName("umod")
private fun mod(a: UInt, b: Int): Int = (a % b.toUInt()).toInt()
private fun mod(a: Int, b: Int): Int {
val mod = a % b
return if (mod >= 0) mod else mod + b
}
@JvmName("umod")
private fun mod(a: ULong, b: Long): Long = (a % b.toULong()).toLong()
private fun mod(a: Long, b: Long): Long {
val mod = a % b
return if (mod >= 0) mod else mod + b
}
// (a - b) mod c
private fun differenceModulo(a: UInt, b: UInt, c: Int): UInt {
return mod(mod(a, c) - mod(b, c), c).toUInt()
}
private fun differenceModulo(a: ULong, b: ULong, c: Long): ULong {
return mod(mod(a, c) - mod(b, c), c).toULong()
}
/**
* Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range
* from [start] to [end] in case of a positive [step], or from [end] to [start] in case of a negative
* [step].
*
* No validation on passed parameters is performed. The given parameters should satisfy the condition:
*
* - either `step > 0` and `start <= end`,
* - or `step < 0` and `start >= end`.
*
* @param start first element of the progression
* @param end ending bound for the progression
* @param step increment, or difference of successive elements in the progression
* @return the final element of the progression
* @suppress
*/
@PublishedApi
internal fun getProgressionLastElement(start: UInt, end: UInt, step: Int): UInt = when {
step > 0 -> if (start >= end) end else end - differenceModulo(end, start, step)
step < 0 -> if (start <= end) end else end + differenceModulo(start, end, -step)
else -> throw kotlin.IllegalArgumentException("Step is zero.")
}
/**
* Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range
* from [start] to [end] in case of a positive [step], or from [end] to [start] in case of a negative
* [step].
*
* No validation on passed parameters is performed. The given parameters should satisfy the condition:
*
* - either `step > 0` and `start <= end`,
* - or `step < 0` and `start >= end`.
*
* @param start first element of the progression
* @param end ending bound for the progression
* @param step increment, or difference of successive elements in the progression
* @return the final element of the progression
* @suppress
*/
@PublishedApi
internal fun getProgressionLastElement(start: ULong, end: ULong, step: Long): ULong = when {
step > 0 -> if (start >= end) end else end - differenceModulo(end, start, step)
step < 0 -> if (start <= end) end else end + differenceModulo(start, end, -step)
else -> throw kotlin.IllegalArgumentException("Step is zero.")
}
@@ -101,6 +101,9 @@ public inline class UShort internal constructor(private val data: Short) : Compa
/** Decrements this value. */
public operator fun dec(): UShort = TODO()
/** Creates a range from this value to the specified [other] value. */
public operator fun rangeTo(other: UShort): UIntRange = UIntRange(this.toUInt(), other.toUInt())
/** Performs a bitwise AND operation between the two values. */
public infix fun and(other: UShort): UShort = UShort(this.data and other.data)
/** Performs a bitwise OR operation between the two values. */