#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 */
int /*<<< orphan*/ add_grad(size_t, size_t, double, double *, double *,
                            double *);
int cosh(double);
double distance_delta(double *, double *, double *);
double distance_delta_periodic(double *, double *, double *, double *,
                               double *);
double sinh(double);
double ff_bond_hyper(size_t npair, int periodic, double *cor, long *pairs,
                     double *lengths, double scale, double amp,
                     double *gradient, double *matrix, double *reciprocal) {
  size_t b, i, j;
  double delta[3], result, d, tmp;
  result = 0.0;
  for (b = 0; b < npair; b++) {
    i = pairs[2 * b];
    j = pairs[2 * b + 1];
    if (periodic) {
      d = distance_delta_periodic(cor + 3 * i, cor + 3 * j, delta, matrix,
                                  reciprocal);
    } else {
      d = distance_delta(cor + 3 * i, cor + 3 * j, delta);
    }
    tmp = d - lengths[b];
    result += amp * (cosh(scale * tmp) - 1);
    if (gradient != NULL) {
      tmp = amp * scale * sinh(scale * tmp) / d;
      add_grad(i, j, tmp, cor, delta, gradient);
    }
  }
  return result;
}


x86 assembly (clang, -O0):
<ff_bond_hyper>:
push   %rbp
mov    %rsp,%rbp
sub    $0xa0,%rsp
mov    0x18(%rbp),%rax
mov    0x10(%rbp),%rax
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
movsd  %xmm0,-0x30(%rbp)
movsd  %xmm1,-0x38(%rbp)
mov    %r9,-0x40(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x78(%rbp)
movq   $0x0,-0x48(%rbp)
mov    -0x48(%rbp),%rax
cmp    -0x8(%rbp),%rax
jae    131a <ff_bond_hyper+0x1ca>
mov    -0x20(%rbp),%rax
mov    -0x48(%rbp),%rcx
shl    $0x1,%rcx
mov    (%rax,%rcx,8),%rax
mov    %rax,-0x50(%rbp)
mov    -0x20(%rbp),%rax
mov    -0x48(%rbp),%rcx
shl    $0x1,%rcx
mov    0x8(%rax,%rcx,8),%rax
mov    %rax,-0x58(%rbp)
cmpl   $0x0,-0xc(%rbp)
je     1210 <ff_bond_hyper+0xc0>
mov    -0x18(%rbp),%rdi
imul   $0x3,-0x50(%rbp),%rax
shl    $0x3,%rax
add    %rax,%rdi
mov    -0x18(%rbp),%rsi
imul   $0x3,-0x58(%rbp),%rax
shl    $0x3,%rax
add    %rax,%rsi
lea    -0x70(%rbp),%rdx
mov    0x10(%rbp),%rcx
mov    0x18(%rbp),%r8
call   1060 <distance_delta_periodic@plt>
movsd  %xmm0,-0x80(%rbp)
jmp    123e <ff_bond_hyper+0xee>
mov    -0x18(%rbp),%rdi
imul   $0x3,-0x50(%rbp),%rax
shl    $0x3,%rax
add    %rax,%rdi
mov    -0x18(%rbp),%rsi
imul   $0x3,-0x58(%rbp),%rax
shl    $0x3,%rax
add    %rax,%rsi
lea    -0x70(%rbp),%rdx
call   1070 <distance_delta@plt>
movsd  %xmm0,-0x80(%rbp)
movsd  -0x80(%rbp),%xmm0
mov    -0x28(%rbp),%rax
mov    -0x48(%rbp),%rcx
subsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x88(%rbp)
ff
movsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x90(%rbp)
ff
movsd  -0x30(%rbp),%xmm0
mulsd  -0x88(%rbp),%xmm0
ff
call   1050 <cosh@plt>
movsd  -0x90(%rbp),%xmm0
ff
sub    $0x1,%eax
cvtsi2sd %eax,%xmm2
movsd  -0x78(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x78(%rbp)
cmpq   $0x0,-0x40(%rbp)
je     1304 <ff_bond_hyper+0x1b4>
movsd  -0x38(%rbp),%xmm0
mulsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x98(%rbp)
ff
movsd  -0x30(%rbp),%xmm0
mulsd  -0x88(%rbp),%xmm0
ff
call   1030 <sinh@plt>
movaps %xmm0,%xmm1
movsd  -0x98(%rbp),%xmm0
ff
mulsd  %xmm1,%xmm0
divsd  -0x80(%rbp),%xmm0
movsd  %xmm0,-0x88(%rbp)
ff
mov    -0x50(%rbp),%rdi
mov    -0x58(%rbp),%rsi
movsd  -0x88(%rbp),%xmm0
ff
mov    -0x18(%rbp),%rdx
lea    -0x70(%rbp),%rcx
mov    -0x40(%rbp),%r8
call   1040 <add_grad@plt>
jmp    1309 <ff_bond_hyper+0x1b9>
mov    -0x48(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x48(%rbp)
jmp    1194 <ff_bond_hyper+0x44>
movsd  -0x78(%rbp),%xmm0
add    $0xa0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<ff_bond_hyper>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x78,%rsp
mov    %r8,0x40(%rsp)
mov    %rdx,0x18(%rsp)
mov    %esi,0xc(%rsp)
mov    %rdi,0x38(%rsp)
test   %rdi,%rdi
je     129d <ff_bond_hyper+0x14d>
mov    %rcx,%rbx
mov    %r9,0x30(%rsp)
movsd  %xmm0,0x10(%rsp)
mulsd  %xmm1,%xmm0
movsd  %xmm0,0x20(%rsp)
add    $0x8,%rbx
xorpd  %xmm0,%xmm0
xor    %r15d,%r15d
movsd  %xmm1,0x28(%rsp)
mov    0x30(%rsp),%r12
jmp    11de <ff_bond_hyper+0x8e>
nopw   0x0(%rax,%rax,1)
xorps  %xmm0,%xmm0
cvtsi2sd %ebp,%xmm0
mulsd  0x28(%rsp),%xmm0
movsd  0x58(%rsp),%xmm1
addsd  %xmm0,%xmm1
movapd %xmm1,%xmm0
add    $0x1,%r15
add    $0x10,%rbx
cmp    %r15,0x38(%rsp)
je     12a1 <ff_bond_hyper+0x151>
mov    -0x8(%rbx),%r14
mov    (%rbx),%r13
lea    (%r14,%r14,2),%rax
mov    0x18(%rsp),%rcx
lea    (%rcx,%rax,8),%rdi
lea    0x0(,%r13,2),%rax
add    %r13,%rax
lea    (%rcx,%rax,8),%rsi
cmpl   $0x0,0xc(%rsp)
movsd  %xmm0,0x58(%rsp)
lea    0x60(%rsp),%rdx
je     1230 <ff_bond_hyper+0xe0>
mov    0xb0(%rsp),%rcx
mov    0xb8(%rsp),%r8
call   1060 <distance_delta_periodic@plt>
jmp    1235 <ff_bond_hyper+0xe5>
nopw   0x0(%rax,%rax,1)
call   1070 <distance_delta@plt>
movsd  0x10(%rsp),%xmm1
movsd  %xmm0,0x50(%rsp)
mov    0x40(%rsp),%rax
subsd  (%rax,%r15,8),%xmm0
mulsd  %xmm1,%xmm0
movsd  %xmm0,0x48(%rsp)
call   1050 <cosh@plt>
mov    %eax,%ebp
add    $0xffffffff,%ebp
test   %r12,%r12
je     11b0 <ff_bond_hyper+0x60>
movsd  0x48(%rsp),%xmm0
call   1030 <sinh@plt>
mulsd  0x20(%rsp),%xmm0
divsd  0x50(%rsp),%xmm0
mov    %r14,%rdi
mov    %r13,%rsi
mov    0x18(%rsp),%rdx
lea    0x60(%rsp),%rcx
mov    %r12,%r8
call   1040 <add_grad@plt>
jmp    11b0 <ff_bond_hyper+0x60>
xorpd  %xmm0,%xmm0
add    $0x78,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define double @ff_bond_hyper(i64 %0, i32 %1, double* %2, i64* %3, double* %4, double %5, double %6, double* %7, double* %8, double* %9) {
%11 = alloca i64
%12 = alloca i32
%13 = alloca double*
%14 = alloca i64*
%15 = alloca double*
%16 = alloca double
%17 = alloca double
%18 = alloca double*
%19 = alloca double*
%20 = alloca double*
%21 = alloca i64
%22 = alloca i64
%23 = alloca i64
%24 = alloca [3 x double]
%25 = alloca double
%26 = alloca double
%27 = alloca double
store i64 %0, i64* %11
store i32 %1, i32* %12
store double* %2, double** %13
store i64* %3, i64** %14
store double* %4, double** %15
store double %5, double* %16
store double %6, double* %17
store double* %7, double** %18
store double* %8, double** %19
store double* %9, double** %20
store double 0.000000e+00, double* %25
store i64 0, i64* %21
br label %28
28: ; preds = %107, %10
%29 = load i64, i64* %21
%30 = load i64, i64* %11
%31 = icmp ult i64 %29, %30
br i1 %31, label %32, label %110
32: ; preds = %28
%33 = load i64*, i64** %14
%34 = load i64, i64* %21
%35 = mul i64 2, %34
%36 = getelementptr inbounds i64, i64* %33, i64 %35
%37 = load i64, i64* %36
store i64 %37, i64* %22
%38 = load i64*, i64** %14
%39 = load i64, i64* %21
%40 = mul i64 2, %39
%41 = add i64 %40, 1
%42 = getelementptr inbounds i64, i64* %38, i64 %41
%43 = load i64, i64* %42
store i64 %43, i64* %23
%44 = load i32, i32* %12
%45 = icmp ne i32 %44, 0
br i1 %45, label %46, label %59
46: ; preds = %32
%47 = load double*, double** %13
%48 = load i64, i64* %22
%49 = mul i64 3, %48
%50 = getelementptr inbounds double, double* %47, i64 %49
%51 = load double*, double** %13
%52 = load i64, i64* %23
%53 = mul i64 3, %52
%54 = getelementptr inbounds double, double* %51, i64 %53
%55 = getelementptr inbounds [3 x double], [3 x double]* %24, i64 0, i64 0
%56 = load double*, double** %19
%57 = load double*, double** %20
%58 = call double @distance_delta_periodic(double* %50, double* %54, double* %55, double* %56, double* %57)
store double %58, double* %26
br label %70
59: ; preds = %32
%60 = load double*, double** %13
%61 = load i64, i64* %22
%62 = mul i64 3, %61
%63 = getelementptr inbounds double, double* %60, i64 %62
%64 = load double*, double** %13
%65 = load i64, i64* %23
%66 = mul i64 3, %65
%67 = getelementptr inbounds double, double* %64, i64 %66
%68 = getelementptr inbounds [3 x double], [3 x double]* %24, i64 0, i64 0
%69 = call double @distance_delta(double* %63, double* %67, double* %68)
store double %69, double* %26
br label %70
70: ; preds = %59, %46
%71 = load double, double* %26
%72 = load double*, double** %15
%73 = load i64, i64* %21
%74 = getelementptr inbounds double, double* %72, i64 %73
%75 = load double, double* %74
%76 = fsub double %71, %75
store double %76, double* %27
%77 = load double, double* %17
%78 = load double, double* %16
%79 = load double, double* %27
%80 = fmul double %78, %79
%81 = call i32 @cosh(double %80)
%82 = sub nsw i32 %81, 1
%83 = sitofp i32 %82 to double
%84 = load double, double* %25
%85 = call double @llvm.fmuladd.f64(double %77, double %83, double %84)
store double %85, double* %25
%86 = load double*, double** %18
%87 = icmp ne double* %86, null
br i1 %87, label %88, label %106
88: ; preds = %70
%89 = load double, double* %17
%90 = load double, double* %16
%91 = fmul double %89, %90
%92 = load double, double* %16
%93 = load double, double* %27
%94 = fmul double %92, %93
%95 = call double @sinh(double %94)
%96 = fmul double %91, %95
%97 = load double, double* %26
%98 = fdiv double %96, %97
store double %98, double* %27
%99 = load i64, i64* %22
%100 = load i64, i64* %23
%101 = load double, double* %27
%102 = load double*, double** %13
%103 = getelementptr inbounds [3 x double], [3 x double]* %24, i64 0, i64 0
%104 = load double*, double** %18
%105 = call i32 @add_grad(i64 %99, i64 %100, double %101, double* %102, double* %103, double* %104)
br label %106
106: ; preds = %88, %70
br label %107
107: ; preds = %106
%108 = load i64, i64* %21
%109 = add i64 %108, 1
store i64 %109, i64* %21
br label %28
110: ; preds = %28
%111 = load double, double* %25
ret double %111
}

LLVM IR (-O2):
define double @ff_bond_hyper(i64 %0, i32 %1, double* %2, i64* nocapture %3, double* nocapture %4, double %5, double %6, double* %7, double* %8, double* %9) {
%11 = alloca [3 x double]
%12 = bitcast [3 x double]* %11 to i8*
%13 = icmp eq i64 %0, 0
br i1 %13, label %54, label %14
14: ; preds = %10
%15 = icmp eq i32 %1, 0
%16 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 0
%17 = icmp eq double* %7, null
%18 = fmul double %5, %6
br label %19
19: ; preds = %14, %51
%20 = phi double [ 0.000000e+00, %14 ], [ %45, %51 ]
%21 = phi i64 [ 0, %14 ], [ %52, %51 ]
%22 = shl i64 %21, 1
%23 = getelementptr inbounds i64, i64* %3, i64 %22
%24 = load i64, i64* %23
%25 = or i64 %22, 1
%26 = getelementptr inbounds i64, i64* %3, i64 %25
%27 = load i64, i64* %26
%28 = mul i64 %24, 3
%29 = getelementptr inbounds double, double* %2, i64 %28
%30 = mul i64 %27, 3
%31 = getelementptr inbounds double, double* %2, i64 %30
br i1 %15, label %34, label %32
32: ; preds = %19
%33 = call double @distance_delta_periodic(double* %29, double* %31, double* %16, double* %8, double* %9)
br label %36
34: ; preds = %19
%35 = call double @distance_delta(double* %29, double* %31, double* %16)
br label %36
36: ; preds = %34, %32
%37 = phi double [ %33, %32 ], [ %35, %34 ]
%38 = getelementptr inbounds double, double* %4, i64 %21
%39 = load double, double* %38
%40 = fsub double %37, %39
%41 = fmul double %40, %5
%42 = call i32 @cosh(double %41)
%43 = add nsw i32 %42, -1
%44 = sitofp i32 %43 to double
%45 = call double @llvm.fmuladd.f64(double %6, double %44, double %20)
br i1 %17, label %51, label %46
46: ; preds = %36
%47 = call double @sinh(double %41)
%48 = fmul double %18, %47
%49 = fdiv double %48, %37
%50 = call i32 @add_grad(i64 %24, i64 %27, double %49, double* %2, double* %16, double* %7)
br label %51
51: ; preds = %36, %46
%52 = add nuw i64 %21, 1
%53 = icmp eq i64 %52, %0
br i1 %53, label %54, label %19
54: ; preds = %51, %10
%55 = phi double [ 0.000000e+00, %10 ], [ %45, %51 ]
ret double %55
}