#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 INFINITY;
double NAN;
double floor(double);
int isinf(double);
scalar_t__ isnan(double);
double log(double);
double tan(double);
double digamma(double x) {
  static const double c = 12, d1 = -0.57721566490153286,
                      d2 = 1.6449340668482264365, s = 1e-6, s3 = 1. / 12,
                      s4 = 1. / 120, s5 = 1. / 252, s6 = 1. / 240,
                      s7 = 1. / 132, s8 = 691 / 32760, s9 = 1 / 12,
                      s10 = 3617 / 8160;
  double result;
  if ((isinf(x) == -1) || isnan(x)) {
    return NAN;
  }
  if ((x <= 0) && (floor(x) == x)) {
    return -INFINITY;
  }
  if (x < 0) {
    return digamma(1 - x) + 3.14159265 / tan(-3.14159265 * x);
  }
  if (x <= s)
    return d1 - 1 / x + d2 * x;
  result = 0;
  while (x < c) {
    result -= 1 / x;
    x++;
  }
  if (x >= c) {
    double r = 1 / x;
    result += log(x) - 0.5 * r;
    r *= r;
    result -= r * (s3 - r * (s4 - r * (s5 - r * (s6 - r * s7))));
  }
  return result;
}


x86 assembly (clang, -O0):
<digamma>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  -0x10(%rbp),%xmm0
call   1080 <isinf@plt>
cmp    $0xffffffff,%eax
je     1194 <digamma+0x34>
movsd  -0x10(%rbp),%xmm0
call   1040 <isnan@plt>
cmp    $0x0,%rax
je     11a9 <digamma+0x49>
mov    0x2e5d(%rip),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1443 <digamma+0x2e3>
xorps  %xmm0,%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     11fe <digamma+0x9e>
movsd  -0x10(%rbp),%xmm0
call   1070 <floor@plt>
ucomisd -0x10(%rbp),%xmm0
jne    11fe <digamma+0x9e>
jp     11fe <digamma+0x9e>
mov    0x2e07(%rip),%rax
movsd  (%rax),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1443 <digamma+0x2e3>
xorps  %xmm0,%xmm0
ucomisd -0x10(%rbp),%xmm0
jbe    1257 <digamma+0xf7>
movsd  0xe2c(%rip),%xmm0
subsd  -0x10(%rbp),%xmm0
call   1060 <digamma@plt>
movsd  %xmm0,-0x28(%rbp)
movsd  0xe35(%rip),%xmm0
mulsd  -0x10(%rbp),%xmm0
call   1030 <tan@plt>
movaps %xmm0,%xmm2
movsd  -0x28(%rbp),%xmm0
movsd  0xe13(%rip),%xmm1
divsd  %xmm2,%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1443 <digamma+0x2e3>
movsd  0xda1(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     12a2 <digamma+0x142>
movsd  0xdce(%rip),%xmm0
divsd  -0x10(%rbp),%xmm0
movsd  0xdd1(%rip),%xmm1
subsd  %xmm0,%xmm1
movsd  -0x10(%rbp),%xmm0
movsd  0xdb8(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1443 <digamma+0x2e3>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  0xd56(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jbe    12ef <digamma+0x18f>
movsd  0xd7b(%rip),%xmm1
divsd  -0x10(%rbp),%xmm1
movsd  -0x18(%rbp),%xmm0
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  0xd60(%rip),%xmm0
addsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
jmp    12aa <digamma+0x14a>
movsd  -0x10(%rbp),%xmm0
movsd  0xd0c(%rip),%xmm1
ucomisd %xmm1,%xmm0
jb     1439 <digamma+0x2d9>
movsd  0xd32(%rip),%xmm0
divsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x10(%rbp),%xmm0
call   1050 <log@plt>
movaps %xmm0,%xmm1
movsd  -0x20(%rbp),%xmm0
movsd  0xd06(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
addsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x20(%rbp),%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm2
movsd  -0x20(%rbp),%xmm1
movsd  -0x20(%rbp),%xmm3
movsd  -0x20(%rbp),%xmm4
movq   %xmm4,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm4
movsd  0xc9d(%rip),%xmm5
mulsd  %xmm5,%xmm4
movsd  0xc99(%rip),%xmm5
addsd  %xmm5,%xmm4
movq   %xmm3,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm3
mulsd  %xmm4,%xmm3
movsd  0xc62(%rip),%xmm4
addsd  %xmm4,%xmm3
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm3,%xmm1
movsd  0xc33(%rip),%xmm3
addsd  %xmm3,%xmm1
movq   %xmm2,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm2
mulsd  %xmm1,%xmm2
movsd  0xc04(%rip),%xmm1
addsd  %xmm1,%xmm2
movsd  -0x18(%rbp),%xmm1
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<digamma>:
sub    $0x28,%rsp
movsd  %xmm0,(%rsp)
call   1080 <isinf@plt>
cmp    $0xffffffff,%eax
je     1182 <digamma+0x22>
movsd  (%rsp),%xmm0
call   1040 <isnan@plt>
test   %rax,%rax
je     1196 <digamma+0x36>
mov    0x2e6f(%rip),%rax
movsd  (%rax),%xmm4
movapd %xmm4,%xmm0
add    $0x28,%rsp
ret
movsd  (%rsp),%xmm0
call   1070 <floor@plt>
xorpd  %xmm1,%xmm1
movsd  (%rsp),%xmm3
ucomisd %xmm3,%xmm1
jb     11cc <digamma+0x6c>
ucomisd %xmm3,%xmm0
jne    11cc <digamma+0x6c>
jp     11cc <digamma+0x6c>
mov    0x2e22(%rip),%rax
movsd  (%rax),%xmm4
xorpd  0xea6(%rip),%xmm4
jmp    118d <digamma+0x2d>
ucomisd %xmm3,%xmm1
jbe    1212 <digamma+0xb2>
movsd  0xe4e(%rip),%xmm0
subsd  %xmm3,%xmm0
call   1060 <digamma@plt>
movsd  %xmm0,0x10(%rsp)
movsd  (%rsp),%xmm0
mulsd  0xe6a(%rip),%xmm0
call   1030 <tan@plt>
movsd  0xe65(%rip),%xmm4
divsd  %xmm0,%xmm4
addsd  0x10(%rsp),%xmm4
jmp    118d <digamma+0x2d>
movsd  0xde6(%rip),%xmm0
ucomisd %xmm3,%xmm0
jae    1304 <digamma+0x1a4>
xorpd  %xmm4,%xmm4
movsd  0xdf0(%rip),%xmm0
ucomisd %xmm3,%xmm0
jbe    1266 <digamma+0x106>
xorpd  %xmm4,%xmm4
movsd  0xde6(%rip),%xmm1
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movapd %xmm1,%xmm2
divsd  %xmm3,%xmm2
subsd  %xmm2,%xmm4
addsd  %xmm1,%xmm3
ucomisd %xmm3,%xmm0
ja     1250 <digamma+0xf0>
ucomisd 0xdb2(%rip),%xmm3
jb     118d <digamma+0x2d>
movsd  0xdac(%rip),%xmm0
divsd  %xmm3,%xmm0
movapd %xmm0,0x10(%rsp)
movapd %xmm3,%xmm0
movapd %xmm4,(%rsp)
call   1050 <log@plt>
movsd  0xd94(%rip),%xmm1
movapd 0x10(%rsp),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm1,%xmm0
movapd 0xdbe(%rip),%xmm1
xorpd  %xmm2,%xmm1
mulsd  %xmm2,%xmm1
movsd  0xd76(%rip),%xmm2
mulsd  %xmm1,%xmm2
addsd  0xd72(%rip),%xmm2
addsd  (%rsp),%xmm0
mulsd  %xmm1,%xmm2
addsd  0xd69(%rip),%xmm2
mulsd  %xmm1,%xmm2
addsd  0xd65(%rip),%xmm2
mulsd  %xmm1,%xmm2
addsd  0xd61(%rip),%xmm2
mulsd  %xmm1,%xmm2
addsd  %xmm2,%xmm0
add    $0x28,%rsp
ret
movsd  0xcfc(%rip),%xmm0
divsd  %xmm3,%xmm0
addsd  0xcf8(%rip),%xmm0
mulsd  0xcf8(%rip),%xmm3
addsd  %xmm0,%xmm3
movapd %xmm3,%xmm0
add    $0x28,%rsp
ret

LLVM IR (-O0):
@digamma.c = internal constant double 1.200000e+01
@digamma.d1 = internal constant double 0xBFE2788CFC6FB619
@digamma.d2 = internal constant double 0x3FFA51A6625307D3
@digamma.s = internal constant double 0x3EB0C6F7A0B5ED8D
@digamma.s3 = internal constant double 0x3FB5555555555555
@digamma.s4 = internal constant double 0x3F81111111111111
@digamma.s5 = internal constant double 0x3F70410410410410
@digamma.s6 = internal constant double 0x3F71111111111111
@digamma.s7 = internal constant double 0x3F7F07C1F07C1F08
@digamma.s8 = internal constant double 0.000000e+00
@digamma.s9 = internal constant double 0.000000e+00
@digamma.s10 = internal constant double 0.000000e+00
@NAN = global double 0.000000e+00
@INFINITY = global double 0.000000e+00
define double @digamma(double %0) {
%2 = alloca double
%3 = alloca double
%4 = alloca double
%5 = alloca double
store double %0, double* %3
%6 = load double, double* %3
%7 = call i32 @isinf(double %6)
%8 = icmp eq i32 %7, -1
br i1 %8, label %13, label %9
9: ; preds = %1
%10 = load double, double* %3
%11 = call i64 @isnan(double %10)
%12 = icmp ne i64 %11, 0
br i1 %12, label %13, label %15
13: ; preds = %9, %1
%14 = load double, double* @NAN
store double %14, double* %2
br label %91
15: ; preds = %9
%16 = load double, double* %3
%17 = fcmp ole double %16, 0.000000e+00
br i1 %17, label %18, label %26
18: ; preds = %15
%19 = load double, double* %3
%20 = call double @llvm.floor.f64(double %19)
%21 = load double, double* %3
%22 = fcmp oeq double %20, %21
br i1 %22, label %23, label %26
23: ; preds = %18
%24 = load double, double* @INFINITY
%25 = fneg double %24
store double %25, double* %2
br label %91
26: ; preds = %18, %15
%27 = load double, double* %3
%28 = fcmp olt double %27, 0.000000e+00
br i1 %28, label %29, label %38
29: ; preds = %26
%30 = load double, double* %3
%31 = fsub double 1.000000e+00, %30
%32 = call double @digamma(double %31)
%33 = load double, double* %3
%34 = fmul double 0xC00921FB53C8D4F1, %33
%35 = call double @tan(double %34)
%36 = fdiv double 0x400921FB53C8D4F1, %35
%37 = fadd double %32, %36
store double %37, double* %2
br label %91
38: ; preds = %26
%39 = load double, double* %3
%40 = fcmp ole double %39, 0x3EB0C6F7A0B5ED8D
br i1 %40, label %41, label %47
41: ; preds = %38
%42 = load double, double* %3
%43 = fdiv double 1.000000e+00, %42
%44 = fsub double 0xBFE2788CFC6FB619, %43
%45 = load double, double* %3
%46 = call double @llvm.fmuladd.f64(double 0x3FFA51A6625307D3, double %45, double %44)
store double %46, double* %2
br label %91
47: ; preds = %38
store double 0.000000e+00, double* %4
br label %48
48: ; preds = %51, %47
%49 = load double, double* %3
%50 = fcmp olt double %49, 1.200000e+01
br i1 %50, label %51, label %58
51: ; preds = %48
%52 = load double, double* %3
%53 = fdiv double 1.000000e+00, %52
%54 = load double, double* %4
%55 = fsub double %54, %53
store double %55, double* %4
%56 = load double, double* %3
%57 = fadd double %56, 1.000000e+00
store double %57, double* %3
br label %48
58: ; preds = %48
%59 = load double, double* %3
%60 = fcmp oge double %59, 1.200000e+01
br i1 %60, label %61, label %89
61: ; preds = %58
%62 = load double, double* %3
%63 = fdiv double 1.000000e+00, %62
store double %63, double* %5
%64 = load double, double* %3
%65 = call double @log(double %64)
%66 = load double, double* %5
%67 = call double @llvm.fmuladd.f64(double -5.000000e-01, double %66, double %65)
%68 = load double, double* %4
%69 = fadd double %68, %67
store double %69, double* %4
%70 = load double, double* %5
%71 = load double, double* %5
%72 = fmul double %71, %70
store double %72, double* %5
%73 = load double, double* %5
%74 = load double, double* %5
%75 = load double, double* %5
%76 = load double, double* %5
%77 = load double, double* %5
%78 = fneg double %77
%79 = call double @llvm.fmuladd.f64(double %78, double 0x3F7F07C1F07C1F08, double 0x3F71111111111111)
%80 = fneg double %76
%81 = call double @llvm.fmuladd.f64(double %80, double %79, double 0x3F70410410410410)
%82 = fneg double %75
%83 = call double @llvm.fmuladd.f64(double %82, double %81, double 0x3F81111111111111)
%84 = fneg double %74
%85 = call double @llvm.fmuladd.f64(double %84, double %83, double 0x3FB5555555555555)
%86 = load double, double* %4
%87 = fneg double %73
%88 = call double @llvm.fmuladd.f64(double %87, double %85, double %86)
store double %88, double* %4
br label %89
89: ; preds = %61, %58
%90 = load double, double* %4
store double %90, double* %2
br label %91
91: ; preds = %89, %41, %29, %23, %13
%92 = load double, double* %2
ret double %92
}

LLVM IR (-O2):
@NAN = global double 0.000000e+00
@INFINITY = global double 0.000000e+00
define double @digamma(double %0) {
%2 = tail call i32 @isinf(double %0)
%3 = icmp eq i32 %2, -1
br i1 %3, label %7, label %4
4: ; preds = %1
%5 = tail call i64 @isnan(double %0)
%6 = icmp eq i64 %5, 0
br i1 %6, label %9, label %7
7: ; preds = %4, %1
%8 = load double, double* @NAN
br label %19
9: ; preds = %4
%10 = fcmp ole double %0, 0.000000e+00
%11 = tail call double @llvm.floor.f64(double %0)
%12 = fcmp oeq double %11, %0
%13 = select i1 %10, i1 %12, i1 false
br i1 %13, label %14, label %17
14: ; preds = %9
%15 = load double, double* @INFINITY
%16 = fneg double %15
br label %19
17: ; preds = %9
%18 = fcmp olt double %0, 0.000000e+00
br i1 %18, label %21, label %28
19: ; preds = %7, %14, %32, %47, %43, %21
%20 = phi double [ %27, %21 ], [ %8, %7 ], [ %16, %14 ], [ %35, %32 ], [ %58, %47 ], [ %45, %43 ]
ret double %20
21: ; preds = %17
%22 = fsub double 1.000000e+00, %0
%23 = tail call double @digamma(double %22)
%24 = fmul double %0, 0xC00921FB53C8D4F1
%25 = tail call double @tan(double %24)
%26 = fdiv double 0x400921FB53C8D4F1, %25
%27 = fadd double %23, %26
br label %19
28: ; preds = %17
%29 = fcmp ugt double %0, 0x3EB0C6F7A0B5ED8D
br i1 %29, label %30, label %32
30: ; preds = %28
%31 = fcmp olt double %0, 1.200000e+01
br i1 %31, label %36, label %43
32: ; preds = %28
%33 = fdiv double 1.000000e+00, %0
%34 = fsub double 0xBFE2788CFC6FB619, %33
%35 = tail call double @llvm.fmuladd.f64(double %0, double 0x3FFA51A6625307D3, double %34)
br label %19
36: ; preds = %30, %36
%37 = phi double [ %40, %36 ], [ 0.000000e+00, %30 ]
%38 = phi double [ %41, %36 ], [ %0, %30 ]
%39 = fdiv double 1.000000e+00, %38
%40 = fsub double %37, %39
%41 = fadd double %38, 1.000000e+00
%42 = fcmp olt double %41, 1.200000e+01
br i1 %42, label %36, label %43
43: ; preds = %36, %30
%44 = phi double [ %0, %30 ], [ %41, %36 ]
%45 = phi double [ 0.000000e+00, %30 ], [ %40, %36 ]
%46 = fcmp ult double %44, 1.200000e+01
br i1 %46, label %19, label %47
47: ; preds = %43
%48 = fdiv double 1.000000e+00, %44
%49 = tail call double @log(double %44)
%50 = tail call double @llvm.fmuladd.f64(double %48, double -5.000000e-01, double %49)
%51 = fadd double %45, %50
%52 = fneg double %48
%53 = fmul double %48, %52
%54 = tail call double @llvm.fmuladd.f64(double %53, double 0x3F7F07C1F07C1F08, double 0x3F71111111111111)
%55 = tail call double @llvm.fmuladd.f64(double %53, double %54, double 0x3F70410410410410)
%56 = tail call double @llvm.fmuladd.f64(double %53, double %55, double 0x3F81111111111111)
%57 = tail call double @llvm.fmuladd.f64(double %53, double %56, double 0x3FB5555555555555)
%58 = tail call double @llvm.fmuladd.f64(double %53, double %57, double %51)
br label %19
}