Untitled
unknown
plain_text
2 years ago
27 kB
13
Indexable
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "algorithm.h"
static void swap(void *a, void *b, size_t size) {
// Using a stack-allocated buffer for small elements
unsigned char temp[size];
memcpy(temp, a, size);
memcpy(a, b, size);
memcpy(b, temp, size);
}
static void reverse(void *first, void *last, size_t size) {
char *a = (char *)first;
char *b = (char *)last - size;
while (a < b) {
swap(a, b, size);
a += size;
b -= size;
}
}
static void quickSortInternal(void *base, size_t low, size_t high, size_t size, CompareFunc comp, void *temp) {
if (low < high) {
char* pivot = (char*)base + high * size;
size_t i = low;
for (size_t j = low; j < high; j++) {
if (comp((char*)base + j * size, pivot) < 0) {
memcpy(temp, (char*)base + j * size, size);
memcpy((char*)base + j * size, (char*)base + i * size, size);
memcpy((char*)base + i * size, temp, size);
i++;
}
}
memcpy(temp, (char*)base + i * size, size);
memcpy((char*)base + i * size, pivot, size);
memcpy(pivot, temp, size);
if (i > 0)
quickSortInternal(base, low, i - 1, size, comp, temp);
quickSortInternal(base, i + 1, high, size, comp, temp);
}
}
static void merge(void *base, size_t low, size_t mid, size_t high, size_t size, CompareFunc comp, void *temp) {
size_t i = low, j = mid, k = 0;
while (i < mid && j < high) {
if (comp((char*)base + i * size, (char*)base + j * size) <= 0) {
memcpy((char*)temp + k * size, (char*)base + i * size, size);
i++;
} else {
memcpy((char*)temp + k * size, (char*)base + j * size, size);
j++;
}
k++;
}
while (i < mid) {
memcpy((char*)temp + k * size, (char*)base + i * size, size);
i++; k++;
}
while (j < high) {
memcpy((char*)temp + k * size, (char*)base + j * size, size);
j++; k++;
}
memcpy((char*)base + low * size, temp, k * size);
}
static void mergeSortInternal(void *base, size_t low, size_t high, size_t size, CompareFunc comp, void *temp) {
if (high - low > 1) {
size_t mid = low + (high - low) / 2;
mergeSortInternal(base, low, mid, size, comp, temp);
mergeSortInternal(base, mid, high, size, comp, temp);
merge(base, low, mid, high, size, comp, temp);
}
}
void algorithm_stable_sort(void *base, size_t num, size_t size, CompareFunc comp) {
if (num > 1) {
void* temp = malloc(num * size);
if (temp) {
mergeSortInternal(base, 0, num, size, comp, temp);
free(temp);
} else {
perror("Failed to allocate memory for stable sorting");
exit(EXIT_FAILURE);
}
}
}
void algorithm_sort(void *base, size_t num, size_t size, CompareFunc comp) {
if (num > 1) {
void* temp = malloc(size);
if (temp) {
quickSortInternal(base, 0, num - 1, size, comp, temp);
free(temp);
}
else {
perror("Failed to allocate memory for sorting");
exit(EXIT_FAILURE);
}
}
}
void *algorithm_find(const void *base, size_t num, size_t size, const void *val, CompareFunc comp) {
const char *ptr = (const char*)base;
for (size_t i = 0; i < num; i++) {
if (comp(ptr + i * size, val) == 0) {
return (void *)(ptr + i * size);
}
}
return NULL;
}
void *algorithm_find_if(const void *base, size_t num, size_t size, BoolPredicateFunc pred) {
const char *ptr = (const char*)base;
for (size_t i = 0; i < num; i++) {
if (pred(ptr + i * size)) {
return (void *)(ptr + i * size);
}
}
return NULL;
}
void *algorithm_find_if_not(const void *base, size_t num, size_t size, BoolPredicateFunc pred) {
const char *ptr = (const char*)base;
for (size_t i = 0; i < num; i++) {
if (!pred(ptr + i * size)) {
return (void *)(ptr + i * size);
}
}
return NULL;
}
void *algorithm_find_end(const void *base1, size_t num1, size_t size1, const void *base2, size_t num2, size_t size2, CompareFunc comp) {
if (num2 == 0) {
return (void*)((char*)base1 + num1 * size1);
}
void *ret = NULL;
const char *ptr1 = (const char*)base1;
const char *ptr2 = (const char*)base2;
for (size_t i = 0; i <= num1 - num2; ++i) {
bool found = true;
for (size_t j = 0; j < num2; ++j) {
if (!comp(ptr1 + (i + j) * size1, ptr2 + j * size2)) {
found = false;
break;
}
}
if (found) {
ret = (void *)(ptr1 + i * size1);
}
}
return ret;
}
void *algorithm_find_first_of(const void *base1, size_t num1, size_t size1, const void *base2, size_t num2, size_t size2, CompareFunc comp) {
const char *ptr1 = (const char*)base1;
const char *ptr2 = (const char*)base2;
for (size_t i = 0; i < num1; ++i) {
for (size_t j = 0; j < num2; ++j) {
if (comp(ptr1 + i * size1, ptr2 + j * size2) == 0) {
return (void *)(ptr1 + i * size1);
}
}
}
return NULL;
}
size_t algorithm_binary_search(const void *base, size_t num, size_t size, const void *val, CompareFunc comp) {
size_t low = 0;
size_t high = num;
while (low < high) {
size_t mid = low + (high - low) / 2;
const void *mid_elem = (const char *)base + mid * size;
int result = comp(mid_elem, val);
if (result < 0) {
low = mid + 1;
}
else if (result > 0) {
high = mid;
}
else {
return (size_t)mid; // Element found, return index
}
}
return (size_t)-1; // Element not found
}
void *algorithm_max_element(const void *base, size_t num, size_t size, CompareFunc comp) {
if (num == 0) {
return NULL;
}
const char *max_element = (const char *)base;
for (size_t i = 1; i < num; ++i) {
const char *element = (const char *)base + i * size;
if (comp(max_element, element) < 0) {
max_element = element;
}
}
return (void *)max_element;
}
void *algorithm_min_element(const void *base, size_t num, size_t size, CompareFunc comp) {
if (num == 0) {
return NULL;
}
const char *min_element = (const char *)base;
for (size_t i = 1; i < num; ++i) {
const char *element = (const char *)base + i * size;
if (comp(min_element, element) > 0) {
min_element = element;
}
}
return (void *)min_element;
}
void algorithm_for_each(void *base, size_t num, size_t size, ForEachOpFunc op) {
char *ptr = (char *)base;
for (size_t i = 0; i < num; ++i) {
op(ptr + i * size);
}
}
void algorithm_copy(const void *source, size_t num, size_t size, void *dest) {
const char *src_ptr = (const char *)source;
char *dest_ptr = (char *)dest;
for (size_t i = 0; i < num; ++i) {
memcpy(dest_ptr + i * size, src_ptr + i * size, size);
}
}
void *algorithm_accumulate(const void *base, size_t num, size_t size, void *init, AccumulateOpFunc op) {
char *result = (char *)init;
const char *ptr = (const char *)base;
for (size_t i = 0; i < num; ++i) {
op(result, ptr + i * size);
}
return result;
}
bool algorithm_all_of(const void *base, size_t num, size_t size, BoolPredicateFunc pred) {
const char *ptr = (const char *)base;
for (size_t i = 0; i < num; ++i) {
if (!pred(ptr + i * size)) {
return false;
}
}
return true;
}
bool algorithm_any_of(const void *base, size_t num, size_t size, BoolPredicateFunc pred) {
const char *ptr = (const char *)base;
for (size_t i = 0; i < num; ++i) {
if (pred(ptr + i * size)) {
return true;
}
}
return false;
}
bool algorithm_none_of(const void *base, size_t num, size_t size, BoolPredicateFunc pred) {
const char *ptr = (const char *)base;
for (size_t i = 0; i < num; ++i) {
if (pred(ptr + i * size)) {
return false;
}
}
return true;
}
void algorithm_fill(void *first, void *last, size_t size, const void *val) {
for (char *ptr = first; ptr != last; ptr += size) {
memcpy(ptr, val, size);
}
}
void algorithm_fill_n(void *first, size_t n, size_t size, const void *val) {
for (char *ptr = first; n > 0; ptr += size, n--) {
memcpy(ptr, val, size);
}
}
size_t algorithm_count(const void *base, size_t num, size_t size, const void *val, CompareFunc comp) {
size_t count = 0;
const char *ptr = (const char *)base;
for (size_t i = 0; i < num; ++i) {
if (comp(ptr + i * size, val) == 0) {
++count;
}
}
return count;
}
size_t algorithm_count_if(const void *base, size_t num, size_t size, BoolPredicateFunc pred) {
size_t count = 0;
const char *ptr = (const char *)base;
for (size_t i = 0; i < num; ++i) {
if (pred(ptr + i * size)) {
++count;
}
}
return count;
}
void algorithm_shuffle(void *base, size_t num, size_t size, UniformRandomNumberGenerator rng) {
if (num > 1) {
char *arr = (char *)base;
char *temp = malloc(size);
if (!temp) {
perror("Failed to allocate memory for shuffle");
exit(EXIT_FAILURE);
}
for (size_t i = num - 1; i > 0; i--) {
size_t j = rng() % (i + 1);
// Swap arr[i] and arr[j]
memcpy(temp, arr + i * size, size);
memcpy(arr + i * size, arr + j * size, size);
memcpy(arr + j * size, temp, size);
}
free(temp);
}
}
void *algorithm_lower_bound(const void *base, size_t num, size_t size, const void *val, CompareFunc comp) {
size_t low = 0;
size_t high = num;
while (low < high) {
size_t mid = low + (high - low) / 2;
const void *mid_elem = (const char *)base + mid * size;
if (comp(mid_elem, val) < 0) {
low = mid + 1;
}
else {
high = mid;
}
}
return (void *)((const char *)base + low * size);
}
void *algorithm_upper_bound(const void *base, size_t num, size_t size, const void *val, CompareFunc comp) {
size_t low = 0;
size_t high = num;
while (low < high) {
size_t mid = low + (high - low) / 2;
const void *mid_elem = (const char *)base + mid * size;
if (comp(mid_elem, val) <= 0) {
low = mid + 1;
}
else {
high = mid;
}
}
return (void *)((const char *)base + low * size);
}
void algorithm_transform(const void *base, size_t num, size_t size, void *result, TransformFunc op) {
const char *input_ptr = (const char *)base;
char *output_ptr = (char *)result;
for (size_t i = 0; i < num; ++i) {
op(output_ptr + i * size, input_ptr + i * size);
}
}
void *algorithm_reduce(const void *base, size_t num, size_t size, void *init, ReduceFunc op) {
const char *ptr = (const char *)base;
char *result = (char *)init;
for (size_t i = 0; i < num; ++i) {
op(result, ptr + i * size);
}
return result;
}
size_t algorithm_unique(void *base, size_t num, size_t size, CompareFunc comp) {
if (num == 0) {
return 0;
}
size_t uniqueCount = 1; // First element is always unique
char *array = (char *)base;
for (size_t i = 1; i < num; ++i) {
// Compare current element with the last unique element
if (comp(array + (uniqueCount - 1) * size, array + i * size) != 0) {
// If different, move it to the next unique position
if (uniqueCount != i) {
memcpy(array + uniqueCount * size, array + i * size, size);
}
uniqueCount++;
}
}
return uniqueCount;
}
bool algorithm_equal(const void *base1, size_t num1, size_t size1, const void *base2, size_t num2, size_t size2,
CompareFunc comp) {
// If the number of elements or sizes differ, the ranges are not equal
if (num1 != num2 || size1 != size2) {
return false;
}
const char *ptr1 = (const char *)base1;
const char *ptr2 = (const char *)base2;
for (size_t i = 0; i < num1; ++i) {
if (comp(ptr1 + i * size1, ptr2 + i * size2) != 0) {
return false;
}
}
return true;
}
bool algorithm_next_permutation(void *first, void *last, size_t size, CompareFuncBool comp) {
if (first == last) {
return false;
}
char *i = (char *)last - size;
while (i != (char *)first) {
char *j = i;
i -= size;
if (comp(i, j)) {
char *k = (char *)last - size;
while (!comp(i, k)) {
k -= size;
}
swap(i, k, size);
reverse(j, last, size);
return true;
}
if (i == (char *)first) {
reverse(first, last, size);
return false;
}
}
return false; // This should not be reached
}
bool algorithm_prev_permutation(void *first, void *last, size_t size, CompareFuncBool comp) {
if (first == last) {
return false;
}
char *i = (char *)last - size;
while (i != (char *)first) {
char *j = i;
i -= size;
if (comp(j, i)) {
char *k = (char *)last - size;
while (!comp(k, i)) {
k -= size;
}
swap(i, k, size);
reverse(j, last, size);
return true;
}
if (i == (char *)first) {
reverse(first, last, size);
return false;
}
}
return false;
}
void *algorithm_partition(void *base, size_t num, size_t size, BoolPredicateFunc pred) {
char *first = (char *)base;
char *last = first + num * size;
while (first != last) {
while (first != last && pred(first)) {
first += size;
}
do {
last -= size;
if (first == last)
break;
} while (!pred(last));
if (first != last) {
swap(first, last, size);
first += size;
}
}
return first;
}
void algorithm_generate(void *first, void *last, size_t size, GeneratorFunc gen) {
char *current = (char *)first;
while (current != last) {
gen(current);
current += size;
}
}
void algorithm_generate_n(void *first, size_t n, size_t size, GeneratorFunc gen) {
char *current = (char *)first;
for (size_t i = 0; i < n; ++i) {
gen(current);
current += size;
}
}
void algorithm_copy_backward(const void *first, const void *last, size_t size, void *result) {
const char *src = (const char *)last;
char *dest = (char *)result;
while (src != (const char *)first) {
src -= size; // Move source pointer backwards
dest -= size; // Move destination pointer backwards
memcpy(dest, src, size); // Copy element
}
}
void algorithm_copy_if(const void *first, const void *last, size_t size, void *result, UnaryPredicateFunc pred) {
const char *src = (const char *)first;
char *dest = (char *)result;
while (src != (const char *)last) {
if (pred(src)) {
memcpy(dest, src, size);
dest += size;
}
src += size;
}
}
void algorithm_copy_n(const void *first, size_t n, size_t size, void *result) {
const char *src = (const char *)first;
char *dest = (char *)result;
for (size_t i = 0; i < n; ++i) {
memcpy(dest, src, size);
src += size;
dest += size;
}
}
Pair algorithm_equal_range(const void *base, size_t num, size_t size, const void *val, CompareFunc comp) {
Pair range;
range.first = algorithm_lower_bound(base, num, size, val, comp);
range.second = algorithm_upper_bound(range.first, num, size, val, comp);
return range;
}
bool algorithm_includes(const void *first1, size_t num1, size_t size1, const void *first2, size_t num2, size_t size2,
CompareFunc comp) {
const char *ptr1 = (const char *)first1;
const char *ptr2 = (const char *)first2;
const char *last1 = ptr1 + num1 * size1;
const char *last2 = ptr2 + num2 * size2;
while (ptr2 != last2) {
if ((ptr1 == last1) || comp(ptr2, ptr1) < 0) {
return false;
}
if (!comp(ptr1, ptr2)) {
ptr2 += size2;
}
ptr1 += size1;
}
return true;
}
size_t algorithm_unique_copy(const void *first, size_t num, size_t size, void *result, CompareFunc comp) {
if (num == 0) {
return 0;
}
const char *src = (const char *)first;
char *dst = (char *)result;
memcpy(dst, src, size); // Copy first element
size_t count = 1;
for (size_t i = 1; i < num; ++i) {
if (comp(dst + (count - 1) * size, src + i * size) != 0) {
memcpy(dst + count * size, src + i * size, size);
++count;
}
}
return count;
}
void algorithm_swap(void *a, void *b, size_t size) {
void *temp = malloc(size);
if (!temp) {
perror("Failed to allocate memory for swap");
exit(EXIT_FAILURE);
}
memcpy(temp, a, size);
memcpy(a, b, size);
memcpy(b, temp, size);
free(temp);
}
void algorithm_swap_ranges(void *first1, void *first2, size_t num, size_t size) {
char *ptr1 = (char *)first1;
char *ptr2 = (char *)first2;
for (size_t i = 0; i < num; ++i) {
algorithm_swap(ptr1 + i * size, ptr2 + i * size, size);
}
}
bool algorithm_is_sorted(const void *base, size_t num, size_t size, CompareFunc comp) {
if (num < 2) {
return true; // A range with less than two elements is always sorted.
}
const char *ptr = (const char *)base;
for (size_t i = 0; i < num - 1; ++i) {
if (comp(ptr + i * size, ptr + (i + 1) * size) > 0) {
return false; // Found an element that is greater than the next element.
}
}
return true; // All elements are in sorted order.
}
void *algorithm_is_sorted_until(const void *base, size_t num, size_t size, CompareFunc comp) {
if (num < 2) {
return (void *)((char *)base + num * size); // Entire range is sorted
}
const char *ptr = (const char *)base;
for (size_t i = 0; i < num - 1; ++i) {
if (comp(ptr + i * size, ptr + (i + 1) * size) > 0) {
return (void *)(ptr + (i + 1) * size); // Found unsorted element
}
}
return (void *)((char *)base + num * size); // Entire range is sorted
}
void algorithm_rotate(void *first, void *middle, void *last, size_t size) {
char *next = (char *)middle;
while ((char *)first != next) {
swap(first, next, size);
first = (char *)first + size;
next = (char *)next + size;
if (next == (char *)last) {
next = (char *)middle;
}
else if (first == (char *)middle) {
middle = next;
}
}
}
void algorithm_rotate_copy(const void *first, const void *middle, const void *last, size_t size, void *result) {
const char *first_ptr = (const char *)first;
const char *middle_ptr = (const char *)middle;
const char *last_ptr = (const char *)last;
char *result_ptr = (char *)result;
// Copy from middle to last into result
while (middle_ptr != last_ptr) {
memcpy(result_ptr, middle_ptr, size);
result_ptr += size;
middle_ptr += size;
}
// Copy from first to middle into result
while (first_ptr != (const char *)middle) {
memcpy(result_ptr, first_ptr, size);
result_ptr += size;
first_ptr += size;
}
}
void algorithm_merge(const void *base1, size_t num1, const void *base2, size_t num2, size_t size, void *result, CompareFunc comp) {
size_t i = 0, j = 0, k = 0;
const char *a = (const char *)base1;
const char *b = (const char *)base2;
char *res = (char *)result;
while (i < num1 && j < num2) {
if (comp(a + i * size, b + j * size) <= 0) {
memcpy(res + k * size, a + i * size, size);
i++;
}
else {
memcpy(res + k * size, b + j * size, size);
j++;
}
k++;
}
while (i < num1) {
memcpy(res + k * size, a + i * size, size);
i++;
k++;
}
while (j < num2) {
memcpy(res + k * size, b + j * size, size);
j++;
k++;
}
}
void algorithm_inplace_merge(void *base, size_t middle, size_t num, size_t size, CompareFunc comp) {
size_t i = 0, j = middle, k;
char *arr = (char *)base;
char temp[size];
while (i < middle && j < num) {
if (comp(arr + i * size, arr + j * size) <= 0) {
i++;
} else {
memcpy(temp, arr + j * size, size);
for (k = j; k > i; k--) {
memcpy(arr + k * size, arr + (k - 1) * size, size);
}
memcpy(arr + i * size, temp, size);
i++;
middle++;
j++;
}
}
}
void *algorithm_adjacent_find(const void *base, size_t num, size_t size, CompareFunc comp) {
const char *ptr = (const char *)base;
for (size_t i = 0; i < num - 1; ++i) {
if (comp(ptr + i * size, ptr + (i + 1) * size) == 0) {
return (void *)(ptr + i * size);
}
}
return NULL;
}
Pair algorithm_mismatch(const void *base1, size_t num1, size_t size1, const void *base2, size_t num2, size_t size2, CompareFuncBool comp) {
const char *ptr1 = (const char *)base1;
const char *ptr2 = (const char *)base2;
size_t min_num = num1 < num2 ? num1 : num2;
for (size_t i = 0; i < min_num; i++) {
if (comp(ptr1 + i * size1, ptr2 + i * size2) != 0) {
Pair mismatch;
mismatch.first = (void *)(ptr1 + i * size1);
mismatch.second = (void *)(ptr2 + i * size2);
return mismatch;
}
}
Pair mismatch = {NULL, NULL};
return mismatch;
}
bool algorithm_is_permutation(const void *base1, size_t num1, size_t size1, const void *base2, size_t num2, size_t size2, CompareFunc comp) {
// Check if both arrays have the same number of elements
if (num1 != num2 || size1 != size2) {
return false;
}
// Temporary arrays to mark elements as found
bool found1[num1], found2[num2];
memset(found1, 0, sizeof(found1));
memset(found2, 0, sizeof(found2));
for (size_t i = 0; i < num1; ++i) {
for (size_t j = 0; j < num2; ++j) {
// Check if elements match and neither has been paired before
if (!found1[i] && !found2[j] && comp((char *)base1 + i * size1, (char *)base2 + j * size2)) {
found1[i] = true;
found2[j] = true;
break;
}
}
// If an element in base1 does not have a match in base2
if (!found1[i]) {
return false;
}
}
return true;
}
const void* algorithm_search(const void* first1, const void* last1, size_t size1,const void* first2, const void* last2, size_t size2, CompareFuncBool comp) {
const char* ptr1 = (const char*)first1;
const char* ptr2 = (const char*)first2;
const char* end1 = (const char*)last1;
if (ptr2 == last2) {
return first1; // If the second sequence is empty, return the start of the first
}
while (ptr1 != end1) {
const char* it1 = ptr1;
const char* it2 = ptr2;
while (comp(it1, it2)) { // Compare elements
it1 += size1;
it2 += size2;
if (it2 == last2) {
return ptr1; // Found a match
}
if (it1 == end1) {
return last1; // Reached the end of the first sequence
}
}
ptr1 += size1;
}
return last1; // No match found
}
const void *algorithm_search_n(const void *first, const void* last, size_t size, size_t count, const void *val, CompareFuncBool comp) {
const char* ptr = (const char*)first;
const char* end = (const char*)last;
while (ptr + size * count <= end) { // Ensure there's enough room for 'count' elements
size_t matched = 0;
for (size_t i = 0; i < count; ++i) {
if (comp(ptr + i * size, val)) {
matched++;
}
else {
break;
}
}
if (matched == count) {
return ptr; // Found the subsequence
}
ptr += size; // Move to the next element
}
return last; // Subsequence not found
}
void *algorithm_remove(void *base, size_t num, size_t size, const void *val, CompareFunc comp) {
char *ptr = (char *)base;
size_t new_num = 0;
for (size_t i = 0; i < num; ++i) {
if (comp(ptr + i * size, val) != 0) {
if (i != new_num) {
memcpy(ptr + new_num * size, ptr + i * size, size);
}
++new_num;
}
}
return ptr + new_num * size; // Pointer to the new end of the array
}
void algorithm_remove_copy(const void *source, size_t num, size_t size, void *result, const void *val, CompareFunc comp) {
const char *src = (const char *)source;
char *dst = (char *)result;
for (size_t i = 0; i < num; ++i) {
if (comp(src + i * size, val) != 0) {
memcpy(dst, src + i * size, size);
dst += size;
}
}
}Editor is loading...
Leave a Comment