| 306 | } |
| 307 | |
| 308 | void quantize_row_q3_K_ref(const float * __restrict__ x, block_q3_K * __restrict__ y, int64_t k) { |
| 309 | assert(k % QK_K == 0); |
| 310 | const int nb = k / QK_K; |
| 311 | |
| 312 | int8_t L[QK_K]; |
| 313 | float scales[QK_K / 16]; |
| 314 | |
| 315 | for (int i = 0; i < nb; i++) { |
| 316 | |
| 317 | float max_scale = 0; |
| 318 | float amax = 0; |
| 319 | for (int j = 0; j < QK_K/16; ++j) { |
| 320 | scales[j] = make_q3_quants(16, 4, x + 16*j, L + 16*j, true); |
| 321 | float scale = fabsf(scales[j]); |
| 322 | if (scale > amax) { |
| 323 | amax = scale; max_scale = scales[j]; |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | memset(y[i].scales, 0, 12); |
| 328 | if (max_scale) { |
| 329 | float iscale = -32.f/max_scale; |
| 330 | for (int j = 0; j < QK_K/16; ++j) { |
| 331 | int8_t l = nearest_int(iscale*scales[j]); |
| 332 | l = std::max(-32, std::min(31, static_cast<int>(l))) + 32; |
| 333 | if (j < 8) { |
| 334 | y[i].scales[j] = l & 0xF; |
| 335 | } else { |
| 336 | y[i].scales[j-8] |= ((l & 0xF) << 4); |
| 337 | } |
| 338 | l >>= 4; |
| 339 | y[i].scales[j%4 + 8] |= (l << (2*(j/4))); |
| 340 | } |
| 341 | y[i].d = float_to_half(1/iscale); |
| 342 | } else { |
| 343 | y[i].d = float_to_half(0.f); |
| 344 | } |
| 345 | |
| 346 | int8_t sc; |
| 347 | for (int j = 0; j < QK_K/16; ++j) { |
| 348 | sc = j < 8 ? y[i].scales[j] & 0xF : y[i].scales[j-8] >> 4; |
| 349 | sc = (sc | (((y[i].scales[8 + j%4] >> (2*(j/4))) & 3) << 4)) - 32; |
| 350 | float d = half_to_float(y[i].d) * sc; |
| 351 | if (!d) { |
| 352 | continue; |
| 353 | } |
| 354 | for (int ii = 0; ii < 16; ++ii) { |
| 355 | int l = nearest_int(x[16*j + ii]/d); |
| 356 | l = std::max(-4, std::min(3, l)); |
| 357 | L[16*j + ii] = l + 4; |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | memset(y[i].hmask, 0, QK_K/8); |
| 362 | // We put the high-bit for the 1st 8 quants into bit 0, the next 8 into bit 1, etc. |
| 363 | int m = 0; |
| 364 | uint8_t hm = 1; |
| 365 | for (int j = 0; j < QK_K; ++j) { |
no test coverage detected