def quantize_data_pof2s(data, qType, symmetric, reduce_range=False, method=PowerOfTwoMethod.NonOverflow, pos_range=5):
    """
    :param data: data to quantize
    :param qType: data type to quantize to. Supported types UINT8 and INT8
    :param symmetric: whether symmetric quantization is used or not. This is applied to INT8.
    :return: minimum, maximum, zero point, scale, and quantized weights

    To pack weights, we compute a linear transformation

    - when data `type == uint8` mode, from `[rmin, rmax]` -> :math:`[0, 2^{b-1}]` and
    - when data `type == int8`, from `[-m , m]` -> :math:`[-(2^{b-1}-1), 2^{b-1}-1]` where
        `m = max(abs(rmin), abs(rmax))`

    and add necessary intermediate nodes to transform quantized weight to full weight using the equation

    :math:`r = S(q-z)`, where

    - *r*: real original value
    - *q*: quantized value
    - *S*: scale
    - *z*: zero point
    """
    if is_ort_version_below_1_17():
        rmin = 0
        rmax = 0
        if isinstance(data, np.ndarray):
            rmin = data.min()
            rmax = data.max()

        elif isinstance(data, list) and len(data):
            rmin = min(data)
            rmax = max(data)
        data = np.asarray(data)
    else:
        assert data.dtype in {
            np.float16,
            np.float32,
            np.dtype("float16"),
            np.dtype("float32"),
        }, f"Unexpected dtype {data.dtype!r}"
        rmin = data.min()
        rmax = data.max()
        assert rmin.dtype in {
            np.float16,
            np.float32,
            np.dtype("float16"),
            np.dtype("float32"),
        }, f"Unexpected dtype {rmin.dtype!r}"
        assert rmin.dtype == rmax.dtype

    qmin, qmax = get_qmin_qmax_for_qType(qType, reduce_range, symmetric=symmetric)
    zero_point, scale = compute_scale_zp_pof2s(rmin, rmax, qmin, qmax, symmetric)

    quantized_data = quantize_nparray(qType, data, scale, zero_point)

    if method == PowerOfTwoMethod.NonOverflow:
        return rmin, rmax, zero_point, scale, quantized_data

    elif method == PowerOfTwoMethod.MinMSE:
        rmin_dtype = rmin.dtype
        scale_mse = scale
        zp_mse = zero_point
        quantized_data_mse = quantized_data
        diff_min = float("inf")
        for i in range(pos_range):
            new_scale = pos2scale(scale2pos(scale) + i)
            rmin = min((qmin - zero_point) * new_scale, 0)
            if not is_ort_version_below_1_17():
                new_scale = np.array(new_scale, dtype=rmin_dtype)
                rmin = np.array(rmin, dtype=rmin_dtype)
            new_zero_point = quantize_zero_point(rmin, qmin, qmax, symmetric, new_scale)

            new_quantized_data = quantize_nparray(qType, data, new_scale, new_zero_point)
            diff = np.sum((dequantize_data(new_quantized_data, new_scale, new_zero_point) - data) ** 2)
            if diff < diff_min:
                diff_min = diff
                scale_mse = new_scale
                zp_mse = new_zero_point
                quantized_data_mse = new_quantized_data

        rmin_mse = (qmin - zp_mse) * scale_mse
        rmax_mse = (qmax - zp_mse) * scale_mse
        if not is_ort_version_below_1_17():
            rmin_mse = np.array(rmin_mse, dtype=rmin_dtype)
            rmax_mse = np.array(rmax_mse, dtype=rmax.dtype)

        return rmin_mse, rmax_mse, zp_mse, scale_mse, quantized_data_mse
    else:
        raise ValueError(f"Unsupported method: {method}")

    :param data: data to quantize
    :param qType: data type to quantize to. Supported types UINT8 and INT8
    :param symmetric: whether symmetric quantization is used or not. This is applied to INT8.
    :return: minimum, maximum, zero point, scale, and quantized weights

    To pack weights, we compute a linear transformation

    - when data `type == uint8` mode, from `[rmin, rmax]` -> :math:`[0, 2^{b-1}]` and
    - when data `type == int8`, from `[-m , m]` -> :math:`[-(2^{b-1}-1), 2^{b-1}-1]` where
        `m = max(abs(rmin), abs(rmax))`

    and add necessary intermediate nodes to transform quantized weight to full weight using the equation

    :math:`r = S(q-z)`, where

    - *r*: real original value
    - *q*: quantized value
    - *S*: scale
    - *z*: zero point
    
olive/passes/onnx/vitis_ai/quant_utils.py