#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*/ assert(double const *);
double vectord_mean(double const *, size_t);
void vectord_remove_mean(const double *self, size_t size, double *output) {
  assert(self);
  assert(output);
  double mean = vectord_mean(self, size);
  for (size_t i = 0; i < size; i++)
    output[i] = self[i] - mean;
}


x86 assembly (clang, -O0):
<vectord_remove_mean>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    -0x8(%rbp),%rdi
call   1030 <assert@plt>
mov    -0x18(%rbp),%rdi
call   1030 <assert@plt>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1040 <vectord_mean@plt>
movsd  %xmm0,-0x20(%rbp)
movq   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%rax
cmp    -0x10(%rbp),%rax
jae    119e <vectord_remove_mean+0x7e>
mov    -0x8(%rbp),%rax
mov    -0x28(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
subsd  -0x20(%rbp),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x28(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    1160 <vectord_remove_mean+0x40>
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<vectord_remove_mean>:
push   %r15
push   %r14
push   %rbx
mov    %rdx,%r15
mov    %rsi,%r14
mov    %rdi,%rbx
call   1030 <assert@plt>
mov    %r15,%rdi
call   1030 <assert@plt>
mov    %rbx,%rdi
mov    %r14,%rsi
call   1040 <vectord_mean@plt>
test   %r14,%r14
je     12ba <vectord_remove_mean+0x19a>
cmp    $0x4,%r14
jb     116f <vectord_remove_mean+0x4f>
lea    (%rbx,%r14,8),%rax
cmp    %r15,%rax
jbe    1210 <vectord_remove_mean+0xf0>
lea    (%r15,%r14,8),%rax
cmp    %rbx,%rax
jbe    1210 <vectord_remove_mean+0xf0>
xor    %eax,%eax
mov    %rax,%rcx
not    %rcx
add    %r14,%rcx
mov    %r14,%rdx
and    $0x3,%rdx
je     11a9 <vectord_remove_mean+0x89>
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movsd  (%rbx,%rax,8),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,(%r15,%rax,8)
add    $0x1,%rax
add    $0xffffffffffffffff,%rdx
jne    1190 <vectord_remove_mean+0x70>
cmp    $0x3,%rcx
jb     12ba <vectord_remove_mean+0x19a>
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movsd  (%rbx,%rax,8),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,(%r15,%rax,8)
movsd  0x8(%rbx,%rax,8),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,0x8(%r15,%rax,8)
movsd  0x10(%rbx,%rax,8),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,0x10(%r15,%rax,8)
movsd  0x18(%rbx,%rax,8),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,0x18(%r15,%rax,8)
add    $0x4,%rax
cmp    %rax,%r14
jne    11c0 <vectord_remove_mean+0xa0>
jmp    12ba <vectord_remove_mean+0x19a>
mov    %r14,%rax
and    $0xfffffffffffffffc,%rax
movapd %xmm0,%xmm1
unpcklpd %xmm0,%xmm1
lea    -0x4(%rax),%rcx
mov    %rcx,%rdx
shr    $0x2,%rdx
add    $0x1,%rdx
test   %rcx,%rcx
je     12c0 <vectord_remove_mean+0x1a0>
mov    %rdx,%rsi
and    $0xfffffffffffffffe,%rsi
xor    %ecx,%ecx
movupd (%rbx,%rcx,8),%xmm2
movupd 0x10(%rbx,%rcx,8),%xmm3
subpd  %xmm1,%xmm2
subpd  %xmm1,%xmm3
movupd %xmm2,(%r15,%rcx,8)
movupd %xmm3,0x10(%r15,%rcx,8)
movupd 0x20(%rbx,%rcx,8),%xmm2
movupd 0x30(%rbx,%rcx,8),%xmm3
subpd  %xmm1,%xmm2
subpd  %xmm1,%xmm3
movupd %xmm2,0x20(%r15,%rcx,8)
movupd %xmm3,0x30(%r15,%rcx,8)
add    $0x8,%rcx
add    $0xfffffffffffffffe,%rsi
jne    1240 <vectord_remove_mean+0x120>
test   $0x1,%dl
je     12b1 <vectord_remove_mean+0x191>
movupd (%rbx,%rcx,8),%xmm2
movupd 0x10(%rbx,%rcx,8),%xmm3
subpd  %xmm1,%xmm2
subpd  %xmm1,%xmm3
movupd %xmm2,(%r15,%rcx,8)
movupd %xmm3,0x10(%r15,%rcx,8)
cmp    %r14,%rax
jne    1171 <vectord_remove_mean+0x51>
pop    %rbx
pop    %r14
pop    %r15
ret
xor    %ecx,%ecx
test   $0x1,%dl
jne    1291 <vectord_remove_mean+0x171>
jmp    12b1 <vectord_remove_mean+0x191>

LLVM IR (-O0):
define void @vectord_remove_mean(double* %0, i64 %1, double* %2) {
%4 = alloca double*
%5 = alloca i64
%6 = alloca double*
%7 = alloca double
%8 = alloca i64
store double* %0, double** %4
store i64 %1, i64* %5
store double* %2, double** %6
%9 = load double*, double** %4
%10 = call i32 @assert(double* %9)
%11 = load double*, double** %6
%12 = call i32 @assert(double* %11)
%13 = load double*, double** %4
%14 = load i64, i64* %5
%15 = call double @vectord_mean(double* %13, i64 %14)
store double %15, double* %7
store i64 0, i64* %8
br label %16
16: ; preds = %30, %3
%17 = load i64, i64* %8
%18 = load i64, i64* %5
%19 = icmp ult i64 %17, %18
br i1 %19, label %20, label %33
20: ; preds = %16
%21 = load double*, double** %4
%22 = load i64, i64* %8
%23 = getelementptr inbounds double, double* %21, i64 %22
%24 = load double, double* %23
%25 = load double, double* %7
%26 = fsub double %24, %25
%27 = load double*, double** %6
%28 = load i64, i64* %8
%29 = getelementptr inbounds double, double* %27, i64 %28
store double %26, double* %29
br label %30
30: ; preds = %20
%31 = load i64, i64* %8
%32 = add i64 %31, 1
store i64 %32, i64* %8
br label %16
33: ; preds = %16
ret void
}

LLVM IR (-O2):
define void @vectord_remove_mean(double* %0, i64 %1, double* %2) {
%4 = tail call i32 @assert(double* %0)
%5 = tail call i32 @assert(double* %2)
%6 = tail call double @vectord_mean(double* %0, i64 %1)
%7 = icmp eq i64 %1, 0
br i1 %7, label %97, label %8
8: ; preds = %3
%9 = icmp ult i64 %1, 4
br i1 %9, label %78, label %10
10: ; preds = %8
%11 = getelementptr double, double* %2, i64 %1
%12 = getelementptr double, double* %0, i64 %1
%13 = icmp ugt double* %12, %2
%14 = icmp ugt double* %11, %0
%15 = and i1 %13, %14
br i1 %15, label %78, label %16
16: ; preds = %10
%17 = and i64 %1, -4
%18 = insertelement <2 x double> poison, double %6, i64 0
%19 = shufflevector <2 x double> %18, <2 x double> poison, <2 x i32> zeroinitializer
%20 = insertelement <2 x double> poison, double %6, i64 0
%21 = shufflevector <2 x double> %20, <2 x double> poison, <2 x i32> zeroinitializer
%22 = add i64 %17, -4
%23 = lshr exact i64 %22, 2
%24 = add nuw nsw i64 %23, 1
%25 = and i64 %24, 1
%26 = icmp eq i64 %22, 0
br i1 %26, label %60, label %27
27: ; preds = %16
%28 = and i64 %24, 9223372036854775806
br label %29
29: ; preds = %29, %27
%30 = phi i64 [ 0, %27 ], [ %57, %29 ]
%31 = phi i64 [ 0, %27 ], [ %58, %29 ]
%32 = getelementptr inbounds double, double* %0, i64 %30
%33 = bitcast double* %32 to <2 x double>*
%34 = load <2 x double>, <2 x double>* %33
%35 = getelementptr inbounds double, double* %32, i64 2
%36 = bitcast double* %35 to <2 x double>*
%37 = load <2 x double>, <2 x double>* %36
%38 = fsub <2 x double> %34, %19
%39 = fsub <2 x double> %37, %21
%40 = getelementptr inbounds double, double* %2, i64 %30
%41 = bitcast double* %40 to <2 x double>*
store <2 x double> %38, <2 x double>* %41
%42 = getelementptr inbounds double, double* %40, i64 2
%43 = bitcast double* %42 to <2 x double>*
store <2 x double> %39, <2 x double>* %43
%44 = or i64 %30, 4
%45 = getelementptr inbounds double, double* %0, i64 %44
%46 = bitcast double* %45 to <2 x double>*
%47 = load <2 x double>, <2 x double>* %46
%48 = getelementptr inbounds double, double* %45, i64 2
%49 = bitcast double* %48 to <2 x double>*
%50 = load <2 x double>, <2 x double>* %49
%51 = fsub <2 x double> %47, %19
%52 = fsub <2 x double> %50, %21
%53 = getelementptr inbounds double, double* %2, i64 %44
%54 = bitcast double* %53 to <2 x double>*
store <2 x double> %51, <2 x double>* %54
%55 = getelementptr inbounds double, double* %53, i64 2
%56 = bitcast double* %55 to <2 x double>*
store <2 x double> %52, <2 x double>* %56
%57 = add nuw i64 %30, 8
%58 = add i64 %31, 2
%59 = icmp eq i64 %58, %28
br i1 %59, label %60, label %29
60: ; preds = %29, %16
%61 = phi i64 [ 0, %16 ], [ %57, %29 ]
%62 = icmp eq i64 %25, 0
br i1 %62, label %76, label %63
63: ; preds = %60
%64 = getelementptr inbounds double, double* %0, i64 %61
%65 = bitcast double* %64 to <2 x double>*
%66 = load <2 x double>, <2 x double>* %65
%67 = getelementptr inbounds double, double* %64, i64 2
%68 = bitcast double* %67 to <2 x double>*
%69 = load <2 x double>, <2 x double>* %68
%70 = fsub <2 x double> %66, %19
%71 = fsub <2 x double> %69, %21
%72 = getelementptr inbounds double, double* %2, i64 %61
%73 = bitcast double* %72 to <2 x double>*
store <2 x double> %70, <2 x double>* %73
%74 = getelementptr inbounds double, double* %72, i64 2
%75 = bitcast double* %74 to <2 x double>*
store <2 x double> %71, <2 x double>* %75
br label %76
76: ; preds = %60, %63
%77 = icmp eq i64 %17, %1
br i1 %77, label %97, label %78
78: ; preds = %10, %8, %76
%79 = phi i64 [ 0, %10 ], [ 0, %8 ], [ %17, %76 ]
%80 = xor i64 %79, -1
%81 = add i64 %80, %1
%82 = and i64 %1, 3
%83 = icmp eq i64 %82, 0
br i1 %83, label %94, label %84
84: ; preds = %78, %84
%85 = phi i64 [ %91, %84 ], [ %79, %78 ]
%86 = phi i64 [ %92, %84 ], [ 0, %78 ]
%87 = getelementptr inbounds double, double* %0, i64 %85
%88 = load double, double* %87
%89 = fsub double %88, %6
%90 = getelementptr inbounds double, double* %2, i64 %85
store double %89, double* %90
%91 = add nuw i64 %85, 1
%92 = add i64 %86, 1
%93 = icmp eq i64 %92, %82
br i1 %93, label %94, label %84
94: ; preds = %84, %78
%95 = phi i64 [ %79, %78 ], [ %91, %84 ]
%96 = icmp ult i64 %81, 3
br i1 %96, label %97, label %98
97: ; preds = %94, %98, %76, %3
ret void
98: ; preds = %94, %98
%99 = phi i64 [ %119, %98 ], [ %95, %94 ]
%100 = getelementptr inbounds double, double* %0, i64 %99
%101 = load double, double* %100
%102 = fsub double %101, %6
%103 = getelementptr inbounds double, double* %2, i64 %99
store double %102, double* %103
%104 = add nuw i64 %99, 1
%105 = getelementptr inbounds double, double* %0, i64 %104
%106 = load double, double* %105
%107 = fsub double %106, %6
%108 = getelementptr inbounds double, double* %2, i64 %104
store double %107, double* %108
%109 = add nuw i64 %99, 2
%110 = getelementptr inbounds double, double* %0, i64 %109
%111 = load double, double* %110
%112 = fsub double %111, %6
%113 = getelementptr inbounds double, double* %2, i64 %109
store double %112, double* %113
%114 = add nuw i64 %99, 3
%115 = getelementptr inbounds double, double* %0, i64 %114
%116 = load double, double* %115
%117 = fsub double %116, %6
%118 = getelementptr inbounds double, double* %2, i64 %114
store double %117, double* %118
%119 = add nuw i64 %99, 4
%120 = icmp eq i64 %119, %1
br i1 %120, label %97, label %98
}