static size_t
trigram_radix_sort_and_unique_recurse(trgm *trg, size_t count, int base,
									  bool char_is_signed)
{
	size_t		freqs[256];
	size_t		starts[256];
	size_t		cur[256];
	size_t		i;
	int			k;

	if (count <= 1)
		return count;
	if (base >= 3)
		return qunique(trg, count, sizeof(trgm), CMPTRGM_EQ);

	memset(freqs, 0, sizeof(freqs));
	for (i = 0; i < count; i++)
		freqs[radix_key(trg[i][base], char_is_signed)]++;

	starts[0] = 0;
	for (k = 1; k < 256; k++)
		starts[k] = starts[k - 1] + freqs[k - 1];

	memcpy(cur, starts, sizeof(cur));

	for (i = 0; i < count; i++)
	{
		for (;;)
		{
			unsigned char b = radix_key(trg[i][base], char_is_signed);

			if (i >= starts[b] && i < cur[b])
				break;

			{
				size_t		j = cur[b]++;
				trgm		tmp;

				memcpy(tmp, trg[i], sizeof(trgm));
				memcpy(trg[i], trg[j], sizeof(trgm));
				memcpy(trg[j], tmp, sizeof(trgm));
			}
		}
	}

	for (k = 0; k < 256; k++)
		if (freqs[k] > 1)
			trigram_radix_sort_and_unique_recurse(trg + starts[k], freqs[k], base + 1, char_is_signed);
}