#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 */
long double expl(int);
long double logl(long double);
long double powl(int, int);
long double log_gamma(double N) {
  const long double SQRT2PI =
      2.5066282746310005024157652848110452530069867406099383;
  long double Z = (long double)N;
  long double Sc;
  Sc = (logl(Z + 15) * (Z + 0.5)) - (Z + 15) - logl(Z);
  long double F = 1.0;
  long double Ck;
  long double Sum = SQRT2PI;
  for (int K = 1; K < 15; K++) {
    Z++;
    Ck = powl(15 - K, K - 0.5);
    Ck *= expl(15 - K);
    Ck /= F;
    Sum += (Ck / Z);
    F *= (-1.0 * K);
  }
  return logl(Sum) + Sc;
}


x86 assembly (clang, -O0):
<log_gamma>:
push   %rbp
mov    %rsp,%rbp
sub    $0xc0,%rsp
movsd  %xmm0,-0x8(%rbp)
fldl   0xeba(%rip)
fld    %st(0)
fstpt  -0x8c(%rbp)
fstpt  -0x20(%rbp)
fldl   -0x8(%rbp)
fstpt  -0x30(%rbp)
fldt   -0x30(%rbp)
flds   0xeb0(%rip)
fld    %st(0)
fstpt  -0xa4(%rbp)
faddp  %st,%st(1)
mov    %rsp,%rax
fstpt  (%rax)
call   1040 <logl@plt>
fldt   -0xa4(%rbp)
fldt   -0x30(%rbp)
flds   0xe91(%rip)
fadd   %st(1),%st
fxch   %st(2)
fadd   %st(1),%st
fxch   %st(3)
fmulp  %st,%st(2)
fxch   %st(1)
fsubp  %st,%st(2)
fxch   %st(1)
fstpt  -0x98(%rbp)
mov    %rsp,%rax
fstpt  (%rax)
call   1040 <logl@plt>
fldt   -0x98(%rbp)
fldt   -0x8c(%rbp)
fxch   %st(1)
fsubp  %st,%st(2)
fxch   %st(1)
fstpt  -0x40(%rbp)
fld1
fstpt  -0x50(%rbp)
fstpt  -0x70(%rbp)
movl   $0x1,-0x74(%rbp)
cmpl   $0xf,-0x74(%rbp)
jge    1268 <log_gamma+0x138>
fldt   -0x30(%rbp)
fld1
faddp  %st,%st(1)
fstpt  -0x30(%rbp)
mov    -0x74(%rbp),%eax
mov    $0xf,%edi
mov    %edi,-0xa8(%rbp)
sub    %eax,%edi
cvtsi2sd %eax,%xmm0
movsd  0xe11(%rip),%xmm1
addsd  %xmm1,%xmm0
cvttsd2si %xmm0,%esi
call   1030 <powl@plt>
mov    -0xa8(%rbp),%edi
fstpt  -0x60(%rbp)
mov    -0x74(%rbp),%eax
sub    %eax,%edi
call   1050 <expl@plt>
fldt   -0x60(%rbp)
fmulp  %st,%st(1)
fstpt  -0x60(%rbp)
fldt   -0x50(%rbp)
fldt   -0x60(%rbp)
fdivp  %st,%st(1)
fstpt  -0x60(%rbp)
fldt   -0x60(%rbp)
fldt   -0x30(%rbp)
fdivrp %st,%st(1)
fldt   -0x70(%rbp)
faddp  %st,%st(1)
fstpt  -0x70(%rbp)
cvtsi2sdl -0x74(%rbp),%xmm0
movaps 0xdda(%rip),%xmm1
pxor   %xmm1,%xmm0
movlpd %xmm0,-0x80(%rbp)
fldl   -0x80(%rbp)
fldt   -0x50(%rbp)
fmulp  %st,%st(1)
fstpt  -0x50(%rbp)
mov    -0x74(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x74(%rbp)
jmp    11c7 <log_gamma+0x97>
fldt   -0x70(%rbp)
mov    %rsp,%rax
fstpt  (%rax)
call   1040 <logl@plt>
fldt   -0x40(%rbp)
faddp  %st,%st(1)
add    $0xc0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<log_gamma>:
push   %rbx
sub    $0xb0,%rsp
movsd  %xmm0,0x60(%rsp)
fldl   0x60(%rsp)
fld    %st(0)
fstpt  0x18(%rsp)
fadds  0xeb2(%rip)
fld    %st(0)
fstpt  0x80(%rsp)
fstpt  (%rsp)
call   1040 <logl@plt>
fstpt  0x74(%rsp)
fldt   0x18(%rsp)
fstpt  (%rsp)
fld1
fstpt  0x4c(%rsp)
fldl   0xe92(%rip)
fstpt  0x24(%rsp)
mov    $0xe,%ebx
call   1040 <logl@plt>
fstpt  0x68(%rsp)
movsd  0xe80(%rip),%xmm0
fldt   0x18(%rsp)
fldt   0x4c(%rsp)
nopl   0x0(%rax,%rax,1)
fstpt  0x98(%rsp)
movapd %xmm0,0x30(%rsp)
fldt   0x4c(%rsp)
faddp  %st,%st(1)
fstpt  0xa4(%rsp)
movapd 0x30(%rsp),%xmm0
addsd  0xe50(%rip),%xmm0
cvttsd2si %xmm0,%esi
mov    %ebx,%edi
call   1030 <powl@plt>
fstpt  0x8c(%rsp)
mov    %ebx,%edi
call   1050 <expl@plt>
fldt   0x98(%rsp)
fldt   0xa4(%rsp)
fldt   0x8c(%rsp)
fmulp  %st,%st(3)
fxch   %st(2)
fdiv   %st(1),%st
fdiv   %st(2),%st
fldt   0x24(%rsp)
faddp  %st,%st(1)
fstpt  0x24(%rsp)
movaps 0x30(%rsp),%xmm0
xorps  0xe0c(%rip),%xmm0
movlps %xmm0,0x58(%rsp)
movapd 0x30(%rsp),%xmm0
fmull  0x58(%rsp)
addsd  0xde5(%rip),%xmm0
add    $0xffffffff,%ebx
jne    11a0 <log_gamma+0x70>
fstp   %st(1)
fstp   %st(0)
fldt   0x18(%rsp)
fadds  0xdc2(%rip)
fldt   0x74(%rsp)
fmulp  %st,%st(1)
fldt   0x80(%rsp)
fsubrp %st,%st(1)
fldt   0x68(%rsp)
fsubrp %st,%st(1)
fstpt  0x30(%rsp)
fldt   0x24(%rsp)
fstpt  (%rsp)
call   1040 <logl@plt>
fldt   0x30(%rsp)
faddp  %st,%st(1)
add    $0xb0,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define x86_fp80 @log_gamma(double %0) {
%2 = alloca double
%3 = alloca x86_fp80
%4 = alloca x86_fp80
%5 = alloca x86_fp80
%6 = alloca x86_fp80
%7 = alloca x86_fp80
%8 = alloca x86_fp80
%9 = alloca i32
store double %0, double* %2
store x86_fp80 0xK4000A06C98FFB1383000, x86_fp80* %3
%10 = load double, double* %2
%11 = fpext double %10 to x86_fp80
store x86_fp80 %11, x86_fp80* %4
%12 = load x86_fp80, x86_fp80* %4
%13 = fadd x86_fp80 %12, 0xK4002F000000000000000
%14 = call x86_fp80 @logl(x86_fp80 %13)
%15 = load x86_fp80, x86_fp80* %4
%16 = fadd x86_fp80 %15, 0xK3FFE8000000000000000
%17 = load x86_fp80, x86_fp80* %4
%18 = fadd x86_fp80 %17, 0xK4002F000000000000000
%19 = fneg x86_fp80 %18
%20 = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %14, x86_fp80 %16, x86_fp80 %19)
%21 = load x86_fp80, x86_fp80* %4
%22 = call x86_fp80 @logl(x86_fp80 %21)
%23 = fsub x86_fp80 %20, %22
store x86_fp80 %23, x86_fp80* %5
store x86_fp80 0xK3FFF8000000000000000, x86_fp80* %6
store x86_fp80 0xK4000A06C98FFB1383000, x86_fp80* %8
store i32 1, i32* %9
br label %24
24: ; preds = %56, %1
%25 = load i32, i32* %9
%26 = icmp slt i32 %25, 15
br i1 %26, label %27, label %59
27: ; preds = %24
%28 = load x86_fp80, x86_fp80* %4
%29 = fadd x86_fp80 %28, 0xK3FFF8000000000000000
store x86_fp80 %29, x86_fp80* %4
%30 = load i32, i32* %9
%31 = sub nsw i32 15, %30
%32 = load i32, i32* %9
%33 = sitofp i32 %32 to double
%34 = fsub double %33, 5.000000e-01
%35 = fptosi double %34 to i32
%36 = call x86_fp80 @powl(i32 %31, i32 %35)
store x86_fp80 %36, x86_fp80* %7
%37 = load i32, i32* %9
%38 = sub nsw i32 15, %37
%39 = call x86_fp80 @expl(i32 %38)
%40 = load x86_fp80, x86_fp80* %7
%41 = fmul x86_fp80 %40, %39
store x86_fp80 %41, x86_fp80* %7
%42 = load x86_fp80, x86_fp80* %6
%43 = load x86_fp80, x86_fp80* %7
%44 = fdiv x86_fp80 %43, %42
store x86_fp80 %44, x86_fp80* %7
%45 = load x86_fp80, x86_fp80* %7
%46 = load x86_fp80, x86_fp80* %4
%47 = fdiv x86_fp80 %45, %46
%48 = load x86_fp80, x86_fp80* %8
%49 = fadd x86_fp80 %48, %47
store x86_fp80 %49, x86_fp80* %8
%50 = load i32, i32* %9
%51 = sitofp i32 %50 to double
%52 = fmul double -1.000000e+00, %51
%53 = fpext double %52 to x86_fp80
%54 = load x86_fp80, x86_fp80* %6
%55 = fmul x86_fp80 %54, %53
store x86_fp80 %55, x86_fp80* %6
br label %56
56: ; preds = %27
%57 = load i32, i32* %9
%58 = add nsw i32 %57, 1
store i32 %58, i32* %9
br label %24
59: ; preds = %24
%60 = load x86_fp80, x86_fp80* %8
%61 = call x86_fp80 @logl(x86_fp80 %60)
%62 = load x86_fp80, x86_fp80* %5
%63 = fadd x86_fp80 %61, %62
ret x86_fp80 %63
}

