def solve_slice_by_index_shape(x_shape, begin, end, stride, begin_mask, end_mask, squeeze_mask):
    """
    Helper function to solve the shape of tensor slicing.
    """
    # set default values
    rank = len(x_shape)
    if begin is None or len(begin) == 0:
        begin = [None] * rank
    if end is None or len(end) == 0:
        end = [None] * rank
    if stride is None:
        stride = [1] * rank
    if begin_mask is None:
        begin_mask = [False] * rank
    if end_mask is None:
        end_mask = [False] * rank
    if squeeze_mask is None:
        squeeze_mask = [False] * rank

    # basic validation for tensor shape
    if len(begin) != len(x_shape):
        raise TypeError(
            "slice_by_index op: size of 'begin', {}, is not equal to the rank of input, which is {}".format(
                len(begin), len(x_shape)
            )
        )
    if len(end) != len(x_shape):
        raise TypeError(
            "slice_by_index op: size of 'end', {}, is not equal to the rank of input, which is {}".format(
                len(end), len(x_shape)
            )
        )

    # solve for shape inference
    ret_shape = []
    for idx in range(len(x_shape)):
        # skip if we want to squeeze the dimension
        if squeeze_mask[idx]:
            continue

        # for those a[:] cases
        if begin_mask[idx] and end_mask[idx]:
            if is_symbolic(x_shape[idx]):
                if stride[idx] == -1 or stride[idx] == 1:
                    ret_shape.append(x_shape[idx])
                else:
                    ret_shape.append(get_new_symbol())
            else:
                num = np.ceil(float(x_shape[idx]) / abs(stride[idx])).astype(
                    np.int32
                )
                ret_shape.append(num)
            continue

        """
        We first deal with those cases, where the output size is a deterministic number, even if the input dimension
        is unknown (i.e. symbolic)
        - No begin_mask and no end_mask:
          - begin == end. output shape = 0.
          - begin == end - 1, stride > 0. output shape = 1
          - begin == end + 1, stride < 0. output shape = 1
        - begin_mask is false and end_mask is true:
          - begin == -1, stride > 0. output shape = 1
          - begin == 0, stride < 0. output shape = 1
        """
        if (
            not begin_mask[idx]
            and not end_mask[idx]
            and begin[idx] is not None
            and end[idx] is not None
        ):
            out_shape = None
            begin_int64, end_int64 = np.int64(begin[idx]), np.int64(end[idx])
            if begin[idx] >= 0 and end[idx] >= 0 and stride[idx] > 0:
                if end[idx] < begin[idx]:
                    raise ValueError(
                        f"slice_by_index op: unsupported values in for dimension {idx}, "
                        f"(begin, end, stride) : ({begin[idx]}, {end[idx]}, {stride[idx]})"
                    )
                out_shape = max(0, (end_int64 - begin_int64 + stride[idx] - 1) // stride[idx])

            if begin[idx] < 0 and end[idx] < 0 and stride[idx] < 0:
                if begin[idx] < end[idx]:
                    raise ValueError(
                        "slice_by_index op: unsupported values in for dimension {idx}, "
                        "(begin, end, stride) : ({begin[idx]}, {end[idx]}, {stride[idx]})"
                    )
                out_shape = max(0, -(begin_int64 - end_int64 - stride[idx] - 1) // stride[idx])

            if out_shape in (0, 1):
                ret_shape.append(out_shape)
                continue

        if not begin_mask[idx] and end_mask[idx] and begin[idx] is not None:
            if (begin[idx] == 0 and stride[idx] < 0) or (begin[idx] == -1 and stride[idx] > 0):
                ret_shape.append(1)
                continue

        # for symbolic case
        if is_symbolic(x_shape[idx]):
            ret_shape.append(get_new_symbol())
            continue

        # for single-element extraction case
        if x_shape[idx] == 1:
            ret_shape.append(1)
            continue

        # when begin and end are not determined
        if begin[idx] is None and not begin_mask[idx]:
            ret_shape.append(get_new_symbol())
            continue
        if end[idx] is None and not end_mask[idx]:
            ret_shape.append(get_new_symbol())
            continue

        # parse negative dimension
        if begin[idx] is not None and begin[idx] < 0:
            begin[idx] = max(0, begin[idx] + x_shape[idx])
        if end[idx] is not None and end[idx] < 0:
            end[idx] = max(0, end[idx] + x_shape[idx])

        # compute shape
        low, high = [0, x_shape[idx]] if stride[idx] > 0 else [-1, x_shape[idx] - 1]
        begin_idx, end_idx = (
            [begin[idx], end[idx]] if stride[idx] > 0 else [end[idx], begin[idx]]
        )
        is_begin_mask, is_end_mask = (
            [begin_mask[idx], end_mask[idx]]
            if stride[idx] > 0
            else [end_mask[idx], begin_mask[idx]]
        )
        if is_begin_mask:
            begin_idx = low
        end_idx = high if is_end_mask else min(end_idx, high)
        num = np.ceil(float(end_idx - begin_idx) / abs(stride[idx])).astype(
            np.int32
        )
        ret_shape.append(max(0, num))

    return ret_shape

    Helper function to solve the shape of tensor slicing.
    
coremltools/converters/mil/mil/ops/defs/_utils.py