| 614 | } |
| 615 | |
| 616 | void quantize_row_q8_K_ref(const float * __restrict__ x, block_q8_K * __restrict__ y, int64_t k) { |
| 617 | assert(k % QK_K == 0); |
| 618 | const int64_t nb = k / QK_K; |
| 619 | |
| 620 | for (int i = 0; i < nb; i++) { |
| 621 | |
| 622 | float max = 0; |
| 623 | float amax = 0; |
| 624 | for (int j = 0; j < QK_K; ++j) { |
| 625 | float ax = fabsf(x[j]); |
| 626 | if (ax > amax) { |
| 627 | amax = ax; max = x[j]; |
| 628 | } |
| 629 | } |
| 630 | if (!amax) { |
| 631 | y[i].d = 0; |
| 632 | memset(y[i].qs, 0, QK_K); |
| 633 | x += QK_K; |
| 634 | continue; |
| 635 | } |
| 636 | //const float iscale = -128.f/max; |
| 637 | // We need this change for IQ2_XXS, else the AVX implementation becomes very awkward |
| 638 | const float iscale = -127.f/max; |
| 639 | for (int j = 0; j < QK_K; ++j) { |
| 640 | int v = nearest_int(iscale*x[j]); |
| 641 | y[i].qs[j] = std::min(127, v); |
| 642 | } |
| 643 | for (int j = 0; j < QK_K/16; ++j) { |
| 644 | int sum = 0; |
| 645 | for (int ii = 0; ii < 16; ++ii) { |
| 646 | sum += y[i].qs[j*16 + ii]; |
| 647 | } |
| 648 | y[i].bsums[j] = sum; |
| 649 | } |
| 650 | y[i].d = 1/iscale; |
| 651 | x += QK_K; |
| 652 | } |
| 653 | } |
| 654 | |
| 655 | void dequantize_row_q8_K(const block_q8_K * __restrict__ x, float * __restrict__ y, int64_t k) { |
| 656 | assert(k % QK_K == 0); |
no test coverage detected