// File: /workspace/github_cpp_makefile_star2_O3/brianwu02[P]ImageProcessing/briansFunctions.cpp
// Function: padImage(imageS*, int, imageS*)
void padImage(imageP I1, int sz, imageP paddedImg) {
    /* PIXEL REPLICATION PADDING
     * takes I1 as input image, I1 and applies pixel replication technique
     * to paddedImg using kernel size sz * sz.
     *   Pixel Replcation Example:
     *                             leftIdx         rightIdx
     *   AA|ABCDEFGH|HH                    x x x x
     *   AA|ABCDEFGH|HH        region0  |  region1  |  region2   y
     *   --------------        -------------------------------  topIdx
     *   AA|ABCDEFGH|HH        region3  |           |  region5   y
     *   II|IJKLMNOP|PP        region3  |  region4  |  region5   y
     *   QQ|QRSTUVWX|XX        region3  |  orig img |  region5   y
     *   YY|YZabcdef|ff        region3  |           |  region5   y
     *   gg|ghijklmn|nn        -------------------------------  botIdx
     *   oo|opqrstuv|vv        region6  | region 7  | region 8   y
     *   --------------
     *   oo|opqrstuv|vv       
     *   oo|opqrstuv|vv
     *   
     *   region0 = x <  leftIdx  and y <  topIdx
     *   region1 = x >= leftIdx  and x <  rightIdx and y <  topIdx 
     *   region2 = x >= rightIdx and y <  topIdx
     *   region3 = x <  leftIdx  and y >= topIdx   and y <  botIdx
     *   region4 = x >= leftIdx  and x <  rightIdx and y >= topIdx and y < botIdx
     *   region5 = x >= rightIdx and y >= topIdx   and y <  botIdx
     *   region6 = x <  leftIdx  and y >= botIdx
     *   region7 = x >= leftIdx  and x <  rightIdx and y >= botIdx
     *   region8 = x >= rightIdx and y >= botIdx
     *
     */

    int n = (sz - 1) / 2;
    int m = (sz - 1) / 2;
    unsigned char *in, *paddedOut;

    int total = I1->width * I1->height;
    int w = I1->width;
    int h = I1->height;

    paddedImg->width = (w + 2*m);
    paddedImg->height = (h + 2*n);

    int paddedTotal = paddedImg->height * paddedImg->width;
    paddedImg->image = (unsigned char*) malloc(paddedTotal);
    paddedOut = paddedImg->image;
    in = I1->image;

    int paddedHeight = paddedImg->height;
    int paddedWidth = paddedImg->width;

    // vertical indices that represent padding columns
    int leftIdx = n;
    int rightIdx = w + n;

    // horizontal indices that represent padding rows
    int topIdx = m;
    int botIdx = h + m;


    for (int y=0; y < paddedHeight; y++) {
        for (int x=0; x < paddedWidth; x++) {

            // this condition comes first since it will occur most frequent.
            // dont need the branch predictor working so hard.
            if (x >= leftIdx and x < rightIdx and y >= topIdx and y < botIdx) {
                // we are in region 4.
                paddedOut[y*paddedWidth+x] = in[(y-n) * w + (x-m)];

            } else if (x < leftIdx and y < topIdx) {
                // we are in region 0.
                // assign padded pixel as upper left original pixel value.
                paddedOut[y*paddedWidth+x] = in[0]; 

            } else if (x >= leftIdx and x < rightIdx and y < topIdx) {
                // we are in region 1.
                // assign pixel values to be top row of original image.
                paddedOut[y*paddedWidth+x] = in[(x-m)]; 
                
            } else if (x >= rightIdx and y < topIdx) {
                // we are in region 2.
                // assign padded pixels as upper right original pixel value.
                paddedOut[y*paddedWidth+x] = in[w-1];

            } else if (x < leftIdx and y >= topIdx and y < botIdx) {
                // we are in region 3.
                // assigned padded pixel as left most pixel of current row.
                paddedOut[y*paddedWidth+x] = in[(y - n) * w];

            } else if (x >= rightIdx and y >= topIdx and y < botIdx) {
                // we are in region 5
                // assign padded pixel as right most pixel of current row
                paddedOut[y*paddedWidth+x] = in[(y - n) * w + (w-1) ];

            } else if (x < leftIdx and y >= botIdx) {
                // we are in region 6
                // assign padded pixel as bottom left original pixel value.
                paddedOut[y*paddedWidth+x] = in[w*(h-1)];
            
            } else if (x >= leftIdx and x < rightIdx and y >= botIdx) {
                // we are in region 7
                // assign padded pixel to be bottom-most row of original input img.
                paddedOut[y*paddedWidth+x] = in[(h-1) * w + (x-m)];
            
            } else if (x >= rightIdx and y >= botIdx) {
                // we are in region 8
                // assign padded pixel as bottom right original pixel value.
                paddedOut[y*paddedWidth+x] = in[w*h-1];
            
            } else {
                // this should never happen since this will only occur if we have
                // not handled a certain x,y coordinate.
                cerr << "unhandled condition, something bad" << endl;
                cerr << "x is: " << x << " y is: " << y << endl;
            }
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rdx, %r15
movq %rdi, %r14
movl %esi, %eax
decl %eax
shrl $0x1f, %eax
leal (%rsi,%rax), %ebp
decl %ebp
movslq (%rdi), %rbx
movl 0x4(%rdi), %r13d
movl %ebp, %r12d
andl $-0x2, %r12d
leal (%rbx,%r12), %ecx
movl %ecx, 0xc(%rsp)
movl %ecx, (%rdx)
addl %r13d, %r12d
movl %r12d, 0x4(%rdx)
movl %r12d, %eax
imull %ecx, %eax
movslq %eax, %rdi
callq 0x2160
movq %rax, 0x8(%r15)
testl %r12d, %r12d
jle 0x31b8
movq %rbx, %r8
movq %rax, %rbx
sarl %ebp
movl %r8d, %r10d
movq 0x8(%r14), %r11
leal (%r13,%rbp), %eax
leal (%r8,%rbp), %ecx
leal -0x1(%r13), %edx
imull %r10d, %edx
movslq %edx, %rsi
movl %r8d, %edx
imull %r13d, %edx
movslq %edx, %rdx
movq %rdx, 0x38(%rsp)
movslq %ecx, %r13
movslq %ebp, %rbp
movslq %eax, %rdi
movl 0xc(%rsp), %eax
movslq %eax, %rcx
movq %rcx, 0x78(%rsp)
movl %r12d, %ecx
movq %rcx, 0x70(%rsp)
leaq -0x1(%r11,%r8), %rcx
movq %rcx, 0x68(%rsp)
movl %eax, %r9d
movq %r11, %rax
subq %rbp, %rax
movq %rax, 0x80(%rsp)
movq %rsi, 0x60(%rsp)
subl %ebp, %esi
movq %rsi, 0x58(%rsp)
movl %r10d, %eax
notl %eax
imull %ebp, %eax
movq %rax, 0x28(%rsp)
xorl %r14d, %r14d
movq %r8, 0x50(%rsp)
movq %r10, 0x48(%rsp)
movq %r11, 0x40(%rsp)
movq %rdi, 0x30(%rsp)
movq %r9, 0x10(%rsp)
cmpl $0x0, 0xc(%rsp)
jle 0x31a0
movq %r14, %rax
subq %rbp, %rax
setge %r15b
imulq %r8, %rax
movq %rax, 0x20(%rsp)
xorl %r12d, %r12d
cmpq %rbp, %r12
setge %cl
cmpq %r13, %r12
setl %al
andb %cl, %al
movl %eax, %edx
andb %r15b, %dl
cmpb $0x1, %dl
jne 0x2fbe
cmpq %rdi, %r14
jge 0x2fbe
movq 0x28(%rsp), %rax
addl %r12d, %eax
cltq
movb (%r11,%rax), %al
jmp 0x2ffe
cmpq %rbp, %r12
setge %dl
cmpq %rbp, %r14
setge %sil
orb %dl, %sil
jne 0x2fd5
movb (%r11), %al
jmp 0x2ffe
xorb $0x1, %al
cmpq %rbp, %r14
setge %dl
orb %al, %dl
jne 0x2fef
movq 0x80(%rsp), %rax
movb (%rax,%r12), %al
jmp 0x2ffe
cmpq %rbp, %r14
jge 0x300f
cmpq %r13, %r12
jl 0x300f
movb -0x1(%r11,%r8), %al
movb %al, (%rbx,%r12)
incq %r12
cmpq %r12, %r9
jne 0x2f91
jmp 0x31a0
cmpq %rbp, %r12
setl %dl
cmpq %rdi, %r14
setl %sil
andb %r15b, %dl
andb %sil, %dl
cmpb $0x1, %dl
jne 0x302e
movq 0x20(%rsp), %rax
jmp 0x2fb8
cmpq %r13, %r12
setge %dl
cmpq %rdi, %r14
setl %sil
cmpq %rbp, %r14
movq %rdi, %r9
setge %dil
andb %dl, %dil
andb %sil, %dil
cmpb $0x1, %dil
jne 0x3067
movq 0x68(%rsp), %rax
movq 0x20(%rsp), %rcx
movb (%rax,%rcx), %al
movb %al, (%rbx,%r12)
movq %r9, %rdi
jmp 0x30a9
cmpq %r9, %r14
setl %dl
orb %dl, %cl
movq %r9, %rdi
je 0x309c
cmpq %rdi, %r14
setl %cl
orb %cl, %al
movq 0x10(%rsp), %r9
je 0x30b3
cmpq %r13, %r12
jl 0x30bd
cmpq %rdi, %r14
jl 0x30bd
movq 0x38(%rsp), %rax
movb -0x1(%r11,%rax), %al
jmp 0x2ffe
movq 0x60(%rsp), %rax
movb (%r11,%rax), %al
movb %al, (%rbx,%r12)
movq 0x10(%rsp), %r9
jmp 0x3002
movq 0x58(%rsp), %rax
jmp 0x2fb3
movl $0x22, %edx
movq 0x2f27(%rip), %rdi      # 0x5ff0
leaq 0x1014(%rip), %rsi      # 0x40e4
callq 0x2100
movq 0x2f14(%rip), %rcx      # 0x5ff0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x20d0
movsbl %al, %esi
movq 0x2ef6(%rip), %rdi      # 0x5ff0
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movl $0x6, %edx
movq 0x2edd(%rip), %rdi      # 0x5ff0
leaq 0xfed(%rip), %rsi       # 0x4107
callq 0x2100
movq 0x2eca(%rip), %rdi      # 0x5ff0
movl %r12d, %esi
callq 0x21c0
movq %rax, 0x18(%rsp)
movl $0x7, %edx
movq %rax, %rdi
leaq 0xfcc(%rip), %rsi       # 0x410e
callq 0x2100
movq 0x18(%rsp), %rdi
movl %r14d, %esi
callq 0x21c0
movq %rax, 0x18(%rsp)
movq (%rax), %rcx
movq -0x18(%rcx), %rdi
addq %rax, %rdi
movl $0xa, %esi
callq 0x20d0
movsbl %al, %esi
movq 0x18(%rsp), %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movq 0x10(%rsp), %r9
movq 0x30(%rsp), %rdi
movq 0x40(%rsp), %r11
movq 0x48(%rsp), %r10
movq 0x50(%rsp), %r8
jmp 0x3002
incq %r14
addq 0x78(%rsp), %rbx
addq %r10, 0x28(%rsp)
cmpq 0x70(%rsp), %r14
jne 0x2f70
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq