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 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 assoc(self, 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(shift + 5, hsh, key, val, addedLeaf) if n is valOrNode: return self return BitmapIndexedNode(None, self.bitmap, cloneAndSet(self.array, 2*idx+1, n)) if key == keyOrNull: if val is valOrNode: return self return BitmapIndexedNode(None, self.bitmap, cloneAndSet(self.array, 2*idx+1, val)) addedLeaf.val = addedLeaf return BitmapIndexedNode(None, self.bitmap, cloneAndSet(self.array, 2*idx, None, 2*idx+1, createNode(None, shift + 5, keyOrNull, valOrNode, hsh, key, val))) else: n = bitCount(self.bitmap) if n >= 16: nodes = [None] * 32 jdx = mask(hsh, shift) nodes[jdx] = EMPTY_BITMAP_NODE.assoc(shift + 5, hsh, key, val, addedLeaf) j = 0 for i in range(0, 32): if (self.bitmap >> i) & 1: if self.array[j] is None: nodes[i] = self.array[j+1] else: nodes[i] = EMPTY_BITMAP_NODE.assoc(shift + 5, hash(self.array[j]), self.array[j], self.array[j+1], addedLeaf) j += 2 return ArrayNode(None, n + 1, nodes) else: newArray = self.array[:2 * idx] newArray.append(key) newArray.append(val) newArray.extend(self.array[2*idx:]) addedLeaf.val = addedLeaf return BitmapIndexedNode(None, self.bitmap | bit, newArray)
def index(self, bit): return bitCount(self.bitmap & (bit - 1))