#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
double acos(double);
int /*<<< orphan*/ cross(double *, double *, double *);
double dot_product(double *, double *);
double fabs(double);
double sign(double, double);
double sqrt(double);
void calc_dih_ang(double r1[3], double r2[3], double r3[3], double *angle) {
  double p[3], q[3], s[3];
  double arg;
  cross(r1, r2, p);
  cross(r2, r3, q);
  cross(r3, r1, s);
  arg = dot_product(p, q) / sqrt(dot_product(p, p) * dot_product(q, q));
  arg = sign(((fabs(arg)) < (1.0e0)) ? (fabs(arg)) : (1.0e0), arg);
  *angle = sign(acos(arg), dot_product(s, r2));
  return;
}


x86 assembly (clang, -O0):
<calc_dih_ang>:
push   %rbp
mov    %rsp,%rbp
sub    $0xb0,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
lea    -0x40(%rbp),%rdx
call   1070 <cross@plt>
mov    -0x10(%rbp),%rdi
mov    -0x18(%rbp),%rsi
lea    -0x60(%rbp),%rdx
call   1070 <cross@plt>
mov    -0x18(%rbp),%rdi
mov    -0x8(%rbp),%rsi
lea    -0x80(%rbp),%rdx
call   1070 <cross@plt>
lea    -0x40(%rbp),%rdi
lea    -0x60(%rbp),%rsi
call   1040 <dot_product@plt>
movsd  %xmm0,-0x90(%rbp)
ff
lea    -0x40(%rbp),%rdi
lea    -0x40(%rbp),%rsi
call   1040 <dot_product@plt>
movsd  %xmm0,-0x98(%rbp)
ff
lea    -0x60(%rbp),%rdi
lea    -0x60(%rbp),%rsi
call   1040 <dot_product@plt>
movaps %xmm0,%xmm1
movsd  -0x98(%rbp),%xmm0
ff
mulsd  %xmm1,%xmm0
call   1060 <sqrt@plt>
movaps %xmm0,%xmm1
movsd  -0x90(%rbp),%xmm0
ff
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x88(%rbp)
ff
movsd  -0x88(%rbp),%xmm1
ff
movaps 0xe01(%rip),%xmm0
pand   %xmm0,%xmm1
movsd  0xde5(%rip),%xmm0
ucomisd %xmm1,%xmm0
jbe    1245 <calc_dih_ang+0xf5>
movsd  -0x88(%rbp),%xmm0
ff
movaps 0xddc(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  %xmm0,-0xa0(%rbp)
ff
jmp    125a <calc_dih_ang+0x10a>
movsd  0xdb3(%rip),%xmm0
movsd  %xmm0,-0xa0(%rbp)
ff
jmp    125a <calc_dih_ang+0x10a>
movsd  -0xa0(%rbp),%xmm0
ff
movsd  -0x88(%rbp),%xmm1
ff
call   1050 <sign@plt>
movsd  %xmm0,-0x88(%rbp)
ff
movsd  -0x88(%rbp),%xmm0
ff
call   1030 <acos@plt>
movsd  %xmm0,-0xa8(%rbp)
ff
lea    -0x80(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1040 <dot_product@plt>
movaps %xmm0,%xmm1
movsd  -0xa8(%rbp),%xmm0
ff
call   1050 <sign@plt>
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
add    $0xb0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<calc_dih_ang>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x78,%rsp
mov    %rcx,%r14
mov    %rdx,%r12
mov    %rsi,%r15
mov    %rdi,%rbx
lea    0x60(%rsp),%r13
mov    %r13,%rdx
call   1070 <cross@plt>
lea    0x40(%rsp),%rbp
mov    %r15,%rdi
mov    %r12,%rsi
mov    %rbp,%rdx
call   1070 <cross@plt>
lea    0x20(%rsp),%rdx
mov    %r12,%rdi
mov    %rbx,%rsi
call   1070 <cross@plt>
mov    %r13,%rdi
mov    %rbp,%rsi
call   1040 <dot_product@plt>
movapd %xmm0,(%rsp)
mov    %r13,%rdi
mov    %r13,%rsi
call   1040 <dot_product@plt>
movsd  %xmm0,0x18(%rsp)
mov    %rbp,%rdi
mov    %rbp,%rsi
call   1040 <dot_product@plt>
mulsd  0x18(%rsp),%xmm0
xorpd  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jb     11dc <calc_dih_ang+0x8c>
sqrtsd %xmm0,%xmm0
jmp    11e1 <calc_dih_ang+0x91>
call   1060 <sqrt@plt>
movapd (%rsp),%xmm1
divsd  %xmm0,%xmm1
movapd 0xe0e(%rip),%xmm0
andpd  %xmm1,%xmm0
minsd  0xe12(%rip),%xmm0
call   1050 <sign@plt>
call   1030 <acos@plt>
movsd  %xmm0,(%rsp)
lea    0x20(%rsp),%rdi
mov    %r15,%rsi
call   1040 <dot_product@plt>
movapd %xmm0,%xmm1
movsd  (%rsp),%xmm0
call   1050 <sign@plt>
movsd  %xmm0,(%r14)
add    $0x78,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @calc_dih_ang(double* %0, double* %1, double* %2, double* %3) {
%5 = alloca double*
%6 = alloca double*
%7 = alloca double*
%8 = alloca double*
%9 = alloca [3 x double]
%10 = alloca [3 x double]
%11 = alloca [3 x double]
%12 = alloca double
store double* %0, double** %5
store double* %1, double** %6
store double* %2, double** %7
store double* %3, double** %8
%13 = load double*, double** %5
%14 = load double*, double** %6
%15 = getelementptr inbounds [3 x double], [3 x double]* %9, i64 0, i64 0
%16 = call i32 @cross(double* %13, double* %14, double* %15)
%17 = load double*, double** %6
%18 = load double*, double** %7
%19 = getelementptr inbounds [3 x double], [3 x double]* %10, i64 0, i64 0
%20 = call i32 @cross(double* %17, double* %18, double* %19)
%21 = load double*, double** %7
%22 = load double*, double** %5
%23 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 0
%24 = call i32 @cross(double* %21, double* %22, double* %23)
%25 = getelementptr inbounds [3 x double], [3 x double]* %9, i64 0, i64 0
%26 = getelementptr inbounds [3 x double], [3 x double]* %10, i64 0, i64 0
%27 = call double @dot_product(double* %25, double* %26)
%28 = getelementptr inbounds [3 x double], [3 x double]* %9, i64 0, i64 0
%29 = getelementptr inbounds [3 x double], [3 x double]* %9, i64 0, i64 0
%30 = call double @dot_product(double* %28, double* %29)
%31 = getelementptr inbounds [3 x double], [3 x double]* %10, i64 0, i64 0
%32 = getelementptr inbounds [3 x double], [3 x double]* %10, i64 0, i64 0
%33 = call double @dot_product(double* %31, double* %32)
%34 = fmul double %30, %33
%35 = call double @sqrt(double %34)
%36 = fdiv double %27, %35
store double %36, double* %12
%37 = load double, double* %12
%38 = call double @llvm.fabs.f64(double %37)
%39 = fcmp olt double %38, 1.000000e+00
br i1 %39, label %40, label %43
40: ; preds = %4
%41 = load double, double* %12
%42 = call double @llvm.fabs.f64(double %41)
br label %44
43: ; preds = %4
br label %44
44: ; preds = %43, %40
%45 = phi double [ %42, %40 ], [ 1.000000e+00, %43 ]
%46 = load double, double* %12
%47 = call double @sign(double %45, double %46)
store double %47, double* %12
%48 = load double, double* %12
%49 = call double @acos(double %48)
%50 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 0
%51 = load double*, double** %6
%52 = call double @dot_product(double* %50, double* %51)
%53 = call double @sign(double %49, double %52)
%54 = load double*, double** %8
store double %53, double* %54
ret void
}

LLVM IR (-O2):
define void @calc_dih_ang(double* %0, double* %1, double* %2, double* nocapture writeonly %3) {
%5 = alloca [3 x double]
%6 = alloca [3 x double]
%7 = alloca [3 x double]
%8 = bitcast [3 x double]* %5 to i8*
%9 = bitcast [3 x double]* %6 to i8*
%10 = bitcast [3 x double]* %7 to i8*
%11 = getelementptr inbounds [3 x double], [3 x double]* %5, i64 0, i64 0
%12 = call i32 @cross(double* %0, double* %1, double* %11)
%13 = getelementptr inbounds [3 x double], [3 x double]* %6, i64 0, i64 0
%14 = call i32 @cross(double* %1, double* %2, double* %13)
%15 = getelementptr inbounds [3 x double], [3 x double]* %7, i64 0, i64 0
%16 = call i32 @cross(double* %2, double* %0, double* %15)
%17 = call double @dot_product(double* %11, double* %13)
%18 = call double @dot_product(double* %11, double* %11)
%19 = call double @dot_product(double* %13, double* %13)
%20 = fmul double %18, %19
%21 = call double @sqrt(double %20)
%22 = fdiv double %17, %21
%23 = call double @llvm.fabs.f64(double %22)
%24 = fcmp olt double %23, 1.000000e+00
%25 = select i1 %24, double %23, double 1.000000e+00
%26 = call double @sign(double %25, double %22)
%27 = call double @acos(double %26)
%28 = call double @dot_product(double* %15, double* %1)
%29 = call double @sign(double %27, double %28)
store double %29, double* %3
ret void
}