// File: /workspace/github_c_makefile_star2_O3/chatziko-k08[P]lecture-code/tests/../modules/UsingBTree/ADTSet.c
// Function: node_is_btree
static bool node_is_btree(BTreeNode node, CompareFunc compare) {
	if (node == NULL)
		return true;

	// Ο κόμβος έχει περισσότερες τιμές από όσες πρέπει.
	if (node->count > MAX_VALUES)
		return false;

	// Ο κόμβος *δεν* είναι η ρίζα και έχει λιγότερες τιμές από όσες πρέπει.
	if (node->parent != NULL && node->count < MIN_VALUES)
		return false;

	// Όλες οι τιμές του κόμβου είναι σε σωστή διάταξη.
	for (int i = 0; i < node->count-1; i++) {
		if (compare(node->set_nodes[i]->value, node->set_nodes[i+1]->value) >= 0)
			return false;
	}

	// Έλεγξε ότι όλα τα παιδιά του δέντρου έχουν έγκυρο ύψος.
	if (node->parent == NULL && !is_valid_height(node))
		return false;

	// Έλεγξε ότι όλα τα παιδιά του node έχουν τον ίδιο πατέρα.
	if (!is_valid_parent(node))
		return false;

	// Για όλες τις τιμές του κόμβου.
	for (int i = 0; i < node->count; i++) {

		SetNode left_max = node_find_max(node->children[i]);  // Μέγιστο παιδί αριστερού υποδέντρου.
		SetNode right_min = node_find_min(node->children[i+1]);  // Ελάχιστο παιδί δεξιού υποδέντρου.

		Pointer left_last  = (node->children[i] != NULL)  // Μεγαλύτερο στοιχείο αριστερού παιδιού.
			? node->children[i]->set_nodes[ node->children[i]->count-1 ]->value
			: NULL;

		Pointer right_first = (node->children[i+1] != NULL)  // Μικρότερο στοιχείο δεξιού παιδιού.
			? node->children[i+1]->set_nodes[0]->value 
			: NULL;

		Pointer val = node->set_nodes[i]->value;  // Τιμή που ελέγχεται.

		bool correct = 
			(left_last   == NULL || compare(left_last, val)   < 0) &&  // Μεγαλύτερη από την μεγαλύτερη τιμή του αριστερού παιδιού.
			(right_first == NULL || compare(right_first, val) > 0) &&  // Μικρότερη από την μικρότερη του δεξιού παιδιού.
			(left_max  == NULL || compare(left_max->value, val) < 0) &&  // Μεγαλύτερη από τη μέγιστη του αριστερού υποδέντρου
			(right_min == NULL || compare(right_min->value, val) > 0) &&  // Μικρότερη από τη ελάχιστη του δεξιού υποδέντρου
			node_is_btree(node->children[i], compare);  // Έλεγξε και το αριστερό υποδέντρο.

		if (i == node->count-1)  // Εαν είναι η τελευταία διαχωριστική τιμή, έλεγξε και το δεξί υποδέντρο.
			correct = correct && node_is_btree(node->children[node->count], compare);

		if (!correct)
			return false;
	}

	return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movb $0x1, %bl
testq %rdi, %rdi
je 0x5656
movq %rdi, %r15
movl (%rdi), %eax
cmpl $0x4, %eax
jg 0x5654
movq %rsi, %r14
cmpl $0x1, %eax
jg 0x562b
cmpq $0x0, 0x8(%r15)
jne 0x5654
xorl %r12d, %r12d
movslq (%r15), %rax
leaq -0x1(%rax), %rcx
cmpq %rcx, %r12
jge 0x5667
movq 0x40(%r15,%r12,8), %rax
movq 0x48(%r15,%r12,8), %rcx
movq (%rax), %rdi
incq %r12
movq (%rcx), %rsi
callq *%r14
testl %eax, %eax
js 0x562e
xorl %ebx, %ebx
movl %ebx, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpq $0x0, 0x8(%r15)
jne 0x568d
leaq 0xf(%rsp), %r12
movb $0x1, (%r12)
movq %r15, %rdi
movq %r12, %rsi
callq 0x5af0
cmpb $0x1, (%r12)
jne 0x5654
movl (%r15), %eax
cmpq $0x0, 0x10(%r15)
je 0x56b0
testl %eax, %eax
js 0x5656
leal 0x1(%rax), %ecx
xorl %edx, %edx
movq 0x10(%r15,%rdx,8), %rsi
cmpq %r15, 0x8(%rsi)
jne 0x5654
incq %rdx
cmpq %rdx, %rcx
jne 0x569d
testl %eax, %eax
jle 0x5656
xorl %ebp, %ebp
movq 0x10(%r15,%rbp,8), %rax
movq %rax, %rsi
testq %rsi, %rsi
je 0x56df
movq %rsi, %rcx
movslq (%rsi), %rdx
movq 0x10(%rsi,%rdx,8), %rsi
testq %rsi, %rsi
jne 0x56be
movq 0x38(%rcx,%rdx,8), %rcx
movq %rcx, 0x18(%rsp)
jmp 0x56e8
movq $0x0, 0x18(%rsp)
leaq 0x1(%rbp), %rcx
movq %rcx, 0x20(%rsp)
movq 0x18(%r15,%rbp,8), %rcx
movq %rcx, %rsi
testq %rsi, %rsi
je 0x5715
movq %rsi, %rdx
movq 0x10(%rsi), %rsi
testq %rsi, %rsi
jne 0x56f9
movq 0x40(%rdx), %rdx
movq %rdx, 0x10(%rsp)
jmp 0x571e
movq $0x0, 0x10(%rsp)
testq %rax, %rax
je 0x5730
movslq (%rax), %rdx
movq 0x38(%rax,%rdx,8), %rax
movq (%rax), %rdi
jmp 0x5732
xorl %edi, %edi
testq %rcx, %rcx
je 0x5740
movq 0x40(%rcx), %rax
movq (%rax), %r13
jmp 0x5743
xorl %r13d, %r13d
movq 0x40(%r15,%rbp,8), %rax
movq (%rax), %r12
testq %rdi, %rdi
je 0x575e
movq %r12, %rsi
callq *%r14
testl %eax, %eax
jns 0x5654
testq %r13, %r13
je 0x5774
movq %r13, %rdi
movq %r12, %rsi
callq *%r14
testl %eax, %eax
jle 0x5654
movq 0x18(%rsp), %rax
testq %rax, %rax
je 0x578f
movq (%rax), %rdi
movq %r12, %rsi
callq *%r14
testl %eax, %eax
jns 0x5654
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x57aa
movq (%rax), %rdi
movq %r12, %rsi
callq *%r14
testl %eax, %eax
jle 0x5654
movq 0x10(%r15,%rbp,8), %rdi
movq %r14, %rsi
callq 0x55fd
movl (%r15), %ecx
leal -0x1(%rcx), %edx
cmpq %rdx, %rbp
jne 0x57e3
testb %al, %al
je 0x57e3
movslq %ecx, %rax
movq 0x10(%r15,%rax,8), %rdi
movq %r14, %rsi
callq 0x55fd
testb %al, %al
je 0x5654
movl (%r15), %ecx
jmp 0x57f3
cmpq %rdx, %rbp
sete %dl
xorb $0x1, %al
orb %dl, %al
jne 0x5654
movslq %ecx, %rax
movq 0x20(%rsp), %rbp
cmpq %rax, %rbp
jl 0x56b6
jmp 0x5656