| 334 | template <typename T, typename TP> |
| 335 | inline T quantize_ex(const T* o_abs, TP* code, size_t dim, size_t ex_bits) { |
| 336 | constexpr double kEps = 1e-5; |
| 337 | double t = best_rescale_factor<T>(o_abs, dim, ex_bits); |
| 338 | double ipnorm = 0; |
| 339 | |
| 340 | std::vector<int> tmp_code(dim); |
| 341 | for (size_t i = 0; i < dim; i++) { |
| 342 | // compute and store code |
| 343 | tmp_code[i] = static_cast<int>((t * o_abs[i]) + kEps); |
| 344 | if (tmp_code[i] >= (1 << ex_bits)) { |
| 345 | tmp_code[i] = (1 << ex_bits) - 1; |
| 346 | } |
| 347 | code[i] = static_cast<TP>(tmp_code[i]); |
| 348 | |
| 349 | // ip * norm = unnormalized ip |
| 350 | ipnorm += (tmp_code[i] + 0.5) * o_abs[i]; |
| 351 | } |
| 352 | |
| 353 | T ipnorm_inv = static_cast<double>(1 / ipnorm); // 1 / (ip*norm) |
| 354 | if (!std::isnormal(ipnorm_inv)) { |
| 355 | ipnorm_inv = 1.F; |
| 356 | } |
| 357 | |
| 358 | return ipnorm_inv; |
| 359 | } |
| 360 | |
| 361 | // For given dim and ex_bits, use random vectors to get the const rescale factor |
| 362 | inline double get_const_scaling_factors(size_t dim, size_t ex_bits) { |
| 363 | constexpr long kConstNum = 100; |