Skip to content

Commit

Permalink
Return nonnull node from remove method
Browse files Browse the repository at this point in the history
  • Loading branch information
Abduqodiri Qurbonzoda committed Oct 7, 2019
1 parent 3525070 commit 8dc8c13
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,12 @@ internal class PersistentHashMap<K, V>(internal val node: TrieNode<K, V>,
override fun remove(key: K): PersistentHashMap<K, V> {
val newNode = node.remove(key.hashCode(), key, 0)
if (node === newNode) { return this }
if (newNode == null) { return PersistentHashMap.emptyOf() }
return PersistentHashMap(newNode, size - 1)
}

override fun remove(key: K, value: @UnsafeVariance V): PersistentHashMap<K, V> {
val newNode = node.remove(key.hashCode(), key, value, 0)
if (node === newNode) { return this }
if (newNode == null) { return PersistentHashMap.emptyOf() }
return PersistentHashMap(newNode, size - 1)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ internal class PersistentHashMapBuilder<K, V>(private var map: PersistentHashMap
override fun remove(key: K): V? {
operationResult = null
@Suppress("UNCHECKED_CAST")
node = node.mutableRemove(key.hashCode(), key, 0, this) ?: TrieNode.EMPTY as TrieNode<K, V>
node = node.mutableRemove(key.hashCode(), key, 0, this)
return operationResult
}

fun remove(key: K, value: V): Boolean {
val oldSize = size
@Suppress("UNCHECKED_CAST")
node = node.mutableRemove(key.hashCode(), key, value, 0, this) ?: TrieNode.EMPTY as TrieNode<K, V>
node = node.mutableRemove(key.hashCode(), key, value, 0, this)
return oldSize != size
}

Expand Down
39 changes: 16 additions & 23 deletions core/commonMain/src/implementations/immutableMap/TrieNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -292,20 +292,18 @@ internal class TrieNode<K, V>(
return TrieNode(0, 1 shl setBit1, arrayOf<Any?>(node), owner)
}

private fun removeEntryAtIndex(keyIndex: Int, positionMask: Int): TrieNode<K, V>? {
private fun removeEntryAtIndex(keyIndex: Int, positionMask: Int): TrieNode<K, V> {
// assert(hasEntryAt(positionMask))
// It is possible only when this node is the root node
if (buffer.size == ENTRY_SIZE) return null

// assert(buffer.size > ENTRY_SIZE) // can be false only for the root node
val newBuffer = buffer.removeEntryAtIndex(keyIndex)
return TrieNode(dataMap xor positionMask, nodeMap, newBuffer)
}

private fun mutableRemoveEntryAtIndex(keyIndex: Int, positionMask: Int, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V>? {
private fun mutableRemoveEntryAtIndex(keyIndex: Int, positionMask: Int, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V> {
// assert(hasEntryAt(positionMask))
// assert(buffer.size > ENTRY_SIZE)
mutator.size--
mutator.operationResult = valueAtKeyIndex(keyIndex)
if (buffer.size == ENTRY_SIZE) return null

if (ownedBy === mutator.ownership) {
buffer = buffer.removeEntryAtIndex(keyIndex)
Expand All @@ -316,17 +314,16 @@ internal class TrieNode<K, V>(
return TrieNode(dataMap xor positionMask, nodeMap, newBuffer, mutator.ownership)
}

private fun collisionRemoveEntryAtIndex(i: Int): TrieNode<K, V>? {
if (buffer.size == ENTRY_SIZE) return null

private fun collisionRemoveEntryAtIndex(i: Int): TrieNode<K, V> {
// assert(buffer.size > ENTRY_SIZE)
val newBuffer = buffer.removeEntryAtIndex(i)
return TrieNode(0, 0, newBuffer)
}

private fun mutableCollisionRemoveEntryAtIndex(i: Int, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V>? {
private fun mutableCollisionRemoveEntryAtIndex(i: Int, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V> {
// assert(buffer.size > ENTRY_SIZE)
mutator.size--
mutator.operationResult = valueAtKeyIndex(i)
if (buffer.size == ENTRY_SIZE) return null

if (ownedBy === mutator.ownership) {
buffer = buffer.removeEntryAtIndex(i)
Expand Down Expand Up @@ -393,7 +390,7 @@ internal class TrieNode<K, V>(
return TrieNode(0, 0, newBuffer, mutator.ownership)
}

private fun collisionRemove(key: K): TrieNode<K, V>? {
private fun collisionRemove(key: K): TrieNode<K, V> {
for (i in 0 until buffer.size step ENTRY_SIZE) {
if (key == keyAtIndex(i)) {
return collisionRemoveEntryAtIndex(i)
Expand All @@ -402,7 +399,7 @@ internal class TrieNode<K, V>(
return this
}

private fun mutableCollisionRemove(key: K, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V>? {
private fun mutableCollisionRemove(key: K, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V> {
for (i in 0 until buffer.size step ENTRY_SIZE) {
if (key == keyAtIndex(i)) {
return mutableCollisionRemoveEntryAtIndex(i, mutator)
Expand All @@ -411,7 +408,7 @@ internal class TrieNode<K, V>(
return this
}

private fun collisionRemove(key: K, value: V): TrieNode<K, V>? {
private fun collisionRemove(key: K, value: V): TrieNode<K, V> {
for (i in 0 until buffer.size step ENTRY_SIZE) {
if (key == keyAtIndex(i) && value == valueAtKeyIndex(i)) {
return collisionRemoveEntryAtIndex(i)
Expand All @@ -420,7 +417,7 @@ internal class TrieNode<K, V>(
return this
}

private fun mutableCollisionRemove(key: K, value: V, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V>? {
private fun mutableCollisionRemove(key: K, value: V, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V> {
for (i in 0 until buffer.size step ENTRY_SIZE) {
if (key == keyAtIndex(i) && value == valueAtKeyIndex(i)) {
return mutableCollisionRemoveEntryAtIndex(i, mutator)
Expand Down Expand Up @@ -536,7 +533,7 @@ internal class TrieNode<K, V>(
return mutableInsertEntryAt(keyPositionMask, key, value, mutator.ownership)
}

fun remove(keyHash: Int, key: K, shift: Int): TrieNode<K, V>? {
fun remove(keyHash: Int, key: K, shift: Int): TrieNode<K, V> {
val keyPositionMask = 1 shl indexSegment(keyHash, shift)

if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
Expand All @@ -556,7 +553,6 @@ internal class TrieNode<K, V>(
} else {
targetNode.remove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR)
}
checkNotNull(newNode)
if (targetNode === newNode) return this
return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
}
Expand All @@ -565,7 +561,7 @@ internal class TrieNode<K, V>(
return this
}

fun mutableRemove(keyHash: Int, key: K, shift: Int, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V>? {
fun mutableRemove(keyHash: Int, key: K, shift: Int, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V> {
val keyPositionMask = 1 shl indexSegment(keyHash, shift)

if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
Expand All @@ -585,7 +581,6 @@ internal class TrieNode<K, V>(
} else {
targetNode.mutableRemove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR, mutator)
}
checkNotNull(newNode)
if (ownedBy === mutator.ownership || targetNode !== newNode) {
return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
}
Expand All @@ -596,7 +591,7 @@ internal class TrieNode<K, V>(
return this
}

fun remove(keyHash: Int, key: K, value: @UnsafeVariance V, shift: Int): TrieNode<K, V>? {
fun remove(keyHash: Int, key: K, value: @UnsafeVariance V, shift: Int): TrieNode<K, V> {
val keyPositionMask = 1 shl indexSegment(keyHash, shift)

if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
Expand All @@ -616,7 +611,6 @@ internal class TrieNode<K, V>(
} else {
targetNode.remove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR)
}
checkNotNull(newNode)
if (targetNode === newNode) return this
return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
}
Expand All @@ -625,7 +619,7 @@ internal class TrieNode<K, V>(
return this
}

fun mutableRemove(keyHash: Int, key: K, value: @UnsafeVariance V, shift: Int, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V>? {
fun mutableRemove(keyHash: Int, key: K, value: @UnsafeVariance V, shift: Int, mutator: PersistentHashMapBuilder<K, V>): TrieNode<K, V> {
val keyPositionMask = 1 shl indexSegment(keyHash, shift)

if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
Expand All @@ -645,7 +639,6 @@ internal class TrieNode<K, V>(
} else {
targetNode.mutableRemove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR, mutator)
}
checkNotNull(newNode)
if (ownedBy === mutator.ownership || targetNode !== newNode) {
return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ internal class PersistentHashSet<E>(internal val node: TrieNode<E>,
override fun remove(element: E): PersistentSet<E> {
val newNode = node.remove(element.hashCode(), element, 0)
if (node === newNode) { return this }
if (newNode == null) { return PersistentHashSet.emptyOf() }
return PersistentHashSet(newNode, size - 1)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ internal class PersistentHashSetBuilder<E>(private var set: PersistentHashSet<E>
override fun remove(element: E): Boolean {
val size = this.size
@Suppress("UNCHECKED_CAST")
node = node.mutableRemove(element.hashCode(), element, 0, this) ?: TrieNode.EMPTY as TrieNode<E>
node = node.mutableRemove(element.hashCode(), element, 0, this)
return size != this.size
}

Expand Down
27 changes: 10 additions & 17 deletions core/commonMain/src/implementations/immutableSet/TrieNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -188,18 +188,17 @@ internal class TrieNode<E>(
}


private fun removeCellAtIndex(cellIndex: Int, positionMask: Int): TrieNode<E>? {
private fun removeCellAtIndex(cellIndex: Int, positionMask: Int): TrieNode<E> {
// assert(!hasNoCellAt(positionMask))
// It is possible only when this node is the root node
if (buffer.size == 1) return null
// assert(buffer.size > 1) can be false only for the root node

val newBuffer = buffer.removeCellAtIndex(cellIndex)
return TrieNode(bitmap xor positionMask, newBuffer)
}

private fun mutableRemoveCellAtIndex(cellIndex: Int, positionMask: Int, owner: MutabilityOwnership): TrieNode<E>? {
private fun mutableRemoveCellAtIndex(cellIndex: Int, positionMask: Int, owner: MutabilityOwnership): TrieNode<E> {
// assert(!hasNoCellAt(positionMask))
if (buffer.size == 1) return null
// assert(buffer.size > 1)

if (ownedBy === owner) {
buffer = buffer.removeCellAtIndex(cellIndex)
Expand All @@ -210,16 +209,12 @@ internal class TrieNode<E>(
return TrieNode(bitmap xor positionMask, newBuffer, owner)
}

private fun collisionRemoveElementAtIndex(i: Int): TrieNode<E>? {
if (buffer.size == 1) return null

private fun collisionRemoveElementAtIndex(i: Int): TrieNode<E> {
val newBuffer = buffer.removeCellAtIndex(i)
return TrieNode(0, newBuffer)
}

private fun mutableCollisionRemoveElementAtIndex(i: Int, owner: MutabilityOwnership): TrieNode<E>? {
if (buffer.size == 1) return null

private fun mutableCollisionRemoveElementAtIndex(i: Int, owner: MutabilityOwnership): TrieNode<E> {
if (ownedBy === owner) {
buffer = buffer.removeCellAtIndex(i)
return this
Expand Down Expand Up @@ -249,15 +244,15 @@ internal class TrieNode<E>(
return TrieNode(0, newBuffer, mutator.ownership)
}

private fun collisionRemove(element: E): TrieNode<E>? {
private fun collisionRemove(element: E): TrieNode<E> {
val index = buffer.indexOf(element)
if (index != -1) {
return collisionRemoveElementAtIndex(index)
}
return this
}

private fun mutableCollisionRemove(element: E, mutator: PersistentHashSetBuilder<*>): TrieNode<E>? {
private fun mutableCollisionRemove(element: E, mutator: PersistentHashSetBuilder<*>): TrieNode<E> {
val index = buffer.indexOf(element)
if (index != -1) {
mutator.size--
Expand Down Expand Up @@ -333,7 +328,7 @@ internal class TrieNode<E>(
return mutableMoveElementToNode(cellIndex, elementHash, element, shift, mutator.ownership)
}

fun remove(elementHash: Int, element: E, shift: Int): TrieNode<E>? {
fun remove(elementHash: Int, element: E, shift: Int): TrieNode<E> {
val cellPositionMask = 1 shl indexSegment(elementHash, shift)

if (hasNoCellAt(cellPositionMask)) { // element is absent
Expand All @@ -348,7 +343,6 @@ internal class TrieNode<E>(
} else {
targetNode.remove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR)
}
checkNotNull(newNode)
if (targetNode === newNode) return this
return updateNodeAtIndex(cellIndex, newNode)
}
Expand All @@ -359,7 +353,7 @@ internal class TrieNode<E>(
return this
}

fun mutableRemove(elementHash: Int, element: E, shift: Int, mutator: PersistentHashSetBuilder<*>): TrieNode<E>? {
fun mutableRemove(elementHash: Int, element: E, shift: Int, mutator: PersistentHashSetBuilder<*>): TrieNode<E> {
val cellPositionMask = 1 shl indexSegment(elementHash, shift)

if (hasNoCellAt(cellPositionMask)) { // element is absent
Expand All @@ -374,7 +368,6 @@ internal class TrieNode<E>(
} else {
targetNode.mutableRemove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR, mutator)
}
checkNotNull(newNode)
if (ownedBy === mutator.ownership || targetNode !== newNode) {
return mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership)
}
Expand Down

0 comments on commit 8dc8c13

Please sign in to comment.