// File: /workspace/github_cpp_makefile_star2_O2/Luthaf[P]zeopp/networkstorage.cc
// Function: create_unit_cell_from_vectors(std::vector<XYZ, std::allocator<XYZ>>*, ATOM_NETWORK*)
void create_unit_cell_from_vectors(vector<XYZ> *vecs, ATOM_NETWORK *cell) {
  bool verbose = false;
  //DEBUG: complex version - attempts selection of appropriate vectors for each axis
  int num_vecs = vecs->size();
  if(num_vecs!=3) {
    printf("ERROR: create_unit_cell_from_vectors() called with !=3 (%d) vectors\n", num_vecs);
    exit(EXIT_FAILURE);
  }
  vector<int> assignments, scales;
  vector<bool> is_assigned;
  for(int i=0; i<num_vecs; i++) { 
    if(i<2) {
      assignments.push_back(-1);
      scales.push_back(1);
    }
    is_assigned.push_back(false);
  }
  //1) find which vector is closest to the x axis, and which way around it is; repeat for y
  for(int ax=0; ax<2; ax++) {
    XYZ axis(0,0,0);
    if(ax==0) axis.x=1;
    if(ax==1) axis.y=1;
    int index_closest_to_axis = -1;
    int scale = 1;
    double best_angle = -1;
    for(int i=0; i<num_vecs; i++) {
      if(!is_assigned.at(i)) { //candidate
        XYZ cand = vecs->at(i);
        XYZ reverse_cand = cand.scale(-1);
        double angle = axis.angle_between(cand);
        if(angle<best_angle || best_angle<0) {
          best_angle = angle;
          index_closest_to_axis = i;
          scale = 1;
        }
        angle = axis.angle_between(reverse_cand);
        if(angle<best_angle || best_angle<0) {
          best_angle = angle;
          index_closest_to_axis = i;
          scale = -1;
        }
      }
    }
    assignments.at(ax) = index_closest_to_axis;
    scales.at(ax) = scale;
    is_assigned.at(index_closest_to_axis) = true;
    string axis_name("ERROR");
    if(ax==0) axis_name = "x";
    if(ax==1) axis_name = "y";
    if(verbose) {
      if(scale==-1) printf("DEBUG: reversed vector %d is closest to the %s axis\n", index_closest_to_axis, axis_name.c_str());
      else printf("DEBUG: vector %d is closest to the %s axis\n", index_closest_to_axis, axis_name.c_str());
    }
  }
  //2) z axis is different - we know x and y, and want to find z to satisfy the right hand rule!
  XYZ x = vecs->at(assignments.at(0)).scale(scales.at(0));
  XYZ y = vecs->at(assignments.at(1)).scale(scales.at(1));
  XYZ z(0,0,1);
  bool found_z = false;
  for(int i=0; i<num_vecs; i++) {
    if(!is_assigned.at(i)) { //found z
      if(found_z) {
        printf("ERROR: after setting x and y vectors, more than one vector remains to be assigned to z\n");
        exit(EXIT_FAILURE);
      }
      z = vecs->at(i);
      found_z = true;
    }
  }
  XYZ cross = x.cross(y);
  if(verbose) printf("DEBUG: x = %.3f %.3f %.3f, y = %.3f %.3f %.3f, cross = %.3f %.3f %.3f; need to know which orientation of z = %.3f %.3f %.3f satisfies right hand rule\n", x.x, x.y, x.z, y.x, y.y, y.z, cross.x, cross.y, cross.z, z.x, z.y, z.z);
  int z_scale = 1;
  if(cross.angle_between(z)>cross.angle_between(z.scale(-1))) z_scale = -1;
  z = z.scale(z_scale);
  if(verbose) printf("DEBUG: selected z to be %.3f %.3f %.3f\n", z.x, z.y, z.z);
  //3) build the cell
  cell->make(x,y,z);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x168, %rsp            # imm = 0x168
movq %rsi, 0xf8(%rsp)
movq 0x8(%rdi), %rax
movq %rdi, 0x48(%rsp)
subq (%rdi), %rax
pushq $0x18
popq %rcx
cqto
idivq %rcx
cmpl $0x3, %eax
jne 0x44399
leaq 0xe0(%rsp), %rbx
andq $0x0, 0x10(%rbx)
leaq 0xc0(%rsp), %r14
andq $0x0, 0x10(%r14)
leaq 0x118(%rsp), %r15
andq $0x0, (%r15)
andl $0x0, 0x8(%r15)
andq $0x0, 0x10(%r15)
andl $0x0, 0x18(%r15)
xorpd %xmm0, %xmm0
andq $0x0, 0x20(%r15)
movapd %xmm0, (%rbx)
movapd %xmm0, (%r14)
xorl %ebp, %ebp
leaq 0x70(%rsp), %r12
cmpl $0x2, %ebp
je 0x43f56
cmpl $0x3, %ebp
je 0x43f64
orl $-0x1, 0x70(%rsp)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x10324
movl $0x1, 0x70(%rsp)
movq %r14, %rdi
movq %r12, %rsi
callq 0x10324
movq %r15, %rdi
xorl %esi, %esi
callq 0xa8f6
incl %ebp
jmp 0x43f29
xorl %r14d, %r14d
leaq 0xa8(%rsp), %rdi
leaq 0x70(%rsp), %rbx
cmpq $0x2, %r14
je 0x44159
xorpd %xmm0, %xmm0
xorpd %xmm1, %xmm1
xorpd %xmm2, %xmm2
movq %rdi, %rbp
callq 0x6402e
testq %r14, %r14
movq %r14, 0x68(%rsp)
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
je 0x43fb0
movq %rax, 0xb0(%rsp)
jmp 0x43fb8
movq %rax, 0xa8(%rsp)
xorl %r14d, %r14d
pushq $-0x1
popq %r15
pushq $0x1
popq %r12
movsd 0xbc31d(%rip), %xmm0    # 0x1002e8
movapd %xmm0, 0x90(%rsp)
cmpq $0x3, %r14
je 0x440d2
leaq 0x118(%rsp), %rdi
movq %r14, %rsi
callq 0xaba4
testq %rdx, (%rax)
jne 0x440ca
movq 0x48(%rsp), %rdi
movq %r14, %rsi
callq 0x4b6d6
movq 0x10(%rax), %rcx
movq %rcx, 0x80(%rsp)
movups (%rax), %xmm0
movaps %xmm0, 0x70(%rsp)
leaq 0x50(%rsp), %rdi
movq %rbx, %rsi
movsd 0xbc2c0(%rip), %xmm0    # 0x1002e8
callq 0x640ba
movq %rbx, %rsi
movq %rbp, %r13
movq %rbp, %rdi
callq 0x641b2
movapd %xmm0, 0x140(%rsp)
movq %r13, %rdi
leaq 0x50(%rsp), %rsi
callq 0x641b2
movapd 0x140(%rsp), %xmm5
movapd %xmm5, %xmm1
movapd 0x90(%rsp), %xmm4
cmpltpd %xmm4, %xmm1
movapd %xmm4, %xmm2
xorpd %xmm3, %xmm3
cmpltpd %xmm3, %xmm2
orpd %xmm1, %xmm2
movd %xmm2, %eax
testb $0x1, %al
jne 0x44089
movapd %xmm4, %xmm5
pushq $0x1
popq %rax
cmovnel %eax, %r12d
movapd %xmm0, %xmm1
cmpltpd %xmm5, %xmm1
movapd %xmm5, %xmm2
cmpltpd %xmm3, %xmm2
orpd %xmm1, %xmm2
movd %xmm2, %eax
cmovnel %r14d, %r15d
testb $0x1, %al
cmovnel %r14d, %r15d
pushq $-0x1
popq %rax
cmovnel %eax, %r12d
jne 0x440c1
movapd %xmm5, %xmm0
movapd %xmm0, 0x90(%rsp)
incq %r14
jmp 0x43fd4
leaq 0xe0(%rsp), %rdi
movq 0x68(%rsp), %r14
movq %r14, %rsi
callq 0xac00
movl %r15d, (%rax)
leaq 0xc0(%rsp), %rdi
movq %r14, %rsi
callq 0xac00
movl %r12d, (%rax)
movslq %r15d, %rsi
leaq 0x118(%rsp), %rdi
callq 0xaba4
orq %rdx, (%rax)
movq %rbx, %rdi
leaq 0xbe11a(%rip), %rsi     # 0x102234
leaq 0x50(%rsp), %rdx
callq 0x1b80e
movq 0x68(%rsp), %r14
testq %r14, %r14
leaq 0xb8745(%rip), %rsi     # 0xfc878
leaq 0xb8c11(%rip), %rax     # 0xfcd4b
cmoveq %rax, %rsi
movq %rbx, %rdi
callq 0x4810
movq %rbx, %rdi
callq 0x4210
incq %r14
movq %rbp, %rdi
jmp 0x43f74
leaq 0xe0(%rsp), %rdi
xorl %esi, %esi
callq 0xac00
movslq (%rax), %rsi
movq 0x48(%rsp), %rdi
callq 0x4b6d6
movq %rax, %rbx
leaq 0xc0(%rsp), %rdi
xorl %esi, %esi
callq 0xac00
cvtsi2sdl (%rax), %xmm0
leaq 0x70(%rsp), %rdi
movq %rbx, %rsi
callq 0x640ba
leaq 0xe0(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0xac00
movslq (%rax), %rsi
movq 0x48(%rsp), %rdi
callq 0x4b6d6
movq %rax, %rbx
leaq 0xc0(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0xac00
cvtsi2sdl (%rax), %xmm0
leaq 0xa8(%rsp), %rdi
movq %rbx, %rsi
callq 0x640ba
leaq 0x50(%rsp), %rdi
movsd 0xb7e6f(%rip), %xmm2    # 0xfc058
xorpd %xmm0, %xmm0
xorpd %xmm1, %xmm1
callq 0x6402e
xorl %ebx, %ebx
leaq 0x118(%rsp), %r14
xorl %r15d, %r15d
cmpq $0x3, %rbx
je 0x4424b
movq %r14, %rdi
movq %rbx, %rsi
callq 0xaba4
testq %rdx, (%rax)
jne 0x44246
testb $0x1, %r15b
jne 0x44385
movq 0x48(%rsp), %rdi
movq %rbx, %rsi
callq 0x4b6d6
movq 0x10(%rax), %rcx
movq %rcx, 0x60(%rsp)
movupd (%rax), %xmm0
movapd %xmm0, 0x50(%rsp)
movb $0x1, %r15b
incq %rbx
jmp 0x44203
leaq 0x150(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0xa8(%rsp), %rdx
callq 0x64146
leaq 0x150(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x641b2
movsd %xmm0, 0x90(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0x50(%rsp), %rsi
movsd 0xbc053(%rip), %xmm0    # 0x1002e8
callq 0x640ba
leaq 0x150(%rsp), %rdi
leaq 0x100(%rsp), %rsi
callq 0x641b2
xorl %eax, %eax
movsd 0x90(%rsp), %xmm1
ucomisd %xmm0, %xmm1
seta %al
leaq 0xbd488(%rip), %rcx     # 0x101750
movsd (%rcx,%rax,8), %xmm0
leaq 0x100(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x640ba
movq 0x110(%rsp), %rax
movq %rax, 0x60(%rsp)
movups 0x100(%rsp), %xmm0
movaps %xmm0, 0x50(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x40(%rsp)
movaps 0x50(%rsp), %xmm0
movups %xmm0, 0x30(%rsp)
movq 0xb8(%rsp), %rax
movq %rax, 0x28(%rsp)
movups 0xa8(%rsp), %xmm0
movups %xmm0, 0x18(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0x10(%rsp)
movupd 0x70(%rsp), %xmm0
movupd %xmm0, (%rsp)
movq 0xf8(%rsp), %rdi
callq 0x3e74a
leaq 0x118(%rsp), %rdi
callq 0xa976
leaq 0xc0(%rsp), %rdi
callq 0xb290
leaq 0xe0(%rsp), %rdi
callq 0xb290
addq $0x168, %rsp            # imm = 0x168
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xbec0f(%rip), %rdi     # 0x102f9b
callq 0x4670
pushq $0x1
popq %rdi
callq 0x524c
leaq 0xbde4f(%rip), %rdi     # 0x1021ef
movl %eax, %esi
xorl %eax, %eax
callq 0x4050
jmp 0x44391
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x4210
jmp 0x443e3
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
jmp 0x443e0
movq %rax, %rbx
leaq 0x118(%rsp), %rdi
callq 0xa976
leaq 0xc0(%rsp), %rdi
callq 0xb290
leaq 0xe0(%rsp), %rdi
callq 0xb290
movq %rbx, %rdi
callq 0x4780