Skip to content

Commit 0738906

Browse files
author
Abduqodiri Qurbonzoda
committed
Implement set TrieNode canonicalization
1 parent 5b44313 commit 0738906

File tree

1 file changed

+28
-12
lines changed
  • core/commonMain/src/implementations/immutableSet

1 file changed

+28
-12
lines changed

core/commonMain/src/implementations/immutableSet/TrieNode.kt

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,36 @@ internal class TrieNode<E>(
9292
// assert(buffer[nodeIndex] !== newNode)
9393

9494
val newBuffer = buffer.copyOf()
95-
newBuffer[nodeIndex] = newNode
95+
96+
// TODO: check how this changes affect `add` operation performance.
97+
// Try to not create this newNode, but pass here the remained element.
98+
val newNodeBuffer = newNode.buffer
99+
if (newNodeBuffer.size == 1 && newNodeBuffer[0] !is TrieNode<*>) {
100+
newBuffer[nodeIndex] = newNodeBuffer[0]
101+
} else {
102+
newBuffer[nodeIndex] = newNode
103+
}
104+
96105
return TrieNode(bitmap, newBuffer)
97106
}
98107

99108
private fun mutableUpdateNodeAtIndex(nodeIndex: Int, newNode: TrieNode<E>, owner: MutabilityOwnership): TrieNode<E> {
100109
// assert(buffer[nodeIndex] !== newNode)
101110

111+
val cell: Any?
112+
val newNodeBuffer = newNode.buffer
113+
if (newNodeBuffer.size == 1 && newNodeBuffer[0] !is TrieNode<*>) {
114+
cell = newNodeBuffer[0]
115+
} else {
116+
cell = newNode
117+
}
118+
102119
if (ownedBy === owner) {
103-
buffer[nodeIndex] = newNode
120+
buffer[nodeIndex] = cell
104121
return this
105122
}
106123
val newBuffer = buffer.copyOf()
107-
newBuffer[nodeIndex] = newNode
124+
newBuffer[nodeIndex] = cell
108125
return TrieNode(bitmap, newBuffer, owner)
109126
}
110127

@@ -184,6 +201,7 @@ internal class TrieNode<E>(
184201

185202
private fun removeCellAtIndex(cellIndex: Int, positionMask: Int): TrieNode<E>? {
186203
// assert(!hasNoCellAt(positionMask))
204+
// It is possible only when this node is the root node
187205
if (buffer.size == 1) return null
188206

189207
val newBuffer = buffer.removeCellAtIndex(cellIndex)
@@ -355,11 +373,9 @@ internal class TrieNode<E>(
355373
if (buffer[cellIndex] is TrieNode<*>) { // element may be in node
356374
val targetNode = nodeAtIndex(cellIndex)
357375
val newNode = targetNode.remove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR)
358-
return when {
359-
targetNode === newNode -> this
360-
newNode == null -> removeCellAtIndex(cellIndex, cellPositionMask)
361-
else -> updateNodeAtIndex(cellIndex, newNode)
362-
}
376+
checkNotNull(newNode)
377+
if (targetNode === newNode) return this
378+
return updateNodeAtIndex(cellIndex, newNode)
363379
}
364380
// element is directly in buffer
365381
if (element == buffer[cellIndex]) {
@@ -383,11 +399,11 @@ internal class TrieNode<E>(
383399
if (buffer[cellIndex] is TrieNode<*>) { // element may be in node
384400
val targetNode = nodeAtIndex(cellIndex)
385401
val newNode = targetNode.mutableRemove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR, mutator)
386-
return when {
387-
targetNode === newNode -> this
388-
newNode == null -> mutableRemoveCellAtIndex(cellIndex, cellPositionMask, mutator.ownership)
389-
else -> mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership)
402+
checkNotNull(newNode)
403+
if (ownedBy === mutator.ownership || targetNode !== newNode) {
404+
return mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership)
390405
}
406+
return this
391407
}
392408
// element is directly in buffer
393409
if (element == buffer[cellIndex]) {

0 commit comments

Comments
 (0)