| 508 | } |
| 509 | |
| 510 | void quantize_row_q5_0_reference(const float * restrict x, block_q5_0 * restrict y, int k) { |
| 511 | static const int qk = QK5_0; |
| 512 | |
| 513 | assert(k % qk == 0); |
| 514 | |
| 515 | const int nb = k / qk; |
| 516 | |
| 517 | for (int i = 0; i < nb; i++) { |
| 518 | float amax = 0.0f; // absolute max |
| 519 | float max = 0.0f; |
| 520 | |
| 521 | for (int j = 0; j < qk; j++) { |
| 522 | const float v = x[i*qk + j]; |
| 523 | if (amax < fabsf(v)) { |
| 524 | amax = fabsf(v); |
| 525 | max = v; |
| 526 | } |
| 527 | } |
| 528 | |
| 529 | const float d = max / -16; |
| 530 | const float id = d ? 1.0f/d : 0.0f; |
| 531 | |
| 532 | y[i].d = GGML_FP32_TO_FP16(d); |
| 533 | |
| 534 | uint32_t qh = 0; |
| 535 | |
| 536 | for (int j = 0; j < qk/2; ++j) { |
| 537 | const float x0 = x[i*qk + 0 + j]*id; |
| 538 | const float x1 = x[i*qk + qk/2 + j]*id; |
| 539 | |
| 540 | const uint8_t xi0 = MIN(31, (int8_t)(x0 + 16.5f)); |
| 541 | const uint8_t xi1 = MIN(31, (int8_t)(x1 + 16.5f)); |
| 542 | |
| 543 | y[i].qs[j] = (xi0 & 0x0F) | ((xi1 & 0x0F) << 4); |
| 544 | |
| 545 | // get the 5-th bit and store it in qh at the right position |
| 546 | qh |= ((xi0 & 0x10u) >> 4) << (j + 0); |
| 547 | qh |= ((xi1 & 0x10u) >> 4) << (j + qk/2); |
| 548 | } |
| 549 | |
| 550 | memcpy(&y[i].qh, &qh, sizeof(qh)); |
| 551 | } |
| 552 | } |
| 553 | |
| 554 | void quantize_row_q5_0(const float * restrict x, void * restrict y, int k) { |
| 555 | quantize_row_q5_0_reference(x, y, k); |
no outgoing calls
no test coverage detected