Created
June 9, 2020 07:53
-
-
Save kmansoft/1df832a3b111b7f5d3fa6f39513880e5 to your computer and use it in GitHub Desktop.
A multi-map of long's in Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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