#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 log(double);
double lgamma(double x) {
  double x0, x2, xp, gl, gl0;
  int n, k;
  double M_PI = 3.14159265358979323846;
  static double a[] = {8.333333333333333e-02, -2.777777777777778e-03,
                       7.936507936507937e-04, -5.952380952380952e-04,
                       8.417508417508418e-04, -1.917526917526918e-03,
                       6.410256410256410e-03, -2.955065359477124e-02,
                       1.796443723688307e-01, -1.39243221690590};
  x0 = x;
  if (x <= 0.0)
    return 1e308;
  else if ((x == 1.0) || (x == 2.0))
    return 0.0;
  else if (x <= 7.0) {
    n = (int)(7 - x);
    x0 = x + n;
  }
  x2 = 1.0 / (x0 * x0);
  xp = 2.0 * M_PI;
  gl0 = a[9];
  for (k = 8; k >= 0; k--) {
    gl0 = gl0 * x2 + a[k];
  }
  gl = gl0 / x0 + 0.5 * log(xp) + (x0 - 0.5) * log(x0) - x0;
  if (x <= 7.0) {
    for (k = 1; k <= n; k++) {
      gl -= log(x0 - 1.0);
      x0 -= 1.0;
    }
  }
  return gl;
}


x86 assembly (clang, -O0):
<lgamma>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  0xedb(%rip),%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     1154 <lgamma+0x44>
movsd  0xede(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1356 <lgamma+0x246>
movsd  -0x10(%rbp),%xmm0
movsd  0xea7(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    1176 <lgamma+0x66>
jp     1176 <lgamma+0x66>
jmp    1193 <lgamma+0x83>
movsd  -0x10(%rbp),%xmm0
movsd  0xe8d(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    11a0 <lgamma+0x90>
jp     11a0 <lgamma+0x90>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1356 <lgamma+0x246>
movsd  0xe70(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     11da <lgamma+0xca>
movsd  0xe5d(%rip),%xmm0
subsd  -0x10(%rbp),%xmm0
cvttsd2si %xmm0,%eax
mov    %eax,-0x3c(%rbp)
movsd  -0x10(%rbp),%xmm0
cvtsi2sdl -0x3c(%rbp),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    11df <lgamma+0xcf>
jmp    11e4 <lgamma+0xd4>
movsd  -0x18(%rbp),%xmm1
mulsd  -0x18(%rbp),%xmm1
movsd  0xe12(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  0xe09(%rip),%xmm0
mulsd  -0x48(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  0x2e5f(%rip),%xmm0
movsd  %xmm0,-0x38(%rbp)
movl   $0x8,-0x40(%rbp)
cmpl   $0x0,-0x40(%rbp)
jl     1264 <lgamma+0x154>
movsd  -0x38(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm2
movslq -0x40(%rbp),%rcx
lea    0x2dec(%rip),%rax
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x40(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x40(%rbp)
jmp    1225 <lgamma+0x115>
movsd  -0x38(%rbp),%xmm0
divsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  -0x28(%rbp),%xmm0
call   1030 <log@plt>
movsd  -0x60(%rbp),%xmm1
movsd  0xd96(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  0xd7c(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x18(%rbp),%xmm0
call   1030 <log@plt>
movsd  -0x58(%rbp),%xmm1
movaps %xmm0,%xmm2
movsd  -0x50(%rbp),%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
subsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  0xd3a(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     134c <lgamma+0x23c>
movl   $0x1,-0x40(%rbp)
mov    -0x40(%rbp),%eax
cmp    -0x3c(%rbp),%eax
jg     1347 <lgamma+0x237>
movsd  -0x18(%rbp),%xmm0
movsd  0xcff(%rip),%xmm1
subsd  %xmm1,%xmm0
call   1030 <log@plt>
movaps %xmm0,%xmm1
movsd  -0x30(%rbp),%xmm0
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  0xcd8(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x40(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x40(%rbp)
jmp    12f0 <lgamma+0x1e0>
jmp    134c <lgamma+0x23c>
movsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<lgamma>:
push   %rbx
sub    $0x50,%rsp
xorpd  %xmm1,%xmm1
ucomisd %xmm0,%xmm1
jae    12b3 <lgamma+0x1a3>
ucomisd 0xedd(%rip),%xmm0
jne    1133 <lgamma+0x23>
jnp    12bb <lgamma+0x1ab>
ucomisd 0xed5(%rip),%xmm0
jne    1143 <lgamma+0x33>
jnp    12bb <lgamma+0x1ab>
movsd  0xecd(%rip),%xmm2
movapd %xmm2,%xmm1
subsd  %xmm0,%xmm1
movapd %xmm0,%xmm3
movapd %xmm0,0x10(%rsp)
movapd %xmm1,0x30(%rsp)
cvttpd2dq %xmm1,%xmm0
cvtdq2pd %xmm0,%xmm1
addsd  %xmm3,%xmm1
movapd %xmm3,%xmm4
cmplesd %xmm2,%xmm4
movapd %xmm4,%xmm0
movapd %xmm1,(%rsp)
andpd  %xmm1,%xmm0
andnpd %xmm3,%xmm4
orpd   %xmm0,%xmm4
movapd %xmm4,%xmm1
mulsd  %xmm4,%xmm1
movsd  0xe6b(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  0xe77(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xe73(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xe6f(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xe6b(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xe67(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xe63(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xe5f(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xe5b(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xe57(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xe53(%rip),%xmm1
movapd %xmm4,%xmm0
movapd %xmm4,0x40(%rsp)
divsd  %xmm4,%xmm1
addsd  0xe45(%rip),%xmm1
movsd  %xmm1,0x28(%rsp)
movsd  0xe3f(%rip),%xmm1
addsd  %xmm4,%xmm1
movsd  %xmm1,0x20(%rsp)
call   1030 <log@plt>
movapd %xmm0,%xmm1
mulsd  0x20(%rsp),%xmm1
addsd  0x28(%rsp),%xmm1
subsd  0x40(%rsp),%xmm1
movsd  0xdb2(%rip),%xmm0
ucomisd 0x10(%rsp),%xmm0
jb     12bb <lgamma+0x1ab>
cvttsd2si 0x30(%rsp),%ebx
test   %ebx,%ebx
jle    12bb <lgamma+0x1ab>
movapd (%rsp),%xmm0
nopl   (%rax)
movsd  %xmm1,0x10(%rsp)
addsd  0xdf2(%rip),%xmm0
movapd %xmm0,(%rsp)
movapd (%rsp),%xmm0
call   1030 <log@plt>
movsd  0x10(%rsp),%xmm1
subsd  %xmm0,%xmm1
movapd (%rsp),%xmm0
add    $0xffffffff,%ebx
jne    1280 <lgamma+0x170>
jmp    12bb <lgamma+0x1ab>
movsd  0xd45(%rip),%xmm1
movapd %xmm1,%xmm0
add    $0x50,%rsp
pop    %rbx
ret

LLVM IR (-O0):
@lgamma.a = internal global [10 x double] [double 0x3FB5555555555555, double 0xBF66C16C16C16C17, double 0x3F4A01A01A01A01A, double 0xBF43813813813813, double 0x3F4B951E2B18FF24, double 0xBF5F6AB0D9993C7F, double 0x3F7A41A41A41A41A, double 0xBF9E4286CB0F5397, double 0x3FC6FE96381E0685, double 0xBFF6476701181F35]
define double @lgamma(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 i32
%10 = alloca i32
%11 = alloca double
store double %0, double* %3
store double 0x400921FB54442D18, double* %11
%12 = load double, double* %3
store double %12, double* %4
%13 = load double, double* %3
%14 = fcmp ole double %13, 0.000000e+00
br i1 %14, label %15, label %16
15: ; preds = %1
store double 1.000000e+308, double* %2
br label %93
16: ; preds = %1
%17 = load double, double* %3
%18 = fcmp oeq double %17, 1.000000e+00
br i1 %18, label %22, label %19
19: ; preds = %16
%20 = load double, double* %3
%21 = fcmp oeq double %20, 2.000000e+00
br i1 %21, label %22, label %23
22: ; preds = %19, %16
store double 0.000000e+00, double* %2
br label %93
23: ; preds = %19
%24 = load double, double* %3
%25 = fcmp ole double %24, 7.000000e+00
br i1 %25, label %26, label %34
26: ; preds = %23
%27 = load double, double* %3
%28 = fsub double 7.000000e+00, %27
%29 = fptosi double %28 to i32
store i32 %29, i32* %9
%30 = load double, double* %3
%31 = load i32, i32* %9
%32 = sitofp i32 %31 to double
%33 = fadd double %30, %32
store double %33, double* %4
br label %34
34: ; preds = %26, %23
br label %35
35: ; preds = %34
br label %36
36: ; preds = %35
%37 = load double, double* %4
%38 = load double, double* %4
%39 = fmul double %37, %38
%40 = fdiv double 1.000000e+00, %39
store double %40, double* %5
%41 = load double, double* %11
%42 = fmul double 2.000000e+00, %41
store double %42, double* %6
%43 = load double, double* getelementptr inbounds ([10 x double], [10 x double]* @lgamma.a, i64 0, i64 9)
store double %43, double* %8
store i32 8, i32* %10
br label %44
44: ; preds = %55, %36
%45 = load i32, i32* %10
%46 = icmp sge i32 %45, 0
br i1 %46, label %47, label %58
47: ; preds = %44
%48 = load double, double* %8
%49 = load double, double* %5
%50 = load i32, i32* %10
%51 = sext i32 %50 to i64
%52 = getelementptr inbounds [10 x double], [10 x double]* @lgamma.a, i64 0, i64 %51
%53 = load double, double* %52
%54 = call double @llvm.fmuladd.f64(double %48, double %49, double %53)
store double %54, double* %8
br label %55
55: ; preds = %47
%56 = load i32, i32* %10
%57 = add nsw i32 %56, -1
store i32 %57, i32* %10
br label %44
58: ; preds = %44
%59 = load double, double* %8
%60 = load double, double* %4
%61 = fdiv double %59, %60
%62 = load double, double* %6
%63 = call double @log(double %62)
%64 = call double @llvm.fmuladd.f64(double 5.000000e-01, double %63, double %61)
%65 = load double, double* %4
%66 = fsub double %65, 5.000000e-01
%67 = load double, double* %4
%68 = call double @log(double %67)
%69 = call double @llvm.fmuladd.f64(double %66, double %68, double %64)
%70 = load double, double* %4
%71 = fsub double %69, %70
store double %71, double* %7
%72 = load double, double* %3
%73 = fcmp ole double %72, 7.000000e+00
br i1 %73, label %74, label %91
74: ; preds = %58
store i32 1, i32* %10
br label %75
75: ; preds = %87, %74
%76 = load i32, i32* %10
%77 = load i32, i32* %9
%78 = icmp sle i32 %76, %77
br i1 %78, label %79, label %90
79: ; preds = %75
%80 = load double, double* %4
%81 = fsub double %80, 1.000000e+00
%82 = call double @log(double %81)
%83 = load double, double* %7
%84 = fsub double %83, %82
store double %84, double* %7
%85 = load double, double* %4
%86 = fsub double %85, 1.000000e+00
store double %86, double* %4
br label %87
87: ; preds = %79
%88 = load i32, i32* %10
%89 = add nsw i32 %88, 1
store i32 %89, i32* %10
br label %75
90: ; preds = %75
br label %91
91: ; preds = %90, %58
%92 = load double, double* %7
store double %92, double* %2
br label %93
93: ; preds = %91, %22, %15
%94 = load double, double* %2
ret double %94
}

LLVM IR (-O2):
define double @lgamma(double %0) {
%2 = fcmp ugt double %0, 0.000000e+00
br i1 %2, label %3, label %44
3: ; preds = %1
%4 = fcmp oeq double %0, 1.000000e+00
%5 = fcmp oeq double %0, 2.000000e+00
%6 = or i1 %4, %5
br i1 %6, label %44, label %7
7: ; preds = %3
%8 = fcmp ole double %0, 7.000000e+00
%9 = fsub double 7.000000e+00, %0
%10 = fptosi double %9 to i32
%11 = sitofp i32 %10 to double
%12 = fadd double %11, %0
%13 = select i1 %8, double %12, double %0
%14 = fmul double %13, %13
%15 = fdiv double 1.000000e+00, %14
%16 = tail call double @llvm.fmuladd.f64(double %15, double 0xBFF6476701181F35, double 0x3FC6FE96381E0685)
%17 = tail call double @llvm.fmuladd.f64(double %16, double %15, double 0xBF9E4286CB0F5397)
%18 = tail call double @llvm.fmuladd.f64(double %17, double %15, double 0x3F7A41A41A41A41A)
%19 = tail call double @llvm.fmuladd.f64(double %18, double %15, double 0xBF5F6AB0D9993C7F)
%20 = tail call double @llvm.fmuladd.f64(double %19, double %15, double 0x3F4B951E2B18FF24)
%21 = tail call double @llvm.fmuladd.f64(double %20, double %15, double 0xBF43813813813813)
%22 = tail call double @llvm.fmuladd.f64(double %21, double %15, double 0x3F4A01A01A01A01A)
%23 = tail call double @llvm.fmuladd.f64(double %22, double %15, double 0xBF66C16C16C16C17)
%24 = tail call double @llvm.fmuladd.f64(double %23, double %15, double 0x3FB5555555555555)
%25 = select i1 %8, i32 %10, i32 undef
%26 = fdiv double %24, %13
%27 = fadd double %26, 0x3FED67F1C864BEB4
%28 = fadd double %13, -5.000000e-01
%29 = tail call double @log(double %13)
%30 = tail call double @llvm.fmuladd.f64(double %28, double %29, double %27)
%31 = fsub double %30, %13
%32 = xor i1 %8, true
%33 = icmp slt i32 %25, 1
%34 = select i1 %32, i1 true, i1 %33
br i1 %34, label %44, label %35
35: ; preds = %7, %35
%36 = phi i32 [ %42, %35 ], [ 1, %7 ]
%37 = phi double [ %41, %35 ], [ %31, %7 ]
%38 = phi double [ %39, %35 ], [ %12, %7 ]
%39 = fadd double %38, -1.000000e+00
%40 = tail call double @log(double %39)
%41 = fsub double %37, %40
%42 = add nuw i32 %36, 1
%43 = icmp eq i32 %36, %25
br i1 %43, label %44, label %35
44: ; preds = %35, %7, %3, %1
%45 = phi double [ 1.000000e+308, %1 ], [ 0.000000e+00, %3 ], [ %31, %7 ], [ %41, %35 ]
ret double %45
}