| 1446 | } |
| 1447 | |
| 1448 | void radix_sort7(render_item_t *a, size_t count) { |
| 1449 | // Resize up if needed |
| 1450 | if (radix_queue_size < count) { |
| 1451 | sk_free(radix_queue_area); |
| 1452 | radix_queue_area = sk_malloc_t(render_item_t, count); |
| 1453 | radix_queue_size = count; |
| 1454 | } |
| 1455 | freq_array_type freqs = {}; |
| 1456 | count_frequency(a, count, freqs); |
| 1457 | |
| 1458 | render_item_t *from = a, *to = radix_queue_area; |
| 1459 | |
| 1460 | for (size_t pass = 0; pass < RADIX_LEVELS; pass++) { |
| 1461 | |
| 1462 | if (is_trivial(freqs[pass], count)) { |
| 1463 | // this pass would do nothing, just skip it |
| 1464 | continue; |
| 1465 | } |
| 1466 | |
| 1467 | uint64_t shift = pass * RADIX_BITS; |
| 1468 | |
| 1469 | // array of pointers to the current position in each queue, which we set up based on the |
| 1470 | // known final sizes of each queue (i.e., "tighly packed") |
| 1471 | render_item_t *queue_ptrs[RADIX_SIZE], *next = to; |
| 1472 | for (size_t i = 0; i < RADIX_SIZE; i++) { |
| 1473 | queue_ptrs[i] = next; |
| 1474 | next += freqs[pass][i]; |
| 1475 | } |
| 1476 | |
| 1477 | // copy each element into the appropriate queue based on the current RADIX_BITS sized |
| 1478 | // "digit" within it |
| 1479 | for (size_t i = 0; i < count; i++) { |
| 1480 | render_item_t value = from[i]; |
| 1481 | size_t index = (value.sort_id >> shift) & RADIX_MASK; |
| 1482 | *queue_ptrs[index]++ = value; |
| 1483 | #ifdef _MSC_VER |
| 1484 | #if defined(_M_ARM) || defined(_M_ARM64) |
| 1485 | __prefetch (queue_ptrs[index] + 1); |
| 1486 | #else |
| 1487 | _m_prefetch(queue_ptrs[index] + 1); |
| 1488 | #endif |
| 1489 | #else |
| 1490 | __builtin_prefetch(queue_ptrs[index] + 1); |
| 1491 | #endif |
| 1492 | } |
| 1493 | |
| 1494 | // swap from and to areas |
| 1495 | render_item_t *tmp = to; |
| 1496 | to = from; |
| 1497 | from = tmp; |
| 1498 | } |
| 1499 | |
| 1500 | // because of the last swap, the "from" area has the sorted payload: if it's |
| 1501 | // not the original array "a", do a final copy |
| 1502 | if (from != a) { |
| 1503 | memcpy(a, from, count*sizeof(render_item_t)); |
| 1504 | } |
| 1505 | } |
no test coverage detected