// File: /workspace/github_cpp_makefile_star2_O3/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, %r15d
movq %rsi, (%rsp)
movq %rdi, %r13
leal 0x1(%r15), %r12d
leaq (,%r12,4), %rbp
cmpl $-0x1, %edx
movq $-0x1, %rbx
cmovgeq %rbp, %rbx
movq %rbx, %rdi
callq 0x2030
movq %rax, %r14
movq %rbx, %rdi
callq 0x2030
movq %rax, %rbx
testl %r15d, %r15d
js 0x513d
movq %r14, %rdi
xorl %esi, %esi
movq %rbp, %rdx
callq 0x2140
movq %rbx, %rdi
xorl %esi, %esi
movq %rbp, %rdx
callq 0x2140
movq (%r13), %rax
movq 0x8(%r13), %rsi
subq %rax, %rsi
je 0x51d5
sarq $0x2, %rsi
movq (%rsp), %rcx
movq (%rcx), %rcx
incq %rsi
cmpq $0x3, %rsi
movl $0x2, %edx
cmovaeq %rsi, %rdx
movl $0x1, %esi
movq %r14, %rdi
movq %rbx, %r14
movq %rdi, %rbx
testl %r15d, %r15d
jle 0x51bd
movl $0x1, %edi
movslq -0x4(%rcx,%rsi,4), %r8
cmpq %r8, %rdi
jge 0x5191
movl (%r14,%rdi,4), %r8d
jmp 0x51b1
shlq $0x2, %r8
leaq (%r14,%rdi,4), %r9
movq %r9, %r10
subq %r8, %r10
movl -0x4(%rax,%rsi,4), %r8d
addl (%r10), %r8d
movl (%r9), %r9d
cmpl %r8d, %r9d
cmovgl %r9d, %r8d
movl %r8d, (%rbx,%rdi,4)
incq %rdi
cmpq %rdi, %r12
jne 0x5181
incq %rsi
movq %r14, %rdi
cmpq %rdx, %rsi
jne 0x5171
movslq %r15d, %rax
movl (%rbx,%rax,4), %ebp
testq %r14, %r14
jne 0x51db
jmp 0x51e3
movslq %r15d, %rax
movl (%rbx,%rax,4), %ebp
movq %r14, %rdi
callq 0x2260
movq %rbx, %rdi
callq 0x2260
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq