Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

// declare function here, linker will find this when linked to
// libx86simdsortcpp.so
void keyvalue_qsort_float_sizet(float *, size_t *, size_t);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a header file for these declarations? They probably should be documented somewhere, definitely if there's no header file for them

void keyvalue_qsort_float_uint32(float *, uint32_t *, uint32_t);
void keyvalue_qsort_sizet_sizet(size_t *, size_t *, size_t);
void keyvalue_qsort_sizet_uint32(size_t *, uint32_t *, uint32_t);
void keyvalue_qsort_uint32_sizet(uint32_t *, size_t *, size_t);
void keyvalue_qsort_uint32_uint32(uint32_t *, uint32_t *, uint32_t);
void keyvalue_qsort_int32_sizet(int32_t *, size_t *, size_t);
void keyvalue_qsort_int32_uint32(int32_t *, uint32_t *, uint32_t);

// struct definition, we will sort an array of these:
struct Point {
int x;
int y;
float distance;
size_t metric;
};

#define SWAP(a, b, type) \
{ \
type temp = a; \
a = b; \
b = temp; \
}

// Function to sort an array of objects:
void object_qsort(struct Point *arr, size_t size)
{
/* (1) Create and initialize arrays of key and value */
size_t *key = malloc(size * sizeof(size_t));
size_t *arg = malloc(size * sizeof(size_t));
bool *done = malloc(size * sizeof(bool));
for (size_t ii = 0; ii < size; ++ii) {
key[ii] = arr[ii].metric;
arg[ii] = ii;
done[ii] = false;
}

/* (2) IndexSort using the keyvalue_qsort */
keyvalue_qsort_sizet_sizet(key, arg, size);

/* (3) Permute obj array in-place */
for (size_t ii = 0; ii < size; ++ii) {
if (done[ii]) { continue; }
done[ii] = true;
size_t prev_j = ii;
size_t jj = arg[ii];
while (ii != jj) {
SWAP(arr[prev_j], arr[jj], struct Point);
done[jj] = true;
prev_j = jj;
jj = arg[jj];
}
}
free(key);
free(arg);
free(done);
}

int main()
{
const size_t size = 10;
struct Point arr[size];

// Initialize:
for (size_t ii = 0; ii < size; ++ii) {
arr[ii].distance = (float)rand() / RAND_MAX;
arr[ii].metric = rand() % 100;
}

// sort:
object_qsort(arr, size);

// check if it is sorted:
printf("arr = ");
for (size_t ii = 0; ii < size; ++ii) {
printf("%ld, ", arr[ii].metric);
}
printf("\n");
return 0;
}
44 changes: 44 additions & 0 deletions lib/x86simdsort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,47 @@ DISPATCH_KEYVALUE_SORT_FORTYPE(int32_t)
DISPATCH_KEYVALUE_SORT_FORTYPE(float)

} // namespace x86simdsort
//

extern "C" {
XSS_EXPORT_SYMBOL
void keyvalue_qsort_float_uint32(float *key, uint32_t *val, uint32_t size)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why some of these functions take the size of the array as a uint32_t instead of a size_t? I'd prefer they all be the same if there's no reason for them not to be.

{
x86simdsort::keyvalue_qsort(key, val, size, true);
}
XSS_EXPORT_SYMBOL
void keyvalue_qsort_float_sizet(float *key, size_t *val, size_t size)
Copy link
Contributor

@sterrettm2 sterrettm2 Nov 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think the argument type/function name of these being size_t is a little awkward. I think I would probably call them uint64; I guess that might not technically always be the same, if it was running on a 32-bit system. But I presume 64 bit unsigned integer is what is meant here

{
x86simdsort::keyvalue_qsort(key, val, size, true);
}
XSS_EXPORT_SYMBOL
void keyvalue_qsort_sizet_uint32(size_t *key, uint32_t *val, uint32_t size)
{
x86simdsort::keyvalue_qsort(key, val, size, true);
}
XSS_EXPORT_SYMBOL
void keyvalue_qsort_sizet_sizet(size_t *key, size_t *val, size_t size)
{
x86simdsort::keyvalue_qsort(key, val, size, true);
}
XSS_EXPORT_SYMBOL
void keyvalue_qsort_int32_uint32(int32_t *key, uint32_t *val, uint32_t size)
{
x86simdsort::keyvalue_qsort(key, val, size, true);
}
XSS_EXPORT_SYMBOL
void keyvalue_qsort_int32_sizet(int32_t *key, size_t *val, size_t size)
{
x86simdsort::keyvalue_qsort(key, val, size, true);
}
XSS_EXPORT_SYMBOL
void keyvalue_qsort_uint32_uint32(uint32_t *key, uint32_t *val, uint32_t size)
{
x86simdsort::keyvalue_qsort(key, val, size, true);
}
XSS_EXPORT_SYMBOL
void keyvalue_qsort_uint32_sizet(uint32_t *key, size_t *val, size_t size)
{
x86simdsort::keyvalue_qsort(key, val, size, true);
}
}