// File: /workspace/github_cpp_makefile_star2_O2/Luthaf[P]zeopp/networkstorage.cc
// Function: place_molecule(std::vector<MOLECULE, std::allocator<MOLECULE>>*, std::vector<CONNECTION, std::allocator<CONNECTION>>*, ATOM_NETWORK*, std::vector<bool, std::allocator<bool>>*, std::vector<bool, std::allocator<bool>>*, std::vector<MOLECULE, std::allocator<MOLECULE>>*, int, double*)
int place_molecule(vector<MOLECULE> *molecules, vector<CONNECTION> *two_way_connections, ATOM_NETWORK *cell, vector<bool> *placed, vector<bool> *connected, vector<MOLECULE> *framework, int num_placed, double *sum_edge_lengths) {
  bool verbose = false;
  //1) if no molecules have been placed yet, just fix the first one in position with its first edge at the origin
  if(num_placed==0) {
if(verbose) printf("DEBUG: detected that no molecules have yet been placed - positioning first molecule with first edge at the origin\n");
    int v_index = two_way_connections->at(0).v1;
    int e_index = two_way_connections->at(0).e1;
    MOLECULE placing = molecules->at(v_index);
    int site_index = placing.permutation.at(e_index);
    int atom_index = placing.sites.at(site_index);
    XYZ site = placing.atoms_xyz.at(atom_index);
    XYZ shift = site.scale(-1);
if(verbose) printf("DEBUG: v=%d, e=%d; site=%.3f %.3f %.3f; shift=%.3f %.3f %.3f\n", v_index, e_index, site.x, site.y, site.z, shift.x, shift.y, shift.z);
    framework->at(v_index) = (translate(placing, shift));
    placed->at(v_index) = true;
    return num_placed+1;
  }
  //2) otherwise, need to find a new molecule to place
if(verbose) printf("DEBUG: detected that %d molecules have already been placed\n", num_placed);
  int num_molecules = molecules->size();
  int num_connections = two_way_connections->size();
  int molecule_index = -1;
  for(int i=0; i<num_molecules && molecule_index==-1; i++) {
    if(!placed->at(i)) { //if this molecule has not yet been placed - it is a candidate for placement, but we must have an adjacent molecule already placed which we can attach it to
      int connection_index = -1;
      for(int j=0; j<num_connections && connection_index==-1; j++) { //is there any two way connection which connects this new molecule and any previously placed one?
        if(!connected->at(j)) { //if this connection was already made, we don't need to check it again
          CONNECTION c = two_way_connections->at(j);
          int placing_edge_index = -1, fixed_edge_index = -1;
          int placing_vertex_index = -1, fixed_vertex_index = -1;
          if(c.v1==i) { //vertex 1 in this connection is the molecule we are placing
            if(placed->at(c.v2)) { //vertex 2 in this connection is a molecule which has already been placed
              placing_edge_index = c.e1;
              fixed_edge_index = c.e2;
              placing_vertex_index = c.v1;
              fixed_vertex_index = c.v2;
            }
          } else if(c.v2==i) { //vertex 2 in this connection is the molecule we are placing
            if(placed->at(c.v1)) { //vertex 1 in this connection is a molecule which has already been placed
              placing_edge_index = c.e2;
              fixed_edge_index = c.e1;
              placing_vertex_index = c.v2;
              fixed_vertex_index = c.v1;
            }
          }
          if(fixed_edge_index!=-1 && placing_edge_index!=-1 && fixed_vertex_index!=-1 && placing_vertex_index!=-1) { //this connection connects this molecule and a fixed molecule, and we have stored the relevant edge and vertex indices - we can proceed to place this molecule!
if(verbose) printf("DEBUG: found that new vertex %d edge %d is connected to fixed vertex %d edge %d\n", placing_vertex_index, placing_edge_index, fixed_vertex_index, fixed_edge_index);
            MOLECULE placing = molecules->at(placing_vertex_index);
            int placing_site_index = placing.permutation.at(placing_edge_index);
            int placing_atom_index = placing.sites.at(placing_site_index);
            MOLECULE fixed = framework->at(fixed_vertex_index);
            int fixed_site_index = fixed.permutation.at(fixed_edge_index);
            int fixed_atom_index = fixed.sites.at(fixed_site_index);
if(verbose) printf("DEBUG: %s in placing connecting to %s in fixed\n", placing.atoms_type.at(placing_atom_index).c_str(), fixed.atoms_type.at(fixed_atom_index).c_str());
            if(placing.atoms_type.at(placing_atom_index)!=fixed.atoms_type.at(fixed_atom_index)) {//only make the connection if the sites are the same type!
if(verbose) printf("DEBUG: trying to connect conflicting connection sites - aborting construction attempt\n");
              return num_placed;
            }
//if(1) exit(1);
            XYZ placing_site = placing.atoms_xyz.at(placing_atom_index);
            XYZ fixed_site = fixed.atoms_xyz.at(fixed_atom_index);
            XYZ shift = fixed_site-placing_site;
if(verbose) printf("DEBUG: site index in fixed = %d, site_index in placing = %d\n", fixed_site_index, placing_site_index);
if(verbose) printf("DEBUG: fixed_site=%.3f %.3f %.3f; placing_site=%.3f %.3f %.3f; shift=%.3f %.3f %.3f\n", fixed_site.x, fixed_site.y, fixed_site.z, placing_site.x, placing_site.y, placing_site.z, shift.x, shift.y, shift.z);
            framework->at(placing_vertex_index) = (translate(placing, shift));
            placed->at(placing_vertex_index) = true; //record this new vertex as now being fixed in place
            connected->at(j) = true; //record that this connection was used
            double com_dist = (fixed.com - framework->at(placing_vertex_index).com).magnitude();
if(verbose) printf("DEBUG: made a connection indicating a topological edge length of %.3f\n", com_dist);
            XYZ start_abc = cell->vertices.at(fixed_vertex_index).abc;
            XYZ end_abc = cell->vertices.at(fixed_vertex_index).edges.at(fixed_edge_index);
if(verbose) printf("\tDEBUG: this edge in the underlying net goes from fractional %.3f %.3f %.3f to fractional %.3f %.3f %.3f\n", start_abc.x, start_abc.y, start_abc.z, end_abc.x, end_abc.y, end_abc.z);
            XYZ shift_abc = end_abc-start_abc;
            XYZ shift_xyz = framework->at(placing_vertex_index).com-fixed.com;
if(verbose) printf("\tDEBUG: this edge in the underlying net had a fractional shift %.3f %.3f %.3f; here we observe a cartesian shift %.3f %.3f %.3f\n", shift_abc.x, shift_abc.y, shift_abc.z, shift_xyz.x, shift_xyz.y, shift_xyz.z);
            XYZ unit_cell_parameter_suggestion(shift_xyz.x/shift_abc.x, shift_xyz.y/shift_abc.y, shift_xyz.z/shift_abc.z);
if(verbose) printf("\tDEBUG: suggests unit cell dimensions %.3f %.3f %.3f\n", unit_cell_parameter_suggestion.x, unit_cell_parameter_suggestion.y, unit_cell_parameter_suggestion.z);
            (*sum_edge_lengths)+=com_dist;
            return num_placed+1;
          }
        }
      }
      if(connection_index==-1) {
if(verbose) printf("DEBUG: could not find any connection between vertex %d and any fixed vertex\n", i);
      }
    }
  }
  printf("WARNING: could not find a molecule which has not been placed and which is adjacent to an already placed molecule - this may happen if the net is interpenetrated (not currently handled with the connection-based alignment method)\n");
  return num_placed;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x478, %rsp            # imm = 0x478
movq %r9, 0x20(%rsp)
movq %r8, 0x40(%rsp)
movq %rcx, 0x28(%rsp)
movq %rsi, %r14
movq %rdi, %r15
movl 0x4b0(%rsp), %ebx
testl %ebx, %ebx
je 0x43a69
movq %rdx, %r8
movq 0x8(%r15), %rax
movq %r15, 0x70(%rsp)
subq (%r15), %rax
movl $0xa8, %ecx
cqto
idivq %rcx
movq %rax, %rdi
movq 0x8(%r14), %rax
subq (%r14), %rax
pushq $0x1c
popq %rcx
cqto
idivq %rcx
xorl %esi, %esi
testl %eax, %eax
cmovlel %esi, %eax
movq %rax, 0x48(%rsp)
testl %edi, %edi
cmovlel %esi, %edi
movq %rdi, 0x78(%rsp)
movq %r8, 0x68(%rsp)
movq %r14, 0x80(%rsp)
cmpq 0x78(%rsp), %rsi
je 0x43dee
movq 0x28(%rsp), %rdi
movq %rsi, 0x38(%rsp)
callq 0xaba4
testq %rdx, (%rax)
je 0x438b5
movq 0x38(%rsp), %rsi
incq %rsi
jmp 0x4388c
xorl %r13d, %r13d
cmpq %r13, 0x48(%rsp)
je 0x438ab
movq 0x40(%rsp), %rdi
movq %r13, %rsi
callq 0xaba4
testq %rdx, (%rax)
jne 0x43992
movq %r14, %rdi
movq %r13, %rsi
callq 0x4b9ca
movl (%rax), %r14d
movl 0x4(%rax), %ebx
movl 0x8(%rax), %ecx
movl %ecx, 0x34(%rsp)
movl 0xc(%rax), %eax
movl %eax, 0x30(%rsp)
movq 0x38(%rsp), %rax
cmpq %r14, %rax
jne 0x4392e
movslq %ebx, %rsi
movq 0x28(%rsp), %rdi
callq 0xaba4
pushq $-0x1
popq %r15
movl %r15d, %r12d
movl %r15d, %ebp
movl %r15d, %ecx
testq %rdx, (%rax)
je 0x4396d
movl 0x34(%rsp), %r12d
movl 0x30(%rsp), %ebp
movl %r14d, %ecx
movl %ebx, %r15d
jmp 0x4396d
pushq $-0x1
popq %r15
movl %r15d, %r12d
movl %r15d, %ebp
movl %r15d, %ecx
cmpq %rbx, %rax
jne 0x4396d
movslq %r14d, %rsi
movq 0x28(%rsp), %rdi
callq 0xaba4
pushq $-0x1
popq %r15
movl %r15d, %r12d
movl %r15d, %ebp
movl %r15d, %ecx
testq %rdx, (%rax)
je 0x4396d
movl 0x30(%rsp), %r12d
movl 0x34(%rsp), %ebp
movl %ebx, %ecx
movl %r14d, %r15d
cmpl $-0x1, %ebp
movl 0x4b0(%rsp), %ebx
movq 0x80(%rsp), %r14
je 0x43992
cmpl $-0x1, %r12d
je 0x43992
cmpl $-0x1, %r15d
je 0x43992
cmpl $-0x1, %ecx
jne 0x4399a
incq %r13
jmp 0x438b8
movslq %ecx, %rsi
movq 0x70(%rsp), %rdi
movq %rsi, 0x48(%rsp)
callq 0x4b9e8
leaq 0xd0(%rsp), %rdi
movq %rax, %rsi
callq 0x4ba0a
leaq 0x148(%rsp), %rdi
movslq %r12d, %rsi
callq 0xac00
movslq (%rax), %rsi
leaq 0x118(%rsp), %rdi
callq 0xac00
movslq (%rax), %r14
movslq %r15d, %rsi
movq 0x20(%rsp), %rdi
movq %rsi, 0x38(%rsp)
callq 0x4b9e8
leaq 0x178(%rsp), %rdi
movq %rax, %rsi
callq 0x4ba0a
leaq 0x1f0(%rsp), %rdi
movslq %ebp, %r15
movq %r15, %rsi
callq 0xac00
movslq (%rax), %rsi
leaq 0x1c0(%rsp), %rdi
callq 0xac00
movslq (%rax), %rbp
leaq 0xe8(%rsp), %rdi
movq %r14, %rsi
callq 0x4bb9a
movq %rax, %rbx
leaq 0x190(%rsp), %rdi
movq %rbp, %rsi
callq 0x4bb9a
movq %rbx, %rdi
movq %rax, %rsi
callq 0x4bbbb
testb %al, %al
je 0x43b8e
movl 0x4b0(%rsp), %ebx
jmp 0x43dd2
movq %r14, %rdi
xorl %esi, %esi
callq 0x4b9ca
movslq (%rax), %rbx
movq %r14, %rdi
xorl %esi, %esi
callq 0x4b9ca
movslq 0x8(%rax), %r14
movq %r15, %rdi
movq %rbx, %rsi
callq 0x4b9e8
leaq 0xd0(%rsp), %rdi
movq %rax, %rsi
callq 0x4ba0a
leaq 0x148(%rsp), %rdi
movq %r14, %rsi
callq 0xac00
movslq (%rax), %rsi
leaq 0x118(%rsp), %rdi
callq 0xac00
movslq (%rax), %rsi
leaq 0xd0(%rsp), %rdi
callq 0x4b6d6
movq 0x10(%rax), %rcx
leaq 0x220(%rsp), %rsi
movq %rcx, 0x10(%rsi)
movups (%rax), %xmm0
movaps %xmm0, (%rsi)
leaq 0x50(%rsp), %rdi
movsd 0xbc7f6(%rip), %xmm0    # 0x1002e8
callq 0x640ba
leaq 0x3d0(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x4ba0a
movq 0x60(%rsp), %rax
movq %rax, 0x10(%rsp)
movups 0x50(%rsp), %xmm0
movups %xmm0, (%rsp)
leaq 0x178(%rsp), %rdi
leaq 0x3d0(%rsp), %rsi
callq 0x76138
movq 0x20(%rsp), %rdi
movq %rbx, %rsi
callq 0x4b9e8
leaq 0x178(%rsp), %r14
movq %rax, %rdi
movq %r14, %rsi
callq 0x4bae8
movq %r14, %rdi
callq 0x4bb60
leaq 0x3d0(%rsp), %rdi
callq 0x4bb60
movq 0x28(%rsp), %rdi
movq %rbx, %rsi
callq 0xaba4
orq %rdx, (%rax)
leaq 0xd0(%rsp), %rdi
callq 0x4bb60
pushq $0x1
popq %rbx
jmp 0x43dfa
leaq 0xd0(%rsp), %rdi
movq %r14, %rsi
callq 0x4b6d6
movq 0x10(%rax), %rcx
movq %rcx, 0x60(%rsp)
movupd (%rax), %xmm0
movapd %xmm0, 0x50(%rsp)
leaq 0x178(%rsp), %rdi
movq %rbp, %rsi
callq 0x4b6d6
movq 0x10(%rax), %rcx
leaq 0x2f0(%rsp), %rsi
movq %rcx, 0x10(%rsi)
movupd (%rax), %xmm0
movapd %xmm0, (%rsi)
leaq 0xb8(%rsp), %rdi
leaq 0x50(%rsp), %rdx
callq 0x642ae
movq 0x48(%rsp), %r12
leaq 0x328(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x4ba0a
movq 0xc8(%rsp), %rax
movq %rax, 0x10(%rsp)
movupd 0xb8(%rsp), %xmm0
movupd %xmm0, (%rsp)
leaq 0x220(%rsp), %rdi
leaq 0x328(%rsp), %rsi
callq 0x76138
movq 0x20(%rsp), %rdi
movq %r12, %rsi
callq 0x4b9e8
leaq 0x220(%rsp), %rbx
movq %rax, %rdi
movq %rbx, %rsi
callq 0x4bae8
movq %rbx, %rdi
callq 0x4bb60
leaq 0x328(%rsp), %rdi
callq 0x4bb60
movq 0x28(%rsp), %rdi
movq %r12, %rsi
callq 0xaba4
movq %r15, %rbp
orq %rdx, (%rax)
movq 0x40(%rsp), %rdi
movq %r13, %rsi
callq 0xaba4
movl 0x4b0(%rsp), %ebx
orq %rdx, (%rax)
movq 0x20(%rsp), %rdi
movq %r12, %rsi
callq 0x4b9e8
movq 0x68(%rsp), %r15
movq 0x38(%rsp), %r13
leaq 0x208(%rsp), %r14
addq $0x90, %rax
leaq 0x220(%rsp), %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x642ae
leaq 0x220(%rsp), %rdi
callq 0x63758
movsd %xmm0, 0x40(%rsp)
addq $0x3c0, %r15            # imm = 0x3C0
movq %r15, %rdi
movq %r13, %rsi
callq 0x4b63c
movq 0x10(%rax), %rcx
movq %rcx, 0x230(%rsp)
movupd (%rax), %xmm0
movapd %xmm0, 0x220(%rsp)
movq %r15, %rdi
movq %r13, %rsi
callq 0x4b63c
addq $0x20, %rax
movq %rax, %rdi
movq %rbp, %rsi
callq 0x4b6d6
movq 0x10(%rax), %rcx
leaq 0x2d0(%rsp), %rsi
movq %rcx, 0x10(%rsi)
movupd (%rax), %xmm0
movapd %xmm0, (%rsi)
leaq 0xa0(%rsp), %rdi
leaq 0x220(%rsp), %rdx
callq 0x642ae
movq 0x20(%rsp), %rdi
movq %r12, %rsi
callq 0x4b9e8
addq $0x90, %rax
leaq 0x88(%rsp), %rdi
movq %rax, %rsi
movq %r14, %rdx
callq 0x642ae
movsd 0x88(%rsp), %xmm0
movsd 0x90(%rsp), %xmm1
divsd 0xa0(%rsp), %xmm0
divsd 0xa8(%rsp), %xmm1
movsd 0x98(%rsp), %xmm2
divsd 0xb0(%rsp), %xmm2
leaq 0x310(%rsp), %rdi
callq 0x6402e
movq 0x4b8(%rsp), %rax
movsd 0x40(%rsp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
incl %ebx
leaq 0x178(%rsp), %rdi
callq 0x4bb60
leaq 0xd0(%rsp), %rdi
callq 0x4bb60
jmp 0x43dfa
leaq 0xbf0c2(%rip), %rdi     # 0x102eb7
callq 0x4670
movl %ebx, %eax
addq $0x478, %rsp            # imm = 0x478
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x43e80
jmp 0x43e80
jmp 0x43e80
jmp 0x43e80
jmp 0x43e80
movq %rax, %rbx
leaq 0x220(%rsp), %rdi
callq 0x4bb60
jmp 0x43e2d
movq %rax, %rbx
leaq 0x328(%rsp), %rdi
callq 0x4bb60
jmp 0x43e83
jmp 0x43e80
jmp 0x43e80
jmp 0x43e80
jmp 0x43e80
jmp 0x43e7b
movq %rax, %rbx
leaq 0x178(%rsp), %rdi
callq 0x4bb60
jmp 0x43e5b
movq %rax, %rbx
leaq 0x3d0(%rsp), %rdi
jmp 0x43e8b
jmp 0x43e7b
jmp 0x43e7b
jmp 0x43e7b
jmp 0x43e7b
jmp 0x43e7b
jmp 0x43e80
jmp 0x43e80
jmp 0x43e80
jmp 0x43e7b
jmp 0x43e7b
jmp 0x43e80
movq %rax, %rbx
jmp 0x43e90
movq %rax, %rbx
leaq 0x178(%rsp), %rdi
callq 0x4bb60
leaq 0xd0(%rsp), %rdi
callq 0x4bb60
movq %rbx, %rdi
callq 0x4780