diff --git a/buffer.c b/buffer.c deleted file mode 100644 index 8750210..0000000 --- a/buffer.c +++ /dev/null @@ -1,129 +0,0 @@ -#include "buffer.h" -#include "record.h" -#include "status_codes.h" -#include -#include - -buffer* create_buffer(int capacity) -{ - buffer* out = malloc(sizeof(buffer)); - out->length = 0; - out->capacity = capacity; - out->location = malloc(sizeof(record) * capacity); - out->original = true; - return out; -} - -void destroy_buffer(buffer* buff) -{ - if (buff->original) { - free(buff->location); - } - free(buff); -} - -buffer** split_buffer(buffer* original, int pieces) -{ - int size = original->capacity; - if (size <= 0) { - return NULL; - } - buffer** out = malloc(sizeof(buffer) * pieces); - for (int i = 0; i < pieces; i++) { - out[i]->length = 0; - out[i]->capacity = size; - out[i]->original = 0; - out[i]->location = original->location; - out[i]->location += i * size * sizeof(record); - } - return out; -} - -int read_buffer(buffer* buff, FILE* in) -{ - int status; - record* current = buff->location; - buff->length = 0; - for (int i = 0; i < buff->capacity; i++) { - status = read_record(in, current); - if (status != SUCCESS) { - return status; - } - buff->length++; - current++; - } - return SUCCESS; -} - -int write_buffer(buffer* buff, FILE* out) -{ - int status; - record* current = buff->location; - for (int i = 0; i < buff->length; i++) { - status = print_record(out, current); - if (status < 0) { - return status; - } - fprintf(out, "\n"); - current++; - } - return SUCCESS; -} - -int write_buffer_debug(buffer* buff, FILE* out) -{ - int status; - record* current = buff->location; - for (int i = 0; i < buff->length; i++) { - fprintf(out, "%d\t", g(current)); - status = print_record(out, current); - if (status < 0) { - return status; - } - fprintf(out, "\n"); - current++; - } - return SUCCESS; -} - -int partition(record* arr, int start, int end) -{ - int i = start; - record* pivot = arr; - pivot += end; - for (int j = start; j < end; j++) { - record* current = arr; - current += j; - if (compare_records(current, pivot) > 0) { - continue; - } - record* i_rec = arr; - i_rec += i; - record tmp = *i_rec; - *i_rec = *current; - *current = tmp; - i++; - } - record* i_rec = arr; - i_rec += i; - record tmp = *i_rec; - *i_rec = *pivot; - *pivot = tmp; - return i; -} - -void quicksort(record* arr, int start, int end, int depth) -{ - if (start >= end || start < 0) { - return; - } - - int p = partition(arr, start, end); - quicksort(arr, start, p - 1, depth + 1); - quicksort(arr, p + 1, end, depth + 1); -} - -void sort_buffer(buffer* buff) -{ - quicksort(buff->location, 0, buff->length - 1, 0); -} diff --git a/buffer.h b/buffer.h deleted file mode 100644 index 1b1b407..0000000 --- a/buffer.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "record.h" -#include - -typedef struct { - record* location; - int length; - int capacity; - bool original; -} buffer; - -buffer* create_buffer(int capacity); -void destroy_buffer(buffer* buff); -buffer** split_buffer(buffer* original, int pieces); - -int read_buffer(buffer* buff, FILE* in); -int write_buffer(buffer* buff, FILE* in); -int write_buffer_debug(buffer* buff, FILE* in); -void sort_buffer(buffer* buff); diff --git a/config.c b/config.c deleted file mode 100644 index 9dedf89..0000000 --- a/config.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "config.h" -#include -#include -#include -#include - -int process_args(int argc, char** argv, Configuration* opts) -{ - opts->input_file = DEFAULT_IN; - opts->output_file = DEFAULT_OUT; - opts->directory = DEFAULT_DIR; - opts->generate_data = false; - opts->N = DEFAULT_NN; - opts->n = DEFAULT_N; - opts->b = DEFAULT_B; - int opt; - bool input_set = false; - while ((opt = getopt(argc, argv, "i:o:d:gN:n:b:")) != -1) { - switch (opt) { - case 'i': - opts->input_file = optarg; - input_set = true; - break; - case 'o': - opts->output_file = optarg; - break; - case 'd': - opts->directory = optarg; - break; - case 'g': - opts->generate_data = true; - break; - case 'N': - opts->N = atoi(optarg); - break; - case 'n': - opts->n = atoi(optarg); - break; - case 'b': - opts->b = atoi(optarg); - break; - case '?': - printf("wrong argument\n"); - return ERROR; - } - } - if (opts->generate_data && input_set) { - printf("incompatible arguments\n"); - return ERROR; - } - return SUCCESS; -} diff --git a/config.h b/config.h deleted file mode 100644 index d6aa562..0000000 --- a/config.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "status_codes.h" -#include - -#define DEFAULT_IN "1.in" -#define DEFAULT_OUT "1.in" -#define DEFAULT_DIR "tmp" -#define DEFAULT_NN 100000 -#define DEFAULT_N 101 -#define DEFAULT_B 10 - -typedef struct -{ - const char* input_file; - const char* output_file; - const char* directory; - bool generate_data; - int N; // number of records in a file - int b; // blocking factor - int n; // number of buffers -} Configuration; - -int process_args(int argc, char** argv, Configuration* opts); diff --git a/heap.c b/heap.c deleted file mode 100644 index 2d9825f..0000000 --- a/heap.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "heap.h" -#include "status_codes.h" -#include - -heap* create_heap(int size, int (*comparison)(const void* a, const void* b)) -{ - heap* out = malloc(sizeof(heap)); - out->data = malloc(sizeof(void*) * size); - out->length = 0; - out->capacity = size; - out->compare = comparison; - return out; -} - -void destroy_heap(heap* h) -{ - free(h->data); - free(h); -} - -void swap(void** a, void** b) -{ - void* tmp = *a; - *a = *b; - *b = tmp; -} - -int heap_push(heap* h, void* in) -{ - int current = h->length; - void** d = h->data; - h->length++; - d[current] = in; - if (current == 0) { - return SUCCESS; - } - int parent = (current - 1) / 2; - while (h->compare(d[current], d[parent]) == -1) { - swap(&d[current], &d[parent]); - current = parent; - if (current == 0) { - break; - } - parent = (current - 1) / 2; - } - return SUCCESS; -} - -int heap_pop(heap* h, void** out) -{ - void** d = h->data; - *out = d[0]; - h->length--; - if (h->length == 0) { - return SUCCESS; - } - swap(&d[0], &d[h->length]); - int current = 0; - int left = current * 2 + 1; - int right = current * 2 + 2; - while (true) { - int smallest = current; - if (left < h->length && h->compare(d[smallest], d[left]) == 1) { - smallest = left; - } - if (right < h->length && h->compare(d[smallest], d[right]) == 1) { - smallest = right; - } - if (smallest == current) { - break; - } - swap(&d[smallest], &d[current]); - current = smallest; - left = current * 2 + 1; - right = current * 2 + 2; - } - return SUCCESS; -} diff --git a/heap.h b/heap.h deleted file mode 100644 index 601745b..0000000 --- a/heap.h +++ /dev/null @@ -1,19 +0,0 @@ -// doesn't ceck for user erros, so no veryfying that the void* supplied are valid -// unsafe for general use, but just fnuctional enough for the purposes of this project -// does not maintain ownership of its elements, they are managed by the caller -#pragma once - -#include "stdbool.h" - -typedef struct { - void** data; - int length; - int capacity; - int (*compare)(const void* a, const void* b); -} heap; - -heap* create_heap(int size, int (*comparison)(const void* a, const void* b)); -void destroy_heap(heap* h); - -int heap_pop(heap* h, void** out); -int heap_push(heap* h, void* in); diff --git a/heap_test.c b/heap_test.c deleted file mode 100644 index 2769954..0000000 --- a/heap_test.c +++ /dev/null @@ -1,302 +0,0 @@ -// the tests are ai generated, with prompt based on the heap.h file -#include "heap.h" -#include -#include -#include - -// Comparator for integers -int compare_ints(const void* a, const void* b) -{ - int ia = *(const int*)a; - int ib = *(const int*)b; - return (ia > ib) - (ia < ib); -} - -// Comparator for doubles -int compare_doubles(const void* a, const void* b) -{ - double da = *(const double*)a; - double db = *(const double*)b; - if (da < db) - return -1; - if (da > db) - return 1; - return 0; -} - -// Test structure -typedef struct { - int priority; - char name[32]; -} Task; - -// Comparator for tasks (by priority) -int compare_tasks(const void* a, const void* b) -{ - const Task* ta = (const Task*)a; - const Task* tb = (const Task*)b; - return (ta->priority > tb->priority) - (ta->priority < tb->priority); -} - -void test_basic_push_pop() -{ - printf("Test: Basic push and pop... "); - - heap* h = create_heap(5, compare_ints); - int values[] = { 5, 3, 7, 1, 9 }; - - // Push all values - for (int i = 0; i < 5; i++) { - heap_push(h, &values[i]); - } - - // Pop and verify they come out in sorted order - void* out; - int expected[] = { 1, 3, 5, 7, 9 }; - for (int i = 0; i < 5; i++) { - heap_pop(h, &out); - assert(*(int*)out == expected[i]); - } - - destroy_heap(h); - printf("PASSED\n"); -} - -void test_single_element() -{ - printf("Test: Single element... "); - - heap* h = create_heap(1, compare_ints); - int val = 42; - - heap_push(h, &val); - - void* out; - heap_pop(h, &out); - assert(*(int*)out == 42); - - destroy_heap(h); - printf("PASSED\n"); -} - -void test_already_sorted() -{ - printf("Test: Already sorted input... "); - - heap* h = create_heap(5, compare_ints); - int values[] = { 1, 2, 3, 4, 5 }; - - for (int i = 0; i < 5; i++) { - heap_push(h, &values[i]); - } - - void* out; - for (int i = 0; i < 5; i++) { - heap_pop(h, &out); - assert(*(int*)out == i + 1); - } - - destroy_heap(h); - printf("PASSED\n"); -} - -void test_reverse_sorted() -{ - printf("Test: Reverse sorted input... "); - - heap* h = create_heap(5, compare_ints); - int values[] = { 5, 4, 3, 2, 1 }; - - for (int i = 0; i < 5; i++) { - heap_push(h, &values[i]); - } - - void* out; - for (int i = 0; i < 5; i++) { - heap_pop(h, &out); - assert(*(int*)out == i + 1); - } - - destroy_heap(h); - printf("PASSED\n"); -} - -void test_duplicates() -{ - printf("Test: Duplicate values... "); - - heap* h = create_heap(7, compare_ints); - int values[] = { 3, 1, 4, 1, 5, 9, 2 }; - - for (int i = 0; i < 7; i++) { - heap_push(h, &values[i]); - } - - void* out; - int expected[] = { 1, 1, 2, 3, 4, 5, 9 }; - for (int i = 0; i < 7; i++) { - heap_pop(h, &out); - assert(*(int*)out == expected[i]); - } - - destroy_heap(h); - printf("PASSED\n"); -} - -void test_with_doubles() -{ - printf("Test: Double precision values... "); - - heap* h = create_heap(5, compare_doubles); - double values[] = { 3.14, 1.41, 2.71, 0.57, 1.61 }; - - for (int i = 0; i < 5; i++) { - heap_push(h, &values[i]); - } - - void* out; - double expected[] = { 0.57, 1.41, 1.61, 2.71, 3.14 }; - for (int i = 0; i < 5; i++) { - heap_pop(h, &out); - assert(*(double*)out == expected[i]); - } - - destroy_heap(h); - printf("PASSED\n"); -} - -void test_with_structs() -{ - printf("Test: Custom struct (tasks by priority)... "); - - heap* h = create_heap(4, compare_tasks); - Task tasks[] = { - { 3, "Low priority" }, - { 1, "High priority" }, - { 2, "Medium priority" }, - { 1, "Also high priority" } - }; - - for (int i = 0; i < 4; i++) { - heap_push(h, &tasks[i]); - } - - void* out; - int expected_priorities[] = { 1, 1, 2, 3 }; - for (int i = 0; i < 4; i++) { - heap_pop(h, &out); - Task* t = (Task*)out; - assert(t->priority == expected_priorities[i]); - } - - destroy_heap(h); - printf("PASSED\n"); -} - -void test_interleaved_operations() -{ - printf("Test: Interleaved push/pop... "); - - heap* h = create_heap(10, compare_ints); - int values[] = { 5, 3, 7, 1, 9, 2, 8, 4, 6, 0 }; - - // Push 5, pop 1, push 3 more, pop 2, etc. - heap_push(h, &values[0]); // 5 - heap_push(h, &values[1]); // 3 - heap_push(h, &values[2]); // 7 - - void* out; - heap_pop(h, &out); - assert(*(int*)out == 3); - - heap_push(h, &values[3]); // 1 - heap_push(h, &values[4]); // 9 - heap_push(h, &values[5]); // 2 - - heap_pop(h, &out); - assert(*(int*)out == 1); - heap_pop(h, &out); - assert(*(int*)out == 2); - - heap_push(h, &values[6]); // 8 - heap_push(h, &values[7]); // 4 - - heap_pop(h, &out); - assert(*(int*)out == 4); - - destroy_heap(h); - printf("PASSED\n"); -} - -void test_large_heap() -{ - printf("Test: Large heap (1000 elements)... "); - - heap* h = create_heap(1000, compare_ints); - int* values = malloc(1000 * sizeof(int)); - - // Insert values in random-ish order - for (int i = 0; i < 1000; i++) { - values[i] = (i * 7 + 13) % 1000; - heap_push(h, &values[i]); - } - - // Pop all and verify sorted - void* out; - int prev = -1; - for (int i = 0; i < 1000; i++) { - heap_pop(h, &out); - int curr = *(int*)out; - assert(curr >= prev); - prev = curr; - } - - free(values); - destroy_heap(h); - printf("PASSED\n"); -} - -void test_all_same_values() -{ - printf("Test: All same values... "); - - heap* h = create_heap(5, compare_ints); - int val = 42; - int values[5]; - - for (int i = 0; i < 5; i++) { - values[i] = val; - heap_push(h, &values[i]); - } - - void* out; - for (int i = 0; i < 5; i++) { - heap_pop(h, &out); - assert(*(int*)out == 42); - } - - destroy_heap(h); - printf("PASSED\n"); -} - -int main() -{ - printf("Running Min Heap Tests\n"); - printf("======================\n\n"); - - test_basic_push_pop(); - test_single_element(); - test_already_sorted(); - test_reverse_sorted(); - test_duplicates(); - test_with_doubles(); - test_with_structs(); - test_interleaved_operations(); - test_large_heap(); - test_all_same_values(); - - printf("\n======================\n"); - printf("All tests PASSED! ✓\n"); - - return 0; -} diff --git a/main.c b/main.c deleted file mode 100644 index d6e6acf..0000000 --- a/main.c +++ /dev/null @@ -1,120 +0,0 @@ -#include "buffer.h" -#include "config.h" -#include "record.h" -#include "status_codes.h" -#include -#include -#include -#include - -int generate_file(int N, const char* filename) -{ - srand(time(0)); - FILE* f = fopen(filename, "w"); - record rec; - - for (int i = 0; i < N; i++) { - random_record(&rec); - print_record(f, &rec); - fprintf(f, "\n"); - } - return SUCCESS; -} - -int sort_file(Configuration* opts) -{ - buffer* buff = create_buffer(opts->b * opts->n); - FILE* in = fopen(opts->input_file, "r"); - int runs; - // - for (runs = 0; true; runs++) { - // read buffer - int status = read_buffer(buff, in); - if (status != SUCCESS && status != EOF) { - fclose(in); - destroy_buffer(buff); - } - // sort buffer - sort_buffer(buff); - // write run - char* filename = malloc(256); - sprintf(filename, "%s/%d", opts->directory, runs); - FILE* tmp = fopen(filename, "w"); - write_buffer(buff, tmp); - // write_buffer_debug(buff, stdout); - fclose(tmp); - free(filename); - if (status != SUCCESS) { - break; - } - } - printf("created runs: %d\n", runs); - - // - while (runs > 1) { - - // split buffers - // read buffers - for (int i = 0; i < opts->b - 1; i++) { - } - - // b-1 runs are turned into one, so the total is reduced by b-2 - runs -= (opts->b - 2); - } - fclose(in); - destroy_buffer(buff); - return SUCCESS; -} - -int main(int argc, char** argv) -{ - Configuration opts; - if (argc <= 1) { - // #todo: stdin input - fprintf(stderr, "please specify input args\n"); - return ERROR; - } - int result = process_args(argc, argv, &opts); - if (result != SUCCESS) { - return result; - } - if (opts.generate_data) { - return generate_file(opts.N, opts.output_file); - } - sort_file(&opts); -} -// int sort_block(tape* t, buffer* buff) -// { -// static int counter = 0; -// int status = read_buffer(buff, t); -// if (status != SUCCESS && status != EOF) { -// fprintf(stderr, "Error reading file: %d\n", status); -// return status; -// } - -// sort_buffer(buff); -// printf("sorted the buffer %d, the results:\n", counter); -// print_buffer(buff); -// counter++; -// return status; -// } - -// int sort_file(options* opts) -// { -// tape a = { 0, 0, opts->input }; -// buffer buff; -// buff.capacity = opts->b * opts->n; -// buff.location = malloc(sizeof(record) * buff.capacity); -// int status = 0; -// while (status == SUCCESS) { -// status = sort_block(&a, &buff); -// } -// if (status != EOF) { -// free(buff.location); -// fclose(a.file); -// return status; -// } -// free(buff.location); -// fclose(a.file); -// return SUCCESS; -// } diff --git a/makefile b/makefile index 6dd82d5..437aecf 100644 --- a/makefile +++ b/makefile @@ -1,19 +1,7 @@ -CFLAGS = -g +CFLAGS = -g -lc++ -build/main: build/main.o build/config.o build/buffer.o build/heap.o - clang $(CFLAGS) build/main.o build/config.o build/buffer.o build/heap.o -o build/main - -build/main.o: main.c build - clang $(CFLAGS) -c main.c -o build/main.o - -build/config.o: config.c build - clang $(CFLAGS) -c config.c -o build/config.o - -build/buffer.o: buffer.c build - clang $(CFLAGS) -c buffer.c -o build/buffer.o - -build/heap.o: heap.c build - clang $(CFLAGS) -c heap.c -o build/heap.o +build/main: main.cpp build + clang $(CFLAGS) main.cpp -o build/main build: mkdir -p build @@ -27,22 +15,15 @@ build/run/tmp: build/run clean: rm -rf build +generate: build/run/1.in + build/run/1.in: build/run build/main build/main -g -o build/run/1.in run: build/main build/run/1.in build/run/tmp build/main -i build/run/1.in -d build/run/tmp | less -build/heap_test.o: heap_test.c build - clang $(CFLAGS) -c heap_test.c -o build/heap_test.o - -build/test: build/heap_test.o build/heap.o - clang $(CFLAGS) build/heap_test.o build/heap.o -o build/test - -test: build/test - build/test - debug: build/main tests/1.in lldb -- build/main -.PHONY: clean run debug test +.PHONY: clean run debug test generate diff --git a/record.h b/record.h deleted file mode 100644 index 265b2c5..0000000 --- a/record.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once -#include -#include - -typedef struct { - int a[5]; - int x; -} record; - -static inline int g(const record* x) -{ - int out = 0; - int x_n = 1; - for (int i = 0; i < 5; i++) { - out += x->a[i] * x_n; - x_n *= x->x; - } - return out; -} - -static inline int compare_records(const void* a, const void* b) -{ - const record* ra = (const record*)a; - const record* rb = (const record*)b; - int ga = g(ra); - int gb = g(rb); - int result = (ga > gb) - (ga < gb); - return result; -} - -static inline int print_record(FILE* stream, const record* out) -{ - return fprintf(stream, "%d %d %d %d %d %d", - out->a[0], out->a[1], out->a[2], out->a[3], out->a[4], out->x); -} - -static inline int read_record(FILE* stream, record* out) -{ - record tmp; - int result = fscanf(stream, "%d %d %d %d %d %d", &tmp.a[0], &tmp.a[1], &tmp.a[2], &tmp.a[3], &tmp.a[4], &tmp.x); - if (result == 6) { - *out = tmp; - return 0; - } - if (result == EOF) { - return EOF; - } - return -2; -} - -static inline void random_record(record* out) -{ - for (int i = 0; i < 5; i++) { - out->a[i] = rand(); - } - out->x = rand(); -} diff --git a/status_codes.h b/status_codes.h deleted file mode 100644 index 9866402..0000000 --- a/status_codes.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#define END_PROGRAM -1 -#define SUCCESS 0 -#define ERROR -2 -#define NO_SPACE -3