From: Axy Date: Sun, 14 Dec 2025 02:08:56 +0000 (+0100) Subject: Working splitsort, only needs slight tweaking! X-Git-Url: https://git.uwuaxy.net/?a=commitdiff_plain;h=a3b5588b6b01f14e66095d845bdd0b15014c4fc4;p=axy%2Fft%2Fpushswap.git Working splitsort, only needs slight tweaking! --- diff --git a/_res_leaf_sort_lookup.h b/_res_leaf_sort_lookup.h index 365fde3..487d7d6 100644 --- a/_res_leaf_sort_lookup.h +++ b/_res_leaf_sort_lookup.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/10 16:53:22 by agilliar #+# #+# */ -/* Updated: 2025/12/10 17:07:25 by agilliar ### ########.fr */ +/* Updated: 2025/12/12 13:22:56 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,32 +19,32 @@ ra ra ra ra sa ra ra sa ra ra ra pb sa ra pa ra ra -pb sa ra ra pa ra sa ra sa ra ra +pb sa ra ra pa ra ra ra ra ra ra ra sa ra ra ra sa ra ra ra ra pb sa ra pa ra ra -ra pb sa ra ra pa ra ra sa ra sa ra ra +ra pb sa ra ra pa ra sa ra ra ra ra sa ra ra sa ra ra pb sa ra pa ra ra ra pb pb sa ra pa pa ra ra ra -pb pb ss ra pa ra ra pa ra sa pb sa ra ra ra pa ra -pb sa ra ra pa ra ra -pb pb sa ra pa ra pa ra ra +pb pb ss ra pa ra ra pa ra sa ra sa ra ra ra pb ra sa ra pa ra ra +pb sa ra ra pa ra ra +pb pb sa ra pa ra pa ra ra pb sa ra sa ra pa ra ra pb pb sa ra ra pa pa ra ra -pb pb sa ra pa ra ra pa ra +pb ra ra ra pa ra +pb ra sa ra ra pa ra pb sa ra ra ra pa ra -pb pb sa ra ra pa ra pa ra +pb pb sa ra pa ra ra pa ra pb sa ra sa ra ra pa ra -pb ra sa ra ra pa ra -pb ra ra ra pa ra +pb pb sa ra ra pa ra pa ra pb sa pb pb @@ -53,30 +53,30 @@ sa pb sa pb sb pb sa pb sa pb pb pb sa pb sb pb sa pb pb pb -pb pb pb pb sa pb pb +pb pb pb sa pb rr sa pb pb rrr pb sa pb rr pb pb rrr pb pb pb ss rb pb sb pb rrb sa pb sa pb ss pb pb -pb rb pb pb pb rrb pb pb ss pb sb pb sb +pb rb pb pb pb rrb pb rr sa pb pb rrr pb pb rr pb pb rrr pb sa pb pb rr pb sb rrr pb sa pb sa pb sb pb pb -sa pb sa pb pb pb pb pb ss pb sb pb -pb pb rr pb sb rrr pb -pb sa pb sb pb pb +sa pb sa pb pb pb pb sa pb rr pb sb rrr pb pb sa pb ss pb pb +pb pb rr pb sb rrr pb +pb sa pb sb pb pb pb pb ss pb pb sa pb pb pb pb -pb sa pb pb pb +pb sa pb sa pb sb pb +pb sa pb sa pb pb pb pb sa pb sb pb -pb pb pb pb +pb sa pb pb pb pb pb sa pb pb -pb sa pb sa pb pb -pb sa pb sa pb sb pb +pb pb pb pb */ diff --git a/algorithm_splitsort.c b/algorithm_splitsort.c index fdd84f4..c34c645 100644 --- a/algorithm_splitsort.c +++ b/algorithm_splitsort.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/11 12:45:16 by agilliar #+# #+# */ -/* Updated: 2025/12/12 00:07:33 by agilliar ### ########.fr */ +/* Updated: 2025/12/14 03:07:01 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,241 +19,259 @@ typedef struct s_splitsort size_t blocks; } t_splitsort; -// MODE_NORMAL: sort current elements in ascending order -// top < bottom -// top ascending -// bottom descending -// MODE_REV: sort current elements in descending order -// top > bottom -// top descending -// bottom ascending -// MODE_WRAP: sort current elements in descending order, without unwind -// top < bottom -// top descending -// bottom ascending -typedef enum e_mode -{ - MODE_NORMAL, - MODE_REV, - MODE_WRAP, -} t_mode; - typedef struct s_iter { - t_list top; - t_list bottom; - size_t top_blocks; - size_t bottom_blocks; - bool top_rev; - bool bottom_rev; + t_list range; + size_t blocks; + bool rev; } t_iter; -static t_iter splitsort_iter_new(t_splitsort sort, t_mode mode, t_list range) +static t_iter iter_new(t_list range, size_t blocks, bool rev) { t_iter res; - size_t top_len; - size_t bottom_len; - - if (sort.blocks == 0) - cheatexit(1); - res.top_blocks = sort.blocks / 2; - res.bottom_blocks = sort.blocks - res.top_blocks; - top_len = range.len * res.top_blocks / sort.blocks; - bottom_len = range.len - top_len; - if (mode == MODE_REV) - res.bottom = list_split(&range, bottom_len); - else - res.top = list_split(&range, top_len); - if (mode == MODE_REV) - res.top = range; - else - res.bottom = range; - res.top_rev = mode != MODE_NORMAL; - res.bottom_rev = mode == MODE_NORMAL; + + res.range = range; + res.blocks = blocks; + res.rev = rev; return (res); } -static t_list splitsort_split_start(t_list *range, size_t blocks) +static t_list iter_next(t_iter *self) { + t_list res; size_t count; - count = 0; - if (blocks) - count = range->len / blocks + ((range->len % blocks) != 0); - return (list_split(range, count)); + if (!self->blocks) + return (list_split(&self->range, 0)); + count = self->range.len / self->blocks; + if (self->rev) + { + res = self->range; + self->range = list_split(&res, res.len - count); + } + else + { + if (self->range.len % self->blocks) + count++; + res = list_split(&self->range, count); + } + self->blocks--; + return (res); } -static t_list splitsort_split_end(t_list *range, size_t blocks) +static bool iter_nexti(t_iter *self, t_list *dst) { - size_t count; - t_list res; - - count = 0; - if (blocks) - count = range->len / blocks + ((range->len % blocks) != 0); - res = *range; - *range = list_split(&res, res.len - count); - return (res); + *dst = iter_next(self); + return (dst->len != 0); } -static void splitsort_iter_next(t_iter *self, t_list *top, t_list *bottom) +// Takes the self iterator, skip n elements, and return an iterator which only +// yields said elements +static t_iter iter_splitoff(t_iter *self, size_t n) { - if (self->top_rev) - *top = splitsort_split_end(&self->top, self->top_blocks); - else - *top = splitsort_split_start(&self->top, self->top_blocks); - if (self->bottom_rev) - *bottom = splitsort_split_end(&self->bottom, self->bottom_blocks); - else - *bottom = splitsort_split_start(&self->bottom, self->bottom_blocks); - if (self->top_blocks) - self->top_blocks--; - if (self->bottom_blocks) - self->bottom_blocks--; + t_iter res; + + res = *self; + while (n--) + iter_next(self); + res.range.len -= self->range.len; + res.blocks -= self->blocks; + if (res.rev) + res.range.ptr += self->range.len; + return (res); } typedef struct s_part { - t_mode mode; t_list top; t_list bottom; bool rev; + bool mirror; } t_part; static void splitsort_part_once(t_part self, t_splitsort sort, size_t count) { const t_stack *src; - bool mirror; t_psval val; - mirror = self.mode == MODE_NORMAL; - src = stacks_geta(sort.stacks, mirror); + src = stacks_geta(sort.stacks, self.mirror); while (count--) { if (self.rev) - closure_callm(sort.cb, OP_RRA, mirror); + closure_callm(sort.cb, OP_RRA, self.mirror); val = clist_get_at(src->list, 0); if (list_get_sorted(self.top, val) != -1) { - closure_callm(sort.cb, OP_PB, mirror); - closure_callm(sort.cb, OP_RB, mirror); + closure_callm(sort.cb, OP_PB, self.mirror); + closure_callm(sort.cb, OP_RB, self.mirror); } else if (list_get_sorted(self.bottom, val) != -1) - closure_callm(sort.cb, OP_PB, mirror); + closure_callm(sort.cb, OP_PB, self.mirror); else if (!self.rev) - closure_callm(sort.cb, OP_RA, mirror); + closure_callm(sort.cb, OP_RA, self.mirror); } } -static void splitsort_part(t_splitsort *sort, t_mode mode, t_list range) +// Parts range elements from stack a (which is in ascending order) onto stack b +// in descending order +static void splitsort_part_a(t_splitsort sort, t_list range) { + t_iter topi; + t_iter bottomi; t_part part; - t_iter iter; size_t top_count; size_t bottom_count; - part.mode = mode; + bottomi = iter_new(range, sort.blocks, true); + topi = iter_splitoff(&bottomi, sort.blocks / 2); + bottomi.rev = false; + top_count = 0; + bottom_count = 0; part.rev = false; - iter = splitsort_iter_new(*sort, mode, range); + part.mirror = false; + while (iter_nexti(&topi, &part.top) | iter_nexti(&bottomi, &part.bottom)) + { + splitsort_part_once(part, sort, range.len - top_count - bottom_count); + part.rev = !part.rev; + top_count += part.top.len; + bottom_count += part.bottom.len; + } + while (top_count--) + closure_call(sort.cb, OP_RRB); +} + +// Parts range elements from stack a (which is in ascending order) onto stack b +// in descending order, assuming that stack b is initially empty +static void splitsort_part_a_wrap(t_splitsort sort, t_list range) +{ + t_iter topi; + t_iter bottomi; + t_part part; + size_t top_count; + size_t bottom_count; + + bottomi = iter_new(range, sort.blocks, false); + topi = iter_splitoff(&bottomi, sort.blocks / 2); + topi.rev = true; top_count = 0; bottom_count = 0; - while (splitsort_iter_next(&iter, &part.top, &part.bottom), - part.top.len || part.bottom.len) + part.rev = false; + part.mirror = false; + while (iter_nexti(&topi, &part.top) | iter_nexti(&bottomi, &part.bottom)) { - splitsort_part_once(part, *sort, range.len - top_count - bottom_count); - part.rev = !part.rev && mode != MODE_WRAP; + splitsort_part_once(part, sort, range.len - top_count - bottom_count); + part.rev = !part.rev; top_count += part.top.len; bottom_count += part.bottom.len; } - while (mode != MODE_WRAP && top_count--) - closure_callm(sort->cb, OP_RRB, mode == MODE_NORMAL); } -static void splitsort_fortop(t_splitsort sort, t_mode mode, - t_list range, t_closure func) + +// Parts range elements from stack b (which is in descending order) onto stack +// a in ascending order +static void splitsort_part_b(t_splitsort sort, t_list range) { - t_iter iter; - t_list top; - t_list bottom; + t_iter topi; + t_iter bottomi; + t_part part; + size_t top_count; + size_t bottom_count; - iter = splitsort_iter_new(sort, mode, range); - while (splitsort_iter_next(&iter, &top, &bottom), top.len) - (func.func)(func.data, top); + bottomi = iter_new(range, sort.blocks, false); + topi = iter_splitoff(&bottomi, sort.blocks / 2); + bottomi.rev = true; + top_count = 0; + bottom_count = 0; + part.rev = false; + part.mirror = true; + while (iter_nexti(&topi, &part.top) | iter_nexti(&bottomi, &part.bottom)) + { + splitsort_part_once(part, sort, range.len - top_count - bottom_count); + part.rev = !part.rev; + top_count += part.top.len; + bottom_count += part.bottom.len; + } + while (top_count--) + closure_call(sort.cb, OP_RRA); } -static void splitsort_forbottom_rev(t_splitsort sort, t_mode mode, - t_list range, t_closure func) +typedef void (t_layer_func) (t_splitsort, t_list); + +void splitsort_leaf_a(t_splitsort sort, t_list range) { - t_iter iter; - t_list top; - t_list bottom; + leaf_sort_local(sort.stacks, sort.cb, false, range.len); +} - iter = splitsort_iter_new(sort, mode, range); - iter.bottom_rev ^= true; - while (splitsort_iter_next(&iter, &top, &bottom), bottom.len) - (func.func)(func.data, bottom); +static void splitsort_leaf_b(t_splitsort sort, t_list range) +{ + leaf_sort_other(sort.stacks, sort.cb, true, range.len); +} + +static t_layer_func *layer_from_info(size_t depth, size_t blocks, size_t len) +{ + size_t i; + size_t state; + + i = 0; + state = 4; + while (i++ < depth) + state *= blocks; + if (len <= state) + { + if (depth % 2 == 0) + return (&splitsort_leaf_a); + return (&splitsort_leaf_b); + } + if (depth == 0) + return (&splitsort_part_a_wrap); + if (depth % 2 == 0) + return (&splitsort_part_a); + return (&splitsort_part_b); } typedef struct s_visit { - t_splitsort sort; - t_closure callback; - size_t depth; - t_mode mode; + t_list range; + size_t depth; + t_layer_func *cb; + bool rev; } t_visit; -static void splitsort_visit_inner(t_visit *self, t_list range) +static void splitsort_visit_layer(t_visit self, t_splitsort sort) { - t_visit subdata; - t_closure subvisit; - - if (self->depth == 0) - return ((self->callback.func)(self->callback.data, self->mode, range)); - subdata = *self; - subdata.depth--; - if (subdata.mode == MODE_NORMAL) - subdata.mode = MODE_REV; - else - subdata.mode = MODE_NORMAL; - subvisit.data = &subdata; - subvisit.func = &splitsort_visit_inner; - if (self->mode != MODE_WRAP) - splitsort_fortop(self->sort, self->mode, range, subvisit); - splitsort_forbottom_rev(self->sort, self->mode, range, subvisit); - if (self->mode == MODE_WRAP) - splitsort_fortop(self->sort, self->mode, range, subvisit); + t_iter iter; + + if (self.depth == 0) + { + return (self.cb(sort, self.range)); + } + self.depth--; + iter = iter_new(self.range, sort.blocks, self.rev); + while (iter_nexti(&iter, &self.range)) + splitsort_visit_layer(self, sort); } -void splitsort_visit(t_splitsort sort, t_list range, - size_t depth, t_closure callback) +void splitsort_part_layer(t_splitsort sort, t_list range, size_t depth) { t_visit visit; - visit.sort = sort; - visit.callback = callback; + visit.range = range; visit.depth = depth; - visit.mode = MODE_WRAP; - splitsort_visit_inner(&visit, range); + visit.cb = layer_from_info(depth, sort.blocks, range.len); + visit.rev = depth % 2 == 1; + splitsort_visit_layer(visit, sort); } -typedef struct s_layer -{ - t_splitsort sort; -} t_layer; - void test_splitsort(const t_stacks *stacks, t_closure cb) { t_splitsort sort; t_list range; - t_closure part; sort.stacks = stacks; sort.cb = cb; sort.blocks = 5; range = list_new(stacks->a); list_sort(range); - part.func = &splitsort_part; - part.data = &sort; - for (size_t depth = 0; depth < 2; depth++) - splitsort_visit(sort, range, depth, part); + for (size_t i = 0; i < 4; i++) + splitsort_part_layer(sort, range, i); } diff --git a/leaf_sort.c b/leaf_sort.c index 3abfc2c..2b5f586 100644 --- a/leaf_sort.c +++ b/leaf_sort.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/11 00:27:32 by agilliar #+# #+# */ -/* Updated: 2025/12/11 17:21:30 by agilliar ### ########.fr */ +/* Updated: 2025/12/12 12:27:42 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/output.c b/output.c index 7239040..29bc721 100644 --- a/output.c +++ b/output.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/02 16:47:00 by agilliar #+# #+# */ -/* Updated: 2025/12/03 12:35:06 by agilliar ### ########.fr */ +/* Updated: 2025/12/12 00:36:01 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/output_inner.h b/output_inner.h index 6d32788..9f23cd6 100644 --- a/output_inner.h +++ b/output_inner.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/02 16:51:14 by agilliar #+# #+# */ -/* Updated: 2025/12/03 09:51:35 by agilliar ### ########.fr */ +/* Updated: 2025/12/12 00:39:57 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,7 +14,7 @@ # define OUTPUT_INNER_H # ifndef OUTPUT_STORE_SIZE -# define OUTPUT_STORE_SIZE 1024 +# define OUTPUT_STORE_SIZE 16384 # endif # include