Skip to content

Commit 058f913

Browse files
author
Raghuveer Devulapalli
authored
Merge pull request #207 from r-devulap/objsort-sizet
Make object_qsort generic in arrsize type
2 parents 8a72081 + d96f088 commit 058f913

File tree

2 files changed

+26
-22
lines changed

2 files changed

+26
-22
lines changed

README.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,26 @@ under `src/` directory. The following routines are currently supported:
1111

1212
## Sort an array of custom defined class objects (uses `O(N)` space)
1313
``` cpp
14-
template <typename T, typename Func>
15-
void x86simdsort::object_qsort(T *arr, uint32_t arrsize, Func key_func)
14+
template <typename T, typename U, typename Func>
15+
void x86simdsort::object_qsort(T *arr, U arrsize, Func key_func)
1616
```
1717
`T` is any user defined struct or class and `arr` is a pointer to the first
18-
element in the array of objects of type `T`. `Func` is a lambda function that
19-
computes the `key` value for each object which is the metric used to sort the
20-
objects. `Func` needs to have the following signature:
18+
element in the array of objects of type `T`. The `arrsize` parameter can be any
19+
32-bit or 64-bit integer type. `Func` is a lambda function that computes the
20+
`key` value for each object which is the metric used to sort the objects.
21+
`Func` needs to have the following signature:
2122
2223
```cpp
2324
[] (T obj) -> key_t { key_t key; /* compute key for obj */ return key; }
2425
```
2526

26-
Note that the return type of the key `key_t` needs to be one of the following
27-
: `[float, uint32_t, int32_t, double, uint64_t, int64_t]`. `object_qsort` has a
28-
space complexity of `O(N)`. Specifically, it requires `arrsize *
29-
sizeof(key_t)` bytes to store a vector with all the keys and an additional
30-
`arrsize * sizeof(uint32_t)` bytes to store the indexes of the object array.
31-
For performance reasons, we support `object_qsort` only when the array size is
32-
less than or equal to `UINT32_MAX`. An example usage of `object_qsort` is
27+
Note that the return type of the key `key_t` needs to be one of the following :
28+
`[float, uint32_t, int32_t, double, uint64_t, int64_t]`. `object_qsort` has a
29+
space complexity of `O(N)`. Specifically, it requires `arrsize * sizeof(key_t)`
30+
bytes to store a vector with all the keys and an additional `arrsize *
31+
sizeof(uint32_t)` bytes to store the indexes of the object array. For
32+
performance reasons, we recommend using `object_qsort` when the array size
33+
is less than or equal to `UINT32_MAX`. An example usage of `object_qsort` is
3334
provided in the [examples](#Sort-an-array-of-Points-using-object_qsort)
3435
section. Refer to [section](#Performance-of-object_qsort) to get a sense of
3536
how fast this is relative to `std::sort`.

lib/x86simdsort.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,29 +70,32 @@ XSS_EXPORT_SYMBOL void keyvalue_partial_sort(T1 *key,
7070
bool descending = false);
7171

7272
// sort an object
73-
template <typename T, typename Func>
74-
XSS_EXPORT_SYMBOL void object_qsort(T *arr, uint32_t arrsize, Func key_func)
73+
template <typename T, typename U, typename Func>
74+
XSS_EXPORT_SYMBOL void object_qsort(T *arr, U arrsize, Func key_func)
7575
{
76-
/* (1) Create a vector a keys */
77-
using return_type_of =
78-
typename decltype(std::function {key_func})::result_type;
76+
static_assert(std::is_integral<U>::value, "arrsize must be an integral type");
77+
static_assert(sizeof(U) == sizeof(int32_t) || sizeof(U) == sizeof(int64_t),
78+
"arrsize must be 32 or 64 bits");
79+
using return_type_of = typename decltype(std::function{key_func})::result_type;
80+
static_assert(sizeof(return_type_of) == sizeof(int32_t) || sizeof(return_type_of) == sizeof(int64_t),
81+
"key_func return type must be 32 or 64 bits");
7982
std::vector<return_type_of> keys(arrsize);
80-
for (size_t ii = 0; ii < arrsize; ++ii) {
83+
for (U ii = 0; ii < arrsize; ++ii) {
8184
keys[ii] = key_func(arr[ii]);
8285
}
8386

8487
/* (2) Call arg based on keys using the keyvalue sort */
85-
std::vector<uint32_t> arg(arrsize);
88+
std::vector<U> arg(arrsize);
8689
std::iota(arg.begin(), arg.end(), 0);
8790
x86simdsort::keyvalue_qsort(keys.data(), arg.data(), arrsize);
8891

8992
/* (3) Permute obj array in-place */
9093
std::vector<bool> done(arrsize);
91-
for (size_t i = 0; i < arrsize; ++i) {
94+
for (U i = 0; i < arrsize; ++i) {
9295
if (done[i]) { continue; }
9396
done[i] = true;
94-
size_t prev_j = i;
95-
size_t j = arg[i];
97+
U prev_j = i;
98+
U j = arg[i];
9699
while (i != j) {
97100
std::swap(arr[prev_j], arr[j]);
98101
done[j] = true;

0 commit comments

Comments
 (0)