#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 loggam(double x) {
  double x0, x2, xp, gl, gl0;
  long k, n;
  static double a[10] = {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.39243221690590e+00};
  x0 = x;
  n = 0;
  if ((x == 1.0) || (x == 2.0)) {
    return 0.0;
  } else if (x <= 7.0) {
    n = (long)(7 - x);
    x0 = x + n;
  }
  x2 = 1.0 / (x0 * x0);
  xp = 2 * 3.14159265358979323846264338328;
  gl0 = a[9];
  for (k = 8; k >= 0; k--) {
    gl0 *= x2;
    gl0 += 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):
<loggam>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
movq   $0x0,-0x48(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  0xec4(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    1151 <loggam+0x41>
jp     1151 <loggam+0x41>
jmp    116e <loggam+0x5e>
movsd  -0x10(%rbp),%xmm0
movsd  0xeaa(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    117b <loggam+0x6b>
jp     117b <loggam+0x6b>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1337 <loggam+0x227>
movsd  0xe8d(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     11b8 <loggam+0xa8>
movsd  0xe7a(%rip),%xmm0
subsd  -0x10(%rbp),%xmm0
cvttsd2si %xmm0,%rax
mov    %rax,-0x48(%rbp)
movsd  -0x10(%rbp),%xmm0
cvtsi2sdq -0x48(%rbp),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    11bd <loggam+0xad>
movsd  -0x18(%rbp),%xmm1
mulsd  -0x18(%rbp),%xmm1
movsd  0xe31(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  0xe38(%rip),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  0x2e8b(%rip),%xmm0
movsd  %xmm0,-0x38(%rbp)
movq   $0x8,-0x40(%rbp)
cmpq   $0x0,-0x40(%rbp)
jl     123f <loggam+0x12f>
movsd  -0x20(%rbp),%xmm0
mulsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x40(%rbp),%rcx
lea    0x2e11(%rip),%rax
movsd  (%rax,%rcx,8),%xmm0
addsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x40(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x40(%rbp)
jmp    11fa <loggam+0xea>
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  0xdbb(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  0xda1(%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  0xd57(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     132d <loggam+0x21d>
movq   $0x1,-0x40(%rbp)
mov    -0x40(%rbp),%rax
cmp    -0x48(%rbp),%rax
jg     1328 <loggam+0x218>
movsd  -0x18(%rbp),%xmm0
movsd  0xd19(%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  0xcf2(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x40(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x40(%rbp)
jmp    12cc <loggam+0x1bc>
jmp    132d <loggam+0x21d>
movsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<loggam>:
push   %r14
push   %rbx
sub    $0x18,%rsp
ucomisd 0xee1(%rip),%xmm0
xorpd  %xmm3,%xmm3
jne    112b <loggam+0x1b>
jnp    1292 <loggam+0x182>
movapd %xmm0,%xmm1
ucomisd 0xed1(%rip),%xmm0
jne    113f <loggam+0x2f>
jnp    1292 <loggam+0x182>
movsd  0xec9(%rip),%xmm2
movapd %xmm2,%xmm0
subsd  %xmm1,%xmm0
cvttsd2si %xmm0,%r14
xorps  %xmm0,%xmm0
cvtsi2sd %r14,%xmm0
addsd  %xmm1,%xmm0
ucomisd %xmm1,%xmm2
movsd  %xmm0,(%rsp)
jae    116f <loggam+0x5f>
movapd %xmm1,%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  %xmm1,0x10(%rsp)
call   1030 <log@plt>
xor    %ebx,%ebx
movsd  0xe86(%rip),%xmm1
ucomisd 0x10(%rsp),%xmm1
movsd  0x8(%rsp),%xmm3
movapd %xmm3,%xmm1
mulsd  %xmm3,%xmm1
movsd  0xe5a(%rip),%xmm2
divsd  %xmm1,%xmm2
movsd  0xe66(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe62(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe5e(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe5a(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe56(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe52(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe4e(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe4a(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe46(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe42(%rip),%xmm1
cmovae %r14,%rbx
movapd %xmm3,%xmm2
divsd  %xmm3,%xmm1
addsd  0xe36(%rip),%xmm1
movsd  0xe36(%rip),%xmm3
addsd  %xmm2,%xmm3
mulsd  %xmm0,%xmm3
addsd  %xmm1,%xmm3
subsd  %xmm2,%xmm3
jb     1292 <loggam+0x182>
test   %rbx,%rbx
jle    1292 <loggam+0x182>
movsd  (%rsp),%xmm0
cs nopw 0x0(%rax,%rax,1)
movsd  %xmm3,0x8(%rsp)
addsd  0xe0a(%rip),%xmm0
movsd  %xmm0,(%rsp)
movsd  (%rsp),%xmm0
call   1030 <log@plt>
movsd  0x8(%rsp),%xmm3
subsd  %xmm0,%xmm3
movsd  (%rsp),%xmm0
add    $0xffffffffffffffff,%rbx
jne    1260 <loggam+0x150>
movapd %xmm3,%xmm0
add    $0x18,%rsp
pop    %rbx
pop    %r14
ret

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

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