blob: 9ce9b9751bbbd5e2e00242340a1ff0f818be7133 [file] [edit]
// Copyright 2023 Google LLC
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.
#ifndef XNNPACK_SRC_XNNPACK_QUANTIZATION_H_
#define XNNPACK_SRC_XNNPACK_QUANTIZATION_H_
#include <assert.h>
#include <math.h>
#include <stdint.h>
#include "src/xnnpack/math.h"
#include "src/xnnpack/microparams.h"
static inline struct xnn_qd8_quantization_params
xnn_qd8_asymmetric_quantization_params(float min, float max) {
struct xnn_qd8_quantization_params quantization_params;
const float qmin = INT8_MIN;
const float qmax = INT8_MAX;
const float rmin = math_min_f32(0.0f, min);
const float rmax = math_max_f32(0.0f, max);
const float scale = rmin == rmax ? 1.f : (qmax - qmin) / (rmax - rmin);
const float descaled_min = rmin * scale;
const float descaled_max = rmax * scale;
const float zero_point_from_min_error = qmin + descaled_min;
const float zero_point_from_max_error = qmax + descaled_max;
float zero_point = zero_point_from_min_error + zero_point_from_max_error > 0
? qmin - descaled_min
: qmax - descaled_max;
zero_point = math_max_f32(zero_point, qmin);
zero_point = math_min_f32(zero_point, qmax);
assert(zero_point >= INT8_MIN);
assert(zero_point <= INT8_MAX);
const int8_t nudged_zero_point = (int8_t)lrintf(zero_point);
quantization_params.inv_scale = scale;
quantization_params.zero_point = nudged_zero_point;
return quantization_params;
}
static inline struct xnn_qd8_quantization_params
xnn_qdu8_asymmetric_quantization_params(float min, float max) {
struct xnn_qd8_quantization_params quantization_params =
xnn_qd8_asymmetric_quantization_params(min, max);
quantization_params.zero_point += 128;
assert(quantization_params.zero_point >= 0);
assert(quantization_params.zero_point <= UINT8_MAX);
return quantization_params;
}
static inline struct xnn_qd8_quantization_params
xnn_f16_qdu8_asymmetric_quantization_params(xnn_float16 min, xnn_float16 max,
xnn_float16* f16_scale) {
struct xnn_qd8_quantization_params params =
xnn_qdu8_asymmetric_quantization_params(xnn_float16_to_float(min),
xnn_float16_to_float(max));
*f16_scale = xnn_float16_from_float(params.inv_scale);
params.inv_scale = 1.f / params.inv_scale;
return params;
}
static inline struct xnn_qd8_quantization_params
xnn_f32_qdu8_asymmetric_quantization_params(float min, float max,
float* f32_scale) {
struct xnn_qd8_quantization_params params =
xnn_qdu8_asymmetric_quantization_params(min, max);
*f32_scale = params.inv_scale;
params.inv_scale = 1.f / params.inv_scale;
return params;
}
static inline struct xnn_qd8_quantization_params
xnn_f32_qd8_asymmetric_quantization_params(float min, float max,
float* f32_scale) {
struct xnn_qd8_quantization_params params =
xnn_qd8_asymmetric_quantization_params(min, max);
*f32_scale = params.inv_scale;
params.inv_scale = 1.f / params.inv_scale;
return params;
}
static inline struct xnn_qd8_quantization_params
xnn_f16_qd8_asymmetric_quantization_params(xnn_float16 min, xnn_float16 max,
xnn_float16* f16_scale) {
struct xnn_qd8_quantization_params params =
xnn_qd8_asymmetric_quantization_params(xnn_float16_to_float(min),
xnn_float16_to_float(max));
*f16_scale = xnn_float16_from_float(params.inv_scale);
params.inv_scale = 1.f / params.inv_scale;
return params;
}
static inline struct xnn_qd8_quantization_params
xnn_bf16_qd8_asymmetric_quantization_params(xnn_bfloat16 min, xnn_bfloat16 max,
xnn_bfloat16* bf16_scale) {
struct xnn_qd8_quantization_params params =
xnn_qd8_asymmetric_quantization_params(xnn_bfloat16_to_float(min),
xnn_bfloat16_to_float(max));
*bf16_scale = xnn_bfloat16_from_float(params.inv_scale);
params.inv_scale = 1.f / params.inv_scale;
return params;
}
static inline struct xnn_qd8_quantization_params
xnn_bf16_qdu8_asymmetric_quantization_params(xnn_bfloat16 min, xnn_bfloat16 max,
xnn_bfloat16* bf16_scale) {
struct xnn_qd8_quantization_params params =
xnn_qdu8_asymmetric_quantization_params(xnn_bfloat16_to_float(min),
xnn_bfloat16_to_float(max));
*bf16_scale = xnn_bfloat16_from_float(params.inv_scale);
params.inv_scale = 1.f / params.inv_scale;
return params;
}
#endif // XNNPACK_SRC_XNNPACK_QUANTIZATION_H_