Compare commits

...

3 Commits

12 changed files with 290 additions and 144 deletions

View File

@@ -19,13 +19,16 @@ LIB_INSTALL_PATH := /usr/local/lib
STATIC_BUILD_FILES := $(STATIC_BUILD_DIR)/lsort.o \ STATIC_BUILD_FILES := $(STATIC_BUILD_DIR)/lsort.o \
$(STATIC_BUILD_DIR)/types.o \ $(STATIC_BUILD_DIR)/types.o \
$(STATIC_BUILD_DIR)/radix.o $(STATIC_BUILD_DIR)/radix.o \
$(STATIC_BUILD_DIR)/quicksort.o
DYNAMIC_BUILD_FILES := $(DYNAMIC_BUILD_DIR)/lsort.o \ DYNAMIC_BUILD_FILES := $(DYNAMIC_BUILD_DIR)/lsort.o \
$(STATIC_BUILD_DIR)/types.o \ $(STATIC_BUILD_DIR)/types.o \
$(STATIC_BUILD_DIR)/radix.o $(STATIC_BUILD_DIR)/radix.o \
$(STATIC_BUILD_DIR)/quicksort.o
TEST_BUILD_FILES := $(TEST_BUILD_DIR)/test.o \ TEST_BUILD_FILES := $(TEST_BUILD_DIR)/test.o \
$(TEST_BUILD_DIR)/samples.o \
@@ -38,30 +41,33 @@ dynamic: $(DYNAMIC_BUILD_FILES)
$(CC) -shared -o $(DYNAMIC_BUILD_DIR)/liblsort.so $(DYNAMIC_BUILD_FILES) $(CC) -shared -o $(DYNAMIC_BUILD_DIR)/liblsort.so $(DYNAMIC_BUILD_FILES)
$(DYNAMIC_BUILD_DIR)/%.o: %.c | $(DYNAMIC_BUILD_DIR) $(DYNAMIC_BUILD_DIR)/%.o: %.c | $(DYNAMIC_BUILD_DIR)
$(CC) $(CFLAGS) -c -fPIC $< -o $@ $(CC) $(CFLAGS) -I./test/include -c -fPIC $< -o $@
static: $(STATIC_BUILD_FILES) static: $(STATIC_BUILD_FILES)
ar rcs $(STATIC_BUILD_DIR)/liblsort.a $(STATIC_BUILD_FILES) ar rcs $(STATIC_BUILD_DIR)/liblsort.a $(STATIC_BUILD_FILES)
$(STATIC_BUILD_DIR)/%.o: %.c | $(STATIC_BUILD_DIR) $(STATIC_BUILD_DIR)/%.o: %.c | $(STATIC_BUILD_DIR)
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -I./test/include -c $< -o $@
test: dynamic static $(TEST_BUILD_FILES) test: $(TEST_BUILD_FILES) test_dynamic test_static
$(CC) $(CFLAGS) -L$(CURDIR)/$(DYNAMIC_BUILD_DIR) -llsort -o $(TEST_BUILD_DIR)/test_dynamic $(TEST_BUILD_FILES)
$(CC) $(CFLAGS) -o $(TEST_BUILD_DIR)/test_static $(TEST_BUILD_FILES) $(STATIC_BUILD_DIR)/liblsort.a test_dynamic: dynamic $(TEST_BUILD_FILES)
$(CC) $(CFLAGS) -L$(CURDIR)/$(DYNAMIC_BUILD_DIR) -llsort -o $(TEST_BUILD_DIR)/test_dynamic $(TEST_BUILD_FILES)
@echo "" @echo ""
@echo "Running dynamic test..." @echo "Running dynamic test..."
@echo "" @echo ""
LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(CURDIR)/build/dynamic ./$(TEST_BUILD_DIR)/test_dynamic LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(CURDIR)/build/dynamic ./$(TEST_BUILD_DIR)/test_dynamic
test_static: static $(TEST_BUILD_FILES)
$(CC) $(CFLAGS) -o $(TEST_BUILD_DIR)/test_static $(TEST_BUILD_FILES) $(STATIC_BUILD_DIR)/liblsort.a
@echo "" @echo ""
@echo "Running static test..." @echo "Running static test..."
@echo "" @echo ""
./$(TEST_BUILD_DIR)/test_static ./$(TEST_BUILD_DIR)/test_static
$(TEST_BUILD_DIR)/%.o: test/%.c | $(TEST_BUILD_DIR) $(TEST_BUILD_DIR)/%.o: test/%.c | $(TEST_BUILD_DIR)

