def METHOD_NAME(
    floating_point_func: Callable[[np.ndarray], np.ndarray],
    input_scale: "relay.Expr",
    input_zero_point: "relay.Expr",
    output_scale: "relay.Expr",
    output_zero_point: "relay.Expr",
    in_axis: int = -1,
    out_axis: int = -1,
    in_dtype: str = "uint8",
    out_dtype: str = "uint8",
) -> np.ndarray:
    """
    Return a table where each input indexes to the output quantizing the given function.
    Note this also supports mapping unsigned and signed integers to each other.
    Args:
      floating_point_func: The numpy function which this table is to approximate
      input_scale: The scale of the quantized input tensor.
      input_zero_point: The zero point of the quantized input tensor.
      output_scale: The scale of the quantized output tensor.
      output_zero_point: The zero point of the quantized output tensor.
      in_axis: The axis for multi-channel quantization of the input if applicable.
      out_axis: The axis for multi-channel quantization of the output if applicable.
      in_dtype: The dtype of the input tensor.
      out_dtype: The wanted dtype of the output tensor.
    Returns:
      A numpy array where values in quantized space will index to the output in quantized space
      approximating the given function.
    """
    if not np.issubdtype(np.dtype(in_dtype), np.integer) or not np.issubdtype(
        np.dtype(out_dtype), np.integer
    ):
        raise ValueError(
            f"Only integer dtypes allowed got {in_dtype} and {out_dtype} for in and out dtypes."
        )
    dtype_info = np.iinfo(in_dtype)
    num_bits = dtype_info.bits
    # Use TVMs quantization methods via relay to be consistent
    # inputs_quantized = np.array(range(dtype_info.min, dtype_info.max + 1)).astype(in_dtype)
    # First generate a list of all num_bit integer patterns
    inputs_quantized = np.array(range(0, 2**num_bits), dtype=f"uint{num_bits}")
    # Reinterpret bits as the real datatype
    # Note what we are doing here is a bit tricky, the canonical view of our lookup table
    # is using the uintX version. When we run the lookup in the relay graph, we cast the
    # bit pattern back into this form.
    inputs_quantized = inputs_quantized.view(in_dtype)
    inputs_quantized = relay.const(inputs_quantized, dtype=in_dtype)
    inputs_dequantized = run_const_expr(
        relay.qnn.op.dequantize(
            inputs_quantized,
            input_scale=input_scale,
            input_zero_point=input_zero_point,
            axis=in_axis,
        )
    )
    output_dequantized = relay.const(floating_point_func(inputs_dequantized))
    output_quantized = run_const_expr(
        relay.qnn.op.quantize(
            output_dequantized, output_scale, output_zero_point, out_axis, out_dtype
        )
    )
    return output_quantized