// File: hey-yahei[P]ConvNet/src/Convolution.cpp
// Function: Convolution::Run(float*, bool)
float* Convolution::Run(float* in_data, bool keep_in){
	int idx_gp;
	int start_h, start_w;
	int idx_ih, idx_iw;
	float wt, 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++) {
			idx_gp = idx_oc / oc_per_gp;
			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_ic = ic_per_gp * idx_gp; idx_ic < ic_per_gp * (idx_gp + 1); idx_ic++) {
						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_ic, idx_ih, idx_iw);
								wt = get_weight_data(idx_oc, idx_ic - idx_gp * ic_per_gp, idx_kh, idx_kw);
								result += dat * wt;
							}
						}
					}
					if (with_bias)
						result += bias_data[idx_oc];
					if (with_relu && result < 0)
						result = 0;
					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 $0x60, %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, -0x58(%rbp)
movslq 0x20(%rax), %rdi
shlq $0x2, %rdi
movslq 0x58(%rax), %rax
imulq %rax, %rdi
callq 0x22e0
movq %rax, %rcx
movq -0x58(%rbp), %rax
movq %rcx, 0x78(%rax)
movl $0x0, -0x38(%rbp)
movq -0x58(%rbp), %rcx
movl -0x38(%rbp), %eax
cmpl 0x20(%rcx), %eax
jge 0x6a17
movl $0x0, -0x3c(%rbp)
movq -0x58(%rbp), %rcx
movl -0x3c(%rbp), %eax
cmpl 0x34(%rcx), %eax
jge 0x6a07
movq -0x58(%rbp), %rcx
movl -0x3c(%rbp), %eax
cltd
idivl 0x1c(%rcx)
movl %eax, -0x18(%rbp)
movl $0x0, -0x40(%rbp)
movq -0x58(%rbp), %rcx
movl -0x40(%rbp), %eax
cmpl 0x38(%rcx), %eax
jge 0x69f7
movl $0x0, -0x44(%rbp)
movq -0x58(%rbp), %rcx
movl -0x44(%rbp), %eax
cmpl 0x3c(%rcx), %eax
jge 0x69e7
movq -0x58(%rbp), %rax
movl -0x40(%rbp), %ecx
imull 0x4(%rax), %ecx
subl 0x8(%rax), %ecx
movl %ecx, -0x1c(%rbp)
movl -0x44(%rbp), %ecx
imull 0x4(%rax), %ecx
subl 0x8(%rax), %ecx
movl %ecx, -0x20(%rbp)
xorps %xmm0, %xmm0
movss %xmm0, -0x34(%rbp)
movl 0x18(%rax), %eax
imull -0x18(%rbp), %eax
movl %eax, -0x48(%rbp)
movq -0x58(%rbp), %rcx
movl -0x48(%rbp), %eax
movl 0x18(%rcx), %ecx
movl -0x18(%rbp), %edx
addl $0x1, %edx
imull %edx, %ecx
cmpl %ecx, %eax
jge 0x697e
movl $0x0, -0x4c(%rbp)
movq -0x58(%rbp), %rcx
movl -0x4c(%rbp), %eax
cmpl (%rcx), %eax
jge 0x696e
movl $0x0, -0x50(%rbp)
movq -0x58(%rbp), %rcx
movl -0x50(%rbp), %eax
cmpl (%rcx), %eax
jge 0x695e
movl -0x1c(%rbp), %eax
addl -0x4c(%rbp), %eax
movl %eax, -0x24(%rbp)
movl -0x20(%rbp), %eax
addl -0x50(%rbp), %eax
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x24(%rbp)
jl 0x68e6
cmpl $0x0, -0x28(%rbp)
jl 0x68e6
movq -0x58(%rbp), %rcx
movl -0x24(%rbp), %eax
cmpl 0x28(%rcx), %eax
jge 0x68e6
movq -0x58(%rbp), %rcx
movl -0x28(%rbp), %eax
cmpl 0x2c(%rcx), %eax
jl 0x68f0
xorps %xmm0, %xmm0
movss %xmm0, -0x30(%rbp)
jmp 0x6910
movq -0x58(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl -0x38(%rbp), %edx
movl -0x48(%rbp), %ecx
movl -0x24(%rbp), %r8d
movl -0x28(%rbp), %r9d
callq 0x6b30
movss %xmm0, -0x30(%rbp)
movq -0x58(%rbp), %rdi
movl -0x3c(%rbp), %esi
movl -0x48(%rbp), %edx
movl -0x18(%rbp), %eax
imull 0x18(%rdi), %eax
subl %eax, %edx
movl -0x4c(%rbp), %ecx
movl -0x50(%rbp), %r8d
callq 0x6b80
movss %xmm0, -0x2c(%rbp)
movss -0x30(%rbp), %xmm0
movss -0x2c(%rbp), %xmm2
movss -0x34(%rbp), %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, -0x34(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x68a1
jmp 0x6960
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x688b
jmp 0x6970
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x6869
movq -0x58(%rbp), %rax
testb $0x1, 0x65(%rax)
je 0x69a3
movq -0x58(%rbp), %rax
movq 0x70(%rax), %rax
movslq -0x3c(%rbp), %rcx
movss (%rax,%rcx,4), %xmm0
addss -0x34(%rbp), %xmm0
movss %xmm0, -0x34(%rbp)
movq -0x58(%rbp), %rax
testb $0x1, 0x64(%rax)
je 0x69be
xorps %xmm0, %xmm0
ucomiss -0x34(%rbp), %xmm0
jbe 0x69be
xorps %xmm0, %xmm0
movss %xmm0, -0x34(%rbp)
movq -0x58(%rbp), %rdi
movl -0x38(%rbp), %esi
movl -0x3c(%rbp), %edx
movl -0x40(%rbp), %ecx
movl -0x44(%rbp), %r8d
movss -0x34(%rbp), %xmm0
callq 0x6bd0
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x6829
jmp 0x69e9
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x6812
jmp 0x69f9
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x67ed
jmp 0x6a09
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x67d6
testb $0x1, -0x11(%rbp)
jne 0x6a26
movq -0x10(%rbp), %rdi
callq 0x2280
movq -0x58(%rbp), %rax
movq 0x78(%rax), %rax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)