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 9, 2019
1 parent d14c192 commit 59ac6e5
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 @@ -290,20 +290,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 @@ -314,17 +312,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 @@ -391,7 +388,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 @@ -400,7 +397,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 @@ -409,7 +406,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 @@ -418,7 +415,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 @@ -534,7 +531,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 @@ -554,7 +551,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 @@ -563,7 +559,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 @@ -583,7 +579,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 @@ -594,7 +589,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 @@ -614,7 +609,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 @@ -623,7 +617,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 @@ -643,7 +637,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 @@ -186,18 +186,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 @@ -208,16 +207,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 @@ -247,15 +242,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 @@ -331,7 +326,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 @@ -346,7 +341,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 @@ -357,7 +351,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 @@ -372,7 +366,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 59ac6e5

Please sign in to comment.