104 lines
2.3 KiB
C
104 lines
2.3 KiB
C
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
/**
|
|
* \file bgp/vm_commsort.h
|
|
*
|
|
* Generic basic sorting and binary searching over unsigned integer arrays.
|
|
*
|
|
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
|
* \author Lorenzo Cogotti
|
|
*
|
|
* The following defines a bunch of static functions to sort
|
|
* and search basic integer arrays.
|
|
*
|
|
* `#define` `UINT_TYPE` with an unsigned <= 4 bytes and `FNSUFFIX`
|
|
* before inclusion.
|
|
*
|
|
* \note No guards, file `#include`d by bgp/vm_communities.c
|
|
*/
|
|
|
|
#define _CAT(X, Y) X ## Y
|
|
#define _XCAT(X, Y) _CAT(X, Y)
|
|
|
|
#define _MANGLE(FN) _XCAT(FN, FNSUFFIX)
|
|
|
|
|
|
static Sint64 _MANGLE(BinarySearch) (const UINT_TYPE *arr,
|
|
Uint32 n,
|
|
UINT_TYPE v)
|
|
{
|
|
Uint32 len = n;
|
|
Uint32 mid = n;
|
|
Sint64 off = 0;
|
|
while (mid > 0) {
|
|
mid = len >> 1;
|
|
if (arr[off+mid] <= v)
|
|
off += mid;
|
|
|
|
len -= mid;
|
|
}
|
|
|
|
return (off < n && arr[off] == v) ? off : -1;
|
|
}
|
|
|
|
static void _MANGLE(Radix) (int off,
|
|
const UINT_TYPE *src,
|
|
Uint32 n,
|
|
UINT_TYPE *dest)
|
|
{
|
|
const Uint8 *sortKey;
|
|
|
|
Uint32 index[256];
|
|
Uint32 count[256] = { 0 };
|
|
|
|
for (Uint32 i = 0; i < n; i++) {
|
|
sortKey = ((const Uint8 *) &src[i]) + off;
|
|
count[*sortKey]++;
|
|
}
|
|
|
|
index[0] = 0;
|
|
for (Uint32 i = 1; i < 256; i++)
|
|
index[i] = index[i-1] + count[i-1];
|
|
|
|
for (Uint32 i = 0; i < n; i++) {
|
|
sortKey = ((const Uint8 *) &src[i]) + off;
|
|
dest[index[*sortKey]++] = src[i];
|
|
}
|
|
}
|
|
|
|
static void _MANGLE(RadixSort) (UINT_TYPE *arr, Uint32 n)
|
|
{
|
|
UINT_TYPE *scratch = (UINT_TYPE *) alloca(n * sizeof(*scratch));
|
|
|
|
STATIC_ASSERT(sizeof(UINT_TYPE) % 2 == 0, "?!");
|
|
|
|
if (EDN_NATIVE == EDN_LE) {
|
|
for (unsigned i = 0; i < sizeof(UINT_TYPE); i += 2) {
|
|
_MANGLE(Radix) (i + 0, arr, n, scratch);
|
|
_MANGLE(Radix) (i + 1, scratch, n, arr);
|
|
}
|
|
} else {
|
|
for (unsigned i = sizeof(UINT_TYPE); i > 0; i -= 2) {
|
|
_MANGLE(Radix) (i - 1, arr, n, scratch);
|
|
_MANGLE(Radix) (i - 2, scratch, n, arr);
|
|
}
|
|
}
|
|
}
|
|
|
|
static Uint32 _MANGLE(Uniq) (UINT_TYPE *arr, Uint32 n)
|
|
{
|
|
Uint32 i, j;
|
|
|
|
if (n == 0) return 0;
|
|
|
|
for (i = 0, j = 1; j < n; j++) {
|
|
if (arr[i] != arr[j])
|
|
arr[++i] = arr[j];
|
|
}
|
|
return ++i;
|
|
}
|
|
|
|
#undef _MANGLE
|
|
#undef _XCAT
|
|
#undef _CAT
|