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 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 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 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):
        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)
    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)