// File: MarkCBell[P]twister/./twister/kernel/twister.cpp
// Function: manifold::identify_cusps(tetra*)
void manifold::identify_cusps(tetra *capoff_tetra)
{
	output_debugging("cusps", 2);
	
	// Clear the temp value everywhere.
	for (tetra *current = capoff_tetra; current != NULL; current = current->get_next())
		current->set_temp(-1);
	
	// Write theoretical cusp numbers to the temp field on every cusp.
	int theoretical_num_cusps = 0;  // This is how many cusps we find, although some might not be toroidal.
	for (tetra *basepoint = capoff_tetra; basepoint != NULL; basepoint = basepoint->get_next())
	{
		if (basepoint->get_temp() != -1) continue;  // Has already been assigned a theoretical cusp number.
		basepoint->set_temp(theoretical_num_cusps);
		
		std::queue<tetra *> tetra_list;
		tetra_list.push(basepoint);
		while (!(tetra_list.empty()))
		{
			tetra *current = tetra_list.front();
			tetra_list.pop();
			
			for (int i = 0; i < 3; i++)
			{
				tetra *adjacent = current->get_gluedto(i);
				if (adjacent->get_temp() == -1)
				{
					adjacent->set_temp(theoretical_num_cusps);
					tetra_list.push(adjacent);
				}
			}
		}
		theoretical_num_cusps++;
	}
	
	num_cusps = 0;  // The actual number of cusps that are toroidal. Klein bottles aren't possible as our manifolds are orientable.
	
	// Work on each cusp in turn.
	for (int cusp = 0; cusp < theoretical_num_cusps; cusp++)
	{
		std::vector<tetra *> cusp_tetra;  // All the tetra in this cusp.
		for (tetra *current = capoff_tetra; current != NULL; current = current->get_next())
			if (current->get_temp() == cusp) cusp_tetra.push_back(current);
		
		int num_faces = (int) cusp_tetra.size();
		
		// We've capped off, so the link of any point must be a closed surface.
		// Since Euler characteristic = V - E + F = V - (F/2), F should be even.
		if (num_faces % 2 != 0)
			output_error("Bad vertex link detected. Possible cause; not capping off before computing cusp information.");
		
		int num_vertices = num_faces * 3;
		std::vector<int> degree_frequency(num_vertices + 1, 0);  // The frequency of each degree.
		
		for (int i = 0; i < num_faces; i++)
			for (int j = 0; j < 3; j++)
				degree_frequency[edge_degree(cusp_tetra[i], j, 3)]++;
		
		if (degree_frequency[0] != 0)
			output_error("There should be no vertices of degree 0.");
		
		int Euler_characteristic = -(num_faces / 2);  // Now we work out the Euler characteristic of this cusp.
		
		for (int i = 1; i < num_vertices + 1; i++)
		{
			if (degree_frequency[i] % i != 0)
				output_error("Bad vertex link detected. A vertex of degree k should appear a multiple of k times.");
			
			Euler_characteristic += (degree_frequency[i] / i);
		}
		
		// Since the manifold is orientable, Euler characteristic must be even and <= 2.
		if ((Euler_characteristic > 2) || (Euler_characteristic % 2 != 0))
			output_error("Invalid cusp Euler characteristic.");
		
		// We could install the Euler characteristic to the cusp, but we wont need it again.
		int cusp_number = -1;  // The cusp number we're going to assign to this cusp.
		if (Euler_characteristic == 2)  // Spherical cusp.
		{
			if (this->get_manifold_type() == bundle) output_error("Spherical cusps are not possible in bundles.");
		}
		else if (Euler_characteristic == 0)  // Torus cusp.
		{
			cusp_number = num_cusps++;
		}
		else  // Other cusp.
		{
			output_warning("Non-torus Cusp.");  // Non-torus cusps. SnapPy wont like this.
		}
		
		// Write the real cusp number into the cusp tetra.
		for (int i = 0; i < num_faces; i++)
			cusp_tetra[i]->set_cusp_number(cusp_number);
	}
	
	return;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2b0, %rsp            # imm = 0x2B0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x228(%rbp)
leaq -0x31(%rbp), %rdi
movq %rdi, -0x220(%rbp)
callq 0x3560
movq -0x220(%rbp), %rdx
leaq 0x99a2(%rip), %rsi      # 0x2761e
leaq -0x30(%rbp), %rdi
callq 0x4e10
jmp 0x1dc87
leaq -0x30(%rbp), %rdi
movl $0x2, %esi
callq 0x4c10
jmp 0x1dc97
leaq -0x30(%rbp), %rdi
callq 0x35f8
leaq -0x31(%rbp), %rdi
callq 0x3360
movq -0x10(%rbp), %rax
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
je 0x1dd06
movq -0x50(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x21360
movq -0x50(%rbp), %rdi
callq 0x21300
movq %rax, -0x50(%rbp)
jmp 0x1dcb1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1dcf8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x35f8
leaq -0x31(%rbp), %rdi
callq 0x3360
jmp 0x1e5f1
movl $0x0, -0x54(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x60(%rbp)
je 0x1dea5
movq -0x60(%rbp), %rdi
callq 0x21380
cmpl $-0x1, %eax
je 0x1dd33
jmp 0x1de93
movq -0x60(%rbp), %rdi
movl -0x54(%rbp), %esi
callq 0x21360
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x230(%rbp)
callq 0x213a0
movq -0x230(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x213d0
jmp 0x1dd64
jmp 0x1dd66
leaq -0xb0(%rbp), %rdi
callq 0x21400
movb %al, -0x231(%rbp)
jmp 0x1dd7a
movb -0x231(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x1dd8b
jmp 0x1de7e
leaq -0xb0(%rbp), %rdi
callq 0x21420
movq %rax, -0x240(%rbp)
jmp 0x1dda0
movq -0x240(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xb8(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x21440
jmp 0x1ddbf
movl $0x0, -0xbc(%rbp)
cmpl $0x3, -0xbc(%rbp)
jge 0x1de79
movq -0xb8(%rbp), %rdi
movl -0xbc(%rbp), %esi
callq 0x20b60
movq %rax, -0x248(%rbp)
jmp 0x1ddf1
movq -0x248(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rdi
callq 0x21380
movl %eax, -0x24c(%rbp)
jmp 0x1de13
movl -0x24c(%rbp), %eax
cmpl $-0x1, %eax
jne 0x1de63
movq -0xc8(%rbp), %rdi
movl -0x54(%rbp), %esi
callq 0x21360
jmp 0x1de2f
leaq -0xb0(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x213d0
jmp 0x1de44
jmp 0x1de63
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x21460
jmp 0x1e5f1
jmp 0x1de65
movl -0xbc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xbc(%rbp)
jmp 0x1ddc9
jmp 0x1dd66
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x21460
movq -0x60(%rbp), %rdi
callq 0x21300
movq %rax, -0x60(%rbp)
jmp 0x1dd15
movq -0x228(%rbp), %rax
movl $0x0, 0x3c(%rax)
movl $0x0, -0xcc(%rbp)
movl -0xcc(%rbp), %eax
cmpl -0x54(%rbp), %eax
jge 0x1e5e8
leaq -0xe8(%rbp), %rdi
callq 0x21000
movq -0x10(%rbp), %rax
movq %rax, -0xf0(%rbp)
cmpq $0x0, -0xf0(%rbp)
je 0x1df5e
movq -0xf0(%rbp), %rdi
callq 0x21380
movl %eax, -0x250(%rbp)
jmp 0x1df01
movl -0x250(%rbp), %eax
cmpl -0xcc(%rbp), %eax
jne 0x1df37
leaq -0xe8(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x21480
jmp 0x1df24
jmp 0x1df37
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1e5da
jmp 0x1df39
movq -0xf0(%rbp), %rdi
callq 0x21300
movq %rax, -0x258(%rbp)
jmp 0x1df4e
movq -0x258(%rbp), %rax
movq %rax, -0xf0(%rbp)
jmp 0x1dee3
leaq -0xe8(%rbp), %rdi
callq 0x214f0
movl %eax, -0xf4(%rbp)
movl -0xf4(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0x1e015
leaq -0x119(%rbp), %rdi
movq %rdi, -0x260(%rbp)
callq 0x3560
movq -0x260(%rbp), %rdx
leaq 0x967c(%rip), %rsi      # 0x27624
leaq -0x118(%rbp), %rdi
callq 0x4e10
jmp 0x1dfb6
leaq -0x118(%rbp), %rdi
callq 0x4d40
jmp 0x1dfc4
leaq -0x118(%rbp), %rdi
callq 0x35f8
leaq -0x119(%rbp), %rdi
callq 0x3360
jmp 0x1e015
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1e004
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x118(%rbp), %rdi
callq 0x35f8
leaq -0x119(%rbp), %rdi
callq 0x3360
jmp 0x1e5da
movl -0xf4(%rbp), %ecx
movl %ecx, %eax
leal (%rax,%rax,2), %eax
movl %eax, -0x120(%rbp)
movl -0x120(%rbp), %eax
incl %eax
cltq
movq %rax, -0x270(%rbp)
movl $0x0, -0x13c(%rbp)
leaq -0x13d(%rbp), %rdi
movq %rdi, -0x268(%rbp)
callq 0x9600
movq -0x270(%rbp), %rsi
movq -0x268(%rbp), %rcx
leaq -0x138(%rbp), %rdi
leaq -0x13c(%rbp), %rdx
callq 0x9620
jmp 0x1e077
leaq -0x13d(%rbp), %rdi
callq 0x96a0
movl $0x0, -0x144(%rbp)
movl -0x144(%rbp), %eax
cmpl -0xf4(%rbp), %eax
jge 0x1e155
movl $0x0, -0x148(%rbp)
cmpl $0x3, -0x148(%rbp)
jge 0x1e13f
movslq -0x144(%rbp), %rsi
leaq -0xe8(%rbp), %rdi
callq 0x21140
movq (%rax), %rdi
movl -0x148(%rbp), %esi
movl $0x3, %edx
callq 0x1db40
movl %eax, -0x274(%rbp)
jmp 0x1e0e4
movl -0x274(%rbp), %eax
movslq %eax, %rsi
leaq -0x138(%rbp), %rdi
callq 0x9420
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movl -0x148(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x148(%rbp)
jmp 0x1e0a9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x13d(%rbp), %rdi
callq 0x96a0
jmp 0x1e5da
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1e5ce
jmp 0x1e141
movl -0x144(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x144(%rbp)
jmp 0x1e08d
leaq -0x138(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x9420
cmpl $0x0, (%rax)
je 0x1e1fc
leaq -0x169(%rbp), %rdi
movq %rdi, -0x280(%rbp)
callq 0x3560
movq -0x280(%rbp), %rdx
leaq 0x94f2(%rip), %rsi      # 0x27681
leaq -0x168(%rbp), %rdi
callq 0x4e10
jmp 0x1e19d
leaq -0x168(%rbp), %rdi
callq 0x4d40
jmp 0x1e1ab
leaq -0x168(%rbp), %rdi
callq 0x35f8
leaq -0x169(%rbp), %rdi
callq 0x3360
jmp 0x1e1fc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1e1eb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x168(%rbp), %rdi
callq 0x35f8
leaq -0x169(%rbp), %rdi
callq 0x3360
jmp 0x1e5ce
movl -0xf4(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
xorl %eax, %eax
subl %ecx, %eax
movl %eax, -0x170(%rbp)
movl $0x1, -0x174(%rbp)
movl -0x174(%rbp), %eax
movl -0x120(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jge 0x1e326
movslq -0x174(%rbp), %rsi
leaq -0x138(%rbp), %rdi
callq 0x9420
movl (%rax), %eax
cltd
idivl -0x174(%rbp)
cmpl $0x0, %edx
je 0x1e2ea
leaq -0x199(%rbp), %rdi
movq %rdi, -0x288(%rbp)
callq 0x3560
movq -0x288(%rbp), %rdx
leaq 0x942d(%rip), %rsi      # 0x276aa
leaq -0x198(%rbp), %rdi
callq 0x4e10
jmp 0x1e28b
leaq -0x198(%rbp), %rdi
callq 0x4d40
jmp 0x1e299
leaq -0x198(%rbp), %rdi
callq 0x35f8
leaq -0x199(%rbp), %rdi
callq 0x3360
jmp 0x1e2ea
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1e2d9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x35f8
leaq -0x199(%rbp), %rdi
callq 0x3360
jmp 0x1e5ce
movslq -0x174(%rbp), %rsi
leaq -0x138(%rbp), %rdi
callq 0x9420
movl (%rax), %eax
cltd
idivl -0x174(%rbp)
addl -0x170(%rbp), %eax
movl %eax, -0x170(%rbp)
movl -0x174(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x174(%rbp)
jmp 0x1e220
cmpl $0x2, -0x170(%rbp)
jg 0x1e346
movl -0x170(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0x1e3d4
leaq -0x1c1(%rbp), %rdi
movq %rdi, -0x290(%rbp)
callq 0x3560
movq -0x290(%rbp), %rdx
leaq 0x9397(%rip), %rsi      # 0x276fe
leaq -0x1c0(%rbp), %rdi
callq 0x4e10
jmp 0x1e375
leaq -0x1c0(%rbp), %rdi
callq 0x4d40
jmp 0x1e383
leaq -0x1c0(%rbp), %rdi
callq 0x35f8
leaq -0x1c1(%rbp), %rdi
callq 0x3360
jmp 0x1e3d4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1e3c3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x35f8
leaq -0x1c1(%rbp), %rdi
callq 0x3360
jmp 0x1e5ce
movl $0xffffffff, -0x1c8(%rbp) # imm = 0xFFFFFFFF
cmpl $0x2, -0x170(%rbp)
jne 0x1e4a1
movq -0x228(%rbp), %rdi
callq 0x8d00
movl %eax, -0x294(%rbp)
jmp 0x1e3ff
movl -0x294(%rbp), %eax
cmpl $0x1, %eax
jne 0x1e49c
leaq -0x1e9(%rbp), %rdi
movq %rdi, -0x2a0(%rbp)
callq 0x3560
movq -0x2a0(%rbp), %rdx
leaq 0x92f2(%rip), %rsi      # 0x27721
leaq -0x1e8(%rbp), %rdi
callq 0x4e10
jmp 0x1e43d
leaq -0x1e8(%rbp), %rdi
callq 0x4d40
jmp 0x1e44b
leaq -0x1e8(%rbp), %rdi
callq 0x35f8
leaq -0x1e9(%rbp), %rdi
callq 0x3360
jmp 0x1e49c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1e48b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x1e8(%rbp), %rdi
callq 0x35f8
leaq -0x1e9(%rbp), %rdi
callq 0x3360
jmp 0x1e5ce
jmp 0x1e554
cmpl $0x0, -0x170(%rbp)
jne 0x1e4c7
movq -0x228(%rbp), %rcx
movl 0x3c(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x3c(%rcx)
movl %eax, -0x1c8(%rbp)
jmp 0x1e552
leaq -0x211(%rbp), %rdi
movq %rdi, -0x2a8(%rbp)
callq 0x3560
movq -0x2a8(%rbp), %rdx
leaq 0x9266(%rip), %rsi      # 0x2774e
leaq -0x210(%rbp), %rdi
callq 0x4e10
jmp 0x1e4f6
leaq -0x210(%rbp), %rdi
callq 0x4c90
jmp 0x1e504
leaq -0x210(%rbp), %rdi
callq 0x35f8
leaq -0x211(%rbp), %rdi
callq 0x3360
jmp 0x1e552
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1e544
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x210(%rbp), %rdi
callq 0x35f8
leaq -0x211(%rbp), %rdi
callq 0x3360
jmp 0x1e5ce
jmp 0x1e554
movl $0x0, -0x218(%rbp)
movl -0x218(%rbp), %eax
cmpl -0xf4(%rbp), %eax
jge 0x1e5a2
movslq -0x218(%rbp), %rsi
leaq -0xe8(%rbp), %rdi
callq 0x21140
movq (%rax), %rdi
movl -0x1c8(%rbp), %esi
callq 0x21510
jmp 0x1e58f
jmp 0x1e591
movl -0x218(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x218(%rbp)
jmp 0x1e55e
leaq -0x138(%rbp), %rdi
callq 0x95a0
leaq -0xe8(%rbp), %rdi
callq 0x210c0
movl -0xcc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xcc(%rbp)
jmp 0x1debd
leaq -0x138(%rbp), %rdi
callq 0x95a0
leaq -0xe8(%rbp), %rdi
callq 0x210c0
jmp 0x1e5f1
addq $0x2b0, %rsp            # imm = 0x2B0
popq %rbp
retq
movq -0x40(%rbp), %rdi
callq 0x3550
nopw (%rax,%rax)