// File: /workspace/github_cpp_makefile_star2_O1/Luthaf[P]zeopp/area_and_volume.cc
// Function: blockPockets(ATOM_NETWORK*, std::ostream&, std::vector<Point, std::allocator<Point>>, std::vector<int, std::allocator<int>>, std::vector<Point, std::allocator<Point>>, std::vector<int, std::allocator<int>>, double)
void blockPockets(ATOM_NETWORK *atmnet, ostream &output, vector<Point> axsPoints, vector<int> axsPChIDs, vector<Point> inaxsPoints, vector<int> inaxsPPIDs, double probeRad){
/*
  for(unsigned int i = 0; i < axsPoints.size(); i++){
    Point coords = axsPoints.at(i);
    output << coords[0] << " " << coords[1] << " " << coords[2] << " 1 a " << axsPChIDs[i] << "\n";
   }
*/
/*
  for(unsigned int i = 0; i < inaxsPoints.size(); i++){
    Point coords = inaxsPoints.at(i);
    // print coordinates and pocket ID
    output <<  coords[0] << " " << coords[1] << " " << coords[2] << " 0 block " << inaxsPPIDs[i] << "\n";
  }
*/

  //DESCRIPTION: iterate over each pore ID that corresponds to a pocket, and block all points in that pocket with spheres without blocking any non-pocket points - the spheres are created iteratively, and many spheres may be needed per pocket
  bool debug = false; //prints extra info to terminal, including .xyz format Cartesian pocket info for visualisation
  vector<SPHERE> spheres_vector; //stores blocking spheres we have created below;
  double sphere_radius_overshoot = 0.1; //optional - the amount in A by which a sphere can extend beyond the furthest point to be blocked (so that the sphere does not perfectly intersect the furthest MC point, potentially leaving volume nearby that should have been blocked)

  //1) identify how many pores we have, and which ones are pockets
  int max_pore_ID = 0;
  int num_axsPoints = axsPoints.size();
  int num_inaxsPoints = inaxsPoints.size();
  for(int i=0; i<num_axsPoints; i++) if(axsPChIDs.at(i)>max_pore_ID) max_pore_ID = axsPChIDs.at(i);
  for(int i=0; i<num_inaxsPoints; i++) if(inaxsPPIDs.at(i)>max_pore_ID) max_pore_ID = inaxsPPIDs.at(i);
  int num_pores = max_pore_ID+1;
  vector<bool> is_pocket;
  for(int i=0; i<num_pores; i++) is_pocket.push_back(false);
  for(int i=0; i<num_inaxsPoints; i++) if(!is_pocket.at(inaxsPPIDs.at(i))) is_pocket.at(inaxsPPIDs.at(i)) = true;
  if(debug) {
    printf("DEBUG: there are %d pores and they are assigned to channels and pockets as follows:\n", num_pores);
    for(int i=0; i<num_pores; i++) {
      printf("ID %d: ", i);
      if(is_pocket.at(i)) printf("pocket\n"); else printf("channel\n");
    }
  }

  //2) for each pocket, determine which points are members of this pocket and not already blocked by an earlier sphere (hence the resulting points may not all be connected), and store them all in selected_points
  for(int i=0; i<num_pores; i++) {
    vector<Point> selected_points; //stores to-be-blocked points in this pore
    if(is_pocket.at(i)) { //this pore is a pocket - we are going to block it with spheres
      for(int j=0; j<num_inaxsPoints; j++) {
        if(inaxsPPIDs.at(j)==i) { //inaxs point j is in pore i, so needs to be blocked - if it is not already blocked, push to selected_points vector
          Point p = inaxsPoints.at(j);
          bool already_blocked = false;
          int num_spheres = spheres_vector.size();
					for(int s=0; s<num_spheres && !already_blocked; s++) {
            SPHERE this_sphere = spheres_vector.at(s);
            double dist = atmnet->calcDistanceABC(p[0], p[1], p[2], this_sphere.x, this_sphere.y, this_sphere.z);
						if(dist<this_sphere.r) already_blocked = true;
					}
          if(!already_blocked) selected_points.push_back(p);
        }
      }

      //3) begin a loop - while there are points in selected_points, we need to do more blocking
      int num_selected_points = selected_points.size();
      while(num_selected_points>0) {
        if(debug) printf("DEBUG: there are %d points left to be blocked in pore with ID %d\n", num_selected_points, i);
        int most_dense_index = get_most_dense_index(atmnet, &selected_points);
        Point most_dense = selected_points.at(most_dense_index); //find most dense point in the remaining point cloud
        double closest_channel = -1; //distance to nearest MC point that is in a channel
        for(int j=0; j<num_axsPoints; j++) { //loop over points to be preserved, and find closest
          Point p = axsPoints.at(j);
          double dist = atmnet->calcDistanceABC(p[0], p[1], p[2], most_dense[0], most_dense[1], most_dense[2]);
          if(dist<closest_channel || closest_channel<0) closest_channel=dist;
        }
        double furthest_same_pocket = 0; //distance to furthest MC point that is part of this pore
        vector<double> vector_of_distances_to_sphere_centroid; //keep track of the distance of each to-be-blocked point to the most dense point - it will save us calculating this again later when we check which points were blocked
        for(int j=0; j<num_selected_points; j++) { //loop over points to be blocked, and find furthest
          Point p = selected_points.at(j);
          double dist = atmnet->calcDistanceABC(p[0], p[1], p[2], most_dense[0], most_dense[1], most_dense[2]);
          if(dist>furthest_same_pocket || furthest_same_pocket<0) furthest_same_pocket=dist;
          vector_of_distances_to_sphere_centroid.push_back(dist);
        }

        //4) calculate the largest acceptable sphere at this most dense position
        double radius = 0;
        if(closest_channel<0) radius = furthest_same_pocket + probeRad + sphere_radius_overshoot; //no channels - we can safely have a single sphere, inflated by probeRad to cover the void space here
        else if(furthest_same_pocket<closest_channel) radius = min(furthest_same_pocket + probeRad + sphere_radius_overshoot, closest_channel - (probeRad + sphere_radius_overshoot)); //there are channels, but none are closer than the furthest point in this pocket, so we can extend the sphere to cover everything; try and inflate the sphere by probeRad to ensure the void space is blocked, but not if this would cause anything within probeRad of an accessible MC point to be blocked
        else radius = max(sphere_radius_overshoot, closest_channel - (probeRad + sphere_radius_overshoot)); //else there are channels closer than the furthest pocket MC point, and we have to accommodate them

        //5) create the sphere and remove to-be-blocked points that were blocked by it
        SPHERE new_sphere;
        new_sphere.x = most_dense[0];
        new_sphere.y = most_dense[1];
        new_sphere.z = most_dense[2];
        new_sphere.r = radius;
        spheres_vector.push_back(new_sphere);
        for(int j=num_selected_points-1; j>=0; j--) { //loop over points to be blocked and eliminate blocked ones - we iterate backwards so that the vector of distances is still relevant
          if(vector_of_distances_to_sphere_centroid.at(j)<radius) { //blocked
				    Point swap = selected_points.at(j);
				    selected_points.at(j) = selected_points.at(num_selected_points-1);
				    selected_points.at(num_selected_points-1) = swap;
				    selected_points.pop_back();
				    num_selected_points--; //update counter iteratively
          }
        }
      } //6) end while loop - we have totally blocked this pocket - safe to move on to next pore
    } //7) end if is_pocket - we either ran the blocking part or bypassed this pore
  } //8) end for loop - we have analysed all pores and blocked where necessary
  int num_spheres = spheres_vector.size();
  //9) write to output (directed to .block file)
  if(debug) printf("DEBUG: %d blocking spheres were created, Cartesian positions in xyz format follow, if any\n%d\nXYZ FORMAT CARTESIAN POCKETS FOR VISUALIZATION\n", num_spheres, num_spheres);
  output << num_spheres << "\n";
  for(int i=0; i<num_spheres; i++) {
    SPHERE s = spheres_vector.at(i);
    if(debug) {
      Point f; f[0] = s.x; f[1] = s.y; f[2] = s.z;
      Point c = atmnet->abc_to_xyz(f);
      printf("X %.3f %.3f %.3f %.3f\n", c[0], c[1], c[2], s.r);
    }
    output << s.x << " " << s.y << " " << s.z << " " << s.r << "\n";
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x198, %rsp            # imm = 0x198
movsd %xmm0, 0xb0(%rsp)
movq %r9, %r13
movq %rsi, 0x130(%rsp)
movq %rdi, 0x78(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x50(%rsp)
movq $0x0, 0x60(%rsp)
movq 0x8(%rdx), %r10
movq %rdx, 0x178(%rsp)
subq (%rdx), %r10
sarq $0x3, %r10
movabsq $-0x5555555555555555, %rax # imm = 0xAAAAAAAAAAAAAAAB
imulq %rax, %r10
movq 0x8(%r8), %r14
movq %r8, 0x170(%rsp)
subq (%r8), %r14
movl %r10d, 0xcc(%rsp)
testl %r10d, %r10d
jle 0x406db
movq (%rcx), %rax
movq 0x8(%rcx), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
movl %r10d, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
leal -0x1(%r10), %edi
cmpq %rdi, %rdx
movq %rdi, %rsi
cmovbq %rdx, %rsi
xorl %r8d, %r8d
xorl %r15d, %r15d
cmpq %rdi, %rdx
jbe 0x4128e
movl (%rax,%r8,4), %r9d
cmpl %r15d, %r9d
cmovgl %r9d, %r15d
incq %r8
cmpq %r8, %rcx
jne 0x406bd
jmp 0x406de
xorl %r15d, %r15d
sarq $0x3, %r14
movabsq $-0x5555555555555555, %rax # imm = 0xAAAAAAAAAAAAAAAB
imulq %rax, %r14
testl %r14d, %r14d
movq %r10, 0x148(%rsp)
jle 0x40732
movq (%r13), %rax
movq 0x8(%r13), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
movl %r14d, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
xorl %esi, %esi
cmpq %rsi, %rdx
je 0x4129c
movl (%rax,%rsi,4), %edi
cmpl %r15d, %edi
cmovgl %edi, %r15d
incq %rsi
cmpq %rsi, %rcx
jne 0x40717
xorl %eax, %eax
leaq 0xf8(%rsp), %rbx
movq %rax, (%rbx)
movl %eax, 0x8(%rbx)
movq %rax, 0x10(%rbx)
movl %eax, 0x18(%rbx)
movq %rax, 0x20(%rbx)
leal 0x1(%r15), %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0xe9e6
decl %ebp
jne 0x40751
movq %r15, 0xa8(%rsp)
movq %r14, 0xa0(%rsp)
testl %r14d, %r14d
jle 0x407e5
movq 0xa0(%rsp), %r15
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
xorl %ebx, %ebx
leaq 0xf8(%rsp), %r14
movq (%r13), %rax
movq 0x8(%r13), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
cmpq %rbx, %rdx
jbe 0x412aa
movslq (%rax,%rbx,4), %rsi
movq %r14, %rdi
callq 0xedb6
testq %rdx, (%rax)
jne 0x407dd
movq (%r13), %rax
movq 0x8(%r13), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
cmpq %rbx, %rdx
jbe 0x412cc
movslq (%rax,%rbx,4), %rsi
movq %r14, %rdi
callq 0xedb6
orq %rdx, (%rax)
incq %rbx
cmpq %rbx, %r15
jne 0x4078d
movsd 0x10e87b(%rip), %xmm0   # 0x14f068
addsd 0xb0(%rsp), %xmm0
movsd %xmm0, 0x140(%rsp)
movq 0xa8(%rsp), %rax
incl %eax
movq %rax, 0xa8(%rsp)
movl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movq 0xa0(%rsp), %rcx
andq %rax, %rcx
andq %rax, 0x148(%rsp)
xorl %ebp, %ebp
leaq 0xd0(%rsp), %rbx
leaq 0x180(%rsp), %r15
movq %r13, 0x168(%rsp)
movq %rcx, 0x138(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x20(%rsp)
movq $0x0, 0x30(%rsp)
leaq 0xf8(%rsp), %rdi
movq %rbp, %rsi
callq 0xedb6
testq %rdx, (%rax)
je 0x41059
cmpl $0x0, 0xa0(%rsp)
movq 0x138(%rsp), %r14
movq %rbp, 0xb8(%rsp)
jle 0x40a82
xorl %esi, %esi
movq (%r13), %rax
movq 0x8(%r13), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
cmpq %rsi, %rdx
jbe 0x41264
movl (%rax,%rsi,4), %eax
cmpq %rax, %rbp
jne 0x40a76
movq 0x170(%rsp), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rdx
subq %rax, %rdx
sarq $0x3, %rdx
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rcx, %rdx
cmpq %rsi, %rdx
jbe 0x41280
movq %rsi, 0x120(%rsp)
leaq (%rsi,%rsi,2), %rcx
movq 0x10(%rax,%rcx,8), %rdx
movq %rdx, 0xe0(%rsp)
movupd (%rax,%rcx,8), %xmm0
movapd %xmm0, 0xd0(%rsp)
movq 0x58(%rsp), %r12
subq 0x50(%rsp), %r12
shrq $0x5, %r12
testl %r12d, %r12d
jle 0x40a34
andl $0x7fffffff, %r12d      # imm = 0x7FFFFFFF
movl $0x18, %ebp
xorl %r14d, %r14d
xorl %r13d, %r13d
movq 0x50(%rsp), %rax
movq 0x58(%rsp), %rdx
subq %rax, %rdx
sarq $0x5, %rdx
cmpq %r14, %rdx
jbe 0x41253
movsd -0x18(%rax,%rbp), %xmm0
movsd %xmm0, 0x40(%rsp)
movsd -0x10(%rax,%rbp), %xmm0
movsd %xmm0, (%rsp)
movsd -0x8(%rax,%rbp), %xmm0
movsd %xmm0, 0x18(%rsp)
movsd (%rax,%rbp), %xmm0
movsd %xmm0, 0x70(%rsp)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0xc0(%rsp)
movq %rbx, %rdi
movl $0x2, %esi
callq 0x85478
movsd (%rax), %xmm2
movq 0x78(%rsp), %rdi
movsd 0x68(%rsp), %xmm0
movsd 0xc0(%rsp), %xmm1
movsd 0x40(%rsp), %xmm3
movsd (%rsp), %xmm4
movsd 0x18(%rsp), %xmm5
callq 0x5369a
movsd 0x70(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movzbl %r13b, %r13d
movl $0x1, %eax
cmoval %eax, %r13d
incq %r14
cmpq %r12, %r14
jae 0x40a16
addq $0x20, %rbp
testb $0x1, %r13b
je 0x40938
testb $0x1, %r13b
movq 0x168(%rsp), %r13
movq 0x138(%rsp), %r14
movq 0xb8(%rsp), %rbp
jne 0x40a6e
movq 0x28(%rsp), %rsi
cmpq 0x30(%rsp), %rsi
je 0x40a61
movq 0xe0(%rsp), %rax
movq %rax, 0x10(%rsi)
movapd 0xd0(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0x28(%rsp)
jmp 0x40a6e
leaq 0x20(%rsp), %rdi
movq %rbx, %rdx
callq 0x3012c
movq 0x120(%rsp), %rsi
incq %rsi
cmpq %r14, %rsi
jne 0x40897
movq 0x28(%rsp), %rax
subq 0x20(%rsp), %rax
shrq $0x3, %rax
imull $0xaaaaaaab, %eax, %r14d # imm = 0xAAAAAAAB
testl %r14d, %r14d
jle 0x41059
movq 0x78(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x489bd
movslq %eax, %rsi
movq 0x20(%rsp), %rax
movq 0x28(%rsp), %rdx
subq %rax, %rdx
sarq $0x3, %rdx
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rcx, %rdx
cmpq %rsi, %rdx
jbe 0x41272
leaq (%rsi,%rsi,2), %rcx
movq 0x10(%rax,%rcx,8), %rdx
movq %rdx, 0x190(%rsp)
movupd (%rax,%rcx,8), %xmm0
movapd %xmm0, 0x180(%rsp)
movsd 0x1127cf(%rip), %xmm3   # 0x1532d0
cmpl $0x0, 0xcc(%rsp)
jle 0x40c51
xorl %r12d, %r12d
xorl %ebp, %ebp
movsd 0x1127b4(%rip), %xmm3   # 0x1532d0
movq 0x178(%rsp), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rdx
subq %rax, %rdx
sarq $0x3, %rdx
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rcx, %rdx
cmpq %rbp, %rdx
jbe 0x41242
movapd %xmm3, 0x120(%rsp)
movq 0x10(%rax,%r12), %rcx
movq %rcx, 0xe0(%rsp)
movupd (%rax,%r12), %xmm0
movapd %xmm0, 0xd0(%rsp)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0x40(%rsp)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, (%rsp)
movq %rbx, %rdi
movl $0x2, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
movq %r15, %rdi
xorl %esi, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0x70(%rsp)
movq %r15, %rdi
movl $0x1, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movq %r15, %rdi
movl $0x2, %esi
callq 0x85478
movsd (%rax), %xmm5
movq 0x78(%rsp), %rdi
movsd 0x40(%rsp), %xmm0
movsd (%rsp), %xmm1
movsd 0x18(%rsp), %xmm2
movsd 0x70(%rsp), %xmm3
movsd 0x68(%rsp), %xmm4
callq 0x5369a
movapd %xmm0, %xmm1
movapd 0x120(%rsp), %xmm3
minsd %xmm3, %xmm1
cmpltsd 0x112694(%rip), %xmm3   # 0x1532c0
movapd %xmm3, %xmm2
andnpd %xmm1, %xmm2
andpd %xmm0, %xmm3
orpd %xmm2, %xmm3
incq %rbp
addq $0x18, %r12
cmpq %rbp, 0x148(%rsp)
jne 0x40b1c
movapd %xmm3, 0x120(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x80(%rsp)
movq $0x0, 0x90(%rsp)
cmpl $0x1, %r14d
movl %r14d, %r12d
adcl $0x0, %r12d
xorpd %xmm0, %xmm0
movapd %xmm0, (%rsp)
xorl %ebp, %ebp
movq 0x20(%rsp), %rax
movq 0x28(%rsp), %rdx
subq %rax, %rdx
sarq $0x3, %rdx
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rcx, %rdx
cmpq %rbp, %rdx
jbe 0x41223
leaq (,%rbp,2), %rcx
addq %rbp, %rcx
movq 0x10(%rax,%rcx,8), %rdx
movq %rdx, 0xe0(%rsp)
movupd (%rax,%rcx,8), %xmm0
movapd %xmm0, 0xd0(%rsp)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0x40(%rsp)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
movq %rbx, %rdi
movl $0x2, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0x70(%rsp)
movq %r15, %rdi
xorl %esi, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movq %r15, %rdi
movl $0x1, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0xc0(%rsp)
movq %r15, %rdi
movl $0x2, %esi
callq 0x85478
movsd (%rax), %xmm5
movq 0x78(%rsp), %rdi
movsd 0x40(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
movsd 0x70(%rsp), %xmm2
movsd 0x68(%rsp), %xmm3
movsd 0xc0(%rsp), %xmm4
callq 0x5369a
movapd %xmm0, 0x40(%rsp)
movapd 0x40(%rsp), %xmm0
movsd %xmm0, 0x150(%rsp)
movq 0x88(%rsp), %rsi
cmpq 0x90(%rsp), %rsi
je 0x40dc2
movapd 0x40(%rsp), %xmm0
movsd %xmm0, (%rsi)
addq $0x8, %rsi
movq %rsi, 0x88(%rsp)
jmp 0x40dd7
leaq 0x80(%rsp), %rdi
leaq 0x150(%rsp), %rdx
callq 0x148c4
movapd 0x40(%rsp), %xmm3
movapd %xmm3, %xmm0
movapd (%rsp), %xmm2
maxsd %xmm2, %xmm0
cmpltsd 0x1124cd(%rip), %xmm2   # 0x1532c0
movapd %xmm2, %xmm1
andnpd %xmm0, %xmm1
andpd %xmm3, %xmm2
orpd %xmm1, %xmm2
movapd %xmm2, (%rsp)
incq %rbp
cmpq %r12, %rbp
jne 0x40c89
xorpd %xmm0, %xmm0
movapd 0x120(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x40e4c
movapd (%rsp), %xmm0
addsd 0xb0(%rsp), %xmm0
addsd 0x10e22b(%rip), %xmm0   # 0x14f068
movapd %xmm0, (%rsp)
movq 0xb8(%rsp), %rbp
jmp 0x40e95
movapd (%rsp), %xmm0
ucomisd %xmm0, %xmm1
movq 0xb8(%rsp), %rbp
jbe 0x40e7f
addsd 0xb0(%rsp), %xmm0
addsd 0x10e1f8(%rip), %xmm0   # 0x14f068
subsd 0x140(%rsp), %xmm1
minsd %xmm0, %xmm1
jmp 0x40e90
subsd 0x140(%rsp), %xmm1
maxsd 0x10e1d8(%rip), %xmm1   # 0x14f068
movapd %xmm1, (%rsp)
movq %r15, %rdi
xorl %esi, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0xd0(%rsp)
movq %r15, %rdi
movl $0x1, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0xd8(%rsp)
movq %r15, %rdi
movl $0x2, %esi
callq 0x85478
movsd (%rax), %xmm0
movsd %xmm0, 0xe0(%rsp)
movapd (%rsp), %xmm0
movsd %xmm0, 0xe8(%rsp)
movq 0x58(%rsp), %rsi
cmpq 0x60(%rsp), %rsi
je 0x40f20
movupd 0xd0(%rsp), %xmm0
movupd 0xe0(%rsp), %xmm1
movupd %xmm1, 0x10(%rsi)
movupd %xmm0, (%rsi)
addq $0x20, %rsi
movq %rsi, 0x58(%rsp)
jmp 0x40f2d
leaq 0x50(%rsp), %rdi
movq %rbx, %rdx
callq 0x49c88
movl %r14d, %eax
leal 0x1(%r14), %ecx
decq %rax
movl %eax, %esi
movq 0x80(%rsp), %rdi
movq 0x88(%rsp), %rdx
subq %rdi, %rdx
sarq $0x3, %rdx
cmpq %rsi, %rdx
jbe 0x41234
movapd (%rsp), %xmm0
ucomisd (%rdi,%rsi,8), %xmm0
jbe 0x41025
movq 0x20(%rsp), %rdi
movq 0x28(%rsp), %rdx
subq %rdi, %rdx
sarq $0x3, %rdx
movabsq $-0x5555555555555555, %r8 # imm = 0xAAAAAAAAAAAAAAAB
imulq %r8, %rdx
cmpq %rsi, %rdx
jbe 0x41215
leaq (%rsi,%rsi,2), %r8
movq 0x10(%rdi,%r8,8), %rsi
movq %rsi, 0x160(%rsp)
movupd (%rdi,%r8,8), %xmm0
movapd %xmm0, 0x150(%rsp)
decl %r14d
movslq %r14d, %rsi
cmpq %rsi, %rdx
jbe 0x41215
leaq (%rdi,%r8,8), %rdx
leaq (%rsi,%rsi,2), %r8
movq 0x10(%rdi,%r8,8), %r9
movq %r9, 0x10(%rdx)
movupd (%rdi,%r8,8), %xmm0
movupd %xmm0, (%rdx)
movq 0x20(%rsp), %rdi
movq 0x28(%rsp), %rdx
subq %rdi, %rdx
sarq $0x3, %rdx
movabsq $-0x5555555555555555, %r9 # imm = 0xAAAAAAAAAAAAAAAB
imulq %r9, %rdx
cmpq %rsi, %rdx
jbe 0x41215
movq 0x160(%rsp), %rdx
movq %rdx, 0x10(%rdi,%r8,8)
movapd 0x150(%rsp), %xmm0
movupd %xmm0, (%rdi,%r8,8)
addq $-0x18, 0x28(%rsp)
decl %ecx
decq %rax
cmpl $0x1, %ecx
jg 0x40f37
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x40a97
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
jmp 0x40a97
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x41070
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
incq %rbp
cmpq 0xa8(%rsp), %rbp
jne 0x4084b
movq 0x58(%rsp), %rbx
subq 0x50(%rsp), %rbx
shrq $0x5, %rbx
movq 0x130(%rsp), %rdi
movl %ebx, %esi
callq 0x4750
leaq 0x114489(%rip), %rsi    # 0x15552e
movl $0x1, %edx
movq %rax, %rdi
callq 0x44e0
testl %ebx, %ebx
jle 0x411a7
andl $0x7fffffff, %ebx       # imm = 0x7FFFFFFF
movl $0x18, %ebp
xorl %r14d, %r14d
leaq 0x1163b7(%rip), %r15    # 0x157486
leaq 0x114458(%rip), %r12    # 0x15552e
movq 0x50(%rsp), %rax
movq 0x58(%rsp), %rdx
subq %rax, %rdx
sarq $0x5, %rdx
cmpq %r14, %rdx
jbe 0x412bb
movsd -0x18(%rax,%rbp), %xmm0
movsd -0x10(%rax,%rbp), %xmm1
movsd %xmm1, 0x40(%rsp)
movsd -0x8(%rax,%rbp), %xmm1
movsd %xmm1, (%rsp)
movsd (%rax,%rbp), %xmm1
movsd %xmm1, 0x18(%rsp)
movq 0x130(%rsp), %rdi
callq 0x46b0
movq %rax, %r13
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x44e0
movq %r13, %rdi
movsd 0x40(%rsp), %xmm0
callq 0x46b0
movq %rax, %r13
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x44e0
movq %r13, %rdi
movsd (%rsp), %xmm0
callq 0x46b0
movq %rax, %r13
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x44e0
movq %r13, %rdi
movsd 0x18(%rsp), %xmm0
callq 0x46b0
movl $0x1, %edx
movq %rax, %rdi
movq %r12, %rsi
callq 0x44e0
incq %r14
addq $0x20, %rbp
cmpq %r14, %rbx
jne 0x410d6
movq 0xf8(%rsp), %rdi
testq %rdi, %rdi
je 0x411ec
movq 0x118(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
xorl %eax, %eax
movq %rax, 0xf8(%rsp)
movl %eax, 0x100(%rsp)
movq %rax, 0x108(%rsp)
movl %eax, 0x110(%rsp)
movq %rax, 0x118(%rsp)
movq 0x50(%rsp), %rdi
testq %rdi, %rdi
je 0x41203
movq 0x60(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
addq $0x198, %rsp            # imm = 0x198
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x10e489(%rip), %rdi    # 0x14f6a5
xorl %eax, %eax
callq 0x4630
leaq 0x10e47b(%rip), %rdi    # 0x14f6a5
movq %rbp, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10e46a(%rip), %rdi    # 0x14f6a5
xorl %eax, %eax
callq 0x4630
leaq 0x10e45c(%rip), %rdi    # 0x14f6a5
movq %rbp, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10e44b(%rip), %rdi    # 0x14f6a5
movq %r14, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10e43a(%rip), %rdi    # 0x14f6a5
xorl %eax, %eax
callq 0x4630
leaq 0x10e42c(%rip), %rdi    # 0x14f6a5
xorl %eax, %eax
callq 0x4630
leaq 0x10e41e(%rip), %rdi    # 0x14f6a5
xorl %eax, %eax
callq 0x4630
leaq 0x10e410(%rip), %rdi    # 0x14f6a5
xorl %eax, %eax
callq 0x4630
leaq 0x10e402(%rip), %rdi    # 0x14f6a5
xorl %eax, %eax
callq 0x4630
leaq 0x10e3f4(%rip), %rdi    # 0x14f6a5
movq %rbx, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10e3e3(%rip), %rdi    # 0x14f6a5
movq %r14, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10e3d2(%rip), %rdi    # 0x14f6a5
movq %rbx, %rsi
xorl %eax, %eax
callq 0x4630
jmp 0x412f9
jmp 0x412f9
jmp 0x412f9
jmp 0x412f9
jmp 0x412f9
jmp 0x412f9
jmp 0x412eb
movq %rax, %rbx
jmp 0x41395
jmp 0x41314
jmp 0x412f9
jmp 0x41314
movq %rax, %rbx
jmp 0x41350
jmp 0x41314
jmp 0x41314
jmp 0x41314
jmp 0x41314
jmp 0x41319
jmp 0x41314
jmp 0x41314
jmp 0x41319
jmp 0x41319
jmp 0x41314
jmp 0x41319
movq %rax, %rbx
jmp 0x41339
movq %rax, %rbx
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x41339
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x41350
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
movq 0xf8(%rsp), %rdi
testq %rdi, %rdi
je 0x41395
movq 0x118(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
xorl %eax, %eax
movq %rax, 0xf8(%rsp)
movl %eax, 0x100(%rsp)
movq %rax, 0x108(%rsp)
movl %eax, 0x110(%rsp)
movq %rax, 0x118(%rsp)
movq 0x50(%rsp), %rdi
testq %rdi, %rdi
je 0x413ac
movq 0x60(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
movq %rbx, %rdi
callq 0x4780