Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// Copyright 2017-present Strumenta and contributors, licensed under Apache 2.0.
// Copyright 2024-present Strumenta and contributors, licensed under BSD 3-Clause.
package com.strumenta.antlrkotlin.runtime
import kotlin.math.min
/**
* A vector of bits growing if necessary and allowing one
* to set/clear/read bits from it by a bit index.
*
* Note(Edoardo): this is a cleaned up version of the Kotlin Native BitSet,
* copied because of [KT-57088](https://youtrack.jetbrains.com/issue/KT-57088)
*
* @constructor Creates an empty bit set with the specified [size]
* @param size The size of one element in the array used to store bits
*/
public class SimpleBitSet(size: Int) {
private companion object {
// Default size of one element in the array used to store bits.
private const val ELEMENT_SIZE: Int = 64
private const val MAX_BIT_OFFSET: Int = ELEMENT_SIZE - 1
private const val ALL_TRUE: Long = -1L // 0xFFFF_FFFF_FFFF_FFFF
private const val ALL_FALSE: Long = 0L // 0x0000_0000_0000_0000
}
init {
require(size >= 0) {
"The initial bitset size must be equal or greater than 0"
}
}
private var bits: LongArray = LongArray(bitToElementSize(size))
private val lastIndex: Int
get() = size - 1
// Transforms a bit index into an element index in the `bits` array.
private val Int.elementIndex: Int
get() = this / ELEMENT_SIZE
// Transforms a bit index in the set into a bit in the element of the `bits` array.
private val Int.bitOffset: Int
get() = this % ELEMENT_SIZE
// Transforms a bit index in the set into pair of a `bits` element index and a bit index in the element.
private val Int.asBitCoordinates: Pair
get() = Pair(elementIndex, bitOffset)
// Transforms a bit offset to the mask with only bit set corresponding to the offset.
private val Int.asMask: Long
get() = 0x1L shl this
// Transforms a bit offset to the mask with only bits before the index (inclusive) set.
private val Int.asMaskBefore: Long
get() = getMaskBetween(0, this)
// Transforms a bit offset to the mask with only bits after the index (inclusive) set.
private val Int.asMaskAfter: Long
get() = getMaskBetween(this, MAX_BIT_OFFSET)
/**
* Returns an index of the last bit that has `true` value.
*
* Returns `-1` if the bit set is empty.
*/
public val lastTrueIndex: Int
get() = previousSetBit(size)
/**
* Is `true` if this bit set contains no bits set to `true`.
*/
public val isEmpty: Boolean
get() = bits.all { it == ALL_FALSE }
/**
* Actual number of bits available in this bit set.
*
* All bits with indices >= [size] assumed to be `0`.
*/
public var size: Int = size
private set
/**
* Creates a bit set of the default [ELEMENT_SIZE] length.
*/
public constructor() : this(ELEMENT_SIZE)
/**
* Creates a bit set of given [length] filling elements using [initializer].
*/
public constructor(length: Int, initializer: (Int) -> Boolean) : this(length) {
for (i in 0..= size) {
size = bitIndex + 1
if (bitIndex.elementIndex >= bits.size) {
// Create a new array containing the index-th bit
bits = bits.copyOf(bitToElementSize(bitIndex + 1))
}
}
}
/**
* Sets the bit at the specified [bitIndex] to `true`.
*/
public fun set(bitIndex: Int): Unit =
set(bitIndex, true)
/**
* Sets the bit at the specified [bitIndex] to the specified [value].
*/
public fun set(bitIndex: Int, value: Boolean) {
ensureCapacity(bitIndex)
val (elementIndex, offset) = bitIndex.asBitCoordinates
setBitsWithMask(elementIndex, offset.asMask, value)
}
/**
* Sets the bits at indices between [from] (inclusive) and [to] (exclusive)
* to the specified [value].
*/
public fun set(from: Int, to: Int, value: Boolean = true): Unit =
set(from.. range.last) {
// Empty range
return
}
ensureCapacity(range.last)
val (fromIndex, fromOffset) = range.first.asBitCoordinates
val (toIndex, toOffset) = range.last.asBitCoordinates
if (toIndex == fromIndex) {
val mask = getMaskBetween(fromOffset, toOffset)
setBitsWithMask(fromIndex, mask, value)
} else {
// Set bits in the first element
setBitsWithMask(fromIndex, fromOffset.asMaskAfter, value)
// Set all bits of all elements (excluding border ones) to 0 or 1 depending
for (index in fromIndex + 1.. range.last) {
// Empty range
return
}
ensureCapacity(range.last)
val (fromIndex, fromOffset) = range.first.asBitCoordinates
val (toIndex, toOffset) = range.last.asBitCoordinates
if (toIndex == fromIndex) {
val mask = getMaskBetween(fromOffset, toOffset)
flipBitsWithMask(fromIndex, mask)
} else {
// Flip bits in the first element
flipBitsWithMask(toIndex, toOffset.asMaskAfter)
// Flip bits between the first and the last elements
for (index in fromIndex + 1..= size) {
return if (lookFor) {
-1
} else {
startIndex
}
}
val (startElementIndex, startOffset) = startIndex.asBitCoordinates
// Look for the next set bit in the first element
var element = bits[startElementIndex]
for (offset in startOffset..MAX_BIT_OFFSET) {
val bit = element and (0x1L shl offset) != 0L
if (bit == lookFor) {
// Look for not 0 if we need a set bit and look for 0 otherwise
return bitIndex(startElementIndex, offset)
}
}
// Look for in the remaining elements
for (index in startElementIndex + 1..bits.lastIndex) {
element = bits[index]
for (offset in 0..MAX_BIT_OFFSET) {
val bit = element and (0x1L shl offset) != 0L
if (bit == lookFor) {
// Look for not 0 if we need a set bit and look for 0 otherwise
return bitIndex(index, offset)
}
}
}
return if (lookFor) -1 else size
}
/**
* Returns an index of a next bit which value is `true` after [startIndex] (inclusive).
*
* Returns `-1` if there is no such bits after [startIndex].
*
* @throws IndexOutOfBoundsException If [startIndex] `< 0`
*/
@Suppress("MemberVisibilityCanBePrivate")
public fun nextSetBit(startIndex: Int): Int =
nextBit(startIndex, true)
/**
* Returns an index of a next bit which value is `false` after [startIndex] (inclusive).
*
* Returns [size] if there is no such bits between [startIndex] and [size] `- 1`
* assuming that the set has an infinite sequence of `false` bits after `(size - 1)-th`.
*
* @throws IndexOutOfBoundsException If [startIndex] `< 0`
*/
public fun nextClearBit(startIndex: Int): Int =
nextBit(startIndex, false)
/**
* Returns the biggest index of a bit which value is [lookFor] before [startIndex] (inclusive).
*
* Returns `-1` if there is no such bits before [startIndex], or if [startIndex] >= [size].
*/
@Suppress("MemberVisibilityCanBePrivate")
public fun previousBit(startIndex: Int, lookFor: Boolean): Int {
var correctStartIndex = startIndex
if (startIndex >= size) {
// We assume that all bits after `size - 1` are 0.
// So we can return the start index if we are looking for 0
if (!lookFor) {
return startIndex
}
// If we are looking for 1 we can skip all these 0 after `size - 1`
correctStartIndex = size - 1
}
if (correctStartIndex < -1) {
throw IndexOutOfBoundsException("startIndex < -1: $startIndex")
}
if (correctStartIndex == -1) {
return -1
}
val (startElementIndex, startOffset) = correctStartIndex.asBitCoordinates
// Look for the next set bit in the first element
var element = bits[startElementIndex]
for (offset in startOffset downTo 0) {
val bit = element and (0x1L shl offset) != 0L
if (bit == lookFor) {
// Look for not 0 if we need a set bit and look for 0 otherwise
return bitIndex(startElementIndex, offset)
}
}
// Look for in the remaining elements
for (index in startElementIndex - 1 downTo 0) {
element = bits[index]
for (offset in MAX_BIT_OFFSET downTo 0) {
val bit = element and (0x1L shl offset) != 0L
if (bit == lookFor) {
// Look for not 0 if we need a set bit and look for 0 otherwise
return bitIndex(index, offset)
}
}
}
return -1
}
/**
* Returns the biggest index of a bit which value is `true` before [startIndex] (inclusive).
*
* Returns `-1` if there is no such bits before [startIndex] or if [startIndex] `== -1`.
*
* If [startIndex] >= [size], will search from `(size - 1)-th` bit.
*
* @throws IndexOutOfBoundsException If [startIndex] < `-1`
*/
@Suppress("MemberVisibilityCanBePrivate")
public fun previousSetBit(startIndex: Int): Int =
previousBit(startIndex, true)
/**
* Returns the biggest index of a bit which value is `false` before [startIndex] (inclusive).
*
* Returns `-1` if there is no such bits before [startIndex] or if [startIndex] `== -1`.
*
* If [startIndex] >= [size], will return [startIndex] assuming that
* the set has an infinite sequence of `false` bits after `(size - 1)-th`.
*
* @throws IndexOutOfBoundsException If [startIndex] `< -1`
*/
public fun previousClearBit(startIndex: Int): Int =
previousBit(startIndex, false)
/**
* Returns the value of the bit at the specified [bitIndex].
*/
public operator fun get(bitIndex: Int): Boolean {
if (bitIndex < 0) {
throw IndexOutOfBoundsException("bitIndex < 0: $bitIndex")
}
if (bitIndex >= size) {
return false
}
val (elementIndex, offset) = bitIndex.asBitCoordinates
return bits[elementIndex] and offset.asMask != 0L
}
private inline fun doOperation(another: SimpleBitSet, operation: Long.(Long) -> Long) {
ensureCapacity(another.lastIndex)
var index = 0
while (index < another.bits.size) {
bits[index] = operation(bits[index], another.bits[index])
index++
}
while (index < bits.size) {
bits[index] = operation(bits[index], ALL_FALSE)
index++
}
}
/**
* Performs a logical `and` operation over corresponding bits
* of this and [another] bit sets.
*
* The result is saved in this bit set.
*/
public fun and(another: SimpleBitSet): Unit =
doOperation(another, Long::and)
/**
* Performs a logical `or` operation over corresponding bits
* of this and [another] bit sets.
*
* The result is saved in this bit set.
*/
public fun or(another: SimpleBitSet): Unit =
doOperation(another, Long::or)
/**
* Performs a logical `xor` operation over corresponding bits
* of this and [another] bit sets.
*
* The result is saved in this bit set.
*/
public fun xor(another: SimpleBitSet): Unit =
doOperation(another, Long::xor)
/**
* Performs a logical `and` + `not` operations over corresponding
* bits of this and [another] bit sets.
*
* The result is saved in this bit set.
*/
public fun andNot(another: SimpleBitSet) {
ensureCapacity(another.lastIndex)
var index = 0
while (index < another.bits.size) {
bits[index] = bits[index] and another.bits[index].inv()
index++
}
while (index < bits.size) {
bits[index] = bits[index] and ALL_TRUE
index++
}
}
/**
* Returns `true` if [another] bit set has any bits set to `true`
* that are also set to `true` in this bit set.
*/
public fun intersects(another: SimpleBitSet): Boolean {
val to = min(bits.size, another.bits.size)
return (0.. other.bits.size) {
bits
} else {
other.bits
}
while (index < longestBits.size) {
if (longestBits[index] != ALL_FALSE) {
return false
}
index++
}
return true
}
}