cOMS/sort/EytzingerSearch.h

74 lines
2.1 KiB
C

#ifndef TOS_SORT_EYTZINGER_SEARCH_H
#define TOS_SORT_EYTZINGER_SEARCH_H
#include "../stdlib/Types.h"
#include "../memory/RingMemory.h"
// @performance We could optimize eytzinger by using 1 based index
// Consider this https://en.algorithmica.org/hpc/data-structures/binary-search/
void eytzinger_rearrange(byte* arr, byte* temp, size_t start, size_t* index, size_t num, size_t size) noexcept {
if (start >= num) {
return;
}
// Fill the left child
eytzinger_rearrange(arr, temp, 2 * start + 1, index, num, size);
// Assign the current element
memcpy(temp + start * size, arr + (*index) * size, size);
++(*index);
// Fill the right child
eytzinger_rearrange(arr, temp, 2 * start + 2, index, num, size);
}
// arr MUST be sorted by a sorting algorithm of your choice
void eytzinger_create(byte* arr, size_t num, size_t size, RingMemory* ring) {
byte* temp = ring_get_memory(ring, size * num);
size_t index = 0;
eytzinger_rearrange(arr, temp, 0, &index, num, size);
// Copy the rearranged array back to the original array
for (size_t i = 0; i < size; ++i) {
memcpy(arr + i * size, temp + i * size, size);
}
}
// Example search for structs with an int id
// WARNING: the prefetching is usually only useful, if we go into 256KB array size
/*
void* search_eytzinger(MyStruct* arr, size_t num, int32 target_id) {
int32 index = 0;
while (index < num) {
// Prefetch the left and right children
int32 left_child = 2 * index + 1;
int32 right_child = 2 * index + 2;
if (left_child < num) {
// Prefetch left child
intrin_prefetch(&arr[left_child]);
}
if (right_child < num) {
// Prefetch right child
intrin_prefetch(&arr[right_child]);
}
// Check the current node
if (arr[index].id == target_id) {
return &arr[index];
} else if (arr[index].id < target_id) {
// Move to the right child
index = right_child;
} else {
// Move to the left child
index = left_child;
}
}
return NULL;
}
*/
#endif