// File: /workspace/github_c_makefile_star2_O2/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 $0x18, %rsp
testq %rdi, %rdi
je 0x5207
movq %rdi, %r14
movl (%rdi), %eax
cmpl $0x4, %eax
jg 0x5203
movq %rsi, %rbx
cmpl $0x1, %eax
jg 0x51dc
cmpq $0x0, 0x8(%r14)
jne 0x5203
xorl %r15d, %r15d
movslq (%r14), %rax
decq %rax
cmpq %rax, %r15
jge 0x521b
movq 0x40(%r14,%r15,8), %rax
movq 0x48(%r14,%r15,8), %rcx
movq (%rax), %rdi
incq %r15
movq (%rcx), %rsi
callq *%rbx
testl %eax, %eax
js 0x51df
xorl %ebp, %ebp
jmp 0x520a
movb $0x1, %bpl
movl %ebp, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpq $0x0, 0x8(%r14)
jne 0x523c
leaq 0x7(%rsp), %r15
movb $0x1, (%r15)
movq %r14, %rdi
movq %r15, %rsi
callq 0x564a
cmpb $0x1, (%r15)
jne 0x5203
cmpq $0x0, 0x10(%r14)
je 0x526b
movl (%r14), %eax
testl %eax, %eax
pushq $-0x1
popq %rcx
cmovnsl %eax, %ecx
movslq %ecx, %rax
pushq $-0x1
popq %rcx
xorl %ebp, %ebp
cmpq %rcx, %rax
je 0x526b
movq 0x18(%r14,%rcx,8), %rdx
incq %rcx
cmpq %r14, 0x8(%rdx)
je 0x5256
jmp 0x520a
xorl %r12d, %r12d
movslq (%r14), %rax
cmpq %rax, %r12
setge %bpl
jge 0x520a
movq 0x10(%r14,%r12,8), %r13
movq %r13, %rdi
callq 0x4cc4
movq %rax, 0x10(%rsp)
movq 0x18(%r14,%r12,8), %r15
movq %r15, %rdi
callq 0x4ca7
movq %rax, 0x8(%rsp)
testq %r13, %r13
je 0x52b1
movslq (%r13), %rax
movq 0x38(%r13,%rax,8), %rax
movq (%rax), %rdi
jmp 0x52b3
xorl %edi, %edi
testq %r15, %r15
je 0x52c1
movq 0x40(%r15), %rax
movq (%rax), %r15
jmp 0x52c4
xorl %r15d, %r15d
movq 0x40(%r14,%r12,8), %rax
movq (%rax), %r13
testq %rdi, %rdi
je 0x52da
movq %r13, %rsi
callq *%rbx
testl %eax, %eax
jns 0x5326
testq %r15, %r15
je 0x52eb
movq %r15, %rdi
movq %r13, %rsi
callq *%rbx
testl %eax, %eax
jle 0x5326
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x5301
movq (%rax), %rdi
movq %r13, %rsi
callq *%rbx
testl %eax, %eax
jns 0x5326
movq 0x8(%rsp), %rax
testq %rax, %rax
je 0x5317
movq (%rax), %rdi
movq %r13, %rsi
callq *%rbx
testl %eax, %eax
jle 0x5326
movq 0x10(%r14,%r12,8), %rdi
movq %rbx, %rsi
callq 0x51b0
jmp 0x5328
xorl %eax, %eax
movslq (%r14), %rcx
leal -0x1(%rcx), %edx
cmpq %rdx, %r12
jne 0x534d
testb %al, %al
je 0x534d
movq 0x10(%r14,%rcx,8), %rdi
movq %rbx, %rsi
callq 0x51b0
testb %al, %al
jne 0x535d
jmp 0x520a
cmpq %rdx, %r12
sete %cl
xorb $0x1, %al
orb %cl, %al
jne 0x520a
incq %r12
jmp 0x526e