// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3Mesh::SwapEdges(double)
void R3Mesh::
SwapEdges(RNAngle min_angle_improvement)
{
  // Initialize edge values
  RNHeap<RNScalar *> heap(0, -1, FALSE);
  RNScalar *edge_values = new RNScalar [ NEdges() ];
  for (int i = 0; i < NEdges(); i++) {
    R3MeshEdge *edge = Edge(i);
    edge_values[i] = EdgeSwapAngleImprovement(edge);
    if (edge_values[i] < min_angle_improvement) continue;
    heap.Push(&edge_values[i]);
  }

  // Swap edges
  while (!heap.IsEmpty()) {
    // Pop edge
    RNScalar *edge_value = heap.Pop();
    int edge_index = edge_value - edge_values;
    R3MeshEdge *edge = Edge(edge_index);
    if (*edge_value < min_angle_improvement) break;

    // Check current edge value
    RNScalar current_value = EdgeSwapAngleImprovement(edge);
    if (current_value != edge_values[edge_index]) {
      edge_values[edge_index] = current_value;
      if (current_value >= min_angle_improvement) heap.Push(&edge_values[edge_index]);
      continue;
    }

    // Swap the edge
    if (!SwapEdge(edge)) continue;

    // Update edge value
    edge_values[edge_index] = -current_value; // EdgeSwapAngleImprovement(edge);

    // Update neighbors
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) {
        R3MeshFace *face = FaceOnEdge(edge, i);
        if (!face) continue;
        R3MeshEdge *neighbor_edge = EdgeOnFace(face, edge, j);
        int neighbor_index = EdgeID(neighbor_edge);
        RNScalar old_neighbor_value = edge_values[neighbor_index];
        edge_values[neighbor_index] = EdgeSwapAngleImprovement(neighbor_edge);
        if (old_neighbor_value >= min_angle_improvement) {
          if (edge_values[neighbor_index] >= min_angle_improvement) heap.Update(&edge_values[neighbor_index]);
          else heap.Remove(&edge_values[neighbor_index]);
        }
        else {
          if (edge_values[neighbor_index] >= min_angle_improvement) heap.Push(&edge_values[neighbor_index]);
        }
      }
    }
  }

  // Delete edge values
  delete [] edge_values;
}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x130(%rsp)
movsd %xmm0, 0x128(%rsp)
movq 0x130(%rsp), %rax
movq %rax, 0x78(%rsp)
leaq 0xf0(%rsp), %rdi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
xorl %ecx, %ecx
movl %ecx, %esi
callq 0x382f0
movq 0x78(%rsp), %rdi
callq 0x135c0
movl %eax, 0x84(%rsp)
jmp 0x1fd7e
movl 0x84(%rsp), %eax
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0xf030
movq %rax, 0x70(%rsp)
jmp 0x1fda9
movq 0x70(%rsp), %rax
movq %rax, 0xe8(%rsp)
movl $0x0, 0xd8(%rsp)
movq 0x78(%rsp), %rdi
movl 0xd8(%rsp), %eax
movl %eax, 0x68(%rsp)
callq 0x135c0
movl %eax, 0x6c(%rsp)
jmp 0x1fddc
movl 0x68(%rsp), %eax
movl 0x6c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x1fecd
movq 0x78(%rsp), %rdi
movl 0xd8(%rsp), %esi
callq 0x36930
movq %rax, 0x60(%rsp)
jmp 0x1fe04
movq 0x78(%rsp), %rdi
movq 0x60(%rsp), %rax
movq %rax, 0xd0(%rsp)
movq 0xd0(%rsp), %rsi
callq 0x1f650
movsd %xmm0, 0x58(%rsp)
jmp 0x1fe2b
movsd 0x58(%rsp), %xmm0
movq 0xe8(%rsp), %rax
movslq 0xd8(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq 0xe8(%rsp), %rax
movslq 0xd8(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm1
movsd 0x128(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1fe92
jmp 0x1feb7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x38a60
jmp 0x202ce
movq 0xe8(%rsp), %rax
movslq 0xd8(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0xf0(%rsp), %rdi
callq 0x38350
jmp 0x1feb5
jmp 0x1feb7
movl 0xd8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd8(%rsp)
jmp 0x1fdc1
jmp 0x1fecf
leaq 0xf0(%rsp), %rdi
callq 0x38570
movl %eax, 0x54(%rsp)
jmp 0x1fee2
movl 0x54(%rsp), %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x1fef7
jmp 0x2029c
leaq 0xf0(%rsp), %rdi
callq 0x38590
movq %rax, 0x48(%rsp)
jmp 0x1ff0b
movq 0x78(%rsp), %rdi
movq 0x48(%rsp), %rax
movq %rax, 0xc8(%rsp)
movq 0xc8(%rsp), %rax
movq 0xe8(%rsp), %rcx
subq %rcx, %rax
shrq $0x3, %rax
movl %eax, 0xc4(%rsp)
movl 0xc4(%rsp), %esi
callq 0x36930
movq %rax, 0x40(%rsp)
jmp 0x1ff4e
movq 0x40(%rsp), %rax
movq %rax, 0xb8(%rsp)
movq 0xc8(%rsp), %rax
movsd (%rax), %xmm1
movsd 0x128(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1ff7b
jmp 0x2029c
movq 0x78(%rsp), %rdi
movq 0xb8(%rsp), %rsi
callq 0x1f650
movsd %xmm0, 0x38(%rsp)
jmp 0x1ff95
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0xb0(%rsp)
movsd 0xb0(%rsp), %xmm0
movq 0xe8(%rsp), %rax
movslq 0xc4(%rsp), %rcx
ucomisd (%rax,%rcx,8), %xmm0
jne 0x1ffc8
jp 0x1ffc8
jmp 0x20024
movsd 0xb0(%rsp), %xmm0
movq 0xe8(%rsp), %rax
movslq 0xc4(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movsd 0xb0(%rsp), %xmm0
ucomisd 0x128(%rsp), %xmm0
jb 0x2001f
movq 0xe8(%rsp), %rax
movslq 0xc4(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0xf0(%rsp), %rdi
callq 0x38350
jmp 0x2001d
jmp 0x2001f
jmp 0x1fecf
movq 0x78(%rsp), %rdi
movq 0xb8(%rsp), %rsi
movq (%rdi), %rax
movq 0xd0(%rax), %rax
callq *%rax
movl %eax, 0x34(%rsp)
jmp 0x20043
movl 0x34(%rsp), %eax
cmpl $0x0, %eax
jne 0x20051
jmp 0x1fecf
movsd 0xb0(%rsp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movq 0xe8(%rsp), %rax
movslq 0xc4(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl $0x0, 0xac(%rsp)
cmpl $0x2, 0xac(%rsp)
jge 0x20297
movl $0x0, 0xa8(%rsp)
cmpl $0x2, 0xa8(%rsp)
jge 0x2027f
movq 0x78(%rsp), %rdi
movq 0xb8(%rsp), %rsi
movl 0xac(%rsp), %edx
callq 0x37050
movq %rax, 0x28(%rsp)
jmp 0x200d8
movq 0x28(%rsp), %rax
movq %rax, 0xa0(%rsp)
cmpq $0x0, 0xa0(%rsp)
jne 0x200f5
jmp 0x20269
movq 0x78(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
movl 0xa8(%rsp), %ecx
callq 0x386a0
movq %rax, 0x20(%rsp)
jmp 0x2011d
movq 0x78(%rsp), %rdi
movq 0x20(%rsp), %rax
movq %rax, 0x98(%rsp)
movq 0x98(%rsp), %rsi
callq 0x36980
movl %eax, 0x1c(%rsp)
jmp 0x20142
movq 0x78(%rsp), %rdi
movl 0x1c(%rsp), %eax
movl %eax, 0x94(%rsp)
movq 0xe8(%rsp), %rax
movslq 0x94(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, 0x88(%rsp)
movq 0x98(%rsp), %rsi
callq 0x1f650
movsd %xmm0, 0x10(%rsp)
jmp 0x20185
movsd 0x10(%rsp), %xmm0
movq 0xe8(%rsp), %rax
movslq 0x94(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movsd 0x88(%rsp), %xmm0
ucomisd 0x128(%rsp), %xmm0
jb 0x20220
movq 0xe8(%rsp), %rax
movslq 0x94(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd 0x128(%rsp), %xmm0
jb 0x201f9
movq 0xe8(%rsp), %rax
movslq 0x94(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0xf0(%rsp), %rdi
callq 0x38770
jmp 0x201f7
jmp 0x2021e
movq 0xe8(%rsp), %rax
movslq 0x94(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0xf0(%rsp), %rdi
callq 0x38870
jmp 0x2021c
jmp 0x2021e
jmp 0x20267
movq 0xe8(%rsp), %rax
movslq 0x94(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd 0x128(%rsp), %xmm0
jb 0x20265
movq 0xe8(%rsp), %rax
movslq 0x94(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0xf0(%rsp), %rdi
callq 0x38350
jmp 0x20263
jmp 0x20265
jmp 0x20267
jmp 0x20269
movl 0xa8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa8(%rsp)
jmp 0x200aa
jmp 0x20281
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x20091
jmp 0x1fecf
movq 0xe8(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x202b9
movq 0x8(%rsp), %rdi
callq 0xf670
leaq 0xf0(%rsp), %rdi
callq 0x38a60
addq $0x138, %rsp            # imm = 0x138
retq
movq 0xe0(%rsp), %rdi
callq 0xf890
nopl (%rax,%rax)