// File: /workspace/github_cpp_makefile_star2_O3/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, %r14
movq %rsi, 0x108(%rsp)
movq %rdi, %r13
xorpd %xmm0, %xmm0
movapd %xmm0, 0x50(%rsp)
movq $0x0, 0x60(%rsp)
movq 0x8(%rdx), %rdi
movq %rdx, 0x150(%rsp)
subq (%rdx), %rdi
sarq $0x3, %rdi
movabsq $-0x5555555555555555, %rax # imm = 0xAAAAAAAAAAAAAAAB
imulq %rax, %rdi
movq 0x8(%r8), %r15
movq %r8, 0x140(%rsp)
subq (%r8), %r15
movl %edi, 0xcc(%rsp)
testl %edi, %edi
jle 0x401e3
movq (%rcx), %rax
movq 0x8(%rcx), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
leal -0x1(%rdi), %ecx
cmpq %rcx, %rdx
jbe 0x40d90
movl %edi, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
xorl %edx, %edx
xorl %r8d, %r8d
movl (%rax,%rdx,4), %esi
cmpl %r8d, %esi
cmovgl %esi, %r8d
incq %rdx
cmpq %rdx, %rcx
jne 0x401cf
jmp 0x401e6
xorl %r8d, %r8d
sarq $0x3, %r15
movabsq $-0x5555555555555555, %rax # imm = 0xAAAAAAAAAAAAAAAB
imulq %rax, %r15
testl %r15d, %r15d
movq %rdi, 0x118(%rsp)
jle 0x40239
movq (%r14), %rax
movq 0x8(%r14), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
movl %r15d, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
xorl %esi, %esi
cmpq %rsi, %rdx
je 0x40d4c
movl (%rax,%rsi,4), %edi
cmpl %r8d, %edi
cmovgl %edi, %r8d
incq %rsi
cmpq %rsi, %rcx
jne 0x4021e
xorl %eax, %eax
leaq 0x158(%rsp), %rbx
movq %rax, (%rbx)
movl %eax, 0x8(%rbx)
movq %rax, 0x10(%rbx)
movl %eax, 0x18(%rbx)
movq %rax, 0x20(%rbx)
movq %r8, 0xa8(%rsp)
leal 0x1(%r8), %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0xea58
decl %ebp
jne 0x40260
movq %r14, 0x78(%rsp)
movq %r15, 0xa0(%rsp)
testl %r15d, %r15d
jle 0x402f9
movq 0xa0(%rsp), %r15
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
xorl %ebx, %ebx
leaq 0x158(%rsp), %r14
movq 0x78(%rsp), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
cmpq %rbx, %rdx
jbe 0x40d5d
movslq (%rax,%rbx,4), %rsi
movq %r14, %rdi
callq 0xee36
testq %rdx, (%rax)
jne 0x402f1
movq 0x78(%rsp), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
cmpq %rbx, %rdx
jbe 0x40d7f
movslq (%rax,%rbx,4), %rsi
movq %r14, %rdi
callq 0xee36
orq %rdx, (%rax)
incq %rbx
cmpq %rbx, %r15
jne 0x40299
movsd 0x10cd67(%rip), %xmm0   # 0x14d068
addsd 0xb0(%rsp), %xmm0
movsd %xmm0, 0x110(%rsp)
movq 0xa8(%rsp), %rax
incl %eax
movq %rax, 0xa8(%rsp)
movl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movq 0xa0(%rsp), %rcx
andq %rax, %rcx
movq %rcx, 0x148(%rsp)
andq %rax, 0x118(%rsp)
xorl %ebp, %ebp
leaq 0xd0(%rsp), %rbx
leaq 0x180(%rsp), %r15
xorpd %xmm0, %xmm0
movapd %xmm0, 0x20(%rsp)
movq $0x0, 0x30(%rsp)
leaq 0x158(%rsp), %rdi
movq %rbp, %rsi
callq 0xee36
testq %rdx, (%rax)
je 0x40b3f
cmpl $0x0, 0xa0(%rsp)
movq 0x78(%rsp), %r14
movq %rbp, 0xb8(%rsp)
jle 0x4056e
xorl %esi, %esi
movq (%r14), %rax
movq 0x8(%r14), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
cmpq %rsi, %rdx
jbe 0x40d22
movl (%rax,%rsi,4), %eax
cmpq %rax, %rbp
jne 0x4055d
movq 0x140(%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 0x40d3e
movq %rsi, 0xf0(%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 0x4051b
andl $0x7fffffff, %r12d      # imm = 0x7FFFFFFF
movl $0x18, %ebp
xorl %r14d, %r14d
movq 0x50(%rsp), %rax
movq 0x58(%rsp), %rdx
subq %rax, %rdx
sarq $0x5, %rdx
cmpq %r14, %rdx
jbe 0x40d11
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 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0xc0(%rsp)
movq %rbx, %rdi
movl $0x2, %esi
callq 0x83f9a
movsd (%rax), %xmm2
movq %r13, %rdi
movsd 0x68(%rsp), %xmm0
movsd 0xc0(%rsp), %xmm1
movsd 0x40(%rsp), %xmm3
movsd (%rsp), %xmm4
movsd 0x18(%rsp), %xmm5
callq 0x5339c
incq %r14
cmpq %r12, %r14
movsd 0x70(%rsp), %xmm1
jae 0x40508
addq $0x20, %rbp
ucomisd %xmm0, %xmm1
jbe 0x4043d
ucomisd %xmm0, %xmm1
movq 0x78(%rsp), %r14
movq 0xb8(%rsp), %rbp
ja 0x40555
movq 0x28(%rsp), %rsi
cmpq 0x30(%rsp), %rsi
je 0x40548
movq 0xe0(%rsp), %rax
movq %rax, 0x10(%rsi)
movapd 0xd0(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0x28(%rsp)
jmp 0x40555
leaq 0x20(%rsp), %rdi
movq %rbx, %rdx
callq 0x2fec4
movq 0xf0(%rsp), %rsi
incq %rsi
cmpq 0x148(%rsp), %rsi
jne 0x403a0
movq 0x28(%rsp), %rax
subq 0x20(%rsp), %rax
shrq $0x3, %rax
imull $0xaaaaaaab, %eax, %r14d # imm = 0xAAAAAAAB
testl %r14d, %r14d
jle 0x40b3f
movq %r13, %rdi
leaq 0x20(%rsp), %rsi
callq 0x4811c
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 0x40d30
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 0x110d75(%rip), %xmm3   # 0x151360
cmpl $0x0, 0xcc(%rsp)
jle 0x40739
xorl %r12d, %r12d
xorl %ebp, %ebp
movsd 0x110d5a(%rip), %xmm3   # 0x151360
movq 0x150(%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 0x40d00
movapd %xmm3, 0xf0(%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 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0x40(%rsp)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, (%rsp)
movq %rbx, %rdi
movl $0x2, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
movq %r15, %rdi
xorl %esi, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0x70(%rsp)
movq %r15, %rdi
movl $0x1, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movq %r15, %rdi
movl $0x2, %esi
callq 0x83f9a
movsd (%rax), %xmm5
movq %r13, %rdi
movsd 0x40(%rsp), %xmm0
movsd (%rsp), %xmm1
movsd 0x18(%rsp), %xmm2
movsd 0x70(%rsp), %xmm3
movsd 0x68(%rsp), %xmm4
callq 0x5339c
movapd %xmm0, %xmm1
movapd 0xf0(%rsp), %xmm3
minsd %xmm3, %xmm1
cmpltsd 0x110c3c(%rip), %xmm3   # 0x151350
movapd %xmm3, %xmm2
andnpd %xmm1, %xmm2
andpd %xmm0, %xmm3
orpd %xmm2, %xmm3
incq %rbp
addq $0x18, %r12
cmpq %rbp, 0x118(%rsp)
jne 0x40606
movapd %xmm3, 0xf0(%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 0x40ce1
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 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0x40(%rsp)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
movq %rbx, %rdi
movl $0x2, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0x70(%rsp)
movq %r15, %rdi
xorl %esi, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movq %r15, %rdi
movl $0x1, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0xc0(%rsp)
movq %r15, %rdi
movl $0x2, %esi
callq 0x83f9a
movsd (%rax), %xmm5
movq %r13, %rdi
movsd 0x40(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
movsd 0x70(%rsp), %xmm2
movsd 0x68(%rsp), %xmm3
movsd 0xc0(%rsp), %xmm4
callq 0x5339c
movapd %xmm0, 0x40(%rsp)
movapd 0x40(%rsp), %xmm0
movsd %xmm0, 0x120(%rsp)
movq 0x88(%rsp), %rsi
cmpq 0x90(%rsp), %rsi
je 0x408a8
movapd 0x40(%rsp), %xmm0
movsd %xmm0, (%rsi)
addq $0x8, %rsi
movq %rsi, 0x88(%rsp)
jmp 0x408bd
leaq 0x80(%rsp), %rdi
leaq 0x120(%rsp), %rdx
callq 0x1481e
movapd 0x40(%rsp), %xmm3
movapd %xmm3, %xmm0
movapd (%rsp), %xmm2
maxsd %xmm2, %xmm0
cmpltsd 0x110a77(%rip), %xmm2   # 0x151350
movapd %xmm2, %xmm1
andnpd %xmm0, %xmm1
andpd %xmm3, %xmm2
orpd %xmm1, %xmm2
movapd %xmm2, (%rsp)
incq %rbp
cmpq %r12, %rbp
jne 0x40771
xorpd %xmm0, %xmm0
movapd 0xf0(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x40932
movapd (%rsp), %xmm0
addsd 0xb0(%rsp), %xmm0
addsd 0x10c745(%rip), %xmm0   # 0x14d068
movapd %xmm0, (%rsp)
movq 0xb8(%rsp), %rbp
jmp 0x4097b
movapd (%rsp), %xmm0
ucomisd %xmm0, %xmm1
movq 0xb8(%rsp), %rbp
jbe 0x40965
addsd 0xb0(%rsp), %xmm0
addsd 0x10c712(%rip), %xmm0   # 0x14d068
subsd 0x110(%rsp), %xmm1
minsd %xmm0, %xmm1
jmp 0x40976
subsd 0x110(%rsp), %xmm1
maxsd 0x10c6f2(%rip), %xmm1   # 0x14d068
movapd %xmm1, (%rsp)
movq %r15, %rdi
xorl %esi, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0xd0(%rsp)
movq %r15, %rdi
movl $0x1, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0xd8(%rsp)
movq %r15, %rdi
movl $0x2, %esi
callq 0x83f9a
movsd (%rax), %xmm0
movsd %xmm0, 0xe0(%rsp)
movapd (%rsp), %xmm0
movsd %xmm0, 0xe8(%rsp)
movq 0x58(%rsp), %rsi
cmpq 0x60(%rsp), %rsi
je 0x40a06
movupd 0xd0(%rsp), %xmm0
movupd 0xe0(%rsp), %xmm1
movupd %xmm1, 0x10(%rsi)
movupd %xmm0, (%rsi)
addq $0x20, %rsi
movq %rsi, 0x58(%rsp)
jmp 0x40a13
leaq 0x50(%rsp), %rdi
movq %rbx, %rdx
callq 0x499ba
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 0x40cf2
movapd (%rsp), %xmm0
ucomisd (%rdi,%rsi,8), %xmm0
jbe 0x40b0b
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 0x40cd3
leaq (%rsi,%rsi,2), %r8
movq 0x10(%rdi,%r8,8), %rsi
movq %rsi, 0x130(%rsp)
movupd (%rdi,%r8,8), %xmm0
movapd %xmm0, 0x120(%rsp)
decl %r14d
movslq %r14d, %rsi
cmpq %rsi, %rdx
jbe 0x40cd3
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 0x40cd3
movq 0x130(%rsp), %rdx
movq %rdx, 0x10(%rdi,%r8,8)
movapd 0x120(%rsp), %xmm0
movupd %xmm0, (%rdi,%r8,8)
addq $-0x18, 0x28(%rsp)
decl %ecx
decq %rax
cmpl $0x1, %ecx
jg 0x40a1d
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x40583
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
jmp 0x40583
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x40b56
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
incq %rbp
cmpq 0xa8(%rsp), %rbp
jne 0x40357
movq 0x58(%rsp), %rbx
subq 0x50(%rsp), %rbx
shrq $0x5, %rbx
movq 0x108(%rsp), %rdi
movl %ebx, %esi
callq 0x4750
leaq 0x112a93(%rip), %rsi    # 0x15361e
movl $0x1, %edx
movq %rax, %rdi
callq 0x44e0
testl %ebx, %ebx
jle 0x40c8d
andl $0x7fffffff, %ebx       # imm = 0x7FFFFFFF
movl $0x18, %ebp
xorl %r14d, %r14d
leaq 0x114a21(%rip), %r15    # 0x1555d6
leaq 0x112a62(%rip), %r12    # 0x15361e
movq 0x50(%rsp), %rax
movq 0x58(%rsp), %rdx
subq %rax, %rdx
sarq $0x5, %rdx
cmpq %r14, %rdx
jbe 0x40d6e
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 0x108(%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 0x40bbc
movq 0x158(%rsp), %rdi
testq %rdi, %rdi
je 0x40caa
movq 0x178(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
movq 0x50(%rsp), %rdi
testq %rdi, %rdi
je 0x40cc1
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 0x10ca1b(%rip), %rdi    # 0x14d6f5
xorl %eax, %eax
callq 0x4630
leaq 0x10ca0d(%rip), %rdi    # 0x14d6f5
movq %rbp, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10c9fc(%rip), %rdi    # 0x14d6f5
xorl %eax, %eax
callq 0x4630
leaq 0x10c9ee(%rip), %rdi    # 0x14d6f5
movq %rbp, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10c9dd(%rip), %rdi    # 0x14d6f5
movq %r14, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10c9cc(%rip), %rdi    # 0x14d6f5
xorl %eax, %eax
callq 0x4630
leaq 0x10c9be(%rip), %rdi    # 0x14d6f5
xorl %eax, %eax
callq 0x4630
leaq 0x10c9b0(%rip), %rdi    # 0x14d6f5
xorl %eax, %eax
callq 0x4630
leaq 0x10c9a2(%rip), %rdi    # 0x14d6f5
movq %rdx, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10c991(%rip), %rdi    # 0x14d6f5
movq %rbx, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10c980(%rip), %rdi    # 0x14d6f5
movq %r14, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10c96f(%rip), %rdi    # 0x14d6f5
movq %rbx, %rsi
xorl %eax, %eax
callq 0x4630
leaq 0x10c95e(%rip), %rdi    # 0x14d6f5
movq %rdx, %rsi
xorl %eax, %eax
callq 0x4630
jmp 0x40daf
jmp 0x40dbd
jmp 0x40dbd
jmp 0x40dbd
jmp 0x40dbd
jmp 0x40dbd
jmp 0x40dbd
movq %rax, %rbx
jmp 0x40e4e
jmp 0x40dd8
jmp 0x40dbd
jmp 0x40dd8
movq %rax, %rbx
jmp 0x40e14
jmp 0x40dd8
jmp 0x40dd8
jmp 0x40dd8
jmp 0x40dd8
jmp 0x40ddd
jmp 0x40dd8
jmp 0x40dd8
jmp 0x40ddd
jmp 0x40ddd
jmp 0x40dd8
jmp 0x40ddd
movq %rax, %rbx
jmp 0x40dfd
movq %rax, %rbx
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x40dfd
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x40e14
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
movq 0x158(%rsp), %rdi
testq %rdi, %rdi
je 0x40e4e
movq 0x178(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
xorl %eax, %eax
movq %rax, 0x158(%rsp)
movl $0x0, 0x160(%rsp)
movq %rax, 0x168(%rsp)
movq 0x50(%rsp), %rdi
testq %rdi, %rdi
je 0x40e65
movq 0x60(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
movq %rbx, %rdi
callq 0x4780