#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 M_E;
int M_PI;
long long floor(double);
double log10(int);
long long findDigits(int n) {
  if (n < 0)
    return 0;
  if (n <= 1)
    return 1;
  double x = ((n * log10(n / M_E) + log10(2 * M_PI * n) / 2.0));
  return floor(x) + 1;
}


x86 assembly (clang, -O0):
<findDigits>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %edi,-0xc(%rbp)
cmpl   $0x0,-0xc(%rbp)
jge    1142 <findDigits+0x22>
movq   $0x0,-0x8(%rbp)
jmp    11c9 <findDigits+0xa9>
cmpl   $0x1,-0xc(%rbp)
jg     1159 <findDigits+0x39>
movq   $0x1,-0x8(%rbp)
jmp    11c9 <findDigits+0xa9>
cvtsi2sdl -0xc(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0xc(%rbp),%eax
mov    0x2e6b(%rip),%rcx
cltd
idivl  (%rcx)
mov    %eax,%edi
call   1030 <log10@plt>
movsd  %xmm0,-0x28(%rbp)
mov    0x2e65(%rip),%rax
mov    (%rax),%edi
shl    $0x1,%edi
imul   -0xc(%rbp),%edi
call   1030 <log10@plt>
movsd  -0x28(%rbp),%xmm2
movaps %xmm0,%xmm1
movsd  -0x20(%rbp),%xmm0
movsd  0xe5a(%rip),%xmm3
divsd  %xmm3,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
call   1040 <floor@plt>
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<findDigits>:
push   %rbx
sub    $0x10,%rsp
test   %edi,%edi
js     118c <findDigits+0x6c>
mov    %edi,%ebx
mov    $0x1,%eax
cmp    $0x2,%edi
jb     118e <findDigits+0x6e>
cvtsi2sd %ebx,%xmm0
movsd  %xmm0,0x8(%rsp)
mov    0x2e92(%rip),%rcx
mov    %ebx,%eax
cltd
idivl  (%rcx)
mov    %eax,%edi
call   1030 <log10@plt>
movsd  %xmm0,(%rsp)
mov    0x2e8a(%rip),%rax
imul   (%rax),%ebx
add    %ebx,%ebx
mov    %ebx,%edi
call   1030 <log10@plt>
mulsd  0xe8e(%rip),%xmm0
movsd  (%rsp),%xmm1
mulsd  0x8(%rsp),%xmm1
addsd  %xmm1,%xmm0
call   1040 <floor@plt>
add    $0x1,%rax
jmp    118e <findDigits+0x6e>
xor    %eax,%eax
add    $0x10,%rsp
pop    %rbx
ret

LLVM IR (-O0):
@M_E = global i32 0
@M_PI = global i32 0
define i64 @findDigits(i32 %0) {
%2 = alloca i64
%3 = alloca i32
%4 = alloca double
store i32 %0, i32* %3
%5 = load i32, i32* %3
%6 = icmp slt i32 %5, 0
br i1 %6, label %7, label %8
7: ; preds = %1
store i64 0, i64* %2
br label %29
8: ; preds = %1
%9 = load i32, i32* %3
%10 = icmp sle i32 %9, 1
br i1 %10, label %11, label %12
11: ; preds = %8
store i64 1, i64* %2
br label %29
12: ; preds = %8
%13 = load i32, i32* %3
%14 = sitofp i32 %13 to double
%15 = load i32, i32* %3
%16 = load i32, i32* @M_E
%17 = sdiv i32 %15, %16
%18 = call double @log10(i32 %17)
%19 = load i32, i32* @M_PI
%20 = mul nsw i32 2, %19
%21 = load i32, i32* %3
%22 = mul nsw i32 %20, %21
%23 = call double @log10(i32 %22)
%24 = fdiv double %23, 2.000000e+00
%25 = call double @llvm.fmuladd.f64(double %14, double %18, double %24)
store double %25, double* %4
%26 = load double, double* %4
%27 = call i64 @floor(double %26)
%28 = add nsw i64 %27, 1
store i64 %28, i64* %2
br label %29
29: ; preds = %12, %11, %7
%30 = load i64, i64* %2
ret i64 %30
}

LLVM IR (-O2):
@M_E = global i32 0
@M_PI = global i32 0
define i64 @findDigits(i32 %0) {
%2 = icmp slt i32 %0, 0
br i1 %2, label %18, label %3
3: ; preds = %1
%4 = icmp ult i32 %0, 2
br i1 %4, label %18, label %5
5: ; preds = %3
%6 = sitofp i32 %0 to double
%7 = load i32, i32* @M_E
%8 = sdiv i32 %0, %7
%9 = tail call double @log10(i32 %8)
%10 = load i32, i32* @M_PI
%11 = shl nuw i32 %0, 1
%12 = mul i32 %11, %10
%13 = tail call double @log10(i32 %12)
%14 = fmul double %13, 5.000000e-01
%15 = tail call double @llvm.fmuladd.f64(double %6, double %9, double %14)
%16 = tail call i64 @floor(double %15)
%17 = add nsw i64 %16, 1
br label %18
18: ; preds = %3, %1, %5
%19 = phi i64 [ %17, %5 ], [ 0, %1 ], [ 1, %3 ]
ret i64 %19
}