LLVM IR (-O2):
define x86_fp80 @log_gamma(double %0) {
%2 = fpext double %0 to x86_fp80
%3 = fadd x86_fp80 %2, 0xK4002F000000000000000
%4 = tail call x86_fp80 @logl(x86_fp80 %3)
%5 = tail call x86_fp80 @logl(x86_fp80 %2)
br label %13
6: ; preds = %13
%7 = fadd x86_fp80 %2, 0xK3FFE8000000000000000
%8 = fneg x86_fp80 %3
%9 = tail call x86_fp80 @llvm.fmuladd.f80(x86_fp80 %4, x86_fp80 %7, x86_fp80 %8)
%10 = fsub x86_fp80 %9, %5
%11 = tail call x86_fp80 @logl(x86_fp80 %28)
%12 = fadd x86_fp80 %10, %11
ret x86_fp80 %12
13: ; preds = %1, %13
%14 = phi i32 [ 1, %1 ], [ %32, %13 ]
%15 = phi x86_fp80 [ 0xK4000A06C98FFB1383000, %1 ], [ %28, %13 ]
%16 = phi x86_fp80 [ %2, %1 ], [ %18, %13 ]
%17 = phi x86_fp80 [ 0xK3FFF8000000000000000, %1 ], [ %31, %13 ]
%18 = fadd x86_fp80 %16, 0xK3FFF8000000000000000
%19 = sub nuw nsw i32 15, %14
%20 = sitofp i32 %14 to double
%21 = fadd double %20, -5.000000e-01
%22 = fptosi double %21 to i32
%23 = tail call x86_fp80 @powl(i32 %19, i32 %22)
%24 = tail call x86_fp80 @expl(i32 %19)
%25 = fmul x86_fp80 %23, %24
%26 = fdiv x86_fp80 %25, %17
%27 = fdiv x86_fp80 %26, %18
%28 = fadd x86_fp80 %15, %27
%29 = fneg double %20
%30 = fpext double %29 to x86_fp80
%31 = fmul x86_fp80 %17, %30
%32 = add nuw nsw i32 %14, 1
%33 = icmp eq i32 %32, 15
br i1 %33, label %6, label %13
}