// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3Mesh::GeodesicDistances(gaps::R3MeshVertex const*, double) const
RNLength *R3Mesh::
GeodesicDistances(const R3MeshVertex *source_vertex, RNLength max_distance) const
{
  // Create arrays of upper bounds on distances
  RNLength *vertex_distances = new RNLength [ NVertices() ];
  RNLength *edge_distances = new RNLength [ NEdges() ];
  RNLength *face_distances = new RNLength [ NFaces() ];
  assert(vertex_distances && edge_distances && face_distances);
  for (int i = 0; i < NVertices(); i++) vertex_distances[i] = FLT_MAX;
  for (int i = 0; i < NEdges(); i++) edge_distances[i] = FLT_MAX;
  for (int i = 0; i < NFaces(); i++) face_distances[i] = FLT_MAX;
  vertex_distances [VertexID(source_vertex)] = 0;

  // Initialize heap of beams originating at source vertex
  R3MeshGeodesicBeam tmp;
  RNHeap<R3MeshGeodesicBeam *> heap(&tmp, &(tmp.distance));
  RNArray<R3MeshGeodesicBeam *> beams;
  R3MeshCreateGeodesicBeamsForVertex(this, source_vertex, max_distance, 0, NULL, 
    vertex_distances, edge_distances, face_distances, heap, beams);
  for (int i = 0; i < VertexValence(source_vertex); i++) {
    R3MeshEdge *e = EdgeOnVertex(source_vertex, i);
    R3MeshVertex *vertex = VertexAcrossEdge(e, source_vertex);
    edge_distances [EdgeID(e)] = EdgeLength(e);
    vertex_distances [VertexID(vertex)] = EdgeLength(e);
    if (R3MeshVertexIsSaddleOrBoundary(this, vertex)) {
      R3MeshCreateGeodesicBeamsForVertex(this, vertex, max_distance, EdgeLength(e), NULL, 
        vertex_distances, edge_distances, face_distances, heap, beams);
    }
  }

  // Pop beams off heap
  while (!heap.IsEmpty()) {
    // Get beam
    R3MeshGeodesicBeam *beam = heap.Pop();
    assert(beam);

    // Get face across edge
    R3MeshFace *face = FaceAcrossEdge(beam->edge, beam->face);
    assert(face);

    // Check beam distances versus upper bounds on distances found already
    if (beam->distance > beam->distance - beam->distance_to_source + vertex_distances[VertexID(beam->source)]) continue;
    if (beam->distance >= edge_distances[EdgeID(beam->edge)]) continue;
    if (beam->distance >= face_distances[FaceID(face)]) continue;

    // Construct beam extent
    R3Point left_span_position = beam->span.Start();
    R3Vector left_vector =  left_span_position.Vector();
    R3Vector left_normal = left_vector % R3posz_vector; left_normal.Normalize();
    R3Plane left_plane(left_span_position, left_normal);
    R3Point right_span_position = beam->span.End();
    R3Vector right_vector =  right_span_position.Vector();
    R3Vector right_normal = R3posz_vector % right_vector; right_normal.Normalize();
    R3Plane right_plane(right_span_position, right_normal);

    // Find affine that takes points on face into beam coordinate system
    R3Vector face_normal = FaceNormal(face);
    face_normal.Transform(beam->affine);
    R3Affine affine = R3identity_affine;
    affine.Translate(beam->span.Midpoint().Vector());
    affine.Rotate(face_normal, R3posz_vector);
    affine.Translate(-(beam->span.Midpoint().Vector()));
    affine.Transform(beam->affine);

    // Spawn beams across edges
    for (int i = 0; i < 2; i++) {
      R3MeshEdge *edge = EdgeOnFace(face, beam->edge, i);
      R3MeshFace *neighbor_face = FaceAcrossEdge(edge, face);
      if (!neighbor_face) continue;

      // Check versus upper-bound distances
      if (beam->distance >= edge_distances[EdgeID(edge)]) continue;
      if (beam->distance >= face_distances[FaceID(neighbor_face)]) continue;

      // Get edge span in unfolded beam coordinate system
      R3MeshVertex *v_ccw = VertexOnFace(face, edge, RN_CCW);
      R3MeshVertex *v_cw = VertexOnFace(face, edge, RN_CW);
      R3Point p_ccw = VertexPosition(v_ccw);
      R3Point p_cw = VertexPosition(v_cw);
      p_ccw.Transform(affine);
      p_cw.Transform(affine);
      R3Span edge_span(p_ccw, p_cw);
      // assert(RNIsZero(p_ccw[2]));
      // assert(RNIsZero(p_cw[2]));

      // Check if source is on correct side of edge span
      R3Vector span_vector = edge_span.Vector();
      if (RNIsZero(span_vector.Length())) continue;
      R3Vector span_normal = R3posz_vector % span_vector; span_normal.Normalize();
      R3Plane span_plane(edge_span.Midpoint(), span_normal);
      if (RNIsPositive(R3SignedDistance(span_plane, R3zero_point))) continue;
      
      // Check for edge-beam intersection
      // RNScalar left_dcw = R3SignedDistance(left_plane, edge_span.End());
      // if (RNIsNegative(left_dcw)) continue;
      // RNScalar right_dccw = R3SignedDistance(right_plane, edge_span.Start());
      // if (RNIsNegative(right_dccw)) continue;
        
      // Clip edge span to beam
      if (!edge_span.Clip(left_plane)) continue;
      if (!edge_span.Clip(right_plane)) continue;

      // Get lower bound on distance to edge span
      RNLength beam_distance = beam->distance_to_source + R3Distance(R3zero_point, edge_span);
      if ((max_distance > 0) && (beam_distance > max_distance)) continue;

      // Check versus upper-bound distances
      if (beam_distance >= edge_distances[EdgeID(edge)]) continue;
      if (beam_distance >= face_distances[FaceID(neighbor_face)]) continue;

      // Create beam
      R3MeshGeodesicBeam *child_beam = new R3MeshGeodesicBeam();
      child_beam->source = beam->source;
      child_beam->face = face;
      child_beam->edge = edge;
      child_beam->affine = affine;
      child_beam->span = edge_span;
      child_beam->distance = beam_distance;
      child_beam->distance_to_source = beam->distance_to_source;
      child_beam->parent = beam;

      // Add beam to heap
      heap.Push(child_beam);
      beams.Insert(child_beam);
    }

    // Update upper bound distances and spawn beams from vertices
    for (int i = 0; i < 3; i++) {
      R3MeshVertex *vertex = VertexOnFace(face, i);
      R3Point vertex_position = VertexPosition(vertex);
      vertex_position.Transform(affine);

      // Compute distance to vertex along this path
      RNLength vertex_distance = 0;
      RNBoolean vertex_visible = FALSE;
      if (R3SignedDistance(left_plane, vertex_position) < 0) {
        // Vertex is to the left of the beam
        RNLength left_distance1 = R3Distance(R3zero_point, left_span_position);
        RNLength left_distance2 = R3Distance(left_span_position, vertex_position);
        vertex_distance = beam->distance_to_source + left_distance1 + left_distance2;
      }
      else if (R3SignedDistance(right_plane, vertex_position) < 0) {
        // Vertex is to the right of the beam
        RNLength right_distance1 = R3Distance(R3zero_point, right_span_position);
        RNLength right_distance2 = R3Distance(right_span_position, vertex_position);
        vertex_distance = beam->distance_to_source + right_distance1 + right_distance2;
      }
      else {
        // Vertex is inside the beam
        vertex_distance = beam->distance_to_source + R3Distance(R3zero_point, vertex_position);
        vertex_visible = TRUE;
      }

      // Update upper bound distances
      if (vertex_distance < vertex_distances[VertexID(vertex)]) {
        // Remember vertex distance
        RNLength old_vertex_distance = vertex_distances[VertexID(vertex)];
        vertex_distances[VertexID(vertex)] = vertex_distance;

        // Update edge distances
        for (int j = 0; j < 2; j++) {
          R3MeshEdge *edge = EdgeOnFace(face, beam->edge, j);
          if (vertex_distance < edge_distances[EdgeID(edge)]) {
            R3MeshVertex *v = VertexAcrossEdge(edge, vertex);
            if (vertex_distance > vertex_distances[VertexID(v)]) {
              edge_distances[EdgeID(edge)] = vertex_distance;
            }
          }
        }

        // Update face distance
        if (vertex_distance < face_distances[FaceID(face)]) {
          R3MeshVertex *v0 = VertexOnFace(face, vertex, RN_CCW);
          R3MeshVertex *v1 = VertexOnFace(face, vertex, RN_CW);
          if ((vertex_distance > vertex_distances[VertexID(v0)]) && (vertex_distance > vertex_distances[VertexID(v1)])) {
            face_distances[FaceID(face)] = vertex_distance;
          }
        }

        // Spawn beam from "across" vertex if it is a visible saddle or boundary
        if (vertex_visible && (vertex == VertexAcrossFace(face, beam->edge))) { 
          if (RNIsLess(vertex_distance, old_vertex_distance)) {
            if (R3MeshVertexIsSaddleOrBoundary(this, vertex)) {
              R3MeshCreateGeodesicBeamsForVertex(this, vertex, max_distance, vertex_distance, beam, 
                vertex_distances, edge_distances, face_distances, heap, beams);
            }
          }
        }
      }
    }
  }

  // Delete all beams
  for (int i = 0; i < beams.NEntries(); i++) {
    delete beams[i];
  }

  // Delete edge and face distances
  delete [] edge_distances;
  delete [] face_distances;

  // Return vertex distances
  return vertex_distances;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4f8, %rsp            # imm = 0x4F8
movsd %xmm0, 0x28(%rsp)
movq %rsi, %rbx
movq %rdi, %r12
movslq 0x14(%rdi), %rbp
leaq (,%rbp,8), %rdi
testq %rbp, %rbp
pushq $-0x1
popq %rax
cmovsq %rax, %rdi
movq %rax, %r14
callq 0xe030
movq %rax, 0x20(%rsp)
movslq 0x24(%r12), %r13
leaq (,%r13,8), %rdi
testq %r13, %r13
cmovsq %r14, %rdi
callq 0xe030
movq %rax, %r14
movslq 0x34(%r12), %r15
leaq (,%r15,8), %rdi
testq %r15, %r15
pushq $-0x1
popq %rax
cmovsq %rax, %rdi
callq 0xe030
movq %rax, 0x10(%rsp)
xorl %ecx, %ecx
testl %ebp, %ebp
movl $0x0, %edx
cmovgl %ebp, %edx
movabsq $0x47efffffe0000000, %rax # imm = 0x47EFFFFFE0000000
movq 0x20(%rsp), %rsi
cmpq %rcx, %rdx
je 0x190ce
movq %rax, (%rsi,%rcx,8)
incq %rcx
jmp 0x190c0
xorl %ecx, %ecx
testl %r13d, %r13d
movl $0x0, %edx
cmovgl %r13d, %edx
cmpq %rcx, %rdx
je 0x190ea
movq %rax, (%r14,%rcx,8)
incq %rcx
jmp 0x190dc
xorl %ecx, %ecx
testl %r15d, %r15d
movl $0x0, %edx
cmovgl %r15d, %edx
movq 0x10(%rsp), %rsi
cmpq %rcx, %rdx
je 0x1910b
movq %rax, (%rsi,%rcx,8)
incq %rcx
jmp 0x190fd
movslq 0x70(%rbx), %rax
movq 0x20(%rsp), %rcx
andq $0x0, (%rcx,%rax,8)
leaq 0x368(%rsp), %rdi
callq 0x21cc4
xorpd %xmm0, %xmm0
movapd %xmm0, 0x50(%rsp)
andq $0x0, 0x78(%rsp)
movupd %xmm0, 0x68(%rsp)
movl $0x1, 0x80(%rsp)
movabsq $-0xfffffe88, %rax      # imm = 0xFFFFFFFF00000178
movq %rax, 0x60(%rsp)
leaq 0x38(%rsp), %r15
movq %r15, %rdi
callq 0x6630a
movq %r15, (%rsp)
leaq 0x50(%rsp), %r9
xorpd %xmm1, %xmm1
movq %r12, %rdi
movq %rbx, %rsi
movsd 0x28(%rsp), %xmm0
xorl %edx, %edx
movq %r14, %rcx
movq 0x10(%rsp), %r8
callq 0x19b81
xorl %r15d, %r15d
movslq 0x14(%rbx), %rax
cmpq %rax, %r15
jge 0x19a61
movq 0x8(%rbx), %rax
movq (%rax,%r15,8), %rbp
movq 0x8(%rbp), %r13
cmpq %rbx, %r13
jne 0x191b0
movq 0x10(%rbp), %r13
movq %r12, %rdi
movq %rbp, %rsi
callq 0x10db2
movslq 0x30(%rbp), %rax
movsd %xmm0, (%r14,%rax,8)
movq %r12, %rdi
movq %rbp, %rsi
callq 0x10db2
movslq 0x70(%r13), %rax
movq 0x20(%rsp), %rcx
movsd %xmm0, (%rcx,%rax,8)
movq %r12, %rdi
movq %r13, %rsi
callq 0x19e9f
testl %eax, %eax
je 0x19225
movq %r12, %rdi
movq %rbp, %rsi
callq 0x10db2
movapd %xmm0, %xmm1
leaq 0x38(%rsp), %rax
movq %rax, (%rsp)
movq %r12, %rdi
movq %r13, %rsi
movsd 0x28(%rsp), %xmm0
xorl %edx, %edx
movq %r14, %rcx
movq 0x10(%rsp), %r8
leaq 0x50(%rsp), %r9
callq 0x19b81
incq %r15
jmp 0x1918e
leaq 0x50(%rsp), %rdi
callq 0x21d02
movq %rax, %rbp
movq 0x10(%rax), %rax
movq 0x18(%rax), %r15
cmpq 0x8(%rbp), %r15
jne 0x1924c
movq 0x20(%rax), %r15
movsd 0x178(%rbp), %xmm0
movapd %xmm0, %xmm1
subsd 0x180(%rbp), %xmm1
movq (%rbp), %rcx
movslq 0x70(%rcx), %rcx
movq 0x20(%rsp), %rdx
addsd (%rdx,%rcx,8), %xmm1
ucomisd %xmm1, %xmm0
ja 0x19a61
movslq 0x30(%rax), %rax
ucomisd (%r14,%rax,8), %xmm0
jae 0x19a61
movslq 0xa4(%r15), %rax
movq 0x10(%rsp), %rcx
ucomisd (%rcx,%rax,8), %xmm0
jae 0x19a61
leaq 0x128(%rbp), %rsi
leaq 0x158(%rsp), %r13
movq %r13, %rdi
movq %rsi, 0x8(%rsp)
callq 0x37b5c
leaq 0x240(%rsp), %rbx
movq %rbx, %rdi
movq %r13, %rsi
callq 0x212f8
leaq 0x228(%rsp), %r13
movq %r13, %rdi
movq %rbx, %rsi
leaq 0x80409(%rip), %rdx     # 0x996f0
callq 0x389be
movq %r13, %rdi
callq 0x3860e
leaq 0x190(%rsp), %rdi
leaq 0x158(%rsp), %rsi
movq %r13, %rdx
callq 0x367ac
leaq 0x158(%rbp), %rsi
leaq 0x140(%rsp), %rbx
movq %rbx, %rdi
callq 0x37b5c
leaq 0x210(%rsp), %r13
movq %r13, %rdi
movq %rbx, %rsi
callq 0x212f8
leaq 0x1f8(%rsp), %rbx
movq %rbx, %rdi
leaq 0x803a8(%rip), %rsi     # 0x996f0
movq %r13, %rdx
callq 0x389be
movq %rbx, %rdi
callq 0x3860e
leaq 0x170(%rsp), %rdi
leaq 0x140(%rsp), %rsi
movq %rbx, %rdx
callq 0x367ac
movq %r12, %rdi
movq %r15, %rsi
callq 0x10dd0
leaq 0x128(%rsp), %rdi
movq %rax, %rsi
callq 0x3831c
movq %rbp, %r13
addq $0x18, %r13
leaq 0x128(%rsp), %rdi
movq %r13, %rsi
callq 0x38bb8
leaq 0x258(%rsp), %rdi
leaq 0xc1c5f(%rip), %rsi     # 0xdb010
callq 0x21282
leaq 0xf0(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x371bc
leaq 0xa0(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x212f8
leaq 0x258(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x212e2
leaq 0x258(%rsp), %rdi
leaq 0x128(%rsp), %rsi
leaq 0x802e7(%rip), %rdx     # 0x996f0
callq 0x21da2
leaq 0x88(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x371bc
leaq 0xf0(%rsp), %rdi
leaq 0x88(%rsp), %rsi
callq 0x212f8
leaq 0xa0(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x38c72
leaq 0x258(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x212e2
leaq 0x258(%rsp), %rdi
movq %r13, %rsi
callq 0x2785a
xorl %ecx, %ecx
cmpl $0x2, %ecx
je 0x19796
movq 0x10(%rbp), %rdx
movq %r12, %rdi
movq %r15, %rsi
movl %ecx, 0x8(%rsp)
callq 0x21a5e
movq %rax, %rbx
movq 0x18(%rax), %rax
movq %rax, %rcx
cmpq %r15, %rax
jne 0x194a0
movq 0x20(%rbx), %rcx
movq %rcx, 0x30(%rsp)
testq %rcx, %rcx
je 0x1978b
movsd 0x178(%rbp), %xmm0
movslq 0x30(%rbx), %rcx
ucomisd (%r14,%rcx,8), %xmm0
jae 0x1978b
movq 0x30(%rsp), %rcx
movslq 0xa4(%rcx), %rcx
movq 0x10(%rsp), %rdx
ucomisd (%rdx,%rcx,8), %xmm0
jae 0x1978b
xorl %ecx, %ecx
xorl %edx, %edx
cmpq %r15, %rax
setne %cl
sete %dl
movq 0x8(%rbx,%rdx,8), %rsi
movq 0x8(%rbx,%rcx,8), %r13
addq $0x18, %rsi
leaq 0x88(%rsp), %rdi
callq 0x37b5c
addq $0x18, %r13
leaq 0x110(%rsp), %rdi
movq %r13, %rsi
callq 0x37b5c
leaq 0x88(%rsp), %rdi
leaq 0x258(%rsp), %rsi
callq 0x38192
leaq 0x110(%rsp), %rdi
leaq 0x258(%rsp), %rsi
callq 0x38192
leaq 0xa0(%rsp), %rdi
leaq 0x88(%rsp), %rsi
leaq 0x110(%rsp), %rdx
callq 0x37000
leaq 0x1e0(%rsp), %r13
movq %r13, %rdi
leaq 0xb8(%rsp), %rsi
callq 0x3831c
movq %r13, %rdi
callq 0x38412
leaq 0xc161c(%rip), %rax     # 0xdaba8
movsd (%rax), %xmm1
movapd %xmm1, %xmm2
xorpd 0x79a94(%rip), %xmm2    # 0x93030
ucomisd %xmm2, %xmm0
jb 0x195ac
ucomisd %xmm0, %xmm1
jae 0x1978b
leaq 0x1c8(%rsp), %r13
movq %r13, %rdi
leaq 0x80132(%rip), %rsi     # 0x996f0
leaq 0x1e0(%rsp), %rdx
callq 0x389be
movq %r13, %rdi
callq 0x3860e
leaq 0x1b0(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x371bc
leaq 0xf0(%rsp), %r13
movq %r13, %rdi
leaq 0x1b0(%rsp), %rsi
leaq 0x1c8(%rsp), %rdx
callq 0x367ac
movq %r13, %rdi
leaq 0x4c245e(%rip), %rsi    # 0x4dba70
callq 0x43420
leaq 0xc158a(%rip), %rax     # 0xdaba8
ucomisd (%rax), %xmm0
ja 0x1978b
leaq 0xa0(%rsp), %rdi
leaq 0x190(%rsp), %rsi
callq 0x374d6
testl %eax, %eax
je 0x1978b
leaq 0xa0(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0x374d6
testl %eax, %eax
je 0x1978b
movsd 0x180(%rbp), %xmm0
movsd %xmm0, 0x18(%rsp)
leaq 0x4c23f9(%rip), %rdi    # 0x4dba70
leaq 0xa0(%rsp), %rsi
callq 0x432fc
movsd 0x28(%rsp), %xmm1
ucomisd 0x79b56(%rip), %xmm1    # 0x931e8
movsd 0x18(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x18(%rsp)
jbe 0x196b6
movsd 0x18(%rsp), %xmm0
ucomisd 0x28(%rsp), %xmm0
ja 0x1978b
movslq 0x30(%rbx), %rax
movsd 0x18(%rsp), %xmm0
ucomisd (%r14,%rax,8), %xmm0
jae 0x1978b
movq 0x30(%rsp), %rax
movslq 0xa4(%rax), %rax
movq 0x10(%rsp), %rcx
movsd 0x18(%rsp), %xmm0
ucomisd (%rcx,%rax,8), %xmm0
jae 0x1978b
movl $0x190, %edi            # imm = 0x190
callq 0xe450
movq %rax, %r13
movl $0x190, %edx            # imm = 0x190
movq %rax, %rdi
xorl %esi, %esi
callq 0xe270
movq %r13, %rdi
callq 0x21cc4
movq (%rbp), %rax
movq %rax, (%r13)
movq %r15, 0x8(%r13)
movq %rbx, 0x10(%r13)
leaq 0x18(%r13), %rdi
leaq 0x258(%rsp), %rsi
callq 0x21db8
movq %r13, %rdi
addq $0x128, %rdi            # imm = 0x128
leaq 0xa0(%rsp), %rsi
callq 0x21dfa
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x178(%r13)
movsd 0x180(%rbp), %xmm0
movsd %xmm0, 0x180(%r13)
movq %rbp, 0x188(%r13)
leaq 0x50(%rsp), %rdi
movq %r13, %rsi
callq 0x21e2c
leaq 0x38(%rsp), %rdi
movq %r13, %rsi
callq 0x22bfc
movl 0x8(%rsp), %ecx
incl %ecx
jmp 0x19471
xorl %eax, %eax
cmpq $0x3, %rax
je 0x19a54
movq %rax, 0x30(%rsp)
movq 0x8(%r15,%rax,8), %r13
leaq 0x18(%r13), %rsi
leaq 0xa0(%rsp), %rbx
movq %rbx, %rdi
callq 0x37b5c
movq %rbx, %rdi
leaq 0x258(%rsp), %rsi
callq 0x38192
leaq 0x190(%rsp), %rdi
movq %rbx, %rsi
callq 0x43420
xorpd %xmm1, %xmm1
ucomisd %xmm0, %xmm1
jbe 0x19819
leaq 0x4c227f(%rip), %rdi    # 0x4dba70
leaq 0x158(%rsp), %rbx
movq %rbx, %rsi
callq 0x4321a
movsd %xmm0, 0x8(%rsp)
movq %rbx, %rdi
leaq 0xa0(%rsp), %rsi
callq 0x4321a
jmp 0x19865
leaq 0x170(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x43420
xorpd %xmm1, %xmm1
ucomisd %xmm0, %xmm1
jbe 0x19883
leaq 0x4c2231(%rip), %rdi    # 0x4dba70
leaq 0x140(%rsp), %rbx
movq %rbx, %rsi
callq 0x4321a
movsd %xmm0, 0x8(%rsp)
movq %rbx, %rdi
leaq 0xa0(%rsp), %rsi
callq 0x4321a
movapd %xmm0, %xmm1
movsd 0x8(%rsp), %xmm0
addsd 0x180(%rbp), %xmm0
addsd %xmm0, %xmm1
movb $0x1, %al
movl %eax, 0x18(%rsp)
jmp 0x198b7
movsd 0x180(%rbp), %xmm0
movsd %xmm0, 0x8(%rsp)
leaq 0x4c21d8(%rip), %rdi    # 0x4dba70
leaq 0xa0(%rsp), %rsi
callq 0x4321a
movsd 0x8(%rsp), %xmm1
addsd %xmm0, %xmm1
movl $0x0, 0x18(%rsp)
movslq 0x70(%r13), %rax
movq 0x20(%rsp), %rcx
movsd (%rcx,%rax,8), %xmm0
movsd %xmm1, 0x8(%rsp)
movsd %xmm0, 0x48(%rsp)
ucomisd %xmm1, %xmm0
jbe 0x19a47
movq 0x20(%rsp), %rcx
movsd 0x8(%rsp), %xmm0
movsd %xmm0, (%rcx,%rax,8)
xorl %ebx, %ebx
cmpl $0x2, %ebx
je 0x19948
movq 0x10(%rbp), %rdx
movq %r12, %rdi
movq %r15, %rsi
movl %ebx, %ecx
callq 0x21a5e
movslq 0x30(%rax), %rcx
movsd (%r14,%rcx,8), %xmm0
ucomisd 0x8(%rsp), %xmm0
jbe 0x19944
movq 0x8(%rax), %rdx
cmpq %r13, %rdx
jne 0x19922
movq 0x10(%rax), %rdx
movslq 0x70(%rdx), %rax
movq 0x20(%rsp), %rdx
movsd 0x8(%rsp), %xmm0
ucomisd (%rdx,%rax,8), %xmm0
jbe 0x19944
movsd 0x8(%rsp), %xmm0
movsd %xmm0, (%r14,%rcx,8)
incl %ebx
jmp 0x198ed
movslq 0xa4(%r15), %rax
movq 0x10(%rsp), %rcx
movsd (%rcx,%rax,8), %xmm0
ucomisd 0x8(%rsp), %xmm0
jbe 0x199c8
movq %r12, %rdi
movq %r15, %rsi
movq %r13, %rdx
xorl %ecx, %ecx
callq 0x21f34
movq %rax, %rbx
movq %r12, %rdi
movq %r15, %rsi
movq %r13, %rdx
pushq $0x1
popq %rcx
callq 0x21f34
movslq 0x70(%rbx), %rcx
movq 0x20(%rsp), %rdx
movsd 0x8(%rsp), %xmm0
ucomisd (%rdx,%rcx,8), %xmm0
jbe 0x199c8
movslq 0x70(%rax), %rax
movq 0x20(%rsp), %rcx
movsd 0x8(%rsp), %xmm0
ucomisd (%rcx,%rax,8), %xmm0
jbe 0x199c8
movslq 0xa4(%r15), %rax
movq 0x10(%rsp), %rcx
movsd 0x8(%rsp), %xmm0
movsd %xmm0, (%rcx,%rax,8)
cmpb $0x0, 0x18(%rsp)
jne 0x19a47
movq 0x10(%rbp), %rdx
movq %r12, %rdi
movq %r15, %rsi
callq 0x2136e
cmpq %rax, %r13
jne 0x19a47
movsd 0x8(%rsp), %xmm0
subsd 0x48(%rsp), %xmm0
leaq 0xc11b2(%rip), %rax     # 0xdaba8
movsd (%rax), %xmm1
xorpd 0x7962e(%rip), %xmm1    # 0x93030
ucomisd %xmm0, %xmm1
jbe 0x19a47
movq %r12, %rdi
movq %r13, %rsi
callq 0x19e9f
testl %eax, %eax
je 0x19a47
leaq 0x38(%rsp), %rax
movq %rax, (%rsp)
movq %r12, %rdi
movq %r13, %rsi
movsd 0x28(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
movq %rbp, %rdx
movq %r14, %rcx
movq 0x10(%rsp), %r8
leaq 0x50(%rsp), %r9
callq 0x19b81
movq 0x30(%rsp), %rax
incq %rax
jmp 0x19798
leaq 0x258(%rsp), %rdi
callq 0x276ee
cmpl $0x0, 0x58(%rsp)
jne 0x1922d
xorl %r15d, %r15d
movslq 0x44(%rsp), %rax
cmpq %rax, %r15
jge 0x19aa2
movq 0x38(%rsp), %rax
movq (%rax,%r15,8), %rbx
testq %rbx, %rbx
je 0x19a90
leaq 0x18(%rbx), %rdi
callq 0x276ee
movl $0x190, %esi            # imm = 0x190
movq %rbx, %rdi
callq 0xe460
incq %r15
jmp 0x19a6f
movq %r14, %rdi
callq 0xe5d0
movq 0x10(%rsp), %rdi
callq 0xe5d0
leaq 0x38(%rsp), %rdi
callq 0x66378
leaq 0x50(%rsp), %rdi
callq 0x21f62
leaq 0x380(%rsp), %rdi
callq 0x276ee
movq 0x20(%rsp), %rax
addq $0x4f8, %rsp            # imm = 0x4F8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
movl $0x190, %esi            # imm = 0x190
movq %r13, %rdi
callq 0xe460
jmp 0x19b4b
jmp 0x19b41
movq %rax, %rbx
jmp 0x19b62
jmp 0x19b48
jmp 0x19b48
jmp 0x19b41
jmp 0x19b41
jmp 0x19b41
jmp 0x19b41
jmp 0x19b41
jmp 0x19b41
jmp 0x19b41
jmp 0x19b41
jmp 0x19b48
jmp 0x19b41
jmp 0x19b48
jmp 0x19b41
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b41
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
jmp 0x19b48
movq %rax, %rbx
jmp 0x19b58
jmp 0x19b48
movq %rax, %rbx
leaq 0x258(%rsp), %rdi
callq 0x276ee
leaq 0x38(%rsp), %rdi
callq 0x66378
leaq 0x50(%rsp), %rdi
callq 0x21f62
leaq 0x380(%rsp), %rdi
callq 0x276ee
movq %rbx, %rdi
callq 0xe810