def ensureEditable(self, edit): if self.edit is edit: return self n = bitCount(self.bitmap) newArray = [None] * (2*(n+1) if n >= 0 else 4) # make room for next assoc arrayCopy(self.array, 0, newArray, 0, 2*n) return BitmapIndexedNode(self.edit, self.bitmap, newArray)
def editAndRemovePair(self, edit, bit, i): if self.bitmap == bit: return None editable = self.ensureEditable(edit) editable.bitmap ^= bit arrayCopy(editable.array, 2*(i+1), editable.array, 2*i, len(editable.array) - 2*(i+1)) editable.array[len(editable.array) - 2] = None editable.array[len(editable.array) - 1] = None return editable
def assoc(self, shift, hsh, key, val, addedLeaf): if hsh == self.hsh: idx = self.findIndex(key) if idx != -1: if self.array[idx + 1] == val: return self return HashCollisionNode(None, hsh, self.count, cloneAndSet(self.array, idx + 1, val)) newArray = [None] * (len(self.array) + 2) arrayCopy(self.array, 0, newArray, 0, len(self.array)) newArray[len(self.array)] = key newArray[len(self.array) + 1] = val addedLeaf.val = addedLeaf return HashCollisionNode(self.edit, hsh, self.count + 1, newArray) # nest it in a bitmap node return BitmapIndexedNode(None, bitpos(self.hsh, shift), [None, self]) \ .assoc(shift, hsh, key, val, addedLeaf)
def assocEd(self, edit, shift, hsh, key, val, addedLeaf): bit = bitpos(hsh, shift) idx = self.index(bit) if self.bitmap & bit: keyOrNull = self.array[2*idx] valOrNode = self.array[2*idx+1] if keyOrNull is None: n = valOrNode.assoc(edit, shift + 5, hsh, key, val, addedLeaf) if n == valOrNode: return self return self.editAndSet(edit, 2*idx+1, n) if key == keyOrNull: if val == valOrNode: return self return self.editAndSet(edit, 2*idx+1, val) addedLeaf.val = addedLeaf return self.editAndSet(edit, 2*idx, None, 2*idx+1, createNode(edit, shift + 5, keyOrNull, valOrNode, hsh, key, val)) else: n = bitCount(self.bitmap) if n*2 < len(self.array): addedLeaf.val = addedLeaf editable = self.ensureEditable(edit) arrayCopy(editable.array, 2*idx, editable.array, 2*(idx+1), 2*(n-idx)) editable.array[2*idx] = key editable.array[2*idx+1] = val editable.bitmap |= bit return editable if n >= 16: nodes = [None] * 32 jdx = mask(hsh, shift) nodes[jdx] = EMPTY_BITMAP_NODE.assocEd(edit, shift + 5, hsh, key, val, addedLeaf) j = 0 for i in range(32): if (self.bitmap >> i) & 1: if self.array[j] is None: nodes[i] = self.array[j+1] else: nodes[i] = EMPTY_BITMAP_NODE.assocEd(edit, shift + 5, hash(self.array[j]), self.array[j], self.array[j+1], addedLeaf) j += 2 return ArrayNode(edit, n + 1, nodes) else: newArray = [None] * (2*(n+4)) arrayCopy(self.array, 0, newArray, 0, 2*idx) newArray[2*idx] = key addedLeaf.val = addedLeaf newArray[2*idx+1] = val arrayCopy(self.array, 2*idx, newArray, 2*(idx+1), 2*(n-idx)) editable = self.ensureEditable(edit) editable.array = newArray editable.bitmap |= bit return editable
def assocEd(self, edit, shift, hsh, key, val, addedLeaf): if hsh == self.hsh: idx = self.findIndex(key) if idx != -1: if self.array[idx + 1] == val: return self return self.editAndSet(edit, idx+1, val) if len(self.array) > 2 * self.count: addedLeaf.val = addedLeaf editable = self.editAndSet(edit, 2 * self.count, key, 2 * self.count+1, val) editable.count += 1 return editable newArray = [None] * (len(self.array) + 2) arrayCopy(self.array, 0, newArray, 0, len(self.array)) newArray[len(self.array)] = key newArray[len(self.array) + 1] = val addedLeaf.val = addedLeaf return self.ensureEditable(edit, self.count + 1, newArray) # nest it in a bitmap node return BitmapIndexedNode(edit, bitpos(self.hsh, shift), [None, self, None, None]) \ .assocEd(edit, shift, hsh, key, val, addedLeaf)