def wrap_index(typingctx, idx, size):
    """
    Calculate index value "idx" relative to a size "size" value as
    (idx % size), where "size" is known to be positive.
    Note that we use the mod(%) operation here instead of
    (idx < 0 ? idx + size : idx) because we may have situations
    where idx > size due to the way indices are calculated
    during slice/range analysis.

    Both idx and size have to be Integer types.
    size should be from the array size vars that array_analysis
    adds and the bitwidth should match the platform maximum.
    """
    require(isinstance(idx, types.scalars.Integer))
    require(isinstance(size, types.scalars.Integer))

    # We need both idx and size to be platform size so that we can compare.
    unified_ty = types.intp if size.signed else types.uintp
    idx_unified = types.intp if idx.signed else types.uintp

    def codegen(context, builder, sig, args):
        ll_idx_unified_ty = context.get_data_type(idx_unified)
        ll_unified_ty = context.get_data_type(unified_ty)
        if idx_unified.signed:
            idx = builder.sext(args[0], ll_idx_unified_ty)
        else:
            idx = builder.zext(args[0], ll_idx_unified_ty)
        if unified_ty.signed:
            size = builder.sext(args[1], ll_unified_ty)
        else:
            size = builder.zext(args[1], ll_unified_ty)
        neg_size = builder.neg(size)
        zero = llvmlite.ir.Constant(ll_unified_ty, 0)
        # If idx is unsigned then these signed comparisons will fail in those
        # cases where the idx has the highest bit set, namely more than 2**63
        # on 64-bit platforms.
        idx_negative = builder.icmp_signed("<", idx, zero)
        pos_oversize = builder.icmp_signed(">=", idx, size)
        neg_oversize = builder.icmp_signed("<=", idx, neg_size)
        pos_res = builder.select(pos_oversize, size, idx)
        neg_res = builder.select(neg_oversize, zero, builder.add(idx, size))
        mod = builder.select(idx_negative, neg_res, pos_res)
        return mod

    return signature(unified_ty, idx, size), codegen

    Calculate index value "idx" relative to a size "size" value as
    (idx % size), where "size" is known to be positive.
    Note that we use the mod(%) operation here instead of
    (idx < 0 ? idx + size : idx) because we may have situations
    where idx > size due to the way indices are calculated
    during slice/range analysis.

    Both idx and size have to be Integer types.
    size should be from the array size vars that array_analysis
    adds and the bitwidth should match the platform maximum.
    
numba/parfors/array_analysis.py