// File: /workspace/github_cpp_makefile_star2_O2/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, %rbx
movq %rdi, %r12
leal 0x1(%r15), %eax
shlq $0x2, %rax
cmpl $-0x1, %edx
pushq $-0x1
popq %r13
cmovgeq %rax, %r13
movq %r13, %rdi
callq 0x2030
movq %rax, %r14
movq %r13, %rdi
callq 0x2030
movslq %r15d, %rcx
xorl %edx, %edx
cmpq %rcx, %rdx
jg 0x47e2
andl $0x0, (%r14,%rdx,4)
andl $0x0, (%rax,%rdx,4)
incq %rdx
jmp 0x47cf
movq (%r12), %rdx
movq 0x8(%r12), %rsi
subq %rdx, %rsi
sarq $0x2, %rsi
xorl %edi, %edi
testl %r15d, %r15d
cmovgl %r15d, %edi
negq %rdi
pushq $0x1
popq %r8
movq %r8, %r9
movq %rax, %r15
cmpq %rsi, %r9
ja 0x485e
movq (%rbx), %rax
movq %r8, %r10
leaq (%rdi,%r10), %r11
cmpq $0x1, %r11
je 0x4853
movslq -0x4(%rax,%r9,4), %r11
cmpq %r11, %r10
jge 0x482d
movl (%r15,%r10,4), %r11d
jmp 0x484a
movl %r10d, %ebp
subl %r11d, %ebp
movslq %ebp, %r12
movl -0x4(%rdx,%r9,4), %r11d
addl (%r15,%r12,4), %r11d
movl (%r15,%r10,4), %ebp
cmpl %r11d, %ebp
cmovgl %ebp, %r11d
movl %r11d, (%r14,%r10,4)
incq %r10
jmp 0x4813
incq %r9
movq %r14, %rax
movq %r15, %r14
jmp 0x4805
movl (%r15,%rcx,4), %ebx
testq %r14, %r14
je 0x486f
movq %r14, %rdi
callq 0x2270
movq %r15, %rdi
callq 0x2270
movl %ebx, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq