#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*/ qd_copy(double const *, double *);
int /*<<< orphan*/ qd_div_d_qd(double, double *, double *);
int /*<<< orphan*/ qd_mul(double *, double *, double *);
int /*<<< orphan*/ qd_sqr(double *, double *);
void qd_npwr(const double *a, int n, double *b) {
  if (n == 0) {
    b[0] = 1.0;
    b[1] = 0.0;
    b[2] = 0.0;
    b[3] = 0.0;
  } else {
    int N = (n < 0) ? -n : n;
    double r[4];
    qd_copy(a, r);
    b[0] = 1.0;
    b[1] = 0.0;
    b[2] = 0.0;
    b[3] = 0.0;
    if (N > 1) {
      while (N > 0) {
        if (N % 2 == 1) {
          qd_mul(b, r, b);
        }
        N /= 2;
        if (N > 0)
          qd_sqr(r, r);
      }
    } else {
      qd_copy(r, b);
    }
    if (n < 0)
      qd_div_d_qd(1.0, b, b);
  }
}


x86 assembly (clang, -O0):
<qd_npwr>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %rdx,-0x18(%rbp)
cmpl   $0x0,-0xc(%rbp)
jne    1196 <qd_npwr+0x56>
mov    -0x18(%rbp),%rax
movsd  0xe97(%rip),%xmm0
movsd  %xmm0,(%rax)
mov    -0x18(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x8(%rax)
mov    -0x18(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x10(%rax)
mov    -0x18(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x18(%rax)
jmp    1298 <qd_npwr+0x158>
cmpl   $0x0,-0xc(%rbp)
jge    11ad <qd_npwr+0x6d>
xor    %eax,%eax
sub    -0xc(%rbp),%eax
mov    %eax,-0x44(%rbp)
jmp    11b3 <qd_npwr+0x73>
mov    -0xc(%rbp),%eax
mov    %eax,-0x44(%rbp)
mov    -0x44(%rbp),%eax
mov    %eax,-0x1c(%rbp)
mov    -0x8(%rbp),%rdi
lea    -0x40(%rbp),%rsi
call   1060 <qd_copy@plt>
mov    -0x18(%rbp),%rax
movsd  0xe2e(%rip),%xmm0
movsd  %xmm0,(%rax)
mov    -0x18(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x8(%rax)
mov    -0x18(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x10(%rax)
mov    -0x18(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x18(%rax)
cmpl   $0x1,-0x1c(%rbp)
jle    1267 <qd_npwr+0x127>
jmp    1209 <qd_npwr+0xc9>
cmpl   $0x0,-0x1c(%rbp)
jle    1262 <qd_npwr+0x122>
mov    -0x1c(%rbp),%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
cmp    $0x1,%edx
jne    1238 <qd_npwr+0xf8>
mov    -0x18(%rbp),%rdi
lea    -0x40(%rbp),%rsi
mov    -0x18(%rbp),%rdx
call   1050 <qd_mul@plt>
mov    -0x1c(%rbp),%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
mov    %eax,-0x1c(%rbp)
cmpl   $0x0,-0x1c(%rbp)
jle    125d <qd_npwr+0x11d>
lea    -0x40(%rbp),%rdi
lea    -0x40(%rbp),%rsi
call   1040 <qd_sqr@plt>
jmp    1209 <qd_npwr+0xc9>
jmp    1274 <qd_npwr+0x134>
lea    -0x40(%rbp),%rdi
mov    -0x18(%rbp),%rsi
call   1060 <qd_copy@plt>
cmpl   $0x0,-0xc(%rbp)
jge    1293 <qd_npwr+0x153>
mov    -0x18(%rbp),%rdi
mov    -0x18(%rbp),%rsi
movsd  0xd72(%rip),%xmm0
call   1030 <qd_div_d_qd@plt>
jmp    1298 <qd_npwr+0x158>
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<qd_npwr>:
push   %rbp
push   %r15
push   %r14
push   %rbx
sub    $0x28,%rsp
mov    %rdx,%r15
test   %esi,%esi
je     11b7 <qd_npwr+0x77>
mov    %esi,%r14d
mov    %esi,%ebx
neg    %ebx
cmovs  %esi,%ebx
mov    %rsp,%rsi
call   1060 <qd_copy@plt>
movabs $0x3ff0000000000000,%rax
mov    %rax,(%r15)
xorps  %xmm0,%xmm0
movups %xmm0,0x8(%r15)
movq   $0x0,0x18(%r15)
cmp    $0x2,%ebx
jl     11d6 <qd_npwr+0x96>
mov    %rsp,%rbp
test   $0x1,%bl
je     119e <qd_npwr+0x5e>
nopl   (%rax)
mov    %r15,%rdi
mov    %rbp,%rsi
mov    %r15,%rdx
call   1050 <qd_mul@plt>
cmp    $0x2,%ebx
jb     11e1 <qd_npwr+0xa1>
shr    %ebx
mov    %rbp,%rdi
mov    %rbp,%rsi
call   1040 <qd_sqr@plt>
test   $0x1,%bl
jne    1190 <qd_npwr+0x50>
jmp    119e <qd_npwr+0x5e>
movabs $0x3ff0000000000000,%rax
mov    %rax,(%r15)
xorps  %xmm0,%xmm0
movups %xmm0,0x8(%r15)
movq   $0x0,0x18(%r15)
jmp    11f9 <qd_npwr+0xb9>
mov    %rsp,%rdi
mov    %r15,%rsi
call   1060 <qd_copy@plt>
test   %r14d,%r14d
jns    11f9 <qd_npwr+0xb9>
movsd  0xe12(%rip),%xmm0
mov    %r15,%rdi
mov    %r15,%rsi
call   1030 <qd_div_d_qd@plt>
add    $0x28,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @qd_npwr(double* %0, i32 %1, double* %2) {
%4 = alloca double*
%5 = alloca i32
%6 = alloca double*
%7 = alloca i32
%8 = alloca [4 x double]
store double* %0, double** %4
store i32 %1, i32* %5
store double* %2, double** %6
%9 = load i32, i32* %5
%10 = icmp eq i32 %9, 0
br i1 %10, label %11, label %20
11: ; preds = %3
%12 = load double*, double** %6
%13 = getelementptr inbounds double, double* %12, i64 0
store double 1.000000e+00, double* %13
%14 = load double*, double** %6
%15 = getelementptr inbounds double, double* %14, i64 1
store double 0.000000e+00, double* %15
%16 = load double*, double** %6
%17 = getelementptr inbounds double, double* %16, i64 2
store double 0.000000e+00, double* %17
%18 = load double*, double** %6
%19 = getelementptr inbounds double, double* %18, i64 3
store double 0.000000e+00, double* %19
br label %79
20: ; preds = %3
%21 = load i32, i32* %5
%22 = icmp slt i32 %21, 0
br i1 %22, label %23, label %26
23: ; preds = %20
%24 = load i32, i32* %5
%25 = sub nsw i32 0, %24
br label %28
26: ; preds = %20
%27 = load i32, i32* %5
br label %28
28: ; preds = %26, %23
%29 = phi i32 [ %25, %23 ], [ %27, %26 ]
store i32 %29, i32* %7
%30 = load double*, double** %4
%31 = getelementptr inbounds [4 x double], [4 x double]* %8, i64 0, i64 0
%32 = call i32 @qd_copy(double* %30, double* %31)
%33 = load double*, double** %6
%34 = getelementptr inbounds double, double* %33, i64 0
store double 1.000000e+00, double* %34
%35 = load double*, double** %6
%36 = getelementptr inbounds double, double* %35, i64 1
store double 0.000000e+00, double* %36
%37 = load double*, double** %6
%38 = getelementptr inbounds double, double* %37, i64 2
store double 0.000000e+00, double* %38
%39 = load double*, double** %6
%40 = getelementptr inbounds double, double* %39, i64 3
store double 0.000000e+00, double* %40
%41 = load i32, i32* %7
%42 = icmp sgt i32 %41, 1
br i1 %42, label %43, label %67
43: ; preds = %28
br label %44
44: ; preds = %65, %43
%45 = load i32, i32* %7
%46 = icmp sgt i32 %45, 0
br i1 %46, label %47, label %66
47: ; preds = %44
%48 = load i32, i32* %7
%49 = srem i32 %48, 2
%50 = icmp eq i32 %49, 1
br i1 %50, label %51, label %56
51: ; preds = %47
%52 = load double*, double** %6
%53 = getelementptr inbounds [4 x double], [4 x double]* %8, i64 0, i64 0
%54 = load double*, double** %6
%55 = call i32 @qd_mul(double* %52, double* %53, double* %54)
br label %56
56: ; preds = %51, %47
%57 = load i32, i32* %7
%58 = sdiv i32 %57, 2
store i32 %58, i32* %7
%59 = load i32, i32* %7
%60 = icmp sgt i32 %59, 0
br i1 %60, label %61, label %65
61: ; preds = %56
%62 = getelementptr inbounds [4 x double], [4 x double]* %8, i64 0, i64 0
%63 = getelementptr inbounds [4 x double], [4 x double]* %8, i64 0, i64 0
%64 = call i32 @qd_sqr(double* %62, double* %63)
br label %65
65: ; preds = %61, %56
br label %44
66: ; preds = %44
br label %71
67: ; preds = %28
%68 = getelementptr inbounds [4 x double], [4 x double]* %8, i64 0, i64 0
%69 = load double*, double** %6
%70 = call i32 @qd_copy(double* %68, double* %69)
br label %71
71: ; preds = %67, %66
%72 = load i32, i32* %5
%73 = icmp slt i32 %72, 0
br i1 %73, label %74, label %78
74: ; preds = %71
%75 = load double*, double** %6
%76 = load double*, double** %6
%77 = call i32 @qd_div_d_qd(double 1.000000e+00, double* %75, double* %76)
br label %78
78: ; preds = %74, %71
br label %79
79: ; preds = %78, %11
ret void
}

LLVM IR (-O2):
define void @qd_npwr(double* %0, i32 %1, double* %2) {
%4 = alloca [4 x double]
%5 = icmp eq i32 %1, 0
br i1 %5, label %6, label %9
6: ; preds = %3
store double 1.000000e+00, double* %2
%7 = getelementptr inbounds double, double* %2, i64 1
%8 = bitcast double* %7 to i8*
br label %36
9: ; preds = %3
%10 = icmp slt i32 %1, 0
%11 = sub nsw i32 0, %1
%12 = select i1 %10, i32 %11, i32 %1
%13 = bitcast [4 x double]* %4 to i8*
%14 = getelementptr inbounds [4 x double], [4 x double]* %4, i64 0, i64 0
%15 = call i32 @qd_copy(double* %0, double* %14)
store double 1.000000e+00, double* %2
%16 = getelementptr inbounds double, double* %2, i64 1
%17 = icmp sgt i32 %12, 1
%18 = bitcast double* %16 to i8*
br i1 %17, label %19, label %30
19: ; preds = %9, %27
%20 = phi i32 [ %28, %27 ], [ %12, %9 ]
%21 = and i32 %20, 1
%22 = icmp eq i32 %21, 0
br i1 %22, label %25, label %23
23: ; preds = %19
%24 = call i32 @qd_mul(double* %2, double* %14, double* %2)
br label %25
25: ; preds = %23, %19
%26 = icmp ugt i32 %20, 1
br i1 %26, label %27, label %32
27: ; preds = %25
%28 = lshr i32 %20, 1
%29 = call i32 @qd_sqr(double* %14, double* %14)
br label %19
30: ; preds = %9
%31 = call i32 @qd_copy(double* %14, double* %2)
br label %32
32: ; preds = %25, %30
br i1 %10, label %33, label %35
33: ; preds = %32
%34 = call i32 @qd_div_d_qd(double 1.000000e+00, double* %2, double* %2)
br label %35
35: ; preds = %33, %32
br label %36
36: ; preds = %35, %6
ret void
}