70 #include <type_traits>
90 template <
typename QuantT,
typename MinT,
typename MaxT,
typename ValueT>
91 [[nodiscard]] QuantT
encode(MinT quant_min, MaxT quant_max, ValueT value) noexcept;
101 template <
typename ReturnT,
typename MinT,
typename MaxT,
typename ValueT>
102 [[nodiscard]] ReturnT
decode(MinT quant_min, MaxT quant_max, ValueT value) noexcept;
114 template <
typename QuantT,
typename ExtentT,
typename ValueT>
115 [[nodiscard]] QuantT
encode(ExtentT extent, ValueT value) noexcept;
127 template <
typename ReturnT,
typename ExtentT,
typename ValueT>
128 [[nodiscard]] ReturnT
decode(ExtentT extent, ValueT value) noexcept;
134 template <
typename QuantT,
typename MinT,
typename MaxT,
typename ValueT>
135 inline QuantT
encode(MinT quant_min, MaxT quant_max, ValueT value) noexcept {
136 static_assert(std::is_integral_v<QuantT> && !std::is_same_v<QuantT, bool>,
"QuantT must be integral.");
137 static_assert(std::is_arithmetic_v<MinT>,
"MinT must be arithmetic.");
138 static_assert(std::is_arithmetic_v<MaxT>,
"MaxT must be arithmetic.");
139 static_assert(std::is_arithmetic_v<ValueT>,
"ValueT must be arithmetic.");
141 using CalcT = std::common_type_t<float, MinT, MaxT, ValueT>;
143 auto min =
static_cast<CalcT
>(quant_min);
144 auto max =
static_cast<CalcT
>(quant_max);
145 auto target =
static_cast<CalcT
>(value);
147 if VUNLIKELY (min != min || max != max || target != target || max <= min) {
148 return static_cast<QuantT
>(0);
151 auto quant_max_value =
static_cast<CalcT
>(std::numeric_limits<QuantT>::max());
152 auto quant_min_value =
153 std::is_signed_v<QuantT> ? -quant_max_value :
static_cast<CalcT
>(std::numeric_limits<QuantT>::lowest());
155 auto quant_lowest_value =
static_cast<CalcT
>(std::numeric_limits<QuantT>::lowest());
156 auto quant_range = quant_max_value - quant_min_value;
158 auto scaled = ((target - min) * quant_range / (max - min)) + quant_min_value;
159 auto rounded = scaled >=
static_cast<CalcT
>(0) ? scaled +
static_cast<CalcT
>(0.5) : scaled -
static_cast<CalcT
>(0.5);
161 if VUNLIKELY (rounded >= quant_max_value) {
162 return std::numeric_limits<QuantT>::max();
165 if VUNLIKELY (rounded <= quant_lowest_value) {
166 return std::numeric_limits<QuantT>::lowest();
169 return static_cast<QuantT
>(rounded);
172 template <
typename QuantT,
typename ExtentT,
typename ValueT>
173 inline QuantT
encode(ExtentT extent, ValueT value) noexcept {
174 static_assert(std::is_integral_v<QuantT> && std::is_signed_v<QuantT> && !std::is_same_v<QuantT, bool>,
175 "QuantT must be a signed integral type.");
176 static_assert(std::is_arithmetic_v<ExtentT>,
"ExtentT must be arithmetic.");
177 static_assert(std::is_arithmetic_v<ValueT>,
"ValueT must be arithmetic.");
179 using CalcT = std::common_type_t<float, ExtentT, ValueT>;
181 auto extent_value =
static_cast<CalcT
>(extent);
182 auto target =
static_cast<CalcT
>(value);
184 if VUNLIKELY (extent_value != extent_value || target != target || extent_value <=
static_cast<CalcT
>(0)) {
185 return static_cast<QuantT
>(0);
188 auto quant_max_value =
static_cast<CalcT
>(std::numeric_limits<QuantT>::max());
189 auto quant_lowest_value =
static_cast<CalcT
>(std::numeric_limits<QuantT>::lowest());
190 auto scaled = target * quant_max_value / extent_value;
191 auto rounded = scaled >=
static_cast<CalcT
>(0) ? scaled +
static_cast<CalcT
>(0.5) : scaled -
static_cast<CalcT
>(0.5);
193 if VUNLIKELY (rounded >= quant_max_value) {
194 return std::numeric_limits<QuantT>::max();
197 if VUNLIKELY (rounded <= quant_lowest_value) {
198 return std::numeric_limits<QuantT>::lowest();
201 return static_cast<QuantT
>(rounded);
204 template <
typename ReturnT,
typename MinT,
typename MaxT,
typename ValueT>
205 inline ReturnT
decode(MinT quant_min, MaxT quant_max, ValueT value) noexcept {
206 static_assert(std::is_arithmetic_v<ReturnT>,
"ReturnT must be arithmetic.");
207 static_assert(std::is_arithmetic_v<MinT>,
"MinT must be arithmetic.");
208 static_assert(std::is_arithmetic_v<MaxT>,
"MaxT must be arithmetic.");
209 static_assert(std::is_integral_v<ValueT> && !std::is_same_v<ValueT, bool>,
"ValueT must be integral.");
211 using CalcT = std::common_type_t<float, ReturnT, MinT, MaxT>;
213 auto min =
static_cast<CalcT
>(quant_min);
214 auto max =
static_cast<CalcT
>(quant_max);
215 auto target =
static_cast<CalcT
>(value);
217 if VUNLIKELY (min != min || max != max || target != target || max <= min) {
218 return static_cast<ReturnT
>(0);
221 auto quant_max_value =
static_cast<CalcT
>(std::numeric_limits<ValueT>::max());
222 auto quant_min_value =
223 std::is_signed_v<ValueT> ? -quant_max_value :
static_cast<CalcT
>(std::numeric_limits<ValueT>::lowest());
225 auto quant_lowest_value =
static_cast<CalcT
>(std::numeric_limits<ValueT>::lowest());
226 auto quant_range = quant_max_value - quant_min_value;
228 if VUNLIKELY (target >= quant_max_value) {
229 target = quant_max_value;
230 }
else if VUNLIKELY (target <= quant_lowest_value) {
231 target = quant_lowest_value;
234 return static_cast<ReturnT
>(((target - quant_min_value) * (max - min) / quant_range) + min);
237 template <
typename ReturnT,
typename ExtentT,
typename ValueT>
238 inline ReturnT
decode(ExtentT extent, ValueT value) noexcept {
239 static_assert(std::is_arithmetic_v<ReturnT>,
"ReturnT must be arithmetic.");
240 static_assert(std::is_arithmetic_v<ExtentT>,
"ExtentT must be arithmetic.");
241 static_assert(std::is_integral_v<ValueT> && std::is_signed_v<ValueT> && !std::is_same_v<ValueT, bool>,
242 "ValueT must be a signed integral type.");
244 using CalcT = std::common_type_t<float, ReturnT, ExtentT, ValueT>;
246 auto extent_value =
static_cast<CalcT
>(extent);
248 if VUNLIKELY (extent_value != extent_value || extent_value <=
static_cast<CalcT
>(0)) {
249 return static_cast<ReturnT
>(0);
252 auto target =
static_cast<CalcT
>(value);
253 auto quant_max_value =
static_cast<CalcT
>(std::numeric_limits<ValueT>::max());
255 return static_cast<ReturnT
>(target * extent_value / quant_max_value);
Cross-platform macros for visibility, branch hints, copy prevention, singletons and string helpers.
#define VUNLIKELY(...)
Short alias for VLINK_UNLIKELY.
Definition: macros.h:289
QuantT encode(MinT quant_min, MaxT quant_max, ValueT value) noexcept
Quantizes a value from a real range into an integral type.
Definition: quantize.h:135
ReturnT decode(MinT quant_min, MaxT quant_max, ValueT value) noexcept
Dequantizes an integral value into a real range.
Definition: quantize.h:205