#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 bessi0(double);
double bessi1(double);
double fabs(double);
scalar_t__ sqrt(double);
double bessi(double nn, double x) {
  int j, n;
  double bi, bim, bip, tox, ans;
  n = (int)nn;
  if (n == 0)
    return bessi0(x);
  if (n == 1)
    return bessi1(x);
  if (x == 0.0)
    return 0.0;
  else {
    tox = 2.0 / fabs(x);
    bip = ans = 0.0;
    bi = 1.0;
    for (j = 2 * (n + (int)sqrt(40.0 * n)); j > 0; j--) {
      bim = bip + j * tox * bi;
      bip = bi;
      bi = bim;
      if (fabs(bi) > 1.0e10) {
        ans *= 1.0e-10;
        bi *= 1.0e-10;
        bip *= 1.0e-10;
      }
      if (j == n)
        ans = bip;
    }
    ans *= bessi0(x) / bi;
    return x < 0.0 && (n & 1) ? -ans : ans;
  }
}


x86 assembly (clang, -O0):
<bessi>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
cvttsd2si -0x10(%rbp),%eax
mov    %eax,-0x20(%rbp)
cmpl   $0x0,-0x20(%rbp)
jne    1168 <bessi+0x38>
movsd  -0x18(%rbp),%xmm0
call   1040 <bessi0@plt>
movsd  %xmm0,-0x8(%rbp)
jmp    1343 <bessi+0x213>
cmpl   $0x1,-0x20(%rbp)
jne    1186 <bessi+0x56>
movsd  -0x18(%rbp),%xmm0
call   1030 <bessi1@plt>
movsd  %xmm0,-0x8(%rbp)
jmp    1343 <bessi+0x213>
movsd  -0x18(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    11ab <bessi+0x7b>
jp     11ab <bessi+0x7b>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1343 <bessi+0x213>
movsd  -0x18(%rbp),%xmm1
movaps 0xe79(%rip),%xmm0
pand   %xmm0,%xmm1
movsd  0xe4d(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x48(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  0xe24(%rip),%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x20(%rbp),%eax
mov    %eax,-0x4c(%rbp)
cvtsi2sdl -0x20(%rbp),%xmm1
movsd  0xe04(%rip),%xmm0
mulsd  %xmm1,%xmm0
call   1050 <sqrt@plt>
mov    %rax,%rcx
mov    -0x4c(%rbp),%eax
add    %ecx,%eax
shl    $0x1,%eax
mov    %eax,-0x1c(%rbp)
cmpl   $0x0,-0x1c(%rbp)
jle    12d3 <bessi+0x1a3>
movsd  -0x38(%rbp),%xmm1
cvtsi2sdl -0x1c(%rbp),%xmm0
mulsd  -0x40(%rbp),%xmm0
movsd  -0x28(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
movaps 0xdd2(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  0xdae(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    12aa <bessi+0x17a>
movsd  0xda4(%rip),%xmm0
mulsd  -0x48(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  0xd92(%rip),%xmm0
mulsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  0xd80(%rip),%xmm0
mulsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x1c(%rbp),%eax
cmp    -0x20(%rbp),%eax
jne    12c0 <bessi+0x190>
movsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
jmp    12c5 <bessi+0x195>
mov    -0x1c(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x1c(%rbp)
jmp    1213 <bessi+0xe3>
movsd  -0x18(%rbp),%xmm0
call   1040 <bessi0@plt>
divsd  -0x28(%rbp),%xmm0
mulsd  -0x48(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x18(%rbp),%xmm0
jbe    132f <bessi+0x1ff>
mov    -0x20(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     132f <bessi+0x1ff>
movsd  -0x48(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x58(%rbp)
jmp    1339 <bessi+0x209>
movsd  -0x48(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x58(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<bessi>:
push   %rbx
sub    $0x30,%rsp
cvttsd2si %xmm0,%ebx
cmp    $0x1,%ebx
je     114f <bessi+0x1f>
test   %ebx,%ebx
jne    115c <bessi+0x2c>
movaps %xmm1,%xmm0
add    $0x30,%rsp
pop    %rbx
jmp    1040 <bessi0@plt>
movaps %xmm1,%xmm0
add    $0x30,%rsp
pop    %rbx
jmp    1030 <bessi1@plt>
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm1
jne    116c <bessi+0x3c>
jnp    12aa <bessi+0x17a>
movapd %xmm1,(%rsp)
xorps  %xmm0,%xmm0
cvtsi2sd %ebx,%xmm0
mulsd  0xea8(%rip),%xmm0
call   1050 <sqrt@plt>
mov    %eax,%ecx
add    %ebx,%ecx
jle    124d <bessi+0x11d>
movapd 0xe69(%rip),%xmm1
movapd (%rsp),%xmm0
andpd  %xmm0,%xmm1
movsd  0xe77(%rip),%xmm9
divsd  %xmm1,%xmm9
add    %ecx,%ecx
lea    (%rbx,%rax,2),%eax
movsd  0xe75(%rip),%xmm1
xorpd  %xmm4,%xmm4
movapd 0xe38(%rip),%xmm8
movsd  0xe67(%rip),%xmm10
movsd  0xe67(%rip),%xmm3
xorpd  %xmm6,%xmm6
jmp    11f2 <bessi+0xc2>
nop
lea    -0x1(%rcx),%edx
movapd %xmm2,%xmm4
movapd %xmm7,%xmm1
cmp    $0x1,%ecx
mov    %edx,%ecx
jle    125e <bessi+0x12e>
xorps  %xmm7,%xmm7
cvtsi2sd %ecx,%xmm7
mulsd  %xmm9,%xmm7
mulsd  %xmm1,%xmm7
addsd  %xmm6,%xmm7
movapd %xmm7,%xmm2
andpd  %xmm8,%xmm2
ucomisd %xmm10,%xmm2
jbe    121a <bessi+0xea>
mulsd  %xmm3,%xmm7
jbe    1220 <bessi+0xf0>
mulsd  %xmm3,%xmm4
movapd %xmm1,%xmm5
mulsd  %xmm3,%xmm5
movapd %xmm10,%xmm6
cmpltsd %xmm2,%xmm6
andpd  %xmm6,%xmm5
andnpd %xmm1,%xmm6
orpd   %xmm5,%xmm6
movapd %xmm6,%xmm2
sub    $0x1,%eax
jb     11e0 <bessi+0xb0>
movapd %xmm4,%xmm2
jmp    11e0 <bessi+0xb0>
movsd  0xddb(%rip),%xmm7
xorpd  %xmm2,%xmm2
movapd (%rsp),%xmm0
movapd %xmm7,0x20(%rsp)
movsd  %xmm2,0x18(%rsp)
call   1040 <bessi0@plt>
movapd (%rsp),%xmm2
divsd  0x20(%rsp),%xmm0
mulsd  0x18(%rsp),%xmm0
cmpnltsd 0xdbf(%rip),%xmm2
movapd %xmm2,%xmm1
andpd  %xmm0,%xmm1
test   $0x1,%bl
je     129e <bessi+0x16e>
xorpd  0xd72(%rip),%xmm0
andnpd %xmm0,%xmm2
orpd   %xmm1,%xmm2
movapd %xmm2,%xmm0
add    $0x30,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define double @bessi(double %0, double %1) {
%3 = alloca double
%4 = alloca double
%5 = alloca double
%6 = alloca i32
%7 = alloca i32
%8 = alloca double
%9 = alloca double
%10 = alloca double
%11 = alloca double
%12 = alloca double
store double %0, double* %4
store double %1, double* %5
%13 = load double, double* %4
%14 = fptosi double %13 to i32
store i32 %14, i32* %7
%15 = load i32, i32* %7
%16 = icmp eq i32 %15, 0
br i1 %16, label %17, label %20
17: ; preds = %2
%18 = load double, double* %5
%19 = call double @bessi0(double %18)
store double %19, double* %3
br label %95
20: ; preds = %2
%21 = load i32, i32* %7
%22 = icmp eq i32 %21, 1
br i1 %22, label %23, label %26
23: ; preds = %20
%24 = load double, double* %5
%25 = call double @bessi1(double %24)
store double %25, double* %3
br label %95
26: ; preds = %20
%27 = load double, double* %5
%28 = fcmp oeq double %27, 0.000000e+00
br i1 %28, label %29, label %30
29: ; preds = %26
store double 0.000000e+00, double* %3
br label %95
30: ; preds = %26
%31 = load double, double* %5
%32 = call double @llvm.fabs.f64(double %31)
%33 = fdiv double 2.000000e+00, %32
store double %33, double* %11
store double 0.000000e+00, double* %12
store double 0.000000e+00, double* %10
store double 1.000000e+00, double* %8
%34 = load i32, i32* %7
%35 = load i32, i32* %7
%36 = sitofp i32 %35 to double
%37 = fmul double 4.000000e+01, %36
%38 = call i64 @sqrt(double %37)
%39 = trunc i64 %38 to i32
%40 = add nsw i32 %34, %39
%41 = mul nsw i32 2, %40
store i32 %41, i32* %6
br label %42
42: ; preds = %72, %30
%43 = load i32, i32* %6
%44 = icmp sgt i32 %43, 0
br i1 %44, label %45, label %75
45: ; preds = %42
%46 = load double, double* %10
%47 = load i32, i32* %6
%48 = sitofp i32 %47 to double
%49 = load double, double* %11
%50 = fmul double %48, %49
%51 = load double, double* %8
%52 = call double @llvm.fmuladd.f64(double %50, double %51, double %46)
store double %52, double* %9
%53 = load double, double* %8
store double %53, double* %10
%54 = load double, double* %9
store double %54, double* %8
%55 = load double, double* %8
%56 = call double @llvm.fabs.f64(double %55)
%57 = fcmp ogt double %56, 1.000000e+10
br i1 %57, label %58, label %65
58: ; preds = %45
%59 = load double, double* %12
%60 = fmul double %59, 1.000000e-10
store double %60, double* %12
%61 = load double, double* %8
%62 = fmul double %61, 1.000000e-10
store double %62, double* %8
%63 = load double, double* %10
%64 = fmul double %63, 1.000000e-10
store double %64, double* %10
br label %65
65: ; preds = %58, %45
%66 = load i32, i32* %6
%67 = load i32, i32* %7
%68 = icmp eq i32 %66, %67
br i1 %68, label %69, label %71
69: ; preds = %65
%70 = load double, double* %10
store double %70, double* %12
br label %71
71: ; preds = %69, %65
br label %72
72: ; preds = %71
%73 = load i32, i32* %6
%74 = add nsw i32 %73, -1
store i32 %74, i32* %6
br label %42
75: ; preds = %42
%76 = load double, double* %5
%77 = call double @bessi0(double %76)
%78 = load double, double* %8
%79 = fdiv double %77, %78
%80 = load double, double* %12
%81 = fmul double %80, %79
store double %81, double* %12
%82 = load double, double* %5
%83 = fcmp olt double %82, 0.000000e+00
br i1 %83, label %84, label %91
84: ; preds = %75
%85 = load i32, i32* %7
%86 = and i32 %85, 1
%87 = icmp ne i32 %86, 0
br i1 %87, label %88, label %91
88: ; preds = %84
%89 = load double, double* %12
%90 = fneg double %89
br label %93
91: ; preds = %84, %75
%92 = load double, double* %12
br label %93
93: ; preds = %91, %88
%94 = phi double [ %90, %88 ], [ %92, %91 ]
store double %94, double* %3
br label %95
95: ; preds = %93, %29, %23, %17
%96 = load double, double* %3
ret double %96
}

LLVM IR (-O2):
define double @bessi(double %0, double %1) {
%3 = fptosi double %0 to i32
switch i32 %3, label %8 [
i32 0, label %4
i32 1, label %6
]
4: ; preds = %2
%5 = tail call double @bessi0(double %1)
br label %53
6: ; preds = %2
%7 = tail call double @bessi1(double %1)
br label %53
8: ; preds = %2
%9 = fcmp oeq double %1, 0.000000e+00
br i1 %9, label %53, label %10
10: ; preds = %8
%11 = tail call double @llvm.fabs.f64(double %1)
%12 = fdiv double 2.000000e+00, %11
%13 = sitofp i32 %3 to double
%14 = fmul double %13, 4.000000e+01
%15 = tail call i64 @sqrt(double %14)
%16 = trunc i64 %15 to i32
%17 = add nsw i32 %16, %3
%18 = icmp sgt i32 %17, 0
br i1 %18, label %19, label %41
19: ; preds = %10
%20 = shl nuw nsw i32 %17, 1
br label %21
21: ; preds = %19, %21
%22 = phi double [ %38, %21 ], [ 0.000000e+00, %19 ]
%23 = phi double [ %35, %21 ], [ 0.000000e+00, %19 ]
%24 = phi i32 [ %39, %21 ], [ %20, %19 ]
%25 = phi double [ %34, %21 ], [ 1.000000e+00, %19 ]
%26 = sitofp i32 %24 to double
%27 = fmul double %12, %26
%28 = tail call double @llvm.fmuladd.f64(double %27, double %25, double %23)
%29 = tail call double @llvm.fabs.f64(double %28)
%30 = fcmp ogt double %29, 1.000000e+10
%31 = fmul double %22, 1.000000e-10
%32 = fmul double %28, 1.000000e-10
%33 = fmul double %25, 1.000000e-10
%34 = select i1 %30, double %32, double %28
%35 = select i1 %30, double %33, double %25
%36 = select i1 %30, double %31, double %22
%37 = icmp eq i32 %24, %3
%38 = select i1 %37, double %35, double %36
%39 = add nsw i32 %24, -1
%40 = icmp sgt i32 %24, 1
br i1 %40, label %21, label %41
41: ; preds = %21, %10
%42 = phi double [ 1.000000e+00, %10 ], [ %34, %21 ]
%43 = phi double [ 0.000000e+00, %10 ], [ %38, %21 ]
%44 = tail call double @bessi0(double %1)
%45 = fdiv double %44, %42
%46 = fmul double %43, %45
%47 = fcmp uge double %1, 0.000000e+00
%48 = and i32 %3, 1
%49 = icmp eq i32 %48, 0
%50 = select i1 %47, i1 true, i1 %49
%51 = fneg double %46
%52 = select i1 %50, double %46, double %51
br label %53
53: ; preds = %8, %41, %6, %4
%54 = phi double [ %5, %4 ], [ %7, %6 ], [ %52, %41 ], [ 0.000000e+00, %8 ]
ret double %54
}