#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 /*<<< orphan*/ errno;
double frexp(double, int *);
double log(double arg) {
  double x, z, zsq, temp;
  int exp;
  if (arg <= 0) {
    errno = (arg == 0) ? ERANGE : EDOM;
    return -HUGE_VAL;
  }
  x = frexp(arg, &exp);
  while (x < 0.5) {
    x *= 2;
    exp--;
  }
  if (x < 0.707106781186547524e0) {
    x *= 2;
    exp--;
  }
  z = (x - 1) / (x + 1);
  zsq = z * z;
  temp = ((0.421087371217979714e0 * zsq + -.963769093377840513e1) * zsq +
          0.309572928215376501e2) *
             zsq +
         -.240139179559210510e2;
  temp =
      temp /
      (((zsq + -.891110902798312337e1) * zsq + 0.194809660700889731e2) * zsq +
       -.120069589779605255e2);
  temp = temp * z + exp * 0.693147180559945309e0;
  return temp;
}


x86 assembly (clang, -O0):
<log>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
movsd  %xmm0,-0x10(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     1198 <log+0x88>
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    1154 <log+0x44>
jp     1154 <log+0x44>
mov    0x2e8e(%rip),%rax
mov    (%rax),%eax
mov    %eax,-0x38(%rbp)
jmp    1160 <log+0x50>
mov    0x2e85(%rip),%rax
mov    (%rax),%eax
mov    %eax,-0x38(%rbp)
mov    -0x38(%rbp),%ecx
mov    0x2e5e(%rip),%rax
mov    %ecx,(%rax)
mov    0x2e75(%rip),%rax
movsd  (%rax),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1305 <log+0x1f5>
movsd  -0x10(%rbp),%xmm0
lea    -0x34(%rbp),%rdi
call   1030 <frexp@plt>
movsd  %xmm0,-0x18(%rbp)
movsd  0xe4d(%rip),%xmm0
ucomisd -0x18(%rbp),%xmm0
jbe    11de <log+0xce>
movsd  0xe4a(%rip),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x34(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x34(%rbp)
jmp    11ab <log+0x9b>
movsd  0xe22(%rip),%xmm0
ucomisd -0x18(%rbp),%xmm0
jbe    120c <log+0xfc>
movsd  0xe17(%rip),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x34(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x34(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  0xe3f(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  0xe33(%rip),%xmm1
addsd  -0x18(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  0xdf9(%rip),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xdf5(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  -0x28(%rbp),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xdd0(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  -0x28(%rbp),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xdb3(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  0xd95(%rip),%xmm1
addsd  -0x28(%rbp),%xmm1
movsd  -0x28(%rbp),%xmm2
mulsd  %xmm2,%xmm1
movsd  0xd77(%rip),%xmm2
addsd  %xmm2,%xmm1
movsd  -0x28(%rbp),%xmm2
mulsd  %xmm2,%xmm1
movsd  0xd5a(%rip),%xmm2
addsd  %xmm2,%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm2
cvtsi2sdl -0x34(%rbp),%xmm1
movsd  0xd2e(%rip),%xmm3
mulsd  %xmm3,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<log>:
push   %rax
xorpd  %xmm1,%xmm1
ucomisd %xmm0,%xmm1
jae    11eb <log+0xdb>
lea    0x4(%rsp),%rdi
call   1030 <frexp@plt>
mov    0x4(%rsp),%eax
movsd  0xefb(%rip),%xmm1
ucomisd %xmm0,%xmm1
jbe    114d <log+0x3d>
nopl   0x0(%rax,%rax,1)
addsd  %xmm0,%xmm0
add    $0xffffffff,%eax
ucomisd %xmm0,%xmm1
ja     1140 <log+0x30>
movsd  0xee3(%rip),%xmm1
xor    %ecx,%ecx
ucomisd %xmm0,%xmm1
seta   %cl
jbe    1164 <log+0x54>
addsd  %xmm0,%xmm0
movsd  0xed4(%rip),%xmm1
addsd  %xmm0,%xmm1
addsd  0xed0(%rip),%xmm0
divsd  %xmm0,%xmm1
movapd %xmm1,%xmm2
mulsd  %xmm1,%xmm2
movsd  0xec4(%rip),%xmm0
mulsd  %xmm2,%xmm0
addsd  0xec0(%rip),%xmm0
movsd  0xec0(%rip),%xmm3
addsd  %xmm2,%xmm3
unpcklpd %xmm3,%xmm0
unpcklpd %xmm2,%xmm2
mulpd  %xmm2,%xmm0
addpd  0xe58(%rip),%xmm0
sub    %ecx,%eax
mulpd  %xmm2,%xmm0
addpd  0xe5a(%rip),%xmm0
movapd %xmm0,%xmm2
unpckhpd %xmm0,%xmm2
divsd  %xmm2,%xmm0
xorps  %xmm2,%xmm2
cvtsi2sd %eax,%xmm2
mulsd  0xe87(%rip),%xmm2
mulsd  %xmm1,%xmm0
addsd  %xmm2,%xmm0
pop    %rax
ret
ucomisd %xmm1,%xmm0
mov    0x2dea(%rip),%rax
mov    0x2ddb(%rip),%rcx
cmovne %rax,%rcx
cmovp  %rax,%rcx
mov    (%rcx),%eax
mov    0x2dba(%rip),%rcx
mov    %eax,(%rcx)
mov    0x2dd1(%rip),%rax
movsd  (%rax),%xmm0
xorps  0xdde(%rip),%xmm0
pop    %rax
ret

LLVM IR (-O0):
@ERANGE = global i32 0
@EDOM = global i32 0
@errno = global i32 0
@HUGE_VAL = global double 0.000000e+00
define double @log(double %0) {
%2 = alloca double
%3 = alloca double
%4 = alloca double
%5 = alloca double
%6 = alloca double
%7 = alloca double
%8 = alloca i32
store double %0, double* %3
%9 = load double, double* %3
%10 = fcmp ole double %9, 0.000000e+00
br i1 %10, label %11, label %22
11: ; preds = %1
%12 = load double, double* %3
%13 = fcmp oeq double %12, 0.000000e+00
br i1 %13, label %14, label %16
14: ; preds = %11
%15 = load i32, i32* @ERANGE
br label %18
16: ; preds = %11
%17 = load i32, i32* @EDOM
br label %18
18: ; preds = %16, %14
%19 = phi i32 [ %15, %14 ], [ %17, %16 ]
store i32 %19, i32* @errno
%20 = load double, double* @HUGE_VAL
%21 = fneg double %20
store double %21, double* %2
br label %71
22: ; preds = %1
%23 = load double, double* %3
%24 = call double @frexp(double %23, i32* %8)
store double %24, double* %4
br label %25
25: ; preds = %28, %22
%26 = load double, double* %4
%27 = fcmp olt double %26, 5.000000e-01
br i1 %27, label %28, label %33
28: ; preds = %25
%29 = load double, double* %4
%30 = fmul double %29, 2.000000e+00
store double %30, double* %4
%31 = load i32, i32* %8
%32 = add nsw i32 %31, -1
store i32 %32, i32* %8
br label %25
33: ; preds = %25
%34 = load double, double* %4
%35 = fcmp olt double %34, 0x3FE6A09E667F3BCD
br i1 %35, label %36, label %41
36: ; preds = %33
%37 = load double, double* %4
%38 = fmul double %37, 2.000000e+00
store double %38, double* %4
%39 = load i32, i32* %8
%40 = add nsw i32 %39, -1
store i32 %40, i32* %8
br label %41
41: ; preds = %36, %33
%42 = load double, double* %4
%43 = fsub double %42, 1.000000e+00
%44 = load double, double* %4
%45 = fadd double %44, 1.000000e+00
%46 = fdiv double %43, %45
store double %46, double* %5
%47 = load double, double* %5
%48 = load double, double* %5
%49 = fmul double %47, %48
store double %49, double* %6
%50 = load double, double* %6
%51 = call double @llvm.fmuladd.f64(double 0x3FDAF3187208F30D, double %50, double 0xC023467F6D131162)
%52 = load double, double* %6
%53 = call double @llvm.fmuladd.f64(double %51, double %52, double 0x403EF51124713324)
%54 = load double, double* %6
%55 = call double @llvm.fmuladd.f64(double %53, double %54, double 0xC0380390208D8212)
store double %55, double* %7
%56 = load double, double* %7
%57 = load double, double* %6
%58 = fadd double %57, 0xC021D27CE1EC8E44
%59 = load double, double* %6
%60 = call double @llvm.fmuladd.f64(double %58, double %59, double 0x40337B2097A5848D)
%61 = load double, double* %6
%62 = call double @llvm.fmuladd.f64(double %60, double %61, double 0xC0280390208D8212)
%63 = fdiv double %56, %62
store double %63, double* %7
%64 = load double, double* %7
%65 = load double, double* %5
%66 = load i32, i32* %8
%67 = sitofp i32 %66 to double
%68 = fmul double %67, 0x3FE62E42FEFA39EF
%69 = call double @llvm.fmuladd.f64(double %64, double %65, double %68)
store double %69, double* %7
%70 = load double, double* %7
store double %70, double* %2
br label %71
71: ; preds = %41, %18
%72 = load double, double* %2
ret double %72
}

LLVM IR (-O2):
@ERANGE = global i32 0
@EDOM = global i32 0
@errno = global i32 0
@HUGE_VAL = global double 0.000000e+00
define double @log(double %0) {
%2 = alloca i32
%3 = bitcast i32* %2 to i8*
%4 = fcmp ugt double %0, 0.000000e+00
br i1 %4, label %12, label %5
5: ; preds = %1
%6 = fcmp oeq double %0, 0.000000e+00
%7 = load i32, i32* @ERANGE
%8 = load i32, i32* @EDOM
%9 = select i1 %6, i32 %7, i32 %8
store i32 %9, i32* @errno
%10 = load double, double* @HUGE_VAL
%11 = fneg double %10
br label %48
12: ; preds = %1
%13 = call double @frexp(double %0, i32* %2)
%14 = load i32, i32* %2
%15 = fcmp olt double %13, 5.000000e-01
br i1 %15, label %16, label %22
16: ; preds = %12, %16
%17 = phi double [ %19, %16 ], [ %13, %12 ]
%18 = phi i32 [ %20, %16 ], [ %14, %12 ]
%19 = fmul double %17, 2.000000e+00
%20 = add nsw i32 %18, -1
%21 = fcmp olt double %19, 5.000000e-01
br i1 %21, label %16, label %22
22: ; preds = %16, %12
%23 = phi i32 [ %14, %12 ], [ %20, %16 ]
%24 = phi double [ %13, %12 ], [ %19, %16 ]
%25 = fcmp olt double %24, 0x3FE6A09E667F3BCD
%26 = fmul double %24, 2.000000e+00
%27 = sext i1 %25 to i32
%28 = add nsw i32 %23, %27
%29 = select i1 %25, double %26, double %24
%30 = fadd double %29, -1.000000e+00
%31 = fadd double %29, 1.000000e+00
%32 = fdiv double %30, %31
%33 = fmul double %32, %32
%34 = tail call double @llvm.fmuladd.f64(double %33, double 0x3FDAF3187208F30D, double 0xC023467F6D131162)
%35 = fadd double %33, 0xC021D27CE1EC8E44
%36 = insertelement <2 x double> poison, double %34, i64 0
%37 = insertelement <2 x double> %36, double %35, i64 1
%38 = insertelement <2 x double> poison, double %33, i64 0
%39 = shufflevector <2 x double> %38, <2 x double> poison, <2 x i32> zeroinitializer
%40 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %37, <2 x double> %39, <2 x double> <double 0x403EF51124713324, double 0x40337B2097A5848D>)
%41 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %40, <2 x double> %39, <2 x double> <double 0xC0380390208D8212, double 0xC0280390208D8212>)
%42 = extractelement <2 x double> %41, i64 0
%43 = extractelement <2 x double> %41, i64 1
%44 = fdiv double %42, %43
%45 = sitofp i32 %28 to double
%46 = fmul double %45, 0x3FE62E42FEFA39EF
%47 = tail call double @llvm.fmuladd.f64(double %44, double %32, double %46)
br label %48
48: ; preds = %22, %5
%49 = phi double [ %11, %5 ], [ %47, %22 ]
ret double %49
}