View File

@@ -3,6 +3,6 @@
#include "types.h" #include "types.h"
int check_sorted(lsort_array_i* array); int check_sorted(lsort_array* array);
#endif #endif

8
include/quicksort.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef LSORT_QUICKSORT_H
#define LSORT_QUICKSORT_H
#include "types.h"
int lsort_quicksort(lsort_array* array, int_function_pointer compare_function);
#endif

View File

@@ -3,6 +3,6 @@
#include "types.h" #include "types.h"
int lsort_radix(lsort_array_i* array, lsort_array_i* return_array); int lsort_radix(lsort_array* array, lsort_array* return_array);
#endif #endif

View File

@@ -4,35 +4,43 @@
#include <stddef.h> #include <stddef.h>
#include "string.h" #include "string.h"
typedef struct { typedef struct {
const char *buf; const char *buf;
size_t len; size_t len;
} lsort_string; } lsort_string;
typedef struct { typedef struct {
size_t count; int key;
size_t capacity; void* value;
int* items; } lsort_item;
} lsort_array_i; typedef int (*int_function_pointer)(lsort_item*, lsort_item*);
lsort_array_i* lsort_array_i_create();
void lsort_array_i_destroy(lsort_array_i* array);
void lsort_array_i_append(lsort_array_i* array, int number);
int lsort_array_i_swap(lsort_array_i* array, int indexA, int indexB);
void lsort_array_i_print(lsort_array_i* array);
typedef struct { typedef struct {
size_t count; size_t count;
size_t capacity; size_t capacity;
lsort_array_i** items; lsort_item** items;
} lsort_array_i_array; } lsort_array;
void lsort_array_i_array_append(lsort_array_i_array* array, lsort_array_i* item); typedef struct {
void lsort_array_i_array_destroy(lsort_array_i_array* array); size_t count;
size_t capacity;
lsort_array** items;
} lsort_array_array;
lsort_item* lsort_item_create(int key, void* value);
lsort_array* lsort_array_create();
lsort_array_array* lsort_array_array_create();
void lsort_item_destroy(lsort_item* item);
void lsort_array_destroy(lsort_array* array, int destroyItems);
void lsort_array_array_destroy(lsort_array_array* array, int destroyItems);
void lsort_array_append(lsort_array* array, lsort_item* item);
void lsort_array_array_append(lsort_array_array* array, lsort_array* item);
void lsort_array_clear(lsort_array* array);
int lsort_array_swap(lsort_array* array, int indexA, int indexB);
#endif #endif

View File

@@ -1,9 +1,9 @@
#include "./include/lsort.h" #include "./include/lsort.h"
int check_sorted(lsort_array_i* array) { int check_sorted(lsort_array* array) {
if (array->count <= 0) return 2; if (array->count <= 0) return 2;
for (int i = 0; i < array->count - 1; i++) { for (int i = 0; i < array->count - 1; i++) {
if (array->items[i] > array->items[i + 1]) { if (array->items[i]->key > array->items[i + 1]->key) {
return 1; return 1;
}; };
} }

36
quicksort.c Normal file
View File

@@ -0,0 +1,36 @@
#include "include/lsort.h"
#include "include/types.h"
#include "include/quicksort.h"
static int partition(lsort_array* array, int L, int R, int_function_pointer compare_function) {
lsort_item* pivot = array->items[R];
int i = L - 1;
for (int j = L; j < R; j++) {
if (compare_function(array->items[j], pivot) < 0) {
i = i + 1;
lsort_array_swap(array, i, j);
}
}
lsort_array_swap(array, i + 1, R);
return i + 1;
}
static void _quicksort(lsort_array* array, int L, int R, int_function_pointer compare_function) {
if (L < R) {
int pivotIndex = partition(array, L, R, compare_function);
_quicksort(array, L, pivotIndex - 1, compare_function);
_quicksort(array, pivotIndex + 1, R, compare_function);
}
}
int lsort_quicksort(lsort_array* array, int_function_pointer compare_function) {
if (array->count < 1) {
return 0;
}
_quicksort(array, 0, (int)array->count - 1, compare_function);
return check_sorted(array);
}

60
radix.c
View File

@@ -1,40 +1,42 @@
#include "include/lsort.h"
#include "include/types.h" #include "include/types.h"
#include "include/radix.h" #include "include/radix.h"
int _seperate_pos_neg(lsort_array_i* array, lsort_array_i* pos_array, lsort_array_i* neg_array) { static int _seperate_pos_neg(lsort_array* array, lsort_array* pos_array, lsort_array* neg_array) {
for (int i = 0; i < array->count; i++) { for (int i = 0; i < array->count; i++) {
if ((0x80000000 & array->items[i]) == 0x80000000) { if ((0x80000000 & array->items[i]->key) == 0x80000000) {
lsort_array_i_append(neg_array, array->items[i]); lsort_array_append(neg_array, array->items[i]);
} else { } else {
lsort_array_i_append(pos_array, array->items[i]); lsort_array_append(pos_array, array->items[i]);
} }
} }
return 0; return 0;
} }
int _sort_items(lsort_array_i* numbers, lsort_array_i_array* buckets) { static int _sort_items(lsort_array* numbers, lsort_array_array* buckets) {
int byte_check = 0x0000000F; int byte_check = 0x0000000F;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
// Loop through the list of numbers and append them to their respective buckets for this 4-byte chunk // Loop through the list of numbers and append them to their respective buckets for this 4-byte chunk
for (int item_index = 0; item_index < numbers->count; item_index++) { for (int item_index = 0; item_index < numbers->count; item_index++) {
int* current_number = &numbers->items[item_index]; lsort_item* current_item = numbers->items[item_index];
lsort_array_i* bucket = buckets->items[(*current_number >> (i * 4)) & byte_check]; lsort_array* bucket = buckets->items[(current_item->key >> (i * 4)) & byte_check];
lsort_array_i_append(bucket, *current_number);
lsort_array_append(bucket, current_item);
} }
numbers->count = 0; lsort_array_clear(numbers);
// Add the bucketed numbers back to the original array after emptying it // Add the bucketed numbers back to the original array after emptying it
for (int bucket_number = 0; bucket_number < buckets->count; bucket_number++) { for (int bucket_number = 0; bucket_number < buckets->count; bucket_number++) {
lsort_array_i* bucket = buckets->items[bucket_number]; lsort_array* bucket = buckets->items[bucket_number];
for (int bucket_item = 0; bucket_item < bucket->count; bucket_item++) { for (int bucket_item = 0; bucket_item < bucket->count; bucket_item++) {
lsort_array_i_append(numbers, bucket->items[bucket_item]); lsort_array_append(numbers, bucket->items[bucket_item]);
} }
bucket->count = 0; lsort_array_clear(bucket);
} }
// Repeat for each 4-byte chunk... // Repeat for each 4-byte chunk...
@@ -43,37 +45,41 @@ int _sort_items(lsort_array_i* numbers, lsort_array_i_array* buckets) {
return 0; return 0;
} }
int lsort_radix(lsort_array_i* array, lsort_array_i* return_array) { int lsort_radix(lsort_array* array, lsort_array* return_array) {
if (array->count <= 0) return 1; if (array->count <= 0) return 1;
// Seperate positive and negative numbers // Seperate positive and negative numbers
lsort_array_i positive_numbers = {0}; lsort_array* positive_numbers = lsort_array_create();
lsort_array_i negative_numbers = {0}; lsort_array* negative_numbers = lsort_array_create();
if (_seperate_pos_neg(array, &positive_numbers, &negative_numbers)) return 2; if (_seperate_pos_neg(array, positive_numbers, negative_numbers)) return 2;
// Create buckets // Create buckets
lsort_array_i_array buckets = {0}; lsort_array_array* buckets = lsort_array_array_create();
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
lsort_array_i* bucket = lsort_array_i_create(); lsort_array* bucket = lsort_array_create();
lsort_array_i_array_append(&buckets, bucket); lsort_array_array_append(buckets, bucket);
} }
// Sort each set of numbers using those buckets // Sort each set of numbers using those buckets
_sort_items(&negative_numbers, &buckets); _sort_items(negative_numbers, buckets);
_sort_items(&positive_numbers, &buckets); _sort_items(positive_numbers, buckets);
// Add each array of numbers to the return array // Add each array of numbers to the return array
for (int i = 0; i < negative_numbers.count; i++) { for (int i = 0; i < negative_numbers->count; i++) {
lsort_array_i_append(return_array, negative_numbers.items[i]); lsort_array_append(return_array, negative_numbers->items[i]);
} }
for (int i = 0; i < positive_numbers.count; i++) { for (int i = 0; i < positive_numbers->count; i++) {
lsort_array_i_append(return_array, positive_numbers.items[i]); lsort_array_append(return_array, positive_numbers->items[i]);
} }
lsort_array_destroy(negative_numbers, 0);
lsort_array_destroy(positive_numbers, 0);
// Destroy the buckets // Destroy the buckets
lsort_array_i_array_destroy(&buckets); lsort_array_array_destroy(buckets, 0);
return 0; return check_sorted(return_array);
} }

8
test/include/samples.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef LSORTTEST_SAMPLES_H
#define LSORTTEST_SAMPLES_H
#include "../../include/types.h"
lsort_array* generate_samples(int number);
#endif

15
test/samples.c Normal file
View File

@@ -0,0 +1,15 @@
#include "../include/types.h"
#include "include/samples.h"
#include <stdlib.h>
#include <time.h>
lsort_array* generate_samples(int number) {
srand(time(NULL));
lsort_array* array = lsort_array_create();
for (int i = 0; i < number; i++) {
lsort_array_append(array, lsort_item_create(rand(), NULL));
}
return array;
};

View File

@@ -1,80 +1,103 @@
#include "../include/types.h" #include "../include/types.h"
#include "../include/radix.h" #include "../include/radix.h"
#include "../include/lsort.h" #include "../include/quicksort.h"
#include "include/samples.h"
#include <stdio.h> #include <stdio.h>
int test_array_i_append(lsort_array_i* array) { #define sample_count 64*64*64*64
int test_array_append() {
printf("lsort_array_append()...\n");
int return_code = 0;
lsort_array* array = lsort_array_create();
lsort_array_append(array, lsort_item_create(25, NULL));
lsort_array_append(array, lsort_item_create(64, NULL));
lsort_array_append(array, lsort_item_create(34, NULL));
lsort_array_append(array, lsort_item_create(74, NULL));
lsort_array_append(array, lsort_item_create(99, NULL));
lsort_array_append(array, lsort_item_create(23, NULL));
lsort_array_i_append(array, 25); if (array->items[5]->key != 23) return_code = 1;
lsort_array_i_append(array, 64);
lsort_array_i_append(array, 34); lsort_array_destroy(array, 1);
lsort_array_i_append(array, 74); return return_code;
lsort_array_i_append(array, 99);
lsort_array_i_append(array, 23);
if (array->items[5] != 23) return 1;
return 0;
} }
int test_array_i_swap(lsort_array_i* array) { int test_array_swap() {
lsort_array_i_swap(array, 0, 5); printf("lsort_array_swap()...\n");
lsort_array_i_swap(array, 4, 2);
lsort_array_i_swap(array, 2, 3);
if (array->items[0] != 23 || array->items[5] != 25 || array->items[4] != 34 || array->items[2] != 74 || array->items[3] != 99) return 1;
return 0; int return_code = 0;
} lsort_array* array = lsort_array_create();
int test_append_swap() { lsort_array_append(array, lsort_item_create(25, NULL));
lsort_array_i array_append_swap = {0}; lsort_array_append(array, lsort_item_create(64, NULL));
lsort_array_append(array, lsort_item_create(34, NULL));
if (test_array_i_append(&array_append_swap)) return 1; lsort_array_append(array, lsort_item_create(74, NULL));
if (test_array_i_swap(&array_append_swap)) return 1; lsort_array_append(array, lsort_item_create(99, NULL));
lsort_array_append(array, lsort_item_create(23, NULL));
lsort_array_i array_sort_check = {0};
lsort_array_i_append(&array_sort_check, 1);
lsort_array_i_append(&array_sort_check, 5);
lsort_array_i_append(&array_sort_check, 7);
lsort_array_i_append(&array_sort_check, 8);
lsort_array_i_append(&array_sort_check, 15);
lsort_array_i_append(&array_sort_check, 28);
if (check_sorted(&array_sort_check) == 1) return 1; int index_0 = array->items[0]->key;
lsort_array_i_swap(&array_sort_check, 2, 4); int index_1 = array->items[1]->key;
lsort_array_i_swap(&array_sort_check, 0, 3); int index_2 = array->items[2]->key;
if (check_sorted(&array_sort_check) == 0) return 1; int index_3 = array->items[3]->key;
int index_4 = array->items[4]->key;
int index_5 = array->items[5]->key;
lsort_array_swap(array, 0, 5);
lsort_array_swap(array, 4, 2);
lsort_array_swap(array, 2, 3);
return 0; if (
array->items[0]->key != index_5 ||
array->items[5]->key != index_0 ||
array->items[4]->key != index_2 ||
array->items[3]->key != index_4 ||
array->items[2]->key != index_3 ||
array->items[1]->key != index_1
) return_code = 1;
lsort_array_destroy(array, 1);
return return_code;
} }
int test_radix_sort() { int test_radix_sort() {
lsort_array_i array_radix = {0}; printf("lsort_radix()...\n");
lsort_array_i_append(&array_radix, -2);
lsort_array_i_append(&array_radix, -15);
lsort_array_i_append(&array_radix, 25);
lsort_array_i_append(&array_radix, 56);
lsort_array_i_append(&array_radix, 23);
lsort_array_i_append(&array_radix, -222);
lsort_array_i_append(&array_radix, -58);
lsort_array_i array_radix_return = {0}; lsort_array* array_radix = generate_samples(sample_count);
lsort_radix(&array_radix, &array_radix_return); lsort_array* array_radix_return = lsort_array_create();
int return_code = lsort_radix(array_radix, array_radix_return);
if (check_sorted(&array_radix_return) != 0) return 1; lsort_array_destroy(array_radix, 1);
return return_code;
}
return 0; int test_compare_function(lsort_item* a, lsort_item* b) {
return a->key - b->key;
}
int test_quicksort() {
printf("lsort_quicksort()...\n");
lsort_array* array_quicksort = generate_samples(sample_count);
int return_code = lsort_quicksort(array_quicksort, test_compare_function);
lsort_array_destroy(array_quicksort, 1);
return return_code;
} }
int main(void) { int main(void) {
if ( if (
test_append_swap() || test_array_append() ||
test_radix_sort() test_array_swap() ||
test_radix_sort() ||
test_quicksort()
) return 1; ) return 1;
printf("Test completed successfully.\n"); printf("\nTest completed successfully.\n");
return 0; return 0;
} }

98
types.c
View File

@@ -1,16 +1,57 @@
#include "include/types.h" #include "include/types.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> // #include <stdio.h>
lsort_array_i* lsort_array_i_create() { lsort_item* lsort_item_create(int key, void* value) {
return calloc(1, sizeof(lsort_array_i)); lsort_item* item = calloc(1, sizeof(lsort_item));
item->key = key;
item->value = value;
return item;
};
lsort_array* lsort_array_create() {
return calloc(1, sizeof(lsort_array));
} }
void lsort_array_i_destroy(lsort_array_i* array) { lsort_array_array* lsort_array_array_create() {
return calloc(1, sizeof(lsort_array_array));
}
void lsort_item_destroy(lsort_item* item) {
free(item->value);
item->value = NULL;
free(item);
item = NULL;
};
void lsort_array_destroy(lsort_array* array, int destroyItems) {
if (destroyItems) {
for (int i = 0; i < array->count; i++) {
lsort_item_destroy(array->items[i]);
}
}
free(array->items);
array->items = NULL;
free(array); free(array);
} }
void lsort_array_i_append(lsort_array_i* array, int item) { void lsort_array_array_destroy(lsort_array_array* array, int destroyItems) {
for (int array_number = 0; array_number < array->count; array_number++) {
lsort_array_destroy(array->items[array_number], destroyItems);
}
free(array->items);
array->items = NULL;
free(array);
array = NULL;
}
void lsort_array_append(lsort_array* array, lsort_item* item) {
if (array->count >= array->capacity) { if (array->count >= array->capacity) {
if (array->capacity == 0) array->capacity = 8; if (array->capacity == 0) array->capacity = 8;
else array->capacity *= 2; else array->capacity *= 2;
@@ -20,34 +61,29 @@ void lsort_array_i_append(lsort_array_i* array, int item) {
array->items[array->count++] = item; array->items[array->count++] = item;
} }
int lsort_array_i_swap(lsort_array_i* array, int indexA, int indexB) { void lsort_array_array_append(lsort_array_array* array, lsort_array* item) {
if (array->count >= array->capacity) {
if (array->capacity == 0) array->capacity = 8;
else array->capacity *= 2;
array->items = realloc(array->items, array->capacity * sizeof(*array->items));
}
array->items[array->count++] = item;
}
void lsort_array_clear(lsort_array* array) {
free(array->items);
array->items = NULL;
array->count = 0;
array->capacity = 0;
}
int lsort_array_swap(lsort_array* array, int indexA, int indexB) {
if (indexA > array->count - 1 || indexB > array->count - 1) return 1; if (indexA > array->count - 1 || indexB > array->count - 1) return 1;
int temp = array->items[indexA]; lsort_item* temp = array->items[indexA];
array->items[indexA] = array->items[indexB]; array->items[indexA] = array->items[indexB];
array->items[indexB] = temp; array->items[indexB] = temp;
return 0; return 0;
}
void lsort_array_i_print(lsort_array_i* array) {
for (int i = 0; i < array->count; i++) {
printf("%d ", array->items[i]);
}
printf("\n");
}
void lsort_array_i_array_append(lsort_array_i_array* array, lsort_array_i* item) {
if (array->count >= array->capacity) {
if (array->capacity == 0) array->capacity = 8;
else array->capacity *= 2;
array->items = realloc(array->items, array->capacity * sizeof(*array->items));
}
array->items[array->count++] = item;
}
void lsort_array_i_array_destroy(lsort_array_i_array* array) {
for (int array_number = 0; array_number < array->count; array_number++) {
lsort_array_i_destroy(array->items[array_number]);
}
} }