| 556 | } |
| 557 | |
| 558 | void quantize_row_q5_1_reference(const float * restrict x, block_q5_1 * restrict y, int k) { |
| 559 | const int qk = QK5_1; |
| 560 | |
| 561 | assert(k % qk == 0); |
| 562 | |
| 563 | const int nb = k / qk; |
| 564 | |
| 565 | for (int i = 0; i < nb; i++) { |
| 566 | float min = FLT_MAX; |
| 567 | float max = -FLT_MAX; |
| 568 | |
| 569 | for (int j = 0; j < qk; j++) { |
| 570 | const float v = x[i*qk + j]; |
| 571 | |
| 572 | if (v < min) min = v; |
| 573 | if (v > max) max = v; |
| 574 | } |
| 575 | |
| 576 | const float d = (max - min) / ((1 << 5) - 1); |
| 577 | const float id = d ? 1.0f/d : 0.0f; |
| 578 | |
| 579 | y[i].d = GGML_FP32_TO_FP16(d); |
| 580 | y[i].m = GGML_FP32_TO_FP16(min); |
| 581 | |
| 582 | uint32_t qh = 0; |
| 583 | |
| 584 | for (int j = 0; j < qk/2; ++j) { |
| 585 | const float x0 = (x[i*qk + 0 + j] - min)*id; |
| 586 | const float x1 = (x[i*qk + qk/2 + j] - min)*id; |
| 587 | |
| 588 | const uint8_t xi0 = (uint8_t)(x0 + 0.5f); |
| 589 | const uint8_t xi1 = (uint8_t)(x1 + 0.5f); |
| 590 | |
| 591 | y[i].qs[j] = (xi0 & 0x0F) | ((xi1 & 0x0F) << 4); |
| 592 | |
| 593 | // get the 5-th bit and store it in qh at the right position |
| 594 | qh |= ((xi0 & 0x10u) >> 4) << (j + 0); |
| 595 | qh |= ((xi1 & 0x10u) >> 4) << (j + qk/2); |
| 596 | } |
| 597 | |
| 598 | memcpy(&y[i].qh, &qh, sizeof(y[i].qh)); |
| 599 | } |
| 600 | } |
| 601 | |
| 602 | void quantize_row_q5_1(const float * restrict x, void * restrict y, int k) { |
| 603 | quantize_row_q5_1_reference(x, y, k); |
no outgoing calls
no test coverage detected