#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 DBL_EPSILON;
double const HUGE_VAL;
int /*<<< orphan*/ assert(int);
double exp(double const);
int fabs(double);
double pow(double const, double const);
int tgamma(double const);
double __attribute__((const)) gamma_series(const double x, const double a) {
  double res, term;
  int i;
  assert(x >= 0.);
  assert(a > 0.);
  if (x == 0.) {
    return 0.;
  }
  if (x == HUGE_VAL) {
    return 1.;
  }
  term = 1. / tgamma(a);
  term /= a;
  term *= exp(-x) * pow(x, a);
  res = term;
  for (i = 1;; i++) {
    term *= x;
    term /= a + i;
    res += term;
    if (fabs(term) <= DBL_EPSILON * fabs(res))
      break;
  }
  assert(res >= 0. && res <= 1.);
  return res;
}


x86 assembly (clang, -O0):
<gamma_series>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
setae  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
movsd  -0x18(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
seta   %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    11b9 <gamma_series+0x69>
jp     11b9 <gamma_series+0x69>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    133e <gamma_series+0x1ee>
movsd  -0x10(%rbp),%xmm0
mov    0x2e1b(%rip),%rax
ucomisd (%rax),%xmm0
jne    11e7 <gamma_series+0x97>
jp     11e7 <gamma_series+0x97>
movsd  0xe23(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    133e <gamma_series+0x1ee>
movsd  -0x18(%rbp),%xmm0
call   1030 <tgamma@plt>
cvtsi2sd %eax,%xmm1
movsd  0xe03(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x18(%rbp),%xmm1
movsd  -0x28(%rbp),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x10(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
call   1060 <exp@plt>
movsd  %xmm0,-0x38(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  -0x18(%rbp),%xmm1
call   1070 <pow@plt>
movaps %xmm0,%xmm1
movsd  -0x38(%rbp),%xmm0
mulsd  %xmm1,%xmm0
mulsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movl   $0x1,-0x2c(%rbp)
movsd  -0x10(%rbp),%xmm0
mulsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x18(%rbp),%xmm1
cvtsi2sdl -0x2c(%rbp),%xmm0
addsd  %xmm0,%xmm1
movsd  -0x28(%rbp),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
addsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x28(%rbp),%xmm0
call   1040 <fabs@plt>
mov    %eax,-0x3c(%rbp)
mov    0x2d25(%rip),%rax
mov    (%rax),%eax
mov    %eax,-0x40(%rbp)
movsd  -0x20(%rbp),%xmm0
call   1040 <fabs@plt>
mov    -0x40(%rbp),%ecx
mov    %eax,%edx
mov    -0x3c(%rbp),%eax
imul   %edx,%ecx
cmp    %ecx,%eax
jg     12ea <gamma_series+0x19a>
jmp    12fd <gamma_series+0x1ad>
jmp    12ef <gamma_series+0x19f>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1275 <gamma_series+0x125>
movsd  -0x20(%rbp),%xmm0
xor    %eax,%eax
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
mov    %al,-0x41(%rbp)
jb     1327 <gamma_series+0x1d7>
movsd  0xce4(%rip),%xmm0
ucomisd -0x20(%rbp),%xmm0
setae  %al
mov    %al,-0x41(%rbp)
mov    -0x41(%rbp),%al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<gamma_series>:
push   %rbp
push   %r15
push   %r14
push   %rbx
sub    $0x38,%rsp
movsd  %xmm1,0x10(%rsp)
movapd %xmm0,0x20(%rsp)
xorpd  %xmm1,%xmm1
xor    %edi,%edi
ucomisd %xmm1,%xmm0
setae  %dil
call   1050 <assert@plt>
xor    %edi,%edi
movsd  0x10(%rsp),%xmm0
ucomisd 0xe7f(%rip),%xmm0
seta   %dil
call   1050 <assert@plt>
xorpd  %xmm0,%xmm0
movapd 0x20(%rsp),%xmm1
ucomisd %xmm0,%xmm1
jne    11a8 <gamma_series+0x58>
jnp    12a4 <gamma_series+0x154>
movsd  0x10(%rsp),%xmm0
call   1030 <tgamma@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
movsd  0xe3e(%rip),%xmm1
divsd  %xmm0,%xmm1
divsd  0x10(%rsp),%xmm1
movsd  %xmm1,0x8(%rsp)
movaps 0xe37(%rip),%xmm0
xorps  0x20(%rsp),%xmm0
call   1060 <exp@plt>
movsd  %xmm0,0x18(%rsp)
movapd 0x20(%rsp),%xmm0
movsd  0x10(%rsp),%xmm1
call   1070 <pow@plt>
mulsd  0x18(%rsp),%xmm0
mulsd  0x8(%rsp),%xmm0
mov    $0x1,%ebp
mov    0x2dd6(%rip),%r14
movsd  %xmm0,0x8(%rsp)
nopl   0x0(%rax,%rax,1)
xorps  %xmm1,%xmm1
cvtsi2sd %ebp,%xmm1
mulsd  0x20(%rsp),%xmm0
addsd  0x10(%rsp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,0x18(%rsp)
movsd  0x8(%rsp),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,0x8(%rsp)
call   1040 <fabs@plt>
mov    %eax,%r15d
mov    (%r14),%ebx
movsd  0x8(%rsp),%xmm0
call   1040 <fabs@plt>
movsd  0x18(%rsp),%xmm0
imul   %ebx,%eax
add    $0x1,%ebp
cmp    %eax,%r15d
jg     1220 <gamma_series+0xd0>
xorpd  %xmm0,%xmm0
movsd  0x8(%rsp),%xmm1
ucomisd %xmm0,%xmm1
setae  %al
movsd  0xd73(%rip),%xmm0
ucomisd %xmm1,%xmm0
setae  %cl
and    %al,%cl
movzbl %cl,%edi
call   1050 <assert@plt>
movsd  0x8(%rsp),%xmm0
add    $0x38,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@HUGE_VAL = constant double 0.000000e+00
@DBL_EPSILON = global i32 0
define double @gamma_series(double %0, double %1) {
%3 = alloca double
%4 = alloca double
%5 = alloca double
%6 = alloca double
%7 = alloca double
%8 = alloca i32
store double %0, double* %4
store double %1, double* %5
%9 = load double, double* %4
%10 = fcmp oge double %9, 0.000000e+00
%11 = zext i1 %10 to i32
%12 = call i32 @assert(i32 %11)
%13 = load double, double* %5
%14 = fcmp ogt double %13, 0.000000e+00
%15 = zext i1 %14 to i32
%16 = call i32 @assert(i32 %15)
%17 = load double, double* %4
%18 = fcmp oeq double %17, 0.000000e+00
br i1 %18, label %19, label %20
19: ; preds = %2
store double 0.000000e+00, double* %3
br label %79
20: ; preds = %2
%21 = load double, double* %4
%22 = load double, double* @HUGE_VAL
%23 = fcmp oeq double %21, %22
br i1 %23, label %24, label %25
24: ; preds = %20
store double 1.000000e+00, double* %3
br label %79
25: ; preds = %20
%26 = load double, double* %5
%27 = call i32 @tgamma(double %26)
%28 = sitofp i32 %27 to double
%29 = fdiv double 1.000000e+00, %28
store double %29, double* %7
%30 = load double, double* %5
%31 = load double, double* %7
%32 = fdiv double %31, %30
store double %32, double* %7
%33 = load double, double* %4
%34 = fneg double %33
%35 = call double @exp(double %34)
%36 = load double, double* %4
%37 = load double, double* %5
%38 = call double @pow(double %36, double %37)
%39 = fmul double %35, %38
%40 = load double, double* %7
%41 = fmul double %40, %39
store double %41, double* %7
%42 = load double, double* %7
store double %42, double* %6
store i32 1, i32* %8
br label %43
43: ; preds = %65, %25
%44 = load double, double* %4
%45 = load double, double* %7
%46 = fmul double %45, %44
store double %46, double* %7
%47 = load double, double* %5
%48 = load i32, i32* %8
%49 = sitofp i32 %48 to double
%50 = fadd double %47, %49
%51 = load double, double* %7
%52 = fdiv double %51, %50
store double %52, double* %7
%53 = load double, double* %7
%54 = load double, double* %6
%55 = fadd double %54, %53
store double %55, double* %6
%56 = load double, double* %7
%57 = call i32 @fabs(double %56)
%58 = load i32, i32* @DBL_EPSILON
%59 = load double, double* %6
%60 = call i32 @fabs(double %59)
%61 = mul nsw i32 %58, %60
%62 = icmp sle i32 %57, %61
br i1 %62, label %63, label %64
63: ; preds = %43
br label %68
64: ; preds = %43
br label %65
65: ; preds = %64
%66 = load i32, i32* %8
%67 = add nsw i32 %66, 1
store i32 %67, i32* %8
br label %43
68: ; preds = %63
%69 = load double, double* %6
%70 = fcmp oge double %69, 0.000000e+00
br i1 %70, label %71, label %74
71: ; preds = %68
%72 = load double, double* %6
%73 = fcmp ole double %72, 1.000000e+00
br label %74
74: ; preds = %71, %68
%75 = phi i1 [ false, %68 ], [ %73, %71 ]
%76 = zext i1 %75 to i32
%77 = call i32 @assert(i32 %76)
%78 = load double, double* %6
store double %78, double* %3
br label %79
79: ; preds = %74, %24, %19
%80 = load double, double* %3
ret double %80
}

LLVM IR (-O2):
@HUGE_VAL = constant double 0.000000e+00
@DBL_EPSILON = global i32 0
define double @gamma_series(double %0, double %1) {
%3 = fcmp oge double %0, 0.000000e+00
%4 = zext i1 %3 to i32
%5 = tail call i32 @assert(i32 %4)
%6 = fcmp ogt double %1, 0.000000e+00
%7 = zext i1 %6 to i32
%8 = tail call i32 @assert(i32 %7)
%9 = fcmp oeq double %0, 0.000000e+00
br i1 %9, label %41, label %10
10: ; preds = %2
%11 = tail call i32 @tgamma(double %1)
%12 = sitofp i32 %11 to double
%13 = fdiv double 1.000000e+00, %12
%14 = fdiv double %13, %1
%15 = fneg double %0
%16 = tail call double @exp(double %15)
%17 = tail call double @pow(double %0, double %1)
%18 = fmul double %16, %17
%19 = fmul double %14, %18
br label %20
20: ; preds = %20, %10
%21 = phi double [ %19, %10 ], [ %28, %20 ]
%22 = phi double [ %19, %10 ], [ %27, %20 ]
%23 = phi i32 [ 1, %10 ], [ %34, %20 ]
%24 = fmul double %22, %0
%25 = sitofp i32 %23 to double
%26 = fadd double %25, %1
%27 = fdiv double %24, %26
%28 = fadd double %21, %27
%29 = tail call i32 @fabs(double %27)
%30 = load i32, i32* @DBL_EPSILON
%31 = tail call i32 @fabs(double %28)
%32 = mul nsw i32 %31, %30
%33 = icmp sgt i32 %29, %32
%34 = add nuw nsw i32 %23, 1
br i1 %33, label %20, label %35
35: ; preds = %20
%36 = fcmp oge double %28, 0.000000e+00
%37 = fcmp ole double %28, 1.000000e+00
%38 = and i1 %36, %37
%39 = zext i1 %38 to i32
%40 = tail call i32 @assert(i32 %39)
br label %41
41: ; preds = %2, %35
%42 = phi double [ %28, %35 ], [ 0.000000e+00, %2 ]
ret double %42
}