#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 */
int /*<<< orphan*/ GCI_gamma(float);
int /*<<< orphan*/ fabsf(int /*<<< orphan*/);
float log(float);
float logf(int /*<<< orphan*/);
float GCI_log_gamma(float x) {
  static const double c[8] = {
      1.0 / 12.0,   -1.0 / 360.0,      1.0 / 1260.0, -1.0 / 1680.0,
      1.0 / 1188.0, -691.0 / 360360.0, 1.0 / 156.0,  -3617.0 / 122400.0};
  static const double halfLogTwoPi = 0.91893853320467274178032973640562;
  int i;
  double z, sum, series, logGamma;
  if (x < 12.0f) {
    return logf(fabsf(GCI_gamma(x)));
  }
  z = 1.0 / (x * x);
  sum = c[7];
  for (i = 6; i >= 0; i--) {
    sum *= z;
    sum += c[i];
  }
  series = sum / x;
  logGamma = (x - 0.5) * log(x) - x + halfLogTwoPi + series;
  return (float)logGamma;
}


x86 assembly (clang, -O0):
<GCI_log_gamma>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
movss  %xmm0,-0x8(%rbp)
movss  0xeab(%rip),%xmm0
ucomiss -0x8(%rbp),%xmm0
jbe    1181 <GCI_log_gamma+0x41>
movss  -0x8(%rbp),%xmm0
call   1060 <GCI_gamma@plt>
mov    %eax,%edi
call   1030 <fabsf@plt>
mov    %eax,%edi
call   1040 <logf@plt>
movss  %xmm0,-0x4(%rbp)
jmp    1288 <GCI_log_gamma+0x148>
movss  -0x8(%rbp),%xmm0
mulss  -0x8(%rbp),%xmm0
cvtss2sd %xmm0,%xmm1
movsd  0xe71(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  0xeb0(%rip),%xmm0
movsd  %xmm0,-0x20(%rbp)
movl   $0x6,-0xc(%rbp)
cmpl   $0x0,-0xc(%rbp)
jl     11f5 <GCI_log_gamma+0xb5>
movsd  -0x18(%rbp),%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movslq -0xc(%rbp),%rcx
lea    0xe48(%rip),%rax
movsd  (%rax,%rcx,8),%xmm0
addsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0xc(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0xc(%rbp)
jmp    11b4 <GCI_log_gamma+0x74>
movsd  -0x20(%rbp),%xmm0
movss  -0x8(%rbp),%xmm1
cvtss2sd %xmm1,%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
movss  -0x8(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
movsd  0xdfb(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
movss  -0x8(%rbp),%xmm0
call   1050 <log@plt>
movaps %xmm0,%xmm1
movsd  -0x38(%rbp),%xmm0
cvtss2sd %xmm1,%xmm2
movss  -0x8(%rbp),%xmm1
cvtss2sd %xmm1,%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  0xda4(%rip),%xmm1
addsd  %xmm1,%xmm0
addsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x4(%rbp)
movss  -0x4(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<GCI_log_gamma>:
sub    $0x18,%rsp
movss  0xeb4(%rip),%xmm1
ucomiss %xmm0,%xmm1
jbe    1168 <GCI_log_gamma+0x28>
call   1060 <GCI_gamma@plt>
mov    %eax,%edi
call   1030 <fabsf@plt>
mov    %eax,%edi
add    $0x18,%rsp
jmp    1040 <logf@plt>
movaps %xmm0,%xmm1
mulss  %xmm0,%xmm1
cvtss2sd %xmm1,%xmm1
movsd  0xe8d(%rip),%xmm2
divsd  %xmm1,%xmm2
movsd  0xe89(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe85(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe81(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe7d(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe79(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe75(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe71(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe6d(%rip),%xmm1
xorps  %xmm2,%xmm2
cvtss2sd %xmm0,%xmm2
movsd  %xmm2,0x8(%rsp)
divsd  %xmm2,%xmm1
movsd  %xmm1,0x10(%rsp)
movsd  0xe56(%rip),%xmm1
addsd  %xmm2,%xmm1
movsd  %xmm1,(%rsp)
call   1050 <log@plt>
cvtss2sd %xmm0,%xmm0
mulsd  (%rsp),%xmm0
subsd  0x8(%rsp),%xmm0
addsd  0xe39(%rip),%xmm0
addsd  0x10(%rsp),%xmm0
cvtsd2ss %xmm0,%xmm0
add    $0x18,%rsp
ret

LLVM IR (-O0):
@GCI_log_gamma.c = internal constant [8 x double] [double 0x3FB5555555555555, double 0xBF66C16C16C16C17, double 0x3F4A01A01A01A01A, double 0xBF43813813813814, double 0x3F4B951E2B18FF23, double 0xBF5F6AB0D9993C7D, double 0x3F7A41A41A41A41A, double 0xBF9E4286CB0F5398]
@GCI_log_gamma.halfLogTwoPi = internal constant double 0x3FED67F1C864BEB5
define float @GCI_log_gamma(float %0) {
%2 = alloca float
%3 = alloca float
%4 = alloca i32
%5 = alloca double
%6 = alloca double
%7 = alloca double
%8 = alloca double
store float %0, float* %3
%9 = load float, float* %3
%10 = fcmp olt float %9, 1.200000e+01
br i1 %10, label %11, label %16
11: ; preds = %1
%12 = load float, float* %3
%13 = call i32 @GCI_gamma(float %12)
%14 = call i32 @fabsf(i32 %13)
%15 = call float @logf(i32 %14)
store float %15, float* %2
br label %59
16: ; preds = %1
%17 = load float, float* %3
%18 = load float, float* %3
%19 = fmul float %17, %18
%20 = fpext float %19 to double
%21 = fdiv double 1.000000e+00, %20
store double %21, double* %5
%22 = load double, double* getelementptr inbounds ([8 x double], [8 x double]* @GCI_log_gamma.c, i64 0, i64 7)
store double %22, double* %6
store i32 6, i32* %4
br label %23
23: ; preds = %36, %16
%24 = load i32, i32* %4
%25 = icmp sge i32 %24, 0
br i1 %25, label %26, label %39
26: ; preds = %23
%27 = load double, double* %5
%28 = load double, double* %6
%29 = fmul double %28, %27
store double %29, double* %6
%30 = load i32, i32* %4
%31 = sext i32 %30 to i64
%32 = getelementptr inbounds [8 x double], [8 x double]* @GCI_log_gamma.c, i64 0, i64 %31
%33 = load double, double* %32
%34 = load double, double* %6
%35 = fadd double %34, %33
store double %35, double* %6
br label %36
36: ; preds = %26
%37 = load i32, i32* %4
%38 = add nsw i32 %37, -1
store i32 %38, i32* %4
br label %23
39: ; preds = %23
%40 = load double, double* %6
%41 = load float, float* %3
%42 = fpext float %41 to double
%43 = fdiv double %40, %42
store double %43, double* %7
%44 = load float, float* %3
%45 = fpext float %44 to double
%46 = fsub double %45, 5.000000e-01
%47 = load float, float* %3
%48 = call float @log(float %47)
%49 = fpext float %48 to double
%50 = load float, float* %3
%51 = fpext float %50 to double
%52 = fneg double %51
%53 = call double @llvm.fmuladd.f64(double %46, double %49, double %52)
%54 = fadd double %53, 0x3FED67F1C864BEB5
%55 = load double, double* %7
%56 = fadd double %54, %55
store double %56, double* %8
%57 = load double, double* %8
%58 = fptrunc double %57 to float
store float %58, float* %2
br label %59
59: ; preds = %39, %11
%60 = load float, float* %2
ret float %60
}

LLVM IR (-O2):
define float @GCI_log_gamma(float %0) {
%2 = fcmp olt float %0, 1.200000e+01
br i1 %2, label %3, label %7
3: ; preds = %1
%4 = tail call i32 @GCI_gamma(float %0)
%5 = tail call i32 @fabsf(i32 %4)
%6 = tail call float @logf(i32 %5)
br label %35
7: ; preds = %1
%8 = fmul float %0, %0
%9 = fpext float %8 to double
%10 = fdiv double 1.000000e+00, %9
%11 = fmul double %10, 0xBF9E4286CB0F5398
%12 = fadd double %11, 0x3F7A41A41A41A41A
%13 = fmul double %10, %12
%14 = fadd double %13, 0xBF5F6AB0D9993C7D
%15 = fmul double %10, %14
%16 = fadd double %15, 0x3F4B951E2B18FF23
%17 = fmul double %10, %16
%18 = fadd double %17, 0xBF43813813813814
%19 = fmul double %10, %18
%20 = fadd double %19, 0x3F4A01A01A01A01A
%21 = fmul double %10, %20
%22 = fadd double %21, 0xBF66C16C16C16C17
%23 = fmul double %10, %22
%24 = fadd double %23, 0x3FB5555555555555
%25 = fpext float %0 to double
%26 = fdiv double %24, %25
%27 = fadd double %25, -5.000000e-01
%28 = tail call float @log(float %0)
%29 = fpext float %28 to double
%30 = fneg double %25
%31 = tail call double @llvm.fmuladd.f64(double %27, double %29, double %30)
%32 = fadd double %31, 0x3FED67F1C864BEB5
%33 = fadd double %26, %32
%34 = fptrunc double %33 to float
br label %35
35: ; preds = %7, %3
%36 = phi float [ %6, %3 ], [ %34, %7 ]
ret float %36
}