// File: /workspace/github_cpp_makefile_star2_O1/Manca[P]algorithms2/./assignment3.hpp
// Function: assignment3::knapsack_big::knapsack_smallArray(std::vector<int, std::allocator<int>>&, std::vector<int, std::allocator<int>>&, int)
int knapsack_smallArray(std::vector<int>& values, std::vector<int>& weights, const int W)
        {
            // optimized version! (two arrays with at most W+1 elements)
            int *A = new int[W + 1];    // row 1 (current element being processed)
            int *B = new int[W + 1];    // row 0 (previous)
            for (int i = 0; i <= W; i++)
            {
                A[i] = 0;
                B[i] = 0;
            }

            for (size_t i = 1; i <= values.size(); i++)
            {
                for (int x = 1; x <= W; x++)
                {
                    if (weights[i - 1] > x)
                    {
                        A[x] = B[x];
                    }
                    else
                    {
                        A[x] = std::max(B[x], B[x - weights[i - 1]] + values[i - 1]);
                    }
                }

                // interchange only after row is filled (only swap pointers!)
                int* tmp = A;
                A = B;
                B = tmp;
            }

            int res = B[W]; // since the last swap, our final row is in B now
            delete[] A;
            delete[] B;
            return res;

        /**** Version that works too. Only a bit slower.
            //// define and initialize resulting matrix (rows are integral weights up to W (inclusive), so 0,1,2,3...,W, columns are items up to n (inclusive))
            /* std::vector<std::vector<int>> A;    // 2D-array 2x(n+1)
            A.resize(2);
            for (int i = 0; i < 2; i++)
            {
                A[i].resize(W + 1);
            }
            for (size_t i = 1; i <= values.size(); i++)
            {
                for (int x = 1; x <= W; x++)
                {
                    if (weights[i - 1] > x)
                    {
                        A[1][x] = A[0][x];
                    }
                    else
                    {
                        A[1][x] = std::max(A[0][x], A[0][x - weights[i - 1]] + values[i - 1]);
                    }
                }
                // interchange only after row is filled
                for (int x = 1; x <= W; x++)
                {
                    A[0][x] = A[1][x];  // interchange
                }
            }

            return A[1][W]; // bottom right cell contains optimal value
            *****/
        }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl %edx, %r14d
movq %rsi, %rbp
movq %rdi, %r13
movslq %edx, %r12
leaq 0x4(,%r12,4), %rax
cmpl $-0x1, %r12d
movq $-0x1, %rbx
cmovgeq %rax, %rbx
movq %rbx, %rdi
callq 0x2030
movq %rax, %r15
movq %rbx, %rdi
callq 0x2030
movq %rax, %rbx
testl %r12d, %r12d
js 0x51f0
movl %r14d, %eax
movq %rbp, (%rsp)
leaq 0x4(,%rax,4), %rbp
movq %r15, %rdi
xorl %esi, %esi
movq %rbp, %rdx
callq 0x2140
movq %rbx, %rdi
xorl %esi, %esi
movq %rbp, %rdx
movq (%rsp), %rbp
callq 0x2140
movq (%r13), %rax
movq 0x8(%r13), %rdi
subq %rax, %rdi
je 0x5279
sarq $0x2, %rdi
movq (%rbp), %rcx
leal 0x1(%r14), %edx
incq %rdi
cmpq $0x3, %rdi
movl $0x2, %esi
cmovaeq %rdi, %rsi
movl $0x1, %r8d
movq %rbx, %rdi
movq %r15, %rbx
testl %r14d, %r14d
jle 0x526c
movl $0x1, %r9d
movslq -0x4(%rcx,%r8,4), %r10
cmpq %r10, %r9
jge 0x5240
movl (%rdi,%r9,4), %r10d
jmp 0x5260
shlq $0x2, %r10
leaq (%rdi,%r9,4), %r11
movq %r11, %r15
subq %r10, %r15
movl -0x4(%rax,%r8,4), %r10d
addl (%r15), %r10d
movl (%r11), %r11d
cmpl %r10d, %r11d
cmovgl %r11d, %r10d
movl %r10d, (%rbx,%r9,4)
incq %r9
cmpq %r9, %rdx
jne 0x5230
incq %r8
movq %rdi, %r15
cmpq %rsi, %r8
jne 0x521f
jmp 0x527c
movq %r15, %rdi
movl (%rbx,%r12,4), %ebp
testq %rdi, %rdi
je 0x528a
callq 0x2270
testq %rbx, %rbx
je 0x5297
movq %rbx, %rdi
callq 0x2270
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq