def resolve_negative_axis(ndims, axis):
    """
    Resolve all negative `axis` indices according to `ndims` into positive.

    Usage::

        resolve_negative_axis(4, [0, -1, -2])  # output: (0, 3, 2)

    Args:
        ndims (int): Number of total dimensions.
        axis (Iterable[int]): The axis indices.

    Returns:
        tuple[int]: The resolved positive axis indices.

    Raises:
        ValueError: If any index in `axis` is out of range.
    """
    axis = tuple(int(a) for a in axis)
    ret = []
    for a in axis:
        if a < 0:
            a += ndims
        if a < 0 or a >= ndims:
            raise ValueError('`axis` out of range: {} vs ndims {}.'.
                             format(axis, ndims))
        ret.append(a)
    if len(set(ret)) != len(ret):
        raise ValueError('`axis` has duplicated elements after resolving '
                         'negative axis: ndims {}, axis {}.'.
                         format(ndims, axis))
    return tuple(ret)