// File: hey-yahei[P]ConvNet/src/Pooling.cpp
// Function: Pooling::Run(float*, bool)
float* Pooling::Run(float* in_data, bool keep_in) {
	int start_h, start_w;
	int idx_ih, idx_iw;
	float dat, result;

	out_data = (float*)malloc(sizeof(float) * in_shape[0] * out_chw);

	// Do convolution
	for (int idx_bs = 0; idx_bs < in_shape[0]; idx_bs++) {
		for (int idx_oc = 0; idx_oc < out_shape[1]; idx_oc++) {
			for (int idx_oh = 0; idx_oh < out_shape[2]; idx_oh++) {
				for (int idx_ow = 0; idx_ow < out_shape[3]; idx_ow++) {
					start_h = idx_oh * stride - pad;
					start_w = idx_ow * stride - pad;
					result = 0.;
					for (int idx_kh = 0; idx_kh < kernel; idx_kh++) {
						for (int idx_kw = 0; idx_kw < kernel; idx_kw++) {
							idx_ih = start_h + idx_kh;
							idx_iw = start_w + idx_kw;
							if ((idx_ih < 0) || (idx_iw < 0) || (idx_ih >= in_shape[2]) || (idx_iw >= in_shape[3]))
								dat = 0.;
							else
								dat = get_in_data(in_data, idx_bs, idx_oc, idx_ih, idx_iw);
							if (!strcmp(type, "max")) {
								if (result < dat)
									result = dat;
							} else if(!strcmp(type, "avg")) {
								result += dat / kernel / kernel;
							} else {
								cerr << "Pooling: unknown type" << endl;
								exit(1);
							}
						}
					}
					set_out_data(idx_bs, idx_oc, idx_oh, idx_ow, result);
				}
			}
		}
	}

	if (!keep_in)
		free(in_data);

	return out_data;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movb %dl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
andb $0x1, %al
movb %al, -0x11(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x50(%rbp)
movslq 0x10(%rax), %rdi
shlq $0x2, %rdi
movslq 0x3c(%rax), %rax
imulq %rax, %rdi
callq 0x22e0
movq %rax, %rcx
movq -0x50(%rbp), %rax
movq %rcx, 0x48(%rax)
movl $0x0, -0x30(%rbp)
movq -0x50(%rbp), %rcx
movl -0x30(%rbp), %eax
cmpl 0x10(%rcx), %eax
jge 0x76c6
movl $0x0, -0x34(%rbp)
movq -0x50(%rbp), %rcx
movl -0x34(%rbp), %eax
cmpl 0x24(%rcx), %eax
jge 0x76b6
movl $0x0, -0x38(%rbp)
movq -0x50(%rbp), %rcx
movl -0x38(%rbp), %eax
cmpl 0x28(%rcx), %eax
jge 0x76a6
movl $0x0, -0x3c(%rbp)
movq -0x50(%rbp), %rcx
movl -0x3c(%rbp), %eax
cmpl 0x2c(%rcx), %eax
jge 0x7696
movq -0x50(%rbp), %rcx
movl -0x38(%rbp), %eax
imull 0x4(%rcx), %eax
subl 0x8(%rcx), %eax
movl %eax, -0x18(%rbp)
movl -0x3c(%rbp), %eax
imull 0x4(%rcx), %eax
subl 0x8(%rcx), %eax
movl %eax, -0x1c(%rbp)
xorps %xmm0, %xmm0
movss %xmm0, -0x2c(%rbp)
movl $0x0, -0x40(%rbp)
movq -0x50(%rbp), %rcx
movl -0x40(%rbp), %eax
cmpl (%rcx), %eax
jge 0x766d
movl $0x0, -0x44(%rbp)
movq -0x50(%rbp), %rcx
movl -0x44(%rbp), %eax
cmpl (%rcx), %eax
jge 0x765d
movl -0x18(%rbp), %eax
addl -0x40(%rbp), %eax
movl %eax, -0x20(%rbp)
movl -0x1c(%rbp), %eax
addl -0x44(%rbp), %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x20(%rbp)
jl 0x7583
cmpl $0x0, -0x24(%rbp)
jl 0x7583
movq -0x50(%rbp), %rcx
movl -0x20(%rbp), %eax
cmpl 0x18(%rcx), %eax
jge 0x7583
movq -0x50(%rbp), %rcx
movl -0x24(%rbp), %eax
cmpl 0x1c(%rcx), %eax
jl 0x758d
xorps %xmm0, %xmm0
movss %xmm0, -0x28(%rbp)
jmp 0x75ad
movq -0x50(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl -0x30(%rbp), %edx
movl -0x34(%rbp), %ecx
movl -0x20(%rbp), %r8d
movl -0x24(%rbp), %r9d
callq 0x76f0
movss %xmm0, -0x28(%rbp)
movq -0x50(%rbp), %rax
movq 0x50(%rax), %rdi
leaq 0x4a90(%rip), %rsi      # 0xc04c
callq 0x22f0
cmpl $0x0, %eax
jne 0x75e1
movss -0x2c(%rbp), %xmm1
movss -0x28(%rbp), %xmm0
ucomiss %xmm1, %xmm0
jbe 0x75df
movss -0x28(%rbp), %xmm0
movss %xmm0, -0x2c(%rbp)
jmp 0x764d
movq -0x50(%rbp), %rax
movq 0x50(%rax), %rdi
leaq 0x4d57(%rip), %rsi      # 0xc347
callq 0x22f0
cmpl $0x0, %eax
jne 0x761f
movq -0x50(%rbp), %rax
movss -0x28(%rbp), %xmm0
cvtsi2ssl (%rax), %xmm1
divss %xmm1, %xmm0
cvtsi2ssl (%rax), %xmm1
divss %xmm1, %xmm0
addss -0x2c(%rbp), %xmm0
movss %xmm0, -0x2c(%rbp)
jmp 0x764b
movq 0xa9ca(%rip), %rdi      # 0x11ff0
leaq 0x4d1e(%rip), %rsi      # 0xc34b
callq 0x21c0
movq %rax, %rdi
movq 0xa984(%rip), %rsi      # 0x11fc0
callq 0x2200
movl $0x1, %edi
callq 0x2290
jmp 0x764d
jmp 0x764f
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x753e
jmp 0x765f
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x7528
movq -0x50(%rbp), %rdi
movl -0x30(%rbp), %esi
movl -0x34(%rbp), %edx
movl -0x38(%rbp), %ecx
movl -0x3c(%rbp), %r8d
movss -0x2c(%rbp), %xmm0
callq 0x7740
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x74eb
jmp 0x7698
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x74d4
jmp 0x76a8
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x74bd
jmp 0x76b8
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x74a6
testb $0x1, -0x11(%rbp)
jne 0x76d5
movq -0x10(%rbp), %rdi
callq 0x2280
movq -0x50(%rbp), %rax
movq 0x48(%rax), %rax
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)