#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*/ EDOM;
int /*<<< orphan*/ ERANGE;
double HUGE_VAL;
int M_PI;
int /*<<< orphan*/ errno;
double exp(int /*<<< orphan*/);
double fmod(double, double);
int /*<<< orphan*/ loggamma(double);
double modf(double, double *);
int sin(int);
double tgamma(double x) {
  if (x == 0.0) {
    errno = ERANGE;
    return 1 / x < 0 ? -HUGE_VAL : HUGE_VAL;
  }
  if (x < 0) {
    int sign;
    static double zero = 0.0;
    double i, f;
    f = modf(-x, &i);
    if (f == 0.0) {
      errno = EDOM;
      return zero / zero;
    }
    sign = (fmod(i, 2.0) != 0.0) ? 1 : -1;
    return sign * M_PI / (sin(M_PI * f) * exp(loggamma(1 - x)));
  }
  return exp(loggamma(x));
}


x86 assembly (clang, -O0):
<tgamma>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    11ec <tgamma+0x9c>
jp     11ec <tgamma+0x9c>
mov    0x2e54(%rip),%rax
mov    (%rax),%ecx
mov    0x2e3b(%rip),%rax
mov    %ecx,(%rax)
movsd  0xe71(%rip),%xmm1
divsd  -0x10(%rbp),%xmm1
xorps  %xmm0,%xmm0
ucomisd %xmm1,%xmm0
jbe    11cd <tgamma+0x7d>
mov    0x2e38(%rip),%rax
movsd  (%rax),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x30(%rbp)
jmp    11dd <tgamma+0x8d>
mov    0x2e0c(%rip),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1321 <tgamma+0x1d1>
xorps  %xmm0,%xmm0
ucomisd -0x10(%rbp),%xmm0
jbe    130b <tgamma+0x1bb>
movsd  -0x10(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
lea    -0x20(%rbp),%rdi
call   1040 <modf@plt>
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    1268 <tgamma+0x118>
jp     1268 <tgamma+0x118>
mov    0x2d95(%rip),%rax
mov    (%rax),%ecx
mov    0x2d74(%rip),%rax
mov    %ecx,(%rax)
movsd  0x2e0a(%rip),%xmm0
divsd  0x2e02(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1321 <tgamma+0x1d1>
movsd  -0x20(%rbp),%xmm0
movsd  0xd93(%rip),%xmm1
call   1030 <fmod@plt>
xorps  %xmm1,%xmm1
mov    $0xffffffff,%eax
mov    $0x1,%ecx
ucomisd %xmm1,%xmm0
setp   %sil
setne  %dl
or     %sil,%dl
cmovne %ecx,%eax
mov    %eax,-0x14(%rbp)
mov    -0x14(%rbp),%eax
mov    0x2d43(%rip),%rcx
imul   (%rcx),%eax
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    0x2d30(%rip),%rax
cvtsi2sdl (%rax),%xmm0
mulsd  -0x28(%rbp),%xmm0
cvttsd2si %xmm0,%edi
call   1060 <sin@plt>
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  0xd25(%rip),%xmm0
subsd  -0x10(%rbp),%xmm0
call   1050 <loggamma@plt>
mov    %eax,%edi
call   1070 <exp@plt>
movsd  -0x40(%rbp),%xmm1
movaps %xmm0,%xmm2
movsd  -0x38(%rbp),%xmm0
mulsd  %xmm2,%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1321 <tgamma+0x1d1>
movsd  -0x10(%rbp),%xmm0
call   1050 <loggamma@plt>
mov    %eax,%edi
call   1070 <exp@plt>
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<tgamma>:
sub    $0x38,%rsp
movapd %xmm0,%xmm1
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm1
jne    11b3 <tgamma+0x63>
jp     11b3 <tgamma+0x63>
mov    0x2e65(%rip),%rax
mov    (%rax),%eax
mov    0x2e4c(%rip),%rcx
mov    %eax,(%rcx)
movsd  0xe9a(%rip),%xmm3
divsd  %xmm1,%xmm3
mov    0x2e57(%rip),%rax
movsd  (%rax),%xmm1
movapd 0xe6b(%rip),%xmm2
xorpd  %xmm1,%xmm2
cmpltsd %xmm0,%xmm3
andpd  %xmm3,%xmm2
andnpd %xmm1,%xmm3
orpd   %xmm2,%xmm3
movapd %xmm3,%xmm0
add    $0x38,%rsp
ret
ucomisd %xmm1,%xmm0
jbe    11fd <tgamma+0xad>
movapd 0xe3f(%rip),%xmm0
movapd %xmm1,0x20(%rsp)
xorpd  %xmm1,%xmm0
lea    0x8(%rsp),%rdi
call   1040 <modf@plt>
xorpd  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    1211 <tgamma+0xc1>
jp     1211 <tgamma+0xc1>
mov    0x2df0(%rip),%rax
mov    (%rax),%eax
mov    0x2dcf(%rip),%rcx
mov    %eax,(%rcx)
movsd  0xe25(%rip),%xmm3
jmp    11aa <tgamma+0x5a>
movapd %xmm1,%xmm0
call   1050 <loggamma@plt>
mov    %eax,%edi
add    $0x38,%rsp
jmp    1070 <exp@plt>
movsd  %xmm0,(%rsp)
movsd  0x8(%rsp),%xmm0
movsd  0xdec(%rip),%xmm1
call   1030 <fmod@plt>
mov    0x2db8(%rip),%rax
mov    (%rax),%eax
mov    %eax,%ecx
neg    %ecx
ucomisd 0xdea(%rip),%xmm0
cmovne %eax,%ecx
cmovp  %eax,%ecx
xorps  %xmm0,%xmm0
cvtsi2sd %ecx,%xmm0
movapd %xmm0,0x10(%rsp)
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
movsd  (%rsp),%xmm1
mulsd  %xmm0,%xmm1
cvttsd2si %xmm1,%edi
call   1060 <sin@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
movsd  %xmm0,(%rsp)
movsd  0xd9a(%rip),%xmm0
subsd  0x20(%rsp),%xmm0
call   1050 <loggamma@plt>
mov    %eax,%edi
call   1070 <exp@plt>
movapd 0x10(%rsp),%xmm3
mulsd  (%rsp),%xmm0
divsd  %xmm0,%xmm3
jmp    11aa <tgamma+0x5a>

LLVM IR (-O0):
@ERANGE = global i32 0
@errno = global i32 0
@HUGE_VAL = global double 0.000000e+00
@tgamma.zero = internal global double 0.000000e+00
@EDOM = global i32 0
@M_PI = global i32 0
define double @tgamma(double %0) {
%2 = alloca double
%3 = alloca double
%4 = alloca i32
%5 = alloca double
%6 = alloca double
store double %0, double* %3
%7 = load double, double* %3
%8 = fcmp oeq double %7, 0.000000e+00
br i1 %8, label %9, label %21
9: ; preds = %1
%10 = load i32, i32* @ERANGE
store i32 %10, i32* @errno
%11 = load double, double* %3
%12 = fdiv double 1.000000e+00, %11
%13 = fcmp olt double %12, 0.000000e+00
br i1 %13, label %14, label %17
14: ; preds = %9
%15 = load double, double* @HUGE_VAL
%16 = fneg double %15
br label %19
17: ; preds = %9
%18 = load double, double* @HUGE_VAL
br label %19
19: ; preds = %17, %14
%20 = phi double [ %16, %14 ], [ %18, %17 ]
store double %20, double* %2
br label %62
21: ; preds = %1
%22 = load double, double* %3
%23 = fcmp olt double %22, 0.000000e+00
br i1 %23, label %24, label %58
24: ; preds = %21
%25 = load double, double* %3
%26 = fneg double %25
%27 = call double @modf(double %26, double* %5)
store double %27, double* %6
%28 = load double, double* %6
%29 = fcmp oeq double %28, 0.000000e+00
br i1 %29, label %30, label %35
30: ; preds = %24
%31 = load i32, i32* @EDOM
store i32 %31, i32* @errno
%32 = load double, double* @tgamma.zero
%33 = load double, double* @tgamma.zero
%34 = fdiv double %32, %33
store double %34, double* %2
br label %62
35: ; preds = %24
%36 = load double, double* %5
%37 = call double @fmod(double %36, double 2.000000e+00)
%38 = fcmp une double %37, 0.000000e+00
%39 = zext i1 %38 to i64
%40 = select i1 %38, i32 1, i32 -1
store i32 %40, i32* %4
%41 = load i32, i32* %4
%42 = load i32, i32* @M_PI
%43 = mul nsw i32 %41, %42
%44 = sitofp i32 %43 to double
%45 = load i32, i32* @M_PI
%46 = sitofp i32 %45 to double
%47 = load double, double* %6
%48 = fmul double %46, %47
%49 = fptosi double %48 to i32
%50 = call i32 @sin(i32 %49)
%51 = sitofp i32 %50 to double
%52 = load double, double* %3
%53 = fsub double 1.000000e+00, %52
%54 = call i32 @loggamma(double %53)
%55 = call double @exp(i32 %54)
%56 = fmul double %51, %55
%57 = fdiv double %44, %56
store double %57, double* %2
br label %62
58: ; preds = %21
%59 = load double, double* %3
%60 = call i32 @loggamma(double %59)
%61 = call double @exp(i32 %60)
store double %61, double* %2
br label %62
62: ; preds = %58, %35, %30, %19
%63 = load double, double* %2
ret double %63
}

LLVM IR (-O2):
@ERANGE = global i32 0
@errno = global i32 0
@HUGE_VAL = global double 0.000000e+00
@EDOM = global i32 0
@M_PI = global i32 0
define double @tgamma(double %0) {
%2 = alloca double
%3 = fcmp oeq double %0, 0.000000e+00
br i1 %3, label %4, label %11
4: ; preds = %1
%5 = load i32, i32* @ERANGE
store i32 %5, i32* @errno
%6 = fdiv double 1.000000e+00, %0
%7 = fcmp olt double %6, 0.000000e+00
%8 = load double, double* @HUGE_VAL
%9 = fneg double %8
%10 = select i1 %7, double %9, double %8
br label %43
11: ; preds = %1
%12 = fcmp olt double %0, 0.000000e+00
br i1 %12, label %13, label %40
13: ; preds = %11
%14 = bitcast double* %2 to i8*
%15 = fneg double %0
%16 = call double @modf(double %15, double* %2)
%17 = fcmp oeq double %16, 0.000000e+00
br i1 %17, label %18, label %20
18: ; preds = %13
%19 = load i32, i32* @EDOM
store i32 %19, i32* @errno
br label %38
20: ; preds = %13
%21 = load double, double* %2
%22 = tail call double @fmod(double %21, double 2.000000e+00)
%23 = fcmp une double %22, 0.000000e+00
%24 = load i32, i32* @M_PI
%25 = sub nsw i32 0, %24
%26 = select i1 %23, i32 %24, i32 %25
%27 = sitofp i32 %26 to double
%28 = sitofp i32 %24 to double
%29 = fmul double %16, %28
%30 = fptosi double %29 to i32
%31 = tail call i32 @sin(i32 %30)
%32 = sitofp i32 %31 to double
%33 = fsub double 1.000000e+00, %0
%34 = tail call i32 @loggamma(double %33)
%35 = tail call double @exp(i32 %34)
%36 = fmul double %35, %32
%37 = fdiv double %27, %36
br label %38
38: ; preds = %20, %18
%39 = phi double [ 0x7FF8000000000000, %18 ], [ %37, %20 ]
br label %43
40: ; preds = %11
%41 = tail call i32 @loggamma(double %0)
%42 = tail call double @exp(i32 %41)
br label %43
43: ; preds = %40, %38, %4
%44 = phi double [ %10, %4 ], [ %39, %38 ], [ %42, %40 ]
ret double %44
}