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 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 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 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))
 def index(self, bit):
     return bitCount(self.bitmap & (bit - 1))