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 PersistentHashMap.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 PersistentHashMap.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 PersistentHashMap.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 PersistentHashMap.BitmapIndexedNode(edit, bitpos(self.hsh, shift), [None, self, None, None]) \
                                        .assocEd(edit, shift, hsh, key, val, addedLeaf)