// File: /workspace/github_cpp_makefile_star2_O1/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 $0x78, %rsp
movq %rdx, %r12
movq %rdi, %r14
movl %esi, %eax
decl %eax
shrl $0x1f, %eax
addl %esi, %eax
decl %eax
sarl %eax
movslq (%rdi), %rbx
movl 0x4(%rdi), %ecx
movslq %eax, %r15
leaq (%r15,%r15), %rbp
leaq (%rbx,%r15,2), %r13
movl %r13d, (%rdx)
movq %rcx, (%rsp)
addl %ecx, %ebp
movl %ebp, 0x4(%rdx)
movl %ebp, %eax
imull %r13d, %eax
movslq %eax, %rdi
callq 0x2160
movq %rax, 0x8(%r12)
testl %ebp, %ebp
jle 0x31ad
movq %r13, %r9
movq %rbx, %r8
movq %rax, %rbx
movq 0x8(%r14), %r10
movq (%rsp), %rdi
leal (%rdi,%r15), %eax
leal -0x1(%rdi), %ecx
imull %r8d, %ecx
leal (%r8,%r15), %edx
movslq %ecx, %rsi
movl %r8d, %ecx
imull %edi, %ecx
movslq %ecx, %rcx
movq %rcx, 0x28(%rsp)
movslq %edx, %r13
movslq %eax, %rdi
movl %ebp, %eax
movq %rax, 0x68(%rsp)
leaq -0x1(%r10,%r8), %rax
movq %rax, 0x58(%rsp)
movl %r9d, %r11d
movq %r10, %rax
subq %r15, %rax
movq %rax, 0x70(%rsp)
movq %rsi, 0x50(%rsp)
subl %r15d, %esi
movq %rsi, 0x48(%rsp)
movl %r8d, %eax
movq %rax, 0x60(%rsp)
movl %r8d, %eax
notl %eax
imull %r15d, %eax
movq %rax, (%rsp)
xorl %r14d, %r14d
movq %r8, 0x40(%rsp)
movq %r9, 0x38(%rsp)
movq %r10, 0x30(%rsp)
movq %rdi, 0x20(%rsp)
movq %r11, 0x8(%rsp)
testl %r9d, %r9d
jle 0x318f
movq %r14, %rax
subq %r15, %rax
setge %bpl
imulq %r8, %rax
movq %rax, 0x18(%rsp)
xorl %r12d, %r12d
cmpq %r15, %r12
setge %cl
cmpq %r13, %r12
setl %al
andb %cl, %al
movl %eax, %edx
andb %bpl, %dl
cmpb $0x1, %dl
jne 0x2fb0
cmpq %rdi, %r14
jge 0x2fb0
movq (%rsp), %rax
addl %r12d, %eax
cltq
movb (%r10,%rax), %al
jmp 0x2fed
cmpq %r15, %r12
setge %dl
cmpq %r15, %r14
setge %sil
orb %dl, %sil
jne 0x2fc7
movb (%r10), %al
jmp 0x2fed
xorb $0x1, %al
cmpq %r15, %r14
setge %dl
orb %al, %dl
jne 0x2fde
movq 0x70(%rsp), %rax
movb (%rax,%r12), %al
jmp 0x2fed
cmpq %r15, %r14
jge 0x2ffe
cmpq %r13, %r12
jl 0x2ffe
movb -0x1(%r10,%r8), %al
movb %al, (%rbx,%r12)
incq %r12
cmpq %r12, %r11
jne 0x2f84
jmp 0x318f
cmpq %r15, %r12
setl %dl
cmpq %rdi, %r14
setl %sil
andb %bpl, %dl
andb %sil, %dl
cmpb $0x1, %dl
jne 0x301d
movq 0x18(%rsp), %rax
jmp 0x2faa
cmpq %r13, %r12
setge %dl
cmpq %rdi, %r14
setl %sil
cmpq %r15, %r14
movq %rdi, %r11
setge %dil
andb %dl, %dil
andb %sil, %dil
cmpb $0x1, %dil
jne 0x3056
movq 0x58(%rsp), %rax
movq 0x18(%rsp), %rcx
movb (%rax,%rcx), %al
movb %al, (%rbx,%r12)
movq %r11, %rdi
jmp 0x3098
cmpq %r11, %r14
setl %dl
orb %dl, %cl
movq %r11, %rdi
je 0x308b
cmpq %rdi, %r14
setl %cl
orb %cl, %al
movq 0x8(%rsp), %r11
je 0x30a2
cmpq %r13, %r12
jl 0x30ac
cmpq %rdi, %r14
jl 0x30ac
movq 0x28(%rsp), %rax
movb -0x1(%r10,%rax), %al
jmp 0x2fed
movq 0x50(%rsp), %rax
movb (%r10,%rax), %al
movb %al, (%rbx,%r12)
movq 0x8(%rsp), %r11
jmp 0x2ff1
movq 0x48(%rsp), %rax
jmp 0x2fa5
movl $0x22, %edx
movq 0x2f38(%rip), %rdi      # 0x5ff0
leaq 0x1025(%rip), %rsi      # 0x40e4
callq 0x2100
movq 0x2f25(%rip), %rcx      # 0x5ff0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x20d0
movsbl %al, %esi
movq 0x2f07(%rip), %rdi      # 0x5ff0
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movl $0x6, %edx
movq 0x2eee(%rip), %rdi      # 0x5ff0
leaq 0xffe(%rip), %rsi       # 0x4107
callq 0x2100
movq 0x2edb(%rip), %rdi      # 0x5ff0
movl %r12d, %esi
callq 0x21c0
movq %rax, 0x10(%rsp)
movl $0x7, %edx
movq %rax, %rdi
leaq 0xfdd(%rip), %rsi       # 0x410e
callq 0x2100
movq 0x10(%rsp), %rdi
movl %r14d, %esi
callq 0x21c0
movq %rax, 0x10(%rsp)
movq (%rax), %rcx
movq -0x18(%rcx), %rdi
addq %rax, %rdi
movl $0xa, %esi
callq 0x20d0
movsbl %al, %esi
movq 0x10(%rsp), %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movq 0x8(%rsp), %r11
movq 0x20(%rsp), %rdi
movq 0x30(%rsp), %r10
movq 0x38(%rsp), %r9
movq 0x40(%rsp), %r8
jmp 0x2ff1
incq %r14
addq %r9, %rbx
movq (%rsp), %rax
addq 0x60(%rsp), %rax
movq %rax, (%rsp)
cmpq 0x68(%rsp), %r14
jne 0x2f65
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq