// File: Luthaf[P]zeopp/network.cc
// Function: performVoronoiDecomp(bool, ATOM_NETWORK*, VORONOI_NETWORK*, std::vector<VOR_CELL, std::allocator<VOR_CELL>>&, bool, std::vector<BASIC_VCELL, std::allocator<BASIC_VCELL>>&)
void* performVoronoiDecomp(bool radial, ATOM_NETWORK *cell, VORONOI_NETWORK *vornet, vector<VOR_CELL> &cells, bool saveVorCells,
			   vector<BASIC_VCELL> &bvcells){
  int i,n;
  double bx,bxy,by,bxz,byz,bz;
  vector<int> atomShifts;
  
  // Set the box dimensions and number of particles
  bx  = cell->v_a.x;
  bxy = cell->v_b.x;
  by  = cell->v_b.y;
  bxz = cell->v_c.x;
  byz = cell->v_c.y;
  bz  = cell->v_c.z;
  n   = cell->numAtoms;
  
  // Print the box dimensions
  printf("Box dimensions:\n"
	 "  va=(%f 0 0)\n"
	 "  vb=(%f %f 0)\n"
	 "  vc=(%f %f %f)\n\n",bx,bxy,by,bxz,byz,bz);
  
  // Check that the input parameters make sense
  if(n<1) {
    char* sentence = new char[300];
    sprintf(sentence, "Error: Invalid number of particles provided for Voronoi decomposition (%d particles were read from file, which is <1)\nExiting ...\n", n);
    fputs(sentence, stderr);
    exit(1);
  }
  if(bx<tolerance||by<tolerance||bz<tolerance){
    fputs("Error: Invalid box dimensions calculated for Voronoi decomposition."
	  " Please check unit cell parameters.\nExiting ...\n",stderr);
    exit(1);
  }
  
  // Compute the internal grid size, aiming to make
  // the grid blocks square with around 6 particles
  // in each
  double ls=pow(n/(9*bx*by*bz),1.0/3.0);
  double nxf=bx*ls+1.1;
  double nyf=by*ls+1.1;
  double nzf=bz*ls+1.1;
  
  // Check the grid is not too huge, using floating point numbers to avoid
  // integer wrap-arounds
  if (nxf*nyf*nzf>max_regions) {
    fprintf(stderr,"voro++: Number of computational blocks exceeds the maximum allowed of %d\n"
		   "Either increase the particle length scale, or recompile with an increased\nmaximum.",max_regions);
    exit(1);
  }
  
  // Now that we are confident that the number of regions is reasonable,
  // create integer versions of them
  int nx=int(nxf);
  int ny=int(nyf);
  int nz=int(nzf);
  printf("Total particles = %d\n\nInternal grid size = (%d %d %d)\n\n",n,nx,ny,nz);

  //a temporary fix to the Voronoi volume check issue:
  //if the user allows, when the volume check fails the structure's atom coordinates can be randomly altered by a very small amount, to try and bypass the error
  int numAttemptsPermitted = 1;
  if(cell->allowAdjustCoordsAndCellFlag) numAttemptsPermitted++;
  for(int attempt=0; attempt<numAttemptsPermitted; attempt++) {
    
    if(radial) {
      puts("Using voro++ with radii for particles.");
      // Create a container with the geometry given above
      container_periodic_poly *rad_con;
      rad_con =  new container_periodic_poly (bx,bxy,by,bxz,byz,bz,nx,ny,nz,memory);
      
      // Read in the particles from the provided ATOM_NETWORK
      vector <ATOM> ::iterator iter = cell->atoms.begin();
      i = 0;
      int da, db, dc;
      while(iter != cell->atoms.end()){ 
        rad_con->put(i,iter->x,iter->y,iter->z,iter->radius, da, db, dc);
        atomShifts.push_back(da); atomShifts.push_back(db); atomShifts.push_back(dc);
        iter++;
        i++;
      }

      // Store the Voronoi Network for later use
      bool volume_correct = storeVoronoiNetwork(*rad_con, cell, vornet, bx, by, bz, bvcells, atomShifts, saveVorCells, cells);
      if(volume_correct) {
        vornet->v_a = cell->v_a;
        vornet->v_b = cell->v_b;
        vornet->v_c = cell->v_c;
        return rad_con;
      } else if(attempt==numAttemptsPermitted-1) {
        printf("Exiting...\n");
        exit(1);
      } else {
        cell->randomlyAdjustCoordsAndCell();
      }
    }
    else {
      puts("Using voro++ without radii for particles.");
      // Create a container with the geometry given above
      container_periodic *no_rad_con;
      no_rad_con = new container_periodic(bx,bxy,by,bxz,byz,bz,nx,ny,nz,memory);

      // Read in the particles from the provided ATOM_NETWORK
      vector <ATOM> ::iterator iter = cell->atoms.begin();
      i = 0;
      int da, db, dc;
      while(iter != cell->atoms.end()){
        no_rad_con->put(i,iter->x,iter->y,iter->z, da, db, dc);
        atomShifts.push_back(da); atomShifts.push_back(db); atomShifts.push_back(dc);
        iter++;
        i++;
      }

      // Store the Voronoi Network for later use
      bool volume_correct = storeVoronoiNetwork(*no_rad_con, cell, vornet, bx, by, bz, bvcells, atomShifts, saveVorCells, cells);
      if(volume_correct) {
        vornet->v_a = cell->v_a;
        vornet->v_b = cell->v_b;
        vornet->v_c = cell->v_c;
        return no_rad_con;
      } else if(attempt==numAttemptsPermitted-1) {
        printf("Exiting...\n");
        exit(1);
      } else {
        cell->randomlyAdjustCoordsAndCell();
      }
    }
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1d0, %rsp            # imm = 0x1D0
movb %r8b, %al
andb $0x1, %dil
movb %dil, -0x9(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
andb $0x1, %al
movb %al, -0x29(%rbp)
movq %r9, -0x38(%rbp)
leaq -0x88(%rbp), %rdi
callq 0xd0d0
movq -0x18(%rbp), %rax
movsd 0x38(%rax), %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x18(%rbp), %rax
movsd 0x50(%rax), %xmm0
movsd %xmm0, -0x50(%rbp)
movq -0x18(%rbp), %rax
movsd 0x58(%rax), %xmm0
movsd %xmm0, -0x58(%rbp)
movq -0x18(%rbp), %rax
movsd 0x68(%rax), %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x18(%rbp), %rax
movsd 0x70(%rax), %xmm0
movsd %xmm0, -0x68(%rbp)
movq -0x18(%rbp), %rax
movsd 0x78(%rax), %xmm0
movsd %xmm0, -0x70(%rbp)
movq -0x18(%rbp), %rax
movl 0x110(%rax), %eax
movl %eax, -0x40(%rbp)
movsd -0x48(%rbp), %xmm0
movsd -0x50(%rbp), %xmm1
movsd -0x58(%rbp), %xmm2
movsd -0x60(%rbp), %xmm3
movsd -0x68(%rbp), %xmm4
movsd -0x70(%rbp), %xmm5
leaq 0x1eb69c(%rip), %rdi    # 0x1f20a9
movb $0x6, %al
callq 0x5070
jmp 0x6a16
cmpl $0x1, -0x40(%rbp)
jge 0x6a8e
movl $0x12c, %edi            # imm = 0x12C
callq 0x5030
movq %rax, -0x150(%rbp)
jmp 0x6a2f
movq -0x150(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rdi
movl -0x40(%rbp), %edx
leaq 0x1eb69a(%rip), %rsi    # 0x1f20e8
xorl %eax, %eax
callq 0x5100
movq -0xa0(%rbp), %rdi
movq 0x26c56d(%rip), %rax    # 0x272fd0
movq (%rax), %rsi
callq 0x5610
jmp 0x6a6d
movl $0x1, %edi
callq 0x67c0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x72b4
movsd 0x1eb572(%rip), %xmm0   # 0x1f2008
ucomisd -0x48(%rbp), %xmm0
ja 0x6abb
movsd 0x1eb563(%rip), %xmm0   # 0x1f2008
ucomisd -0x58(%rbp), %xmm0
ja 0x6abb
movsd 0x1eb554(%rip), %xmm0   # 0x1f2008
ucomisd -0x70(%rbp), %xmm0
jbe 0x6add
movq 0x26c50e(%rip), %rax    # 0x272fd0
movq (%rax), %rsi
leaq 0x1eb69f(%rip), %rdi    # 0x1f216b
callq 0x5610
jmp 0x6ad3
movl $0x1, %edi
callq 0x67c0
cvtsi2sdl -0x40(%rbp), %xmm0
movsd 0x1eb53e(%rip), %xmm1   # 0x1f2028
mulsd -0x48(%rbp), %xmm1
mulsd -0x58(%rbp), %xmm1
mulsd -0x70(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd 0x1eb51b(%rip), %xmm1   # 0x1f2020
callq 0x58e0
movsd %xmm0, -0xa8(%rbp)
movsd -0x48(%rbp), %xmm0
movsd -0xa8(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd 0x1eb4ed(%rip), %xmm1   # 0x1f2018
addsd %xmm1, %xmm0
movsd %xmm0, -0xb0(%rbp)
movsd -0x58(%rbp), %xmm0
movsd -0xa8(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd 0x1eb4c8(%rip), %xmm1   # 0x1f2018
addsd %xmm1, %xmm0
movsd %xmm0, -0xb8(%rbp)
movsd -0x70(%rbp), %xmm0
movsd -0xa8(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd 0x1eb4a3(%rip), %xmm1   # 0x1f2018
addsd %xmm1, %xmm0
movsd %xmm0, -0xc0(%rbp)
movsd -0xb0(%rbp), %xmm0
mulsd -0xb8(%rbp), %xmm0
mulsd -0xc0(%rbp), %xmm0
movsd 0x1eb46f(%rip), %xmm1   # 0x1f2010
ucomisd %xmm1, %xmm0
jbe 0x6bce
movq 0x26c422(%rip), %rax    # 0x272fd0
movq (%rax), %rdi
leaq 0x1eb627(%rip), %rsi    # 0x1f21df
movl $0x1000000, %edx        # imm = 0x1000000
movb $0x0, %al
callq 0x5750
movl $0x1, %edi
callq 0x67c0
cvttsd2si -0xb0(%rbp), %eax
movl %eax, -0xc4(%rbp)
cvttsd2si -0xb8(%rbp), %eax
movl %eax, -0xc8(%rbp)
cvttsd2si -0xc0(%rbp), %eax
movl %eax, -0xcc(%rbp)
movl -0x40(%rbp), %esi
movl -0xc4(%rbp), %edx
movl -0xc8(%rbp), %ecx
movl -0xcc(%rbp), %r8d
leaq 0x1eb666(%rip), %rdi    # 0x1f227b
xorl %eax, %eax
callq 0x5070
jmp 0x6c1e
movl $0x1, -0xd0(%rbp)
movq -0x18(%rbp), %rax
testb $0x1, (%rax)
je 0x6c40
movl -0xd0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd0(%rbp)
movl $0x0, -0xd4(%rbp)
movl -0xd4(%rbp), %eax
cmpl -0xd0(%rbp), %eax
jge 0x7299
testb $0x1, -0x9(%rbp)
je 0x6f88
leaq 0x1eb646(%rip), %rdi    # 0x1f22b3
callq 0x57c0
jmp 0x6c74
movl $0x298, %edi            # imm = 0x298
callq 0x5560
movq %rax, -0x158(%rbp)
jmp 0x6c87
movq -0x158(%rbp), %rdi
movsd -0x48(%rbp), %xmm0
movsd -0x50(%rbp), %xmm1
movsd -0x58(%rbp), %xmm2
movsd -0x60(%rbp), %xmm3
movsd -0x68(%rbp), %xmm4
movsd -0x70(%rbp), %xmm5
movl -0xc4(%rbp), %esi
movl -0xc8(%rbp), %edx
movl -0xcc(%rbp), %ecx
movl $0x10, %r8d
callq 0x1ec000
jmp 0x6ccb
movq -0x158(%rbp), %rax
movq %rax, -0xe0(%rbp)
movq -0x18(%rbp), %rdi
addq $0x2f0, %rdi            # imm = 0x2F0
callq 0xd0f0
movq %rax, -0xe8(%rbp)
movl $0x0, -0x3c(%rbp)
movq -0x18(%rbp), %rdi
addq $0x2f0, %rdi            # imm = 0x2F0
callq 0xd160
movq %rax, -0x100(%rbp)
leaq -0xe8(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0xd120
testb $0x1, %al
jne 0x6d2a
jmp 0x6e6e
movq -0xe0(%rbp), %rax
movq %rax, -0x180(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, -0x174(%rbp)
leaq -0xe8(%rbp), %rdi
movq %rdi, -0x188(%rbp)
callq 0xd190
movq -0x188(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x170(%rbp)
callq 0xd190
movq -0x188(%rbp), %rdi
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x168(%rbp)
callq 0xd190
movq -0x188(%rbp), %rdi
movsd 0x10(%rax), %xmm0
movsd %xmm0, -0x160(%rbp)
callq 0xd190
movq -0x180(%rbp), %rdi
movl -0x174(%rbp), %esi
movsd -0x170(%rbp), %xmm0
movsd -0x168(%rbp), %xmm1
movsd -0x160(%rbp), %xmm2
movsd 0x30(%rax), %xmm3
leaq -0xec(%rbp), %rdx
leaq -0xf0(%rbp), %rcx
leaq -0xf4(%rbp), %r8
callq 0x1ecc60
jmp 0x6de4
leaq -0x88(%rbp), %rdi
leaq -0xec(%rbp), %rsi
callq 0xd1b0
jmp 0x6df9
leaq -0x88(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0xd1b0
jmp 0x6e0e
leaq -0x88(%rbp), %rdi
leaq -0xf4(%rbp), %rsi
callq 0xd1b0
jmp 0x6e23
leaq -0xe8(%rbp), %rdi
xorl %esi, %esi
callq 0xd220
movq %rax, -0x108(%rbp)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x6cf7
movq -0x158(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
movl $0x298, %esi            # imm = 0x298
callq 0x5570
jmp 0x72b4
movq -0xe0(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movsd -0x48(%rbp), %xmm0
movsd -0x58(%rbp), %xmm1
movsd -0x70(%rbp), %xmm2
movq -0x38(%rbp), %rcx
movq -0x28(%rbp), %r8
movzbl -0x29(%rbp), %r9d
movq %rsp, %rax
movq %r8, (%rax)
andl $0x1, %r9d
leaq -0x88(%rbp), %r8
callq 0xd260
movb %al, -0x189(%rbp)
jmp 0x6eb7
movb -0x189(%rbp), %al
andb $0x1, %al
movb %al, -0x109(%rbp)
testb $0x1, -0x109(%rbp)
je 0x6f47
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq 0x38(%rcx), %rdx
movq %rdx, (%rax)
movq 0x40(%rcx), %rdx
movq %rdx, 0x8(%rax)
movq 0x48(%rcx), %rcx
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq 0x50(%rcx), %rdx
movq %rdx, 0x18(%rax)
movq 0x58(%rcx), %rdx
movq %rdx, 0x20(%rax)
movq 0x60(%rcx), %rcx
movq %rcx, 0x28(%rax)
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq 0x68(%rcx), %rdx
movq %rdx, 0x30(%rax)
movq 0x70(%rcx), %rdx
movq %rdx, 0x38(%rax)
movq 0x78(%rcx), %rcx
movq %rcx, 0x40(%rax)
movq -0xe0(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x110(%rbp)
jmp 0x729b
movl -0xd4(%rbp), %eax
movl -0xd0(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0x6f74
leaq 0x1eb62f(%rip), %rdi    # 0x1f2590
xorl %eax, %eax
callq 0x5070
jmp 0x6f6a
movl $0x1, %edi
callq 0x67c0
movq -0x18(%rbp), %rdi
callq 0x95a90
jmp 0x6f7f
jmp 0x6f81
jmp 0x6f83
jmp 0x7283
leaq 0x1eb34b(%rip), %rdi    # 0x1f22da
callq 0x57c0
jmp 0x6f96
movl $0x270, %edi            # imm = 0x270
callq 0x5560
movq %rax, -0x198(%rbp)
jmp 0x6fa9
movq -0x198(%rbp), %rdi
movsd -0x48(%rbp), %xmm0
movsd -0x50(%rbp), %xmm1
movsd -0x58(%rbp), %xmm2
movsd -0x60(%rbp), %xmm3
movsd -0x68(%rbp), %xmm4
movsd -0x70(%rbp), %xmm5
movl -0xc4(%rbp), %esi
movl -0xc8(%rbp), %edx
movl -0xcc(%rbp), %ecx
movl $0x10, %r8d
callq 0x1ebf20
jmp 0x6fed
movq -0x198(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x18(%rbp), %rdi
addq $0x2f0, %rdi            # imm = 0x2F0
callq 0xd0f0
movq %rax, -0x120(%rbp)
movl $0x0, -0x3c(%rbp)
movq -0x18(%rbp), %rdi
addq $0x2f0, %rdi            # imm = 0x2F0
callq 0xd160
movq %rax, -0x138(%rbp)
leaq -0x120(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0xd120
testb $0x1, %al
jne 0x704c
jmp 0x716f
movq -0x118(%rbp), %rax
movq %rax, -0x1b8(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, -0x1ac(%rbp)
leaq -0x120(%rbp), %rdi
movq %rdi, -0x1c0(%rbp)
callq 0xd190
movq -0x1c0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x1a8(%rbp)
callq 0xd190
movq -0x1c0(%rbp), %rdi
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x1a0(%rbp)
callq 0xd190
movq -0x1b8(%rbp), %rdi
movl -0x1ac(%rbp), %esi
movsd -0x1a8(%rbp), %xmm0
movsd -0x1a0(%rbp), %xmm1
movsd 0x10(%rax), %xmm2
leaq -0x124(%rbp), %rdx
leaq -0x128(%rbp), %rcx
leaq -0x12c(%rbp), %r8
callq 0x1ec740
jmp 0x70e5
leaq -0x88(%rbp), %rdi
leaq -0x124(%rbp), %rsi
callq 0xd1b0
jmp 0x70fa
leaq -0x88(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0xd1b0
jmp 0x710f
leaq -0x88(%rbp), %rdi
leaq -0x12c(%rbp), %rsi
callq 0xd1b0
jmp 0x7124
leaq -0x120(%rbp), %rdi
xorl %esi, %esi
callq 0xd220
movq %rax, -0x140(%rbp)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x7019
movq -0x198(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
movl $0x270, %esi            # imm = 0x270
callq 0x5570
jmp 0x72b4
movq -0x118(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movsd -0x48(%rbp), %xmm0
movsd -0x58(%rbp), %xmm1
movsd -0x70(%rbp), %xmm2
movq -0x38(%rbp), %rcx
movq -0x28(%rbp), %r8
movzbl -0x29(%rbp), %r9d
movq %rsp, %rax
movq %r8, (%rax)
andl $0x1, %r9d
leaq -0x88(%rbp), %r8
callq 0xdf80
movb %al, -0x1c1(%rbp)
jmp 0x71b8
movb -0x1c1(%rbp), %al
andb $0x1, %al
movb %al, -0x141(%rbp)
testb $0x1, -0x141(%rbp)
je 0x7245
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq 0x38(%rcx), %rdx
movq %rdx, (%rax)
movq 0x40(%rcx), %rdx
movq %rdx, 0x8(%rax)
movq 0x48(%rcx), %rcx
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq 0x50(%rcx), %rdx
movq %rdx, 0x18(%rax)
movq 0x58(%rcx), %rdx
movq %rdx, 0x20(%rax)
movq 0x60(%rcx), %rcx
movq %rcx, 0x28(%rax)
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq 0x68(%rcx), %rdx
movq %rdx, 0x30(%rax)
movq 0x70(%rcx), %rdx
movq %rdx, 0x38(%rax)
movq 0x78(%rcx), %rcx
movq %rcx, 0x40(%rax)
movq -0x118(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x110(%rbp)
jmp 0x729b
movl -0xd4(%rbp), %eax
movl -0xd0(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0x7272
leaq 0x1eb331(%rip), %rdi    # 0x1f2590
xorl %eax, %eax
callq 0x5070
jmp 0x7268
movl $0x1, %edi
callq 0x67c0
movq -0x18(%rbp), %rdi
callq 0x95a90
jmp 0x727d
jmp 0x727f
jmp 0x7281
jmp 0x7283
jmp 0x7285
movl -0xd4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
jmp 0x6c4a
ud2
leaq -0x88(%rbp), %rdi
callq 0xec80
movq -0x8(%rbp), %rax
addq $0x1d0, %rsp            # imm = 0x1D0
popq %rbp
retq
leaq -0x88(%rbp), %rdi
callq 0xec80
movq -0x90(%rbp), %rdi
callq 0x58f0
nopl (%rax)