#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 _logsumexp_pair(double, double);
double _logsumexp_sort_kahan_inplace(double *, int);
extern void _mbar_update_therm_energies(double *log_therm_state_counts,
                                        double *therm_energies,
                                        double *bias_energy_sequence,
                                        int n_therm_states, int seq_length,
                                        double *scratch_T,
                                        double *new_therm_energies) {
  int K, x, L;
  double divisor;
  for (x = 0; x < seq_length; ++x) {
    for (L = 0; L < n_therm_states; ++L)
      scratch_T[L] = log_therm_state_counts[L] + therm_energies[L] -
                     bias_energy_sequence[x * n_therm_states + L];
    divisor = _logsumexp_sort_kahan_inplace(scratch_T, n_therm_states);
    for (K = 0; K < n_therm_states; ++K)
      new_therm_energies[K] = -_logsumexp_pair(
          -new_therm_energies[K],
          -(bias_energy_sequence[x * n_therm_states + K] + divisor));
  }
}


x86 assembly (clang, -O0):
<_mbar_update_therm_energies>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    0x10(%rbp),%rax
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
mov    %r8d,-0x20(%rbp)
mov    %r9,-0x28(%rbp)
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    -0x20(%rbp),%eax
jge    1278 <_mbar_update_therm_energies+0x158>
movl   $0x0,-0x34(%rbp)
mov    -0x34(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jge    11b4 <_mbar_update_therm_energies+0x94>
mov    -0x8(%rbp),%rax
movslq -0x34(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x34(%rbp),%rcx
addsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x30(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
add    -0x34(%rbp),%ecx
movslq %ecx,%rcx
subsd  (%rax,%rcx,8),%xmm0
mov    -0x28(%rbp),%rax
movslq -0x34(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    115d <_mbar_update_therm_energies+0x3d>
mov    -0x28(%rbp),%rdi
mov    -0x1c(%rbp),%esi
call   1030 <_logsumexp_sort_kahan_inplace@plt>
movsd  %xmm0,-0x40(%rbp)
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jge    1265 <_mbar_update_therm_energies+0x145>
mov    0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    -0x18(%rbp),%rax
mov    -0x30(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
add    -0x2c(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm1
addsd  -0x40(%rbp),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
call   1040 <_logsumexp_pair@plt>
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    11cc <_mbar_update_therm_energies+0xac>
jmp    126a <_mbar_update_therm_energies+0x14a>
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    114a <_mbar_update_therm_energies+0x2a>
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<_mbar_update_therm_energies>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x88,%rsp
mov    %rdx,0x20(%rsp)
mov    %rsi,0x10(%rsp)
test   %r8d,%r8d
jle    1413 <_mbar_update_therm_energies+0x2f3>
mov    %r9,%r12
mov    %ecx,%r15d
mov    %rdi,%r13
movslq %ecx,%rsi
mov    %esi,%ebp
lea    (%r9,%rbp,8),%rdi
lea    0x0(,%rbp,8),%rax
add    %r13,%rax
cmp    %r9,%rax
seta   %al
mov    0x10(%rsp),%rbx
lea    (%rbx,%rbp,8),%rcx
cmp    %r13,%rdi
seta   %dl
and    %al,%dl
cmp    %r9,%rcx
seta   %al
mov    %rdi,0x38(%rsp)
cmp    %rbx,%rdi
seta   %cl
mov    %r8d,%edi
mov    %rdi,0x60(%rsp)
and    %al,%cl
or     %dl,%cl
mov    %cl,0xf(%rsp)
mov    %ebp,%eax
and    $0xfffffffc,%eax
mov    %rax,0x30(%rsp)
mov    %rbp,%rax
neg    %rax
mov    %rax,0x40(%rsp)
mov    0x20(%rsp),%rdx
lea    0x10(%rdx),%rdi
mov    %rsi,0x48(%rsp)
lea    0x0(,%rsi,8),%rcx
mov    %rcx,0x58(%rsp)
mov    %rbp,0x18(%rsp)
lea    0x0(,%rbp,8),%rax
and    $0xffffffffffffffe0,%rax
lea    0x8(%rdx),%rbx
xor    %esi,%esi
mov    %rdx,%rbp
mov    %r15d,0x2c(%rsp)
mov    %rax,0x50(%rsp)
jmp    122c <_mbar_update_therm_energies+0x10c>
nop
mov    %r12,%rdi
mov    %r15d,%esi
call   1030 <_logsumexp_sort_kahan_inplace@plt>
mov    0x70(%rsp),%rsi
add    $0x1,%rsi
mov    0x78(%rsp),%rdi
mov    0x58(%rsp),%rax
add    %rax,%rdi
add    %rax,%rbx
add    %rax,%rbp
cmp    0x60(%rsp),%rsi
mov    0x2c(%rsp),%r15d
mov    0x50(%rsp),%rax
je     1413 <_mbar_update_therm_energies+0x2f3>
test   %r15d,%r15d
mov    %rdi,0x78(%rsp)
mov    %rsi,0x70(%rsp)
jle    11f0 <_mbar_update_therm_energies+0xd0>
mov    %rsi,%r8
imul   0x48(%rsp),%r8
cmp    $0x4,%r15d
mov    %rbp,0x68(%rsp)
jb     127e <_mbar_update_therm_energies+0x15e>
mov    0x18(%rsp),%rcx
add    %r8,%rcx
mov    0x20(%rsp),%rdx
lea    (%rdx,%r8,8),%r9
lea    (%rdx,%rcx,8),%rcx
cmp    %r12,%rcx
seta   %cl
cmp    0x38(%rsp),%r9
setb   %dl
and    %cl,%dl
or     0xf(%rsp),%dl
je     130c <_mbar_update_therm_energies+0x1ec>
xor    %edx,%edx
mov    0x18(%rsp),%r14
mov    0x10(%rsp),%rsi
mov    %rdx,%rcx
test   $0x1,%r14b
je     12ba <_mbar_update_therm_energies+0x19a>
movsd  0x0(%r13,%rdx,8),%xmm0
addsd  (%rsi,%rdx,8),%xmm0
add    %rdx,%r8
mov    0x20(%rsp),%rcx
subsd  (%rcx,%r8,8),%xmm0
movsd  %xmm0,(%r12,%rdx,8)
mov    %rdx,%rcx
or     $0x1,%rcx
not    %rdx
cmp    0x40(%rsp),%rdx
je     1380 <_mbar_update_therm_energies+0x260>
nopl   0x0(%rax,%rax,1)
movsd  0x0(%r13,%rcx,8),%xmm0
addsd  (%rsi,%rcx,8),%xmm0
subsd  -0x8(%rbx,%rcx,8),%xmm0
movsd  %xmm0,(%r12,%rcx,8)
movsd  0x8(%r13,%rcx,8),%xmm0
addsd  0x8(%rsi,%rcx,8),%xmm0
subsd  (%rbx,%rcx,8),%xmm0
movsd  %xmm0,0x8(%r12,%rcx,8)
add    $0x2,%rcx
cmp    %rcx,%r14
jne    12d0 <_mbar_update_therm_energies+0x1b0>
jmp    1380 <_mbar_update_therm_energies+0x260>
xor    %ecx,%ecx
mov    0x10(%rsp),%rsi
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movupd 0x0(%r13,%rcx,1),%xmm0
movupd 0x10(%r13,%rcx,1),%xmm1
movupd (%rsi,%rcx,1),%xmm2
addpd  %xmm0,%xmm2
movupd 0x10(%rsi,%rcx,1),%xmm0
addpd  %xmm1,%xmm0
movupd -0x10(%rdi,%rcx,1),%xmm1
subpd  %xmm1,%xmm2
movupd (%rdi,%rcx,1),%xmm1
subpd  %xmm1,%xmm0
movupd %xmm2,(%r12,%rcx,1)
movupd %xmm0,0x10(%r12,%rcx,1)
add    $0x20,%rcx
cmp    %rcx,%rax
jne    1320 <_mbar_update_therm_energies+0x200>
mov    0x30(%rsp),%rcx
mov    %rcx,%rdx
mov    0x18(%rsp),%r14
cmp    %r14,%rcx
jne    128a <_mbar_update_therm_energies+0x16a>
mov    %r12,%rdi
mov    %r15d,%esi
call   1030 <_logsumexp_sort_kahan_inplace@plt>
test   %r15d,%r15d
mov    0xc0(%rsp),%rax
movapd 0xc62(%rip),%xmm1
mov    0x68(%rsp),%rbp
jle    11fb <_mbar_update_therm_energies+0xdb>
movapd %xmm0,%xmm2
xor    %r15d,%r15d
movsd  %xmm0,0x80(%rsp)
nopl   0x0(%rax)
movsd  (%rax,%r15,8),%xmm0
xorpd  %xmm1,%xmm0
movsd  0x0(%rbp,%r15,8),%xmm1
addsd  %xmm2,%xmm1
xorpd  0xc23(%rip),%xmm1
call   1040 <_logsumexp_pair@plt>
movsd  0x80(%rsp),%xmm2
movapd 0xc0d(%rip),%xmm1
mov    0xc0(%rsp),%rax
xorpd  %xmm1,%xmm0
movlpd %xmm0,(%rax,%r15,8)
add    $0x1,%r15
cmp    %r15,%r14
jne    13c0 <_mbar_update_therm_energies+0x2a0>
jmp    11fb <_mbar_update_therm_energies+0xdb>
add    $0x88,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @_mbar_update_therm_energies(double* %0, double* %1, double* %2, i32 %3, i32 %4, double* %5, double* %6) {
%8 = alloca double*
%9 = alloca double*
%10 = alloca double*
%11 = alloca i32
%12 = alloca i32
%13 = alloca double*
%14 = alloca double*
%15 = alloca i32
%16 = alloca i32
%17 = alloca i32
%18 = alloca double
store double* %0, double** %8
store double* %1, double** %9
store double* %2, double** %10
store i32 %3, i32* %11
store i32 %4, i32* %12
store double* %5, double** %13
store double* %6, double** %14
store i32 0, i32* %16
br label %19
19: ; preds = %94, %7
%20 = load i32, i32* %16
%21 = load i32, i32* %12
%22 = icmp slt i32 %20, %21
br i1 %22, label %23, label %97
23: ; preds = %19
store i32 0, i32* %17
br label %24
24: ; preds = %54, %23
%25 = load i32, i32* %17
%26 = load i32, i32* %11
%27 = icmp slt i32 %25, %26
br i1 %27, label %28, label %57
28: ; preds = %24
%29 = load double*, double** %8
%30 = load i32, i32* %17
%31 = sext i32 %30 to i64
%32 = getelementptr inbounds double, double* %29, i64 %31
%33 = load double, double* %32
%34 = load double*, double** %9
%35 = load i32, i32* %17
%36 = sext i32 %35 to i64
%37 = getelementptr inbounds double, double* %34, i64 %36
%38 = load double, double* %37
%39 = fadd double %33, %38
%40 = load double*, double** %10
%41 = load i32, i32* %16
%42 = load i32, i32* %11
%43 = mul nsw i32 %41, %42
%44 = load i32, i32* %17
%45 = add nsw i32 %43, %44
%46 = sext i32 %45 to i64
%47 = getelementptr inbounds double, double* %40, i64 %46
%48 = load double, double* %47
%49 = fsub double %39, %48
%50 = load double*, double** %13
%51 = load i32, i32* %17
%52 = sext i32 %51 to i64
%53 = getelementptr inbounds double, double* %50, i64 %52
store double %49, double* %53
br label %54
54: ; preds = %28
%55 = load i32, i32* %17
%56 = add nsw i32 %55, 1
store i32 %56, i32* %17
br label %24
57: ; preds = %24
%58 = load double*, double** %13
%59 = load i32, i32* %11
%60 = call double @_logsumexp_sort_kahan_inplace(double* %58, i32 %59)
store double %60, double* %18
store i32 0, i32* %15
br label %61
61: ; preds = %90, %57
%62 = load i32, i32* %15
%63 = load i32, i32* %11
%64 = icmp slt i32 %62, %63
br i1 %64, label %65, label %93
65: ; preds = %61
%66 = load double*, double** %14
%67 = load i32, i32* %15
%68 = sext i32 %67 to i64
%69 = getelementptr inbounds double, double* %66, i64 %68
%70 = load double, double* %69
%71 = fneg double %70
%72 = load double*, double** %10
%73 = load i32, i32* %16
%74 = load i32, i32* %11
%75 = mul nsw i32 %73, %74
%76 = load i32, i32* %15
%77 = add nsw i32 %75, %76
%78 = sext i32 %77 to i64
%79 = getelementptr inbounds double, double* %72, i64 %78
%80 = load double, double* %79
%81 = load double, double* %18
%82 = fadd double %80, %81
%83 = fneg double %82
%84 = call double @_logsumexp_pair(double %71, double %83)
%85 = fneg double %84
%86 = load double*, double** %14
%87 = load i32, i32* %15
%88 = sext i32 %87 to i64
%89 = getelementptr inbounds double, double* %86, i64 %88
store double %85, double* %89
br label %90
90: ; preds = %65
%91 = load i32, i32* %15
%92 = add nsw i32 %91, 1
store i32 %92, i32* %15
br label %61
93: ; preds = %61
br label %94
94: ; preds = %93
%95 = load i32, i32* %16
%96 = add nsw i32 %95, 1
store i32 %96, i32* %16
br label %19
97: ; preds = %19
ret void
}

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