Skip to content

Commit

Permalink
ft_list_sort (#9)
Browse files Browse the repository at this point in the history
* feat: implement create_elem, list_push_front, list_size, list_remove_if

* style: format

* fix: add valgrind to github action dependencies

* feat: implement ft_sort_list using merge sort
  • Loading branch information
tdameros authored Aug 3, 2024
1 parent c63751e commit c016591
Show file tree
Hide file tree
Showing 8 changed files with 421 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ LIST_ASM_SRC = \
ft_list_push_front.s \
ft_list_remove_if.s \
ft_list_size.s \
ft_list_sort.s \
ft_read.s \
ft_strcmp.s \
ft_strcpy.s \
Expand All @@ -23,13 +24,15 @@ LIST_TEST_SRC = \
ft_list_push_front.c \
ft_list_remove_if.c \
ft_list_size.c \
ft_list_sort.c \
ft_read.c \
ft_strcmp.c \
ft_strcpy.c \
ft_strdup.c \
ft_strlen.c \
ft_write.c \
main.c
main.c \
utils.c

# ------------ DIRECTORIES ------------ #

Expand Down
1 change: 1 addition & 0 deletions include/libasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ t_list *ft_create_elem(void *data);
void ft_list_push_front(t_list **begin_list, void *data);
int ft_list_size(t_list *begin_list);
void ft_list_remove_if(t_list **begin_list, void *data_ref, int (*cmp)(), void (*free_fct)(void *));
void ft_list_sort(t_list **begin_list, int (*cmp)());

#endif
241 changes: 241 additions & 0 deletions src/ft_list_sort.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
bits 64

%include "ft_list.s"

section .note.GNU-stack

section .text
global ft_list_sort

;typedef struct s_list
;{
; void *data;
; struct s_list *next;
;} t_list;

; void ft_list_sort(t_list **head, int (*cmp)()) {
; if (head == NULL || *head == NULL || (*head)->next == NULL) {
; return;
; }
;
; t_list *middle = get_middle(*head);
; t_list *next_to_middle = middle->next;
; middle->next = NULL;
;
; ft_list_sort(head, cmp);
; return;
; ft_list_sort(&next_to_middle, cmp);
;
; *head = sorted_merge(*head, next_to_middle, cmp);
; }

; t_list* sorted_merge(t_list *left, t_list *right, int (*cmp)(void*, void*)) {
; if (left == NULL) {
; return right;
; }
; if (right == NULL) {
; return left;
; }
;
; t_list *result = NULL;
;
; if (cmp(left->data, right->data) <= 0) {
; result = left;
; result->next = sorted_merge(left->next, right, cmp);
; } else {
; result = right;
; result->next = sorted_merge(left, right->next, cmp);
; }
;
; return result;
; }

; t_list* get_middle(t_list *head) {
; if (head == NULL) {
; return head;
; }
;
; t_list *slow = head;
; t_list *fast = head;
;
; while (fast->next != NULL && fast->next->next != NULL) {
; slow = slow->next;
; fast = fast->next->next;
; }
;
; printf("get_middle result: %p\n", slow);
; return slow;
; }

;void ft_list_sort(t_list **begin_list, int (*cmp)());
ft_list_sort:
test rdi, rdi
jz ft_list_sort_end
mov r8, [rdi]
test r8, r8
jz ft_list_sort_end
mov r8, [r8 + LIST_NEXT_OFFSET]
test r8, r8
jz ft_list_sort_end
sub rsp, 16
push rdi
push rsi
mov rdi, [rdi]
call get_middle
pop rsi
pop rdi
; middle
mov [rsp + 0], rax
; next_to_middle
mov rax, [rax + LIST_NEXT_OFFSET]
mov [rsp + 8], rax
; middle->next = 0
mov rax, [rsp + 0]
mov qword [rax + LIST_NEXT_OFFSET], 0


push rdi
push rsi
call ft_list_sort
pop rsi
pop rdi

mov r8, rsp
add r8, 8
push rdi
push rsi
mov rdi, r8
call ft_list_sort
; right
pop rsi
pop rdi

mov r8, [rsp + 8]
push rdi
push rsi
mov rdi, [rdi]
mov rdx, rsi
mov rsi, r8
call sorted_merge
pop rsi
pop rdi
mov [rdi], rax
add rsp, 16
ret

ft_list_sort_end:
ret


;t_list* sorted_merge(t_list *left, t_list *right, int (*cmp)(void*, void*))
sorted_merge:
test rdi, rdi
jz sorted_merge_ret_right
test rsi, rsi
jz sorted_merge_ret_left
; result
sub rsp, 8
mov qword [rsp + 0], 0
push rdi
push rsi
push rdx
mov rdi, [rdi + LIST_DATA_OFFSET]
mov rsi, [rsi + LIST_DATA_OFFSET]
call rdx
pop rdx
pop rsi
pop rdi
; cmp only int32_t
cmp eax, 0
jle sorted_merge_below_or_equal
jmp sorted_merge_greater

sorted_merge_ret_left:
mov rax, rdi
ret

sorted_merge_ret_right:
mov rax, rsi
ret

sorted_merge_below_or_equal:
mov [rsp + 0], rdi
push rdi
push rsi
push rdx
mov rdi, [rdi + LIST_NEXT_OFFSET]
call sorted_merge
pop rdx
pop rsi
pop rdi
mov r8, [rsp + 0]
mov [r8 + LIST_NEXT_OFFSET], rax
jmp sorted_merge_end

sorted_merge_greater:
mov [rsp + 0], rsi
push rdi
push rsi
push rdx
mov rsi, [rsi + LIST_NEXT_OFFSET]
call sorted_merge
pop rdx
pop rsi
pop rdi
mov r8, [rsp + 0]
mov [r8 + LIST_NEXT_OFFSET], rax
jmp sorted_merge_end

sorted_merge_end:
mov rax, [rsp + 0]
add rsp, 8
ret

;t_list* get_middle(t_list *head)
get_middle:
test rdi, rdi
jz get_middle_ret_head
jnz get_middle_loop

get_middle_loop:
sub rsp, 16
; slow
mov [rsp + 0], rdi
; fast
mov [rsp + 8], rdi
jmp get_middle_loop_condition

get_middle_loop_condition:
mov r8, [rsp + 8]
mov r8, [r8 + LIST_NEXT_OFFSET]
test r8, r8
jnz get_middle_loop_condition2
jmp get_middle_ret_slow

get_middle_loop_condition2:
mov r8, [r8 + LIST_NEXT_OFFSET]
test r8, r8
jnz get_middle_loop_routine
jmp get_middle_ret_slow

get_middle_loop_routine:
mov r8, [rsp + 0]
mov r8, [r8 + LIST_NEXT_OFFSET]
mov [rsp + 0], r8
mov r8, [rsp + 8]
mov r8, [r8 + LIST_NEXT_OFFSET]
mov r8, [r8 + LIST_NEXT_OFFSET]
mov [rsp + 8], r8
jmp get_middle_loop_condition

get_middle_ret_head:
mov rax, rdi
ret

get_middle_ret_slow:
mov rax, [rsp + 0]
add rsp, 16
ret

end:
ret
8 changes: 1 addition & 7 deletions test/ft_list_remove_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "libasm.h"
#include "utest.h"
#include "utils.h"

UTEST(ft_list_remove_if, null_list_ptr) {
t_list **list_ptr = NULL;
Expand All @@ -29,13 +30,6 @@ UTEST(ft_list_remove_if, null_list) {
ASSERT_EQ(errno, 0);
}

static int my_strcmp(const void *s1, const void *s2) {
if (s1 == NULL || s2 == NULL) {
return 1;
}
return strcmp(s1, s2);
}

UTEST(ft_list_remove_if, null_data_ref) {
t_list *list = NULL;
char *data = strdup("Hello, World!");
Expand Down
Loading

0 comments on commit c016591

Please sign in to comment.