Skip to content

Instantly share code, notes, and snippets.

@kmansoft
Created June 9, 2020 07:53
Show Gist options
  • Save kmansoft/1df832a3b111b7f5d3fa6f39513880e5 to your computer and use it in GitHub Desktop.
Save kmansoft/1df832a3b111b7f5d3fa6f39513880e5 to your computer and use it in GitHub Desktop.
A multi-map of long's in Kotlin
class LongToMultiLongArray {
fun put(key: Long, value: Long) {
var i = ContainerHelpers.binarySearch(mKeys, mSize, key)
if (i >= 0) {
val index = mIndices[i]
val offset = ((index shr 32) and 0x7FFF).toInt()
val cap = ((index shr 16) and 0x7FFF).toInt()
val len = ((index) and 0x7FFF).toInt()
if (len < cap) {
mStorage[offset + len] = value
mIndices[i] = (offset.toLong() shl 32) or ((cap shl 16) or (len + 1)).toLong()
} else {
val newCap = newSize(cap)
if (newCap <= MAX_CAP) {
val newOffset = allocateStorage(newCap)
if (offset >= 0) {
System.arraycopy(mStorage, offset, mStorage, newOffset, len)
mStorage[newOffset + len] = value
mIndices[i] = (newOffset.toLong() shl 32) or ((newCap shl 16) or (len + 1)).toLong()
}
}
}
} else {
i = i.inv()
val cap = 1
val offset = allocateStorage(cap)
if (offset >= 0) {
val len = 0
mStorage[offset + len] = value
val index = (offset.toLong() shl 32) or ((cap shl 16) or (len + 1)).toLong()
mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key)
mIndices = GrowingArrayUtils.insert(mIndices, mSize, i, index)
++mSize
}
}
}
fun keyCount(): Int {
return mSize
}
fun keyAt(index: Int): Long {
return mKeys[index]
}
fun get(key: Long, iterator: (Long, Long) -> Unit) {
val i = ContainerHelpers.binarySearch(mKeys, mSize, key)
if (i >= 0) {
val index = mIndices[i]
val offset = ((index shr 32) and 0x7FFF).toInt()
val len = ((index) and 0x7FFF).toInt()
for (j in 0 until len) {
iterator(key, mStorage[offset + j])
}
}
}
private fun allocateStorage(cap: Int): Int {
if (mStorageSize + cap > mStorage.size) {
val newSize = newSize(mStorageSize + cap)
if (newSize > MAX_STORAGE) {
return -1
}
val n = LongArray(newSize)
System.arraycopy(mStorage, 0, n, 0, mStorageSize)
mStorage = n
}
val r = mStorageSize
mStorageSize += cap
return r
}
private fun newSize(s: Int): Int {
return (s * 3 / 2) + 4
}
private var mKeys = LongArray(INITIAL_SIZE)
private var mIndices = LongArray(INITIAL_SIZE)
private var mStorage = LongArray(INITIAL_SIZE)
private var mSize = 0
private var mStorageSize = 0
companion object {
private val INITIAL_SIZE = 16
private val MAX_CAP = 16000
private val MAX_STORAGE = 32000
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment