#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 exp(double);
double const log(double const);
double acceptance_ratio(int i, int j, int n_states, double epsilon,
                        const double *Z, const double *K, const double *N,
                        const double *Q) {
  double term1, term2, term3, term4;
  term1 = Z[i * n_states + j] *
          (log(K[i * n_states + j] + epsilon) - log(K[i * n_states + j]));
  term3 = N[i] * (log(Q[i]) - log(Q[i] + (epsilon)));
  if (i == j)
    return exp(term1 + term3);
  term2 = Z[j * n_states + i] *
          (log(K[j * n_states + i] + epsilon) - log(K[j * n_states + i]));
  term4 = N[j] * (log(Q[j]) - log(Q[j] + (epsilon)));
  return exp(term1 + term2 + term3 + term4);
}


x86 assembly (clang, -O0):
<acceptance_ratio>:
push   %rbp
mov    %rsp,%rbp
sub    $0xa0,%rsp
mov    0x10(%rbp),%rax
mov    %edi,-0xc(%rbp)
mov    %esi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movsd  %xmm0,-0x20(%rbp)
mov    %rcx,-0x28(%rbp)
mov    %r8,-0x30(%rbp)
mov    %r9,-0x38(%rbp)
mov    -0x28(%rbp),%rax
mov    -0xc(%rbp),%ecx
imul   -0x14(%rbp),%ecx
add    -0x10(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x70(%rbp)
mov    -0x30(%rbp),%rax
mov    -0xc(%rbp),%ecx
imul   -0x14(%rbp),%ecx
add    -0x10(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
addsd  -0x20(%rbp),%xmm0
call   1040 <log@plt>
movsd  %xmm0,-0x78(%rbp)
mov    -0x30(%rbp),%rax
mov    -0xc(%rbp),%ecx
imul   -0x14(%rbp),%ecx
add    -0x10(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
call   1040 <log@plt>
movsd  -0x78(%rbp),%xmm1
movaps %xmm0,%xmm2
movsd  -0x70(%rbp),%xmm0
subsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
mov    -0x38(%rbp),%rax
movslq -0xc(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    0x10(%rbp),%rax
movslq -0xc(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
call   1040 <log@plt>
movsd  %xmm0,-0x68(%rbp)
mov    0x10(%rbp),%rax
movslq -0xc(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
addsd  -0x20(%rbp),%xmm0
call   1040 <log@plt>
movsd  -0x68(%rbp),%xmm1
movaps %xmm0,%xmm2
movsd  -0x60(%rbp),%xmm0
subsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x50(%rbp)
mov    -0xc(%rbp),%eax
cmp    -0x10(%rbp),%eax
jne    123d <acceptance_ratio+0x11d>
movsd  -0x40(%rbp),%xmm0
addsd  -0x50(%rbp),%xmm0
call   1030 <exp@plt>
movsd  %xmm0,-0x8(%rbp)
jmp    133c <acceptance_ratio+0x21c>
mov    -0x28(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x14(%rbp),%ecx
add    -0xc(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x90(%rbp)
ff
mov    -0x30(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x14(%rbp),%ecx
add    -0xc(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
addsd  -0x20(%rbp),%xmm0
call   1040 <log@plt>
movsd  %xmm0,-0x98(%rbp)
ff
mov    -0x30(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x14(%rbp),%ecx
add    -0xc(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
call   1040 <log@plt>
movsd  -0x98(%rbp),%xmm1
ff
movaps %xmm0,%xmm2
movsd  -0x90(%rbp),%xmm0
ff
subsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x38(%rbp),%rax
movslq -0x10(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x80(%rbp)
mov    0x10(%rbp),%rax
movslq -0x10(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
call   1040 <log@plt>
movsd  %xmm0,-0x88(%rbp)
ff
mov    0x10(%rbp),%rax
movslq -0x10(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
addsd  -0x20(%rbp),%xmm0
call   1040 <log@plt>
movsd  -0x88(%rbp),%xmm1
ff
movaps %xmm0,%xmm2
movsd  -0x80(%rbp),%xmm0
subsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x40(%rbp),%xmm0
addsd  -0x48(%rbp),%xmm0
addsd  -0x50(%rbp),%xmm0
addsd  -0x58(%rbp),%xmm0
call   1030 <exp@plt>
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0xa0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<acceptance_ratio>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x48,%rsp
mov    %r9,%r12
mov    %r8,%r14
movapd %xmm0,%xmm1
movsd  %xmm0,0x38(%rsp)
mov    %edx,%ebp
mov    %esi,%r13d
mov    %edi,%ebx
mov    0x80(%rsp),%rax
mov    %rax,0x40(%rsp)
mov    %edx,%eax
imul   %edi,%eax
add    %esi,%eax
movslq %eax,%r15
mov    %rcx,0x20(%rsp)
movsd  (%rcx,%r15,8),%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  (%r8,%r15,8),%xmm0
addsd  %xmm1,%xmm0
call   1040 <log@plt>
movsd  %xmm0,0x18(%rsp)
mov    %r14,0x28(%rsp)
movsd  (%r14,%r15,8),%xmm0
mov    %ebx,%r14d
mov    0x40(%rsp),%r15
call   1040 <log@plt>
movsd  0x18(%rsp),%xmm1
subsd  %xmm0,%xmm1
mulsd  0x8(%rsp),%xmm1
movsd  %xmm1,0x18(%rsp)
movslq %ebx,%rbx
mov    %r12,0x30(%rsp)
movsd  (%r12,%rbx,8),%xmm0
movsd  %xmm0,0x10(%rsp)
movsd  (%r15,%rbx,8),%xmm0
call   1040 <log@plt>
movsd  %xmm0,0x8(%rsp)
movsd  (%r15,%rbx,8),%xmm0
addsd  0x38(%rsp),%xmm0
call   1040 <log@plt>
movsd  0x8(%rsp),%xmm1
subsd  %xmm0,%xmm1
mulsd  0x10(%rsp),%xmm1
movsd  %xmm1,0x8(%rsp)
cmp    %r13d,%ebx
jne    1212 <acceptance_ratio+0xf2>
movsd  0x18(%rsp),%xmm0
addsd  0x8(%rsp),%xmm0
jmp    12d0 <acceptance_ratio+0x1b0>
imul   %r13d,%ebp
add    %r14d,%ebp
movslq %ebp,%rbx
mov    0x20(%rsp),%rax
movsd  (%rax,%rbx,8),%xmm0
movsd  %xmm0,0x20(%rsp)
mov    0x28(%rsp),%rbp
movsd  0x0(%rbp,%rbx,8),%xmm0
addsd  0x38(%rsp),%xmm0
call   1040 <log@plt>
movsd  %xmm0,0x10(%rsp)
movsd  0x0(%rbp,%rbx,8),%xmm0
call   1040 <log@plt>
movsd  0x10(%rsp),%xmm1
subsd  %xmm0,%xmm1
mulsd  0x20(%rsp),%xmm1
movsd  %xmm1,0x10(%rsp)
movslq %r13d,%rbx
mov    0x30(%rsp),%rax
movsd  (%rax,%rbx,8),%xmm0
movsd  %xmm0,0x30(%rsp)
movsd  (%r15,%rbx,8),%xmm0
call   1040 <log@plt>
movsd  %xmm0,0x28(%rsp)
movsd  0x38(%rsp),%xmm0
addsd  (%r15,%rbx,8),%xmm0
call   1040 <log@plt>
movsd  0x28(%rsp),%xmm1
subsd  %xmm0,%xmm1
mulsd  0x30(%rsp),%xmm1
movapd %xmm1,%xmm2
movsd  0x18(%rsp),%xmm0
addsd  0x10(%rsp),%xmm0
movsd  0x8(%rsp),%xmm1
addsd  %xmm0,%xmm1
addsd  %xmm2,%xmm1
movapd %xmm1,%xmm0
add    $0x48,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
jmp    1030 <exp@plt>

LLVM IR (-O0):
define double @acceptance_ratio(i32 %0, i32 %1, i32 %2, double %3, double* %4, double* %5, double* %6, double* %7) {
%9 = alloca double
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = alloca double
%14 = alloca double*
%15 = alloca double*
%16 = alloca double*
%17 = alloca double*
%18 = alloca double
%19 = alloca double
%20 = alloca double
%21 = alloca double
store i32 %0, i32* %10
store i32 %1, i32* %11
store i32 %2, i32* %12
store double %3, double* %13
store double* %4, double** %14
store double* %5, double** %15
store double* %6, double** %16
store double* %7, double** %17
%22 = load double*, double** %14
%23 = load i32, i32* %10
%24 = load i32, i32* %12
%25 = mul nsw i32 %23, %24
%26 = load i32, i32* %11
%27 = add nsw i32 %25, %26
%28 = sext i32 %27 to i64
%29 = getelementptr inbounds double, double* %22, i64 %28
%30 = load double, double* %29
%31 = load double*, double** %15
%32 = load i32, i32* %10
%33 = load i32, i32* %12
%34 = mul nsw i32 %32, %33
%35 = load i32, i32* %11
%36 = add nsw i32 %34, %35
%37 = sext i32 %36 to i64
%38 = getelementptr inbounds double, double* %31, i64 %37
%39 = load double, double* %38
%40 = load double, double* %13
%41 = fadd double %39, %40
%42 = call double @log(double %41)
%43 = load double*, double** %15
%44 = load i32, i32* %10
%45 = load i32, i32* %12
%46 = mul nsw i32 %44, %45
%47 = load i32, i32* %11
%48 = add nsw i32 %46, %47
%49 = sext i32 %48 to i64
%50 = getelementptr inbounds double, double* %43, i64 %49
%51 = load double, double* %50
%52 = call double @log(double %51)
%53 = fsub double %42, %52
%54 = fmul double %30, %53
store double %54, double* %18
%55 = load double*, double** %16
%56 = load i32, i32* %10
%57 = sext i32 %56 to i64
%58 = getelementptr inbounds double, double* %55, i64 %57
%59 = load double, double* %58
%60 = load double*, double** %17
%61 = load i32, i32* %10
%62 = sext i32 %61 to i64
%63 = getelementptr inbounds double, double* %60, i64 %62
%64 = load double, double* %63
%65 = call double @log(double %64)
%66 = load double*, double** %17
%67 = load i32, i32* %10
%68 = sext i32 %67 to i64
%69 = getelementptr inbounds double, double* %66, i64 %68
%70 = load double, double* %69
%71 = load double, double* %13
%72 = fadd double %70, %71
%73 = call double @log(double %72)
%74 = fsub double %65, %73
%75 = fmul double %59, %74
store double %75, double* %20
%76 = load i32, i32* %10
%77 = load i32, i32* %11
%78 = icmp eq i32 %76, %77
br i1 %78, label %79, label %84
79: ; preds = %8
%80 = load double, double* %18
%81 = load double, double* %20
%82 = fadd double %80, %81
%83 = call double @exp(double %82)
store double %83, double* %9
br label %147
84: ; preds = %8
%85 = load double*, double** %14
%86 = load i32, i32* %11
%87 = load i32, i32* %12
%88 = mul nsw i32 %86, %87
%89 = load i32, i32* %10
%90 = add nsw i32 %88, %89
%91 = sext i32 %90 to i64
%92 = getelementptr inbounds double, double* %85, i64 %91
%93 = load double, double* %92
%94 = load double*, double** %15
%95 = load i32, i32* %11
%96 = load i32, i32* %12
%97 = mul nsw i32 %95, %96
%98 = load i32, i32* %10
%99 = add nsw i32 %97, %98
%100 = sext i32 %99 to i64
%101 = getelementptr inbounds double, double* %94, i64 %100
%102 = load double, double* %101
%103 = load double, double* %13
%104 = fadd double %102, %103
%105 = call double @log(double %104)
%106 = load double*, double** %15
%107 = load i32, i32* %11
%108 = load i32, i32* %12
%109 = mul nsw i32 %107, %108
%110 = load i32, i32* %10
%111 = add nsw i32 %109, %110
%112 = sext i32 %111 to i64
%113 = getelementptr inbounds double, double* %106, i64 %112
%114 = load double, double* %113
%115 = call double @log(double %114)
%116 = fsub double %105, %115
%117 = fmul double %93, %116
store double %117, double* %19
%118 = load double*, double** %16
%119 = load i32, i32* %11
%120 = sext i32 %119 to i64
%121 = getelementptr inbounds double, double* %118, i64 %120
%122 = load double, double* %121
%123 = load double*, double** %17
%124 = load i32, i32* %11
%125 = sext i32 %124 to i64
%126 = getelementptr inbounds double, double* %123, i64 %125
%127 = load double, double* %126
%128 = call double @log(double %127)
%129 = load double*, double** %17
%130 = load i32, i32* %11
%131 = sext i32 %130 to i64
%132 = getelementptr inbounds double, double* %129, i64 %131
%133 = load double, double* %132
%134 = load double, double* %13
%135 = fadd double %133, %134
%136 = call double @log(double %135)
%137 = fsub double %128, %136
%138 = fmul double %122, %137
store double %138, double* %21
%139 = load double, double* %18
%140 = load double, double* %19
%141 = fadd double %139, %140
%142 = load double, double* %20
%143 = fadd double %141, %142
%144 = load double, double* %21
%145 = fadd double %143, %144
%146 = call double @exp(double %145)
store double %146, double* %9
br label %147
147: ; preds = %84, %79
%148 = load double, double* %9
ret double %148
}

LLVM IR (-O2):
define double @acceptance_ratio(i32 %0, i32 %1, i32 %2, double %3, double* nocapture %4, double* nocapture %5, double* nocapture %6, double* nocapture %7) {
%9 = mul nsw i32 %2, %0
%10 = add nsw i32 %9, %1
%11 = sext i32 %10 to i64
%12 = getelementptr inbounds double, double* %4, i64 %11
%13 = load double, double* %12
%14 = getelementptr inbounds double, double* %5, i64 %11
%15 = load double, double* %14
%16 = fadd double %15, %3
%17 = tail call double @log(double %16)
%18 = load double, double* %14
%19 = tail call double @log(double %18)
%20 = fsub double %17, %19
%21 = fmul double %13, %20
%22 = sext i32 %0 to i64
%23 = getelementptr inbounds double, double* %6, i64 %22
%24 = load double, double* %23
%25 = getelementptr inbounds double, double* %7, i64 %22
%26 = load double, double* %25
%27 = tail call double @log(double %26)
%28 = load double, double* %25
%29 = fadd double %28, %3
%30 = tail call double @log(double %29)
%31 = fsub double %27, %30
%32 = fmul double %24, %31
%33 = icmp eq i32 %0, %1
br i1 %33, label %34, label %36
34: ; preds = %8
%35 = fadd double %21, %32
br label %64
36: ; preds = %8
%37 = mul nsw i32 %2, %1
%38 = add nsw i32 %37, %0
%39 = sext i32 %38 to i64
%40 = getelementptr inbounds double, double* %4, i64 %39
%41 = load double, double* %40
%42 = getelementptr inbounds double, double* %5, i64 %39
%43 = load double, double* %42
%44 = fadd double %43, %3
%45 = tail call double @log(double %44)
%46 = load double, double* %42
%47 = tail call double @log(double %46)
%48 = fsub double %45, %47
%49 = fmul double %41, %48
%50 = sext i32 %1 to i64
%51 = getelementptr inbounds double, double* %6, i64 %50
%52 = load double, double* %51
%53 = getelementptr inbounds double, double* %7, i64 %50
%54 = load double, double* %53
%55 = tail call double @log(double %54)
%56 = load double, double* %53
%57 = fadd double %56, %3
%58 = tail call double @log(double %57)
%59 = fsub double %55, %58
%60 = fmul double %52, %59
%61 = fadd double %21, %49
%62 = fadd double %32, %61
%63 = fadd double %62, %60
br label %64
64: ; preds = %36, %34
%65 = phi double [ %63, %36 ], [ %35, %34 ]
%66 = tail call double @exp(double %65)
ret double %66
}