Skip to content

Commit cb23766

Browse files
author
Abduqodiri Qurbonzoda
committed
Implement set TrieNode canonicalization
1 parent 6e8b652 commit cb23766

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
@@ -93,19 +93,36 @@ internal class TrieNode<E>(
9393
// assert(buffer[nodeIndex] !== newNode)
9494

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

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

112+
val cell: Any?
113+
val newNodeBuffer = newNode.buffer
114+
if (newNodeBuffer.size == 1 && newNodeBuffer[0] !is TrieNode<*>) {
115+
cell = newNodeBuffer[0]
116+
} else {
117+
cell = newNode
118+
}
119+
103120
if (ownedBy === owner) {
104-
buffer[nodeIndex] = newNode
121+
buffer[nodeIndex] = cell
105122
return this
106123
}
107124
val newBuffer = buffer.copyOf()
108-
newBuffer[nodeIndex] = newNode
125+
newBuffer[nodeIndex] = cell
109126
return TrieNode(bitmap, newBuffer, owner)
110127
}
111128

@@ -161,6 +178,7 @@ internal class TrieNode<E>(
161178

162179
private fun removeCellAtIndex(cellIndex: Int, positionMask: Int): TrieNode<E>? {
163180
// assert(!hasNoCellAt(positionMask))
181+
// It is possible only when this node is the root node
164182
if (buffer.size == 1) return null
165183

166184
val newBuffer = buffer.removeCellAtIndex(cellIndex)
@@ -318,11 +336,9 @@ internal class TrieNode<E>(
318336
} else {
319337
targetNode.remove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR)
320338
}
321-
return when {
322-
targetNode === newNode -> this
323-
newNode == null -> removeCellAtIndex(cellIndex, cellPositionMask)
324-
else -> updateNodeAtIndex(cellIndex, newNode)
325-
}
339+
checkNotNull(newNode)
340+
if (targetNode === newNode) return this
341+
return updateNodeAtIndex(cellIndex, newNode)
326342
}
327343
// element is directly in buffer
328344
if (element == buffer[cellIndex]) {
@@ -346,11 +362,11 @@ internal class TrieNode<E>(
346362
} else {
347363
targetNode.mutableRemove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR, mutator)
348364
}
349-
return when {
350-
targetNode === newNode -> this
351-
newNode == null -> mutableRemoveCellAtIndex(cellIndex, cellPositionMask, mutator.ownership)
352-
else -> mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership)
365+
checkNotNull(newNode)
366+
if (ownedBy === mutator.ownership || targetNode !== newNode) {
367+
return mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership)
353368
}
369+
return this
354370
}
355371
// element is directly in buffer
356372
if (element == buffer[cellIndex]) {

0 commit comments

Comments
 (0)