#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);
scalar_t__ floor(double);
int log(double);
double simplerng_getuniform();
double simplerng_logfactorial(int);
double sqrt(double);
int simplerng_poisson_large(double lambda) {
  static double beta, alpha, k;
  static double old_lambda = -999999.;
  if (lambda != old_lambda) {
    double c = 0.767 - 3.36 / lambda;
    beta = 3.1415926535897932384626433832795 / sqrt(3.0 * lambda);
    alpha = beta * lambda;
    k = log(c) - lambda - log(beta);
    old_lambda = lambda;
  }
  for (;;) {
    double u, x, v, y, temp, lhs, rhs;
    int n;
    u = simplerng_getuniform();
    x = (alpha - log((1.0 - u) / u)) / beta;
    n = (int)floor(x + 0.5);
    if (n < 0)
      continue;
    v = simplerng_getuniform();
    y = alpha - beta * x;
    temp = 1.0 + exp(y);
    lhs = y + log(v / (temp * temp));
    rhs = k + n * log(lambda) - simplerng_logfactorial(n);
    if (lhs <= rhs)
      return n;
  }
}


x86 assembly (clang, -O0):
<simplerng_poisson_large>:
push   %rbp
mov    %rsp,%rbp
sub    $0x80,%rsp
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
ucomisd 0x2ed3(%rip),%xmm0
jne    118e <simplerng_poisson_large+0x2e>
jp     118e <simplerng_poisson_large+0x2e>
jmp    1231 <simplerng_poisson_large+0xd1>
movsd  0xe82(%rip),%xmm1
divsd  -0x8(%rbp),%xmm1
movsd  0xe6d(%rip),%xmm0
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  0xe54(%rip),%xmm0
mulsd  -0x8(%rbp),%xmm0
call   1060 <sqrt@plt>
movaps %xmm0,%xmm1
movsd  0xe37(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,0x2e8b(%rip)
movsd  0x2e83(%rip),%xmm0
mulsd  -0x8(%rbp),%xmm0
movsd  %xmm0,0x2e7e(%rip)
movsd  -0x10(%rbp),%xmm0
call   1050 <log@plt>
cvtsi2sd %eax,%xmm0
subsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  0x2e56(%rip),%xmm0
call   1050 <log@plt>
movsd  -0x58(%rbp),%xmm0
cvtsi2sd %eax,%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,0x2e4c(%rip)
movsd  -0x8(%rbp),%xmm0
movsd  %xmm0,0x2e1f(%rip)
jmp    1236 <simplerng_poisson_large+0xd6>
mov    $0x0,%al
call   1030 <simplerng_getuniform@plt>
movsd  %xmm0,-0x18(%rbp)
movsd  0x2e1e(%rip),%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  0xdd1(%rip),%xmm0
subsd  -0x18(%rbp),%xmm0
divsd  -0x18(%rbp),%xmm0
call   1050 <log@plt>
movsd  -0x60(%rbp),%xmm0
cvtsi2sd %eax,%xmm1
subsd  %xmm1,%xmm0
divsd  0x2de5(%rip),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  0xd98(%rip),%xmm0
addsd  -0x20(%rbp),%xmm0
call   1080 <floor@plt>
mov    %eax,-0x4c(%rbp)
cmpl   $0x0,-0x4c(%rbp)
jge    12a4 <simplerng_poisson_large+0x144>
jmp    1236 <simplerng_poisson_large+0xd6>
mov    $0x0,%al
call   1030 <simplerng_getuniform@plt>
movsd  %xmm0,-0x28(%rbp)
movsd  0x2db0(%rip),%xmm1
movsd  0x2da0(%rip),%xmm0
movsd  -0x20(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
call   1040 <exp@plt>
movaps %xmm0,%xmm1
movsd  0xd2a(%rip),%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x80(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  -0x38(%rbp),%xmm1
mulsd  -0x38(%rbp),%xmm1
divsd  %xmm1,%xmm0
call   1050 <log@plt>
movsd  -0x80(%rbp),%xmm0
cvtsi2sd %eax,%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  0x2d2d(%rip),%xmm0
movsd  %xmm0,-0x78(%rbp)
mov    -0x4c(%rbp),%eax
mov    %eax,-0x6c(%rbp)
movsd  -0x8(%rbp),%xmm0
call   1050 <log@plt>
movsd  -0x78(%rbp),%xmm0
mov    %eax,%ecx
mov    -0x6c(%rbp),%eax
imul   %ecx,%eax
cvtsi2sd %eax,%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x4c(%rbp),%edi
call   1070 <simplerng_logfactorial@plt>
movaps %xmm0,%xmm1
movsd  -0x68(%rbp),%xmm0
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x40(%rbp),%xmm1
movsd  -0x48(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jb     13ab <simplerng_poisson_large+0x24b>
mov    -0x4c(%rbp),%eax
add    $0x80,%rsp
pop    %rbp
ret
jmp    1236 <simplerng_poisson_large+0xd6>

x86 assembly (clang, -O2):
<simplerng_poisson_large>:
push   %rbp
push   %rbx
sub    $0x18,%rsp
movapd %xmm0,%xmm1
movsd  0x2ede(%rip),%xmm0
ucomisd %xmm1,%xmm0
movsd  %xmm1,0x10(%rsp)
jne    1184 <simplerng_poisson_large+0x24>
jnp    1233 <simplerng_poisson_large+0xd3>
movsd  0xe74(%rip),%xmm2
divsd  %xmm1,%xmm2
addsd  0xe70(%rip),%xmm2
movsd  0xe70(%rip),%xmm0
mulsd  %xmm1,%xmm0
xorpd  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jb     11b4 <simplerng_poisson_large+0x54>
sqrtsd %xmm0,%xmm0
jmp    11c3 <simplerng_poisson_large+0x63>
movsd  %xmm2,(%rsp)
call   1060 <sqrt@plt>
movsd  (%rsp),%xmm2
movsd  0xe4d(%rip),%xmm1
divsd  %xmm0,%xmm1
movsd  %xmm1,0x2e89(%rip)
mulsd  0x10(%rsp),%xmm1
movsd  %xmm1,0x2e83(%rip)
movapd %xmm2,%xmm0
call   1050 <log@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
subsd  0x10(%rsp),%xmm0
movsd  %xmm0,(%rsp)
movsd  0x2e58(%rip),%xmm0
call   1050 <log@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
movsd  (%rsp),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,0x2e4b(%rip)
movsd  0x10(%rsp),%xmm0
movsd  %xmm0,0x2e1d(%rip)
jmp    12f2 <simplerng_poisson_large+0x192>
nopl   0x0(%rax,%rax,1)
xor    %eax,%eax
call   1030 <simplerng_getuniform@plt>
movsd  %xmm0,0x8(%rsp)
movsd  0x2e13(%rip),%xmm0
movsd  (%rsp),%xmm1
mulsd  0x2dfe(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,(%rsp)
call   1040 <exp@plt>
addsd  0xda8(%rip),%xmm0
mulsd  %xmm0,%xmm0
movsd  0x8(%rsp),%xmm1
divsd  %xmm0,%xmm1
movapd %xmm1,%xmm0
call   1050 <log@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
addsd  (%rsp),%xmm0
movsd  %xmm0,(%rsp)
movsd  0x2dc8(%rip),%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  0x10(%rsp),%xmm0
call   1050 <log@plt>
imul   %ebx,%eax
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
addsd  0x8(%rsp),%xmm0
movsd  %xmm0,0x8(%rsp)
mov    %ebx,%edi
call   1070 <simplerng_logfactorial@plt>
movsd  0x8(%rsp),%xmm1
subsd  %xmm0,%xmm1
xor    %eax,%eax
ucomisd (%rsp),%xmm1
setae  %al
cmovae %ebx,%ebp
cmp    $0x1,%eax
je     1362 <simplerng_poisson_large+0x202>
xor    %eax,%eax
call   1030 <simplerng_getuniform@plt>
movsd  0x2d67(%rip),%xmm1
movsd  %xmm1,(%rsp)
movsd  0xd12(%rip),%xmm1
subsd  %xmm0,%xmm1
divsd  %xmm0,%xmm1
movapd %xmm1,%xmm0
call   1050 <log@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
movsd  (%rsp),%xmm1
subsd  %xmm0,%xmm1
divsd  0x2d29(%rip),%xmm1
movsd  %xmm1,(%rsp)
movapd %xmm1,%xmm0
addsd  0xce0(%rip),%xmm0
call   1080 <floor@plt>
mov    %rax,%rbx
test   %ebx,%ebx
jns    1240 <simplerng_poisson_large+0xe0>
mov    $0x3,%eax
cmp    $0x1,%eax
jne    12f2 <simplerng_poisson_large+0x192>
mov    %ebp,%eax
add    $0x18,%rsp
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
@simplerng_poisson_large.beta = internal global double 0.000000e+00
@simplerng_poisson_large.alpha = internal global double 0.000000e+00
@simplerng_poisson_large.k = internal global double 0.000000e+00
@simplerng_poisson_large.old_lambda = internal global double -9.999990e+05
define i32 @simplerng_poisson_large(double %0) {
%2 = alloca double
%3 = alloca double
%4 = alloca double
%5 = alloca double
%6 = alloca double
%7 = alloca double
%8 = alloca double
%9 = alloca double
%10 = alloca double
%11 = alloca i32
store double %0, double* %2
%12 = load double, double* %2
%13 = load double, double* @simplerng_poisson_large.old_lambda
%14 = fcmp une double %12, %13
br i1 %14, label %15, label %36
15: ; preds = %1
%16 = load double, double* %2
%17 = fdiv double 3.360000e+00, %16
%18 = fsub double 7.670000e-01, %17
store double %18, double* %3
%19 = load double, double* %2
%20 = fmul double 3.000000e+00, %19
%21 = call double @sqrt(double %20)
%22 = fdiv double 0x400921FB54442D18, %21
store double %22, double* @simplerng_poisson_large.beta
%23 = load double, double* @simplerng_poisson_large.beta
%24 = load double, double* %2
%25 = fmul double %23, %24
store double %25, double* @simplerng_poisson_large.alpha
%26 = load double, double* %3
%27 = call i32 @log(double %26)
%28 = sitofp i32 %27 to double
%29 = load double, double* %2
%30 = fsub double %28, %29
%31 = load double, double* @simplerng_poisson_large.beta
%32 = call i32 @log(double %31)
%33 = sitofp i32 %32 to double
%34 = fsub double %30, %33
store double %34, double* @simplerng_poisson_large.k
%35 = load double, double* %2
store double %35, double* @simplerng_poisson_large.old_lambda
br label %36
36: ; preds = %15, %1
br label %37
37: ; preds = %90, %55, %36
%38 = call double (...) @simplerng_getuniform()
store double %38, double* %4
%39 = load double, double* @simplerng_poisson_large.alpha
%40 = load double, double* %4
%41 = fsub double 1.000000e+00, %40
%42 = load double, double* %4
%43 = fdiv double %41, %42
%44 = call i32 @log(double %43)
%45 = sitofp i32 %44 to double
%46 = fsub double %39, %45
%47 = load double, double* @simplerng_poisson_large.beta
%48 = fdiv double %46, %47
store double %48, double* %5
%49 = load double, double* %5
%50 = fadd double %49, 5.000000e-01
%51 = call i64 @floor(double %50)
%52 = trunc i64 %51 to i32
store i32 %52, i32* %11
%53 = load i32, i32* %11
%54 = icmp slt i32 %53, 0
br i1 %54, label %55, label %56
55: ; preds = %37
br label %37
56: ; preds = %37
%57 = call double (...) @simplerng_getuniform()
store double %57, double* %6
%58 = load double, double* @simplerng_poisson_large.alpha
%59 = load double, double* @simplerng_poisson_large.beta
%60 = load double, double* %5
%61 = fneg double %59
%62 = call double @llvm.fmuladd.f64(double %61, double %60, double %58)
store double %62, double* %7
%63 = load double, double* %7
%64 = call double @exp(double %63)
%65 = fadd double 1.000000e+00, %64
store double %65, double* %8
%66 = load double, double* %7
%67 = load double, double* %6
%68 = load double, double* %8
%69 = load double, double* %8
%70 = fmul double %68, %69
%71 = fdiv double %67, %70
%72 = call i32 @log(double %71)
%73 = sitofp i32 %72 to double
%74 = fadd double %66, %73
store double %74, double* %9
%75 = load double, double* @simplerng_poisson_large.k
%76 = load i32, i32* %11
%77 = load double, double* %2
%78 = call i32 @log(double %77)
%79 = mul nsw i32 %76, %78
%80 = sitofp i32 %79 to double
%81 = fadd double %75, %80
%82 = load i32, i32* %11
%83 = call double @simplerng_logfactorial(i32 %82)
%84 = fsub double %81, %83
store double %84, double* %10
%85 = load double, double* %9
%86 = load double, double* %10
%87 = fcmp ole double %85, %86
br i1 %87, label %88, label %90
88: ; preds = %56
%89 = load i32, i32* %11
ret i32 %89
90: ; preds = %56
br label %37
}

LLVM IR (-O2):
@simplerng_poisson_large.beta = internal unnamed_addr global double 0.000000e+00
@simplerng_poisson_large.alpha = internal unnamed_addr global double 0.000000e+00
@simplerng_poisson_large.k = internal unnamed_addr global double 0.000000e+00
@simplerng_poisson_large.old_lambda = internal unnamed_addr global double -9.999990e+05
define i32 @simplerng_poisson_large(double %0) {
%2 = load double, double* @simplerng_poisson_large.old_lambda
%3 = fcmp une double %2, %0
br i1 %3, label %4, label %18
4: ; preds = %1
%5 = fdiv double 3.360000e+00, %0
%6 = fsub double 7.670000e-01, %5
%7 = fmul double %0, 3.000000e+00
%8 = tail call double @sqrt(double %7)
%9 = fdiv double 0x400921FB54442D18, %8
store double %9, double* @simplerng_poisson_large.beta
%10 = fmul double %9, %0
store double %10, double* @simplerng_poisson_large.alpha
%11 = tail call i32 @log(double %6)
%12 = sitofp i32 %11 to double
%13 = fsub double %12, %0
%14 = load double, double* @simplerng_poisson_large.beta
%15 = tail call i32 @log(double %14)
%16 = sitofp i32 %15 to double
%17 = fsub double %13, %16
store double %17, double* @simplerng_poisson_large.k
store double %0, double* @simplerng_poisson_large.old_lambda
br label %18
18: ; preds = %4, %1
br label %19
19: ; preds = %18, %58
%20 = phi i32 [ %59, %58 ], [ undef, %18 ]
%21 = tail call double (...) @simplerng_getuniform()
%22 = load double, double* @simplerng_poisson_large.alpha
%23 = fsub double 1.000000e+00, %21
%24 = fdiv double %23, %21
%25 = tail call i32 @log(double %24)
%26 = sitofp i32 %25 to double
%27 = fsub double %22, %26
%28 = load double, double* @simplerng_poisson_large.beta
%29 = fdiv double %27, %28
%30 = fadd double %29, 5.000000e-01
%31 = tail call i64 @floor(double %30)
%32 = trunc i64 %31 to i32
%33 = icmp slt i32 %32, 0
br i1 %33, label %58, label %34
34: ; preds = %19
%35 = tail call double (...) @simplerng_getuniform()
%36 = load double, double* @simplerng_poisson_large.alpha
%37 = load double, double* @simplerng_poisson_large.beta
%38 = fneg double %37
%39 = tail call double @llvm.fmuladd.f64(double %38, double %29, double %36)
%40 = tail call double @exp(double %39)
%41 = fadd double %40, 1.000000e+00
%42 = fmul double %41, %41
%43 = fdiv double %35, %42
%44 = tail call i32 @log(double %43)
%45 = sitofp i32 %44 to double
%46 = fadd double %39, %45
%47 = load double, double* @simplerng_poisson_large.k
%48 = tail call i32 @log(double %0)
%49 = mul nsw i32 %48, %32
%50 = sitofp i32 %49 to double
%51 = fadd double %47, %50
%52 = tail call double @simplerng_logfactorial(i32 %32)
%53 = fsub double %51, %52
%54 = fcmp ugt double %46, %53
%55 = select i1 %54, i32 %20, i32 %32
%56 = xor i1 %54, true
%57 = zext i1 %56 to i32
br label %58
58: ; preds = %34, %19
%59 = phi i32 [ %20, %19 ], [ %55, %34 ]
%60 = phi i32 [ 3, %19 ], [ %57, %34 ]
%61 = icmp eq i32 %60, 1
br i1 %61, label %62, label %19
62: ; preds = %58
ret i32 %59
}