// File: /workspace/github_c_makefile_star2_O3/josch[P]stride/geometry.c
// Function: Torsion
float Torsion(float *Coord1, float *Coord2, float *Coord3, float *Coord4)
{
  double Comp[3][3], ScalarProd, TripleScalarProd, AbsTorsAng;
  double Perp_123[3], Perp_234[3], Len_Perp_123, Len_Perp_234;
  int i, j, k;

  /* Find the components of the three bond vectors */
  for( i=0; i<3; i++ ) {
    Comp[0][i] = (double)(Coord2[i]-Coord1[i]);
    Comp[1][i] = (double)(Coord3[i]-Coord2[i]);
    Comp[2][i] = (double)(Coord4[i]-Coord3[i]);
  }

  /* Calculate vectors perpendicular to the planes 123 and 234 */
  Len_Perp_123 = 0.0; Len_Perp_234 = 0.0;
  for( i=0; i<3; i++ ) {
    j = (i+1)%3;
    k = (j+1)%3;
    Perp_123[i] = Comp[0][j]*Comp[1][k] - Comp[0][k]*Comp[1][j];
    Perp_234[i] = Comp[1][j]*Comp[2][k] - Comp[1][k]*Comp[2][j];
    Len_Perp_123 += Perp_123[i]*Perp_123[i];
    Len_Perp_234 += Perp_234[i]*Perp_234[i];
  }
  
  Len_Perp_123 = sqrt(Len_Perp_123);
  Len_Perp_234 = sqrt(Len_Perp_234);

  /* Normalize the vectors perpendicular to 123 and 234 */
  for( i=0; i<3; i++ ) {
    Perp_123[i] /= Len_Perp_123;
    Perp_234[i] /= Len_Perp_234;
  }

  /* Find the scalar product of the unit normals */
  ScalarProd = 0.0;
  for( i=0; i<3; i++ ) 
    ScalarProd += Perp_123[i]*Perp_234[i];

  /* Find the absolute value of the torsion angle */
  if( ScalarProd > 0.0 && fabs(ScalarProd - 1.0) < Eps ) 
    ScalarProd -= Eps;
  else
  if( ScalarProd < 0.0 && fabs(ScalarProd + 1.0) < Eps ) 
    ScalarProd += Eps;
  AbsTorsAng = RADDEG*acos(ScalarProd);

  /* Find the triple scalar product of the three bond vectors */
  TripleScalarProd = 0.0;
  for( i=0; i<3; i++ ) 
    TripleScalarProd += Comp[0][i]*Perp_234[i];

  /* Torsion angle has the sign of the triple scalar product */
  return( (TripleScalarProd > 0.0) ? (float)AbsTorsAng : (float)(-AbsTorsAng) );

}

// Assembly:
subq $0x98, %rsp
xorl %eax, %eax
movss (%rsi,%rax), %xmm0
movaps %xmm0, %xmm1
subss (%rdi,%rax), %xmm1
cvtss2sd %xmm1, %xmm1
movsd %xmm1, 0x50(%rsp,%rax,2)
movss (%rdx,%rax), %xmm1
movaps %xmm1, %xmm2
subss %xmm0, %xmm2
xorps %xmm0, %xmm0
cvtss2sd %xmm2, %xmm0
movsd %xmm0, 0x68(%rsp,%rax,2)
movss (%rcx,%rax), %xmm0
subss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x80(%rsp,%rax,2)
addq $0x4, %rax
cmpq $0xc, %rax
jne 0x3ea5
xorpd %xmm4, %xmm4
xorl %eax, %eax
xorl %ecx, %ecx
leaq 0x1(%rcx), %rdx
cmpq $0x2, %rcx
movl %edx, %esi
cmovel %eax, %esi
leal 0x1(%rsi), %edi
leal -0x2(%rsi), %r8d
cmpl $0x3, %edi
cmovbl %edi, %r8d
movl %esi, %esi
movsd 0x68(%rsp,%r8,8), %xmm0
movsd 0x80(%rsp,%r8,8), %xmm1
unpcklpd %xmm0, %xmm1            # xmm1 = xmm1[0],xmm0[0]
movhpd 0x50(%rsp,%r8,8), %xmm0 # xmm0 = xmm0[0],mem[0]
movsd 0x68(%rsp,%rsi,8), %xmm2
movsd 0x80(%rsp,%rsi,8), %xmm3
unpcklpd %xmm2, %xmm3            # xmm3 = xmm3[0],xmm2[0]
mulpd %xmm0, %xmm3
movhpd 0x50(%rsp,%rsi,8), %xmm2 # xmm2 = xmm2[0],mem[0]
mulpd %xmm2, %xmm1
subpd %xmm3, %xmm1
movhpd %xmm1, 0x30(%rsp,%rcx,8)
movlpd %xmm1, 0x10(%rsp,%rcx,8)
mulpd %xmm1, %xmm1
addpd %xmm1, %xmm4
movq %rdx, %rcx
cmpq $0x3, %rdx
jne 0x3efd
movapd %xmm4, %xmm0
unpckhpd %xmm4, %xmm0            # xmm0 = xmm0[1],xmm4[1]
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x3f92
xorps %xmm2, %xmm2
sqrtsd %xmm0, %xmm2
jmp 0x3fa8
movapd %xmm4, (%rsp)
callq 0x2250
xorps %xmm1, %xmm1
movapd (%rsp), %xmm4
movapd %xmm0, %xmm2
ucomisd %xmm1, %xmm4
jb 0x3fb7
xorps %xmm0, %xmm0
sqrtsd %xmm4, %xmm0
jmp 0x3fca
movapd %xmm4, %xmm0
movsd %xmm2, (%rsp)
callq 0x2250
movsd (%rsp), %xmm2
xorl %eax, %eax
movsd 0x30(%rsp,%rax,8), %xmm1
divsd %xmm2, %xmm1
movsd %xmm1, 0x30(%rsp,%rax,8)
movsd 0x10(%rsp,%rax,8), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rsp,%rax,8)
incq %rax
cmpq $0x3, %rax
jne 0x3fcc
xorpd %xmm0, %xmm0
xorl %eax, %eax
movsd 0x30(%rsp,%rax,8), %xmm1
mulsd 0x10(%rsp,%rax,8), %xmm1
addsd %xmm1, %xmm0
incq %rax
cmpq $0x3, %rax
jne 0x3ffb
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x404a
movsd 0x15832(%rip), %xmm2    # 0x19858
addsd %xmm0, %xmm2
andpd 0x1588e(%rip), %xmm2    # 0x198c0
movsd 0x15826(%rip), %xmm3    # 0x19860
ucomisd %xmm2, %xmm3
jbe 0x404a
addsd 0x15828(%rip), %xmm0    # 0x19870
jmp 0x407a
ucomisd %xmm0, %xmm1
jbe 0x407a
movsd 0x15810(%rip), %xmm1    # 0x19868
addsd %xmm0, %xmm1
andpd 0x1585c(%rip), %xmm1    # 0x198c0
movsd 0x157f4(%rip), %xmm2    # 0x19860
ucomisd %xmm1, %xmm2
jbe 0x407a
addsd 0x157e6(%rip), %xmm0    # 0x19860
callq 0x2120
xorpd %xmm1, %xmm1
xorl %eax, %eax
movsd 0x50(%rsp,%rax,8), %xmm2
mulsd 0x10(%rsp,%rax,8), %xmm2
addsd %xmm2, %xmm1
incq %rax
cmpq $0x3, %rax
jne 0x4085
mulsd 0x157d2(%rip), %xmm0    # 0x19878
xorpd %xmm2, %xmm2
ucomisd %xmm2, %xmm1
cvtsd2ss %xmm0, %xmm0
ja 0x40bb
xorps 0x15815(%rip), %xmm0    # 0x198d0
addq $0x98, %rsp
retq