def dequantize_by_scale_and_zp(
    quantized_data: np.ndarray,
    scale: np.ndarray,
    zero_point: Optional[np.ndarray],
    axis: Optional[int] = None,
) -> np.ndarray:
    """
    Given scale and zero_point (if any), calculate dequantized data.

    The axis is for promoting scale and zero_point to the same rank as quantized_data.
    """
    scale = promote_rank_to_same_as_data(scale, quantized_data, axis)
    if zero_point is not None:
        zero_point = promote_rank_to_same_as_data(zero_point, quantized_data, axis)

    dequantized_data = _cast_from_quantized_dtype(quantized_data)
    if zero_point is not None:
        if _need_manual_broadcast(zero_point, dequantized_data):
            zero_point = repeat_data_as(zero_point, dequantized_data.shape)
        dequantized_data -= _cast_from_quantized_dtype(zero_point)
    if _need_manual_broadcast(scale, dequantized_data):
        scale = repeat_data_as(scale, dequantized_data.shape)
    dequantized_data *= scale
    return dequantized_data.astype(scale.dtype)

    Given scale and zero_point (if any), calculate dequantized data.

    The axis is for promoting scale and zero_point to the same rank as quantized_data.
    
coremltools/optimize/_utils.py