#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 log(double const);
int /*<<< orphan*/ printf(char *);
int /*<<< orphan*/ qd_add(double *, double *, double *);
int /*<<< orphan*/ qd_copy(double *, double *);
int /*<<< orphan*/ qd_exp(double *, double *);
int qd_is_one(double const *);
int /*<<< orphan*/ qd_minus(double *);
int /*<<< orphan*/ qd_mul(double const *, double *, double *);
int /*<<< orphan*/ qd_sub_qd_d(double *, double, double *);
void qd_log(const double *a, double *b) {
  double acc[4];
  int i;
  if (qd_is_one(a) == 1) {
    b[0] = 0.0;
    b[1] = 0.0;
    b[2] = 0.0;
    b[3] = 0.0;
    return;
  }
  if (a[0] <= 0.0) {
    printf("qd_log: argument is not positive");
    b[0] = -1.0;
    b[0] = 0.0;
    b[2] = 0.0;
    b[3] = 0.0;
    return;
  }
  b[0] = log(a[0]);
  b[1] = 0.0;
  b[2] = 0.0;
  b[3] = 0.0;
  for (i = 0; i < 3; i++) {
    qd_copy(b, acc);
    qd_minus(acc);
    qd_exp(acc, acc);
    qd_mul(a, acc, acc);
    qd_add(b, acc, b);
    qd_sub_qd_d(b, 1.0, b);
  }
}


x86 assembly (clang, -O0):
<qd_log>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rdi
call   1090 <qd_is_one@plt>
cmp    $0x1,%eax
jne    11e6 <qd_log+0x56>
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x8(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x10(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x18(%rax)
jmp    12ed <qd_log+0x15d>
mov    -0x8(%rbp),%rax
xorps  %xmm0,%xmm0
ucomisd (%rax),%xmm0
jb     123b <qd_log+0xab>
lea    0xe12(%rip),%rdi
call   1040 <printf@plt>
mov    -0x10(%rbp),%rax
movsd  0xdf9(%rip),%xmm0
movsd  %xmm0,(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x10(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x18(%rax)
jmp    12ed <qd_log+0x15d>
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm0
call   10a0 <log@plt>
mov    -0x10(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x8(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x10(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x18(%rax)
movl   $0x0,-0x34(%rbp)
cmpl   $0x3,-0x34(%rbp)
jge    12ed <qd_log+0x15d>
mov    -0x10(%rbp),%rdi
lea    -0x30(%rbp),%rsi
call   10b0 <qd_copy@plt>
lea    -0x30(%rbp),%rdi
call   1030 <qd_minus@plt>
lea    -0x30(%rbp),%rdi
lea    -0x30(%rbp),%rsi
call   1050 <qd_exp@plt>
mov    -0x8(%rbp),%rdi
lea    -0x30(%rbp),%rsi
lea    -0x30(%rbp),%rdx
call   1080 <qd_mul@plt>
mov    -0x10(%rbp),%rdi
lea    -0x30(%rbp),%rsi
mov    -0x10(%rbp),%rdx
call   1070 <qd_add@plt>
mov    -0x10(%rbp),%rdi
mov    -0x10(%rbp),%rsi
movsd  0xd26(%rip),%xmm0
call   1060 <qd_sub_qd_d@plt>
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    127b <qd_log+0xeb>
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<qd_log>:
push   %r15
push   %r14
push   %rbx
sub    $0x20,%rsp
mov    %rsi,%rbx
mov    %rdi,%r14
call   1090 <qd_is_one@plt>
cmp    $0x1,%eax
jne    11bb <qd_log+0x2b>
xorpd  %xmm0,%xmm0
movupd %xmm0,0x10(%rbx)
movupd %xmm0,(%rbx)
jmp    12f0 <qd_log+0x160>
movsd  (%r14),%xmm0
xorpd  %xmm1,%xmm1
ucomisd %xmm0,%xmm1
jae    12d4 <qd_log+0x144>
call   10a0 <log@plt>
movsd  %xmm0,(%rbx)
xorpd  %xmm0,%xmm0
movupd %xmm0,0x8(%rbx)
movq   $0x0,0x18(%rbx)
mov    %rsp,%r15
mov    %rbx,%rdi
mov    %r15,%rsi
call   10b0 <qd_copy@plt>
mov    %r15,%rdi
call   1030 <qd_minus@plt>
mov    %r15,%rdi
mov    %r15,%rsi
call   1050 <qd_exp@plt>
mov    %r14,%rdi
mov    %r15,%rsi
mov    %r15,%rdx
call   1080 <qd_mul@plt>
mov    %rbx,%rdi
mov    %r15,%rsi
mov    %rbx,%rdx
call   1070 <qd_add@plt>
movsd  0xdd3(%rip),%xmm0
mov    %rbx,%rdi
mov    %rbx,%rsi
call   1060 <qd_sub_qd_d@plt>
mov    %rbx,%rdi
mov    %r15,%rsi
call   10b0 <qd_copy@plt>
mov    %r15,%rdi
call   1030 <qd_minus@plt>
mov    %r15,%rdi
mov    %r15,%rsi
call   1050 <qd_exp@plt>
mov    %r14,%rdi
mov    %r15,%rsi
mov    %r15,%rdx
call   1080 <qd_mul@plt>
mov    %rbx,%rdi
mov    %r15,%rsi
mov    %rbx,%rdx
call   1070 <qd_add@plt>
mov    %rbx,%rdi
movsd  0xd83(%rip),%xmm0
mov    %rbx,%rsi
call   1060 <qd_sub_qd_d@plt>
mov    %rbx,%rdi
mov    %r15,%rsi
call   10b0 <qd_copy@plt>
mov    %r15,%rdi
call   1030 <qd_minus@plt>
mov    %r15,%rdi
mov    %r15,%rsi
call   1050 <qd_exp@plt>
mov    %r14,%rdi
mov    %r15,%rsi
mov    %r15,%rdx
call   1080 <qd_mul@plt>
mov    %rbx,%rdi
mov    %r15,%rsi
mov    %rbx,%rdx
call   1070 <qd_add@plt>
mov    %rbx,%rdi
movsd  0xd36(%rip),%xmm0
mov    %rbx,%rsi
call   1060 <qd_sub_qd_d@plt>
jmp    12f0 <qd_log+0x160>
lea    0xd2d(%rip),%rdi
call   1040 <printf@plt>
movq   $0x0,(%rbx)
xorpd  %xmm0,%xmm0
movupd %xmm0,0x10(%rbx)
add    $0x20,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
@.str = [33 x i8] c"qd_log: argument is not positive\00"
define void @qd_log(double* %0, double* %1) {
%3 = alloca double*
%4 = alloca double*
%5 = alloca [4 x double]
%6 = alloca i32
store double* %0, double** %3
store double* %1, double** %4
%7 = load double*, double** %3
%8 = call i32 @qd_is_one(double* %7)
%9 = icmp eq i32 %8, 1
br i1 %9, label %10, label %19
10: ; preds = %2
%11 = load double*, double** %4
%12 = getelementptr inbounds double, double* %11, i64 0
store double 0.000000e+00, double* %12
%13 = load double*, double** %4
%14 = getelementptr inbounds double, double* %13, i64 1
store double 0.000000e+00, double* %14
%15 = load double*, double** %4
%16 = getelementptr inbounds double, double* %15, i64 2
store double 0.000000e+00, double* %16
%17 = load double*, double** %4
%18 = getelementptr inbounds double, double* %17, i64 3
store double 0.000000e+00, double* %18
br label %73
19: ; preds = %2
%20 = load double*, double** %3
%21 = getelementptr inbounds double, double* %20, i64 0
%22 = load double, double* %21
%23 = fcmp ole double %22, 0.000000e+00
br i1 %23, label %24, label %34
24: ; preds = %19
%25 = call i32 @printf(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str, i64 0, i64 0))
%26 = load double*, double** %4
%27 = getelementptr inbounds double, double* %26, i64 0
store double -1.000000e+00, double* %27
%28 = load double*, double** %4
%29 = getelementptr inbounds double, double* %28, i64 0
store double 0.000000e+00, double* %29
%30 = load double*, double** %4
%31 = getelementptr inbounds double, double* %30, i64 2
store double 0.000000e+00, double* %31
%32 = load double*, double** %4
%33 = getelementptr inbounds double, double* %32, i64 3
store double 0.000000e+00, double* %33
br label %73
34: ; preds = %19
%35 = load double*, double** %3
%36 = getelementptr inbounds double, double* %35, i64 0
%37 = load double, double* %36
%38 = call double @log(double %37)
%39 = load double*, double** %4
%40 = getelementptr inbounds double, double* %39, i64 0
store double %38, double* %40
%41 = load double*, double** %4
%42 = getelementptr inbounds double, double* %41, i64 1
store double 0.000000e+00, double* %42
%43 = load double*, double** %4
%44 = getelementptr inbounds double, double* %43, i64 2
store double 0.000000e+00, double* %44
%45 = load double*, double** %4
%46 = getelementptr inbounds double, double* %45, i64 3
store double 0.000000e+00, double* %46
store i32 0, i32* %6
br label %47
47: ; preds = %70, %34
%48 = load i32, i32* %6
%49 = icmp slt i32 %48, 3
br i1 %49, label %50, label %73
50: ; preds = %47
%51 = load double*, double** %4
%52 = getelementptr inbounds [4 x double], [4 x double]* %5, i64 0, i64 0
%53 = call i32 @qd_copy(double* %51, double* %52)
%54 = getelementptr inbounds [4 x double], [4 x double]* %5, i64 0, i64 0
%55 = call i32 @qd_minus(double* %54)
%56 = getelementptr inbounds [4 x double], [4 x double]* %5, i64 0, i64 0
%57 = getelementptr inbounds [4 x double], [4 x double]* %5, i64 0, i64 0
%58 = call i32 @qd_exp(double* %56, double* %57)
%59 = load double*, double** %3
%60 = getelementptr inbounds [4 x double], [4 x double]* %5, i64 0, i64 0
%61 = getelementptr inbounds [4 x double], [4 x double]* %5, i64 0, i64 0
%62 = call i32 @qd_mul(double* %59, double* %60, double* %61)
%63 = load double*, double** %4
%64 = getelementptr inbounds [4 x double], [4 x double]* %5, i64 0, i64 0
%65 = load double*, double** %4
%66 = call i32 @qd_add(double* %63, double* %64, double* %65)
%67 = load double*, double** %4
%68 = load double*, double** %4
%69 = call i32 @qd_sub_qd_d(double* %67, double 1.000000e+00, double* %68)
br label %70
70: ; preds = %50
%71 = load i32, i32* %6
%72 = add nsw i32 %71, 1
store i32 %72, i32* %6
br label %47
73: ; preds = %10, %24, %47
ret void
}

LLVM IR (-O2):
@.str = [33 x i8] c"qd_log: argument is not positive\00"
define void @qd_log(double* %0, double* %1) {
%3 = alloca [4 x double]
%4 = bitcast [4 x double]* %3 to i8*
%5 = tail call i32 @qd_is_one(double* %0)
%6 = icmp eq i32 %5, 1
br i1 %6, label %7, label %9
7: ; preds = %2
%8 = bitcast double* %1 to i8*
br label %39
9: ; preds = %2
%10 = load double, double* %0
%11 = fcmp ugt double %10, 0.000000e+00
br i1 %11, label %16, label %12
12: ; preds = %9
%13 = tail call i32 @printf(i8* dereferenceable(1) getelementptr inbounds ([33 x i8], [33 x i8]* @.str, i64 0, i64 0))
store double 0.000000e+00, double* %1
%14 = getelementptr inbounds double, double* %1, i64 2
%15 = bitcast double* %14 to i8*
br label %39
16: ; preds = %9
%17 = tail call double @log(double %10)
store double %17, double* %1
%18 = getelementptr inbounds double, double* %1, i64 1
%19 = getelementptr inbounds [4 x double], [4 x double]* %3, i64 0, i64 0
%20 = bitcast double* %18 to i8*
%21 = call i32 @qd_copy(double* %1, double* %19)
%22 = call i32 @qd_minus(double* %19)
%23 = call i32 @qd_exp(double* %19, double* %19)
%24 = call i32 @qd_mul(double* %0, double* %19, double* %19)
%25 = call i32 @qd_add(double* %1, double* %19, double* %1)
%26 = call i32 @qd_sub_qd_d(double* %1, double 1.000000e+00, double* %1)
%27 = call i32 @qd_copy(double* %1, double* %19)
%28 = call i32 @qd_minus(double* %19)
%29 = call i32 @qd_exp(double* %19, double* %19)
%30 = call i32 @qd_mul(double* %0, double* %19, double* %19)
%31 = call i32 @qd_add(double* %1, double* %19, double* %1)
%32 = call i32 @qd_sub_qd_d(double* %1, double 1.000000e+00, double* %1)
%33 = call i32 @qd_copy(double* %1, double* %19)
%34 = call i32 @qd_minus(double* %19)
%35 = call i32 @qd_exp(double* %19, double* %19)
%36 = call i32 @qd_mul(double* %0, double* %19, double* %19)
%37 = call i32 @qd_add(double* %1, double* %19, double* %1)
%38 = call i32 @qd_sub_qd_d(double* %1, double 1.000000e+00, double* %1)
br label %39
39: ; preds = %16, %12, %7
ret void
}