Return the smallest *k* such that L[k] == val and i <= k < j`.  Raises
        ValueError if *val* is not present.  *stop* defaults to the end of the
        list. *start* defaults to the beginning. Negative indices are supported,
        as for slice indices.

def index(self, val, start=None, stop=None):
        """
        Return the smallest *k* such that L[k] == val and i <= k < j`.  Raises
        ValueError if *val* is not present.  *stop* defaults to the end of the
        list. *start* defaults to the beginning. Negative indices are supported,
        as for slice indices.
        """
        # pylint: disable=arguments-differ
        _len = self._len

        if not _len:
            raise ValueError('{0!r} is not in list'.format(val))

        if start is None:
            start = 0
        if start < 0:
            start += _len
        if start < 0:
            start = 0

        if stop is None:
            stop = _len
        if stop < 0:
            stop += _len
        if stop > _len:
            stop = _len

        if stop <= start:
            raise ValueError('{0!r} is not in list'.format(val))

        _maxes = self._maxes
        pos_left = bisect_left(_maxes, val)

        if pos_left == len(_maxes):
            raise ValueError('{0!r} is not in list'.format(val))

        _lists = self._lists
        idx_left = bisect_left(_lists[pos_left], val)

        if _lists[pos_left][idx_left] != val:
            raise ValueError('{0!r} is not in list'.format(val))

        stop -= 1
        left = self._loc(pos_left, idx_left)

        if start <= left:
            if left <= stop:
                return left
        else:
            right = self._bisect_right(val) - 1

            if start <= right:
                return start

        raise ValueError('{0!r} is not in list'.format(val))