// File: /workspace/github_cpp_makefile_star2_O3/xbai0624[P]dnn/./include/Layer.h
// Function: Filter2D::GenerateCompleteDropOutSet(unsigned long, double)
std::vector<Filter2D> GenerateCompleteDropOutSet(size_t nBatches, double dropoutRatio)
    {
        // generate a complete set of drop out filters
        // In this set, each element get acitvated at least once, this is to make sure during drop-out every neuron get trained
        // Parameters:
        //     nBatches: number of drop-out branches
        //     dropoutRatio: ratio of elements to drop out
        // 1) basic check
        auto dim = Dimension();

        assert(nBatches >= 1);
        assert(dropoutRatio < 1.0); // one cannot drop all of them
        int total_elements = (int)dim.first * (int)dim.second;
        // make sure there's enough positions to accomodate all elements
        assert(total_elements * (1.0-dropoutRatio) * (int)nBatches >= total_elements);

        // 2) setup a random engine
        std::random_device rd;
        std::mt19937 gen(rd());
        //std::uniform_int_distribution<> row(0, (int)dim.first-1);
        //std::uniform_int_distribution<> col(0, (int)dim.second-1);

        // 3) the result to be returned
        std::vector<Filter2D> Ret;
        for(size_t n=0;n<nBatches;n++)
        {
            Ret.push_back(Filter2D(dim.first, dim.second, false));
        }

        // 4) first save all coords
        std::vector<std::pair<int, int>> all_coords;
        for(size_t i=0;i<dim.first;i++)
        {
            for(size_t j=0;j<dim.second;j++)
                all_coords.push_back(std::pair<int, int>((int)i, (int)j));
        }

        // 5) integer part
        int average = total_elements / (int)nBatches;
        for(auto &M: Ret)
        {
            // for each Filter, set 'average' elements to true
            int True_elements = 0;
            while(True_elements<average && all_coords.size() > 0)
            {
                std::uniform_int_distribution<int> index(0, (int)all_coords.size()-1);
                int pos = index(gen);
                M[all_coords[pos].first][all_coords[pos].second] = true;
                True_elements++;
                all_coords.erase(all_coords.begin()+pos);
            }
        }

        // 6) residue part
        int mod = total_elements % (int)nBatches;
        for(int i=0;i<mod;i++)
        {
            // evenly distribute 'mod' elements to Filters
            int True_elements = 0;
            while(True_elements < 1 && all_coords.size() > 0)
            {
                std::uniform_int_distribution<int> index(0, (int)all_coords.size()-1);
                int pos = index(gen);
                (Ret[i])[all_coords[pos].first][all_coords[pos].second] = true;
                True_elements++;
                all_coords.erase(all_coords.begin()+pos);
            }
        }
        //assert(1 < 0);

        // 7) complete the rest elements
        // a helper
        // complete missing elements
        auto complete = [&](size_t required_active_elements, Filter2D& F)
        {
            int actual_active_elements = F.GetNumberOfTrueElements();
            int residue = (int)required_active_elements - actual_active_elements;
            //assert(residue >= 0); // incorrect
            if(residue < 0) return; // correct, in case number of neurons is odd number

            // first save all inactive coords
            std::vector<std::pair<int, int>> tmp;
            auto dim = F.Dimension();
            for(size_t i=0;i<dim.first;i++)
            {
                for(size_t j=0;j<dim.second;j++)
                    if(!F[i][j]) tmp.push_back(std::pair<int, int>((int)i, (int)j));
            }
            int count = 0;
            while(count < residue && tmp.size() > 0)
            {
                std::uniform_int_distribution<int> index(0, (int)tmp.size()-1);
                int pos = index(gen);
                if(!F[tmp[pos].first][tmp[pos].second])
                {
                    F[tmp[pos].first][tmp[pos].second] = true;
                    tmp.erase(tmp.begin() + pos);
                    count++;
                }
            }
        };

        for(auto &M: Ret)
            complete(total_elements*(1.-dropoutRatio), M);

        return Ret;
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2768, %rsp           # imm = 0x2768
movq %rdx, %rbx
movq %rdi, %rbp
movq (%rsi), %r13
movq 0x8(%rsi), %rsi
movq %rsi, %rax
subq %r13, %rax
je 0x13968
movq 0x10(%r13), %rcx
movl 0x18(%r13), %edx
subq (%r13), %rcx
leaq (%rdx,%rcx,8), %r15
jmp 0x1396b
xorl %r15d, %r15d
testq %rbx, %rbx
je 0x13db7
movq %rsi, 0x30(%rsp)
movsd 0x13bff(%rip), %xmm2    # 0x27580
ucomisd %xmm0, %xmm2
jbe 0x13dd6
sarq $0x3, %rax
movabsq $-0x3333333333333333, %r12 # imm = 0xCCCCCCCCCCCCCCCD
imulq %rax, %r12
movl %r15d, %eax
imull %r12d, %eax
movl %eax, 0xc(%rsp)
cvtsi2sd %eax, %xmm1
subsd %xmm0, %xmm2
xorps %xmm0, %xmm0
cvtsi2sd %ebx, %xmm0
mulsd %xmm1, %xmm2
movapd %xmm2, 0x40(%rsp)
mulsd %xmm2, %xmm0
ucomisd %xmm1, %xmm0
jb 0x13df5
leaq 0x13e0(%rsp), %r14
movq %r14, %rdi
callq 0x14082
movq %r14, %rdi
callq 0x42d0
movl %eax, %eax
movq %rax, 0x58(%rsp)
movl $0x1, %ecx
movq %rax, %rdx
shrq $0x1e, %rdx
xorl %eax, %edx
imull $0x6c078965, %edx, %eax # imm = 0x6C078965
addl %ecx, %eax
movq %rax, 0x58(%rsp,%rcx,8)
incq %rcx
cmpq $0x270, %rcx            # imm = 0x270
jne 0x139f3
movq $0x270, 0x13d8(%rsp) # imm = 0x270
xorpd %xmm0, %xmm0
movupd %xmm0, (%rbp)
movq $0x0, 0x10(%rbp)
leaq 0x10(%rsp), %r14
movq %rbx, 0x38(%rsp)
movq %r14, %rdi
movq %r12, %rsi
movq %r15, %rdx
xorl %ecx, %ecx
callq 0x152ce
movq %rbp, %rdi
movq %r14, %rsi
callq 0x155f6
movq %r14, %rdi
callq 0x14654
decq %rbx
jne 0x13a3c
movq %rbp, 0x28(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x10(%rsp)
movq $0x0, 0x20(%rsp)
cmpq %r13, 0x30(%rsp)
je 0x13ad9
cmpq $0x1, %r12
adcq $0x0, %r12
xorl %ebx, %ebx
leaq 0x10(%rsp), %r13
movq %rsp, %r14
testq %r15, %r15
je 0x13ad1
xorl %ebp, %ebp
movl %ebx, (%rsp)
movl %ebp, 0x4(%rsp)
movq 0x18(%rsp), %rsi
cmpq 0x20(%rsp), %rsi
je 0x13abe
movq (%rsp), %rax
movq %rax, (%rsi)
addq $0x8, 0x18(%rsp)
jmp 0x13ac9
movq %r13, %rdi
movq %r14, %rdx
callq 0x157f8
incq %rbp
cmpq %rbp, %r15
jne 0x13a9c
incq %rbx
cmpq %r12, %rbx
jne 0x13a95
movl 0xc(%rsp), %eax
cltd
idivl 0x38(%rsp)
movl %eax, %r14d
movl %edx, 0xc(%rsp)
movq 0x28(%rsp), %rax
movq (%rax), %rbp
movq 0x8(%rax), %rax
movq %rax, 0x30(%rsp)
cmpq %rax, %rbp
je 0x13c15
leaq 0x58(%rsp), %r15
movq %rsp, %r12
movabsq $-0x8000000000000000, %rax # imm = 0x8000000000000000
leaq 0x3f(%rax), %rbx
testl %r14d, %r14d
jle 0x13c06
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %rcx
xorl %r13d, %r13d
subq %rax, %rcx
je 0x13c06
shrq $0x3, %rcx
decl %ecx
movl $0x0, (%rsp)
movl %ecx, 0x4(%rsp)
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x15c08
movslq %eax, %rdx
movq 0x10(%rsp), %rax
leaq (%rax,%rdx,8), %rsi
addq $0x8, %rsi
movslq -0x8(%rsi), %rcx
movq (%rbp), %rdi
leaq (%rcx,%rcx,4), %r8
movslq -0x4(%rsi), %rcx
leal 0x3f(%rcx), %r9d
testq %rcx, %rcx
cmovnsl %ecx, %r9d
sarl $0x6, %r9d
movslq %r9d, %r9
shlq $0x3, %r9
addq (%rdi,%r8,8), %r9
movq %rcx, %rdi
andq %rbx, %rdi
xorl %r8d, %r8d
movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000
cmpq %r10, %rdi
setbe %r8b
movl $0x1, %edi
shlq %cl, %rdi
orq %rdi, -0x8(%r9,%r8,8)
movq 0x18(%rsp), %rcx
cmpq %rcx, %rsi
je 0x13bf1
movq %rcx, %rdi
subq %rsi, %rdi
sarq $0x3, %rdi
testq %rdi, %rdi
jle 0x13bf1
incq %rdi
leaq (%rax,%rdx,8), %rdx
addq $0xc, %rdx
movq -0x4(%rdx), %rsi
movq %rsi, -0xc(%rdx)
decq %rdi
addq $0x8, %rdx
cmpq $0x1, %rdi
ja 0x13bdc
addq $-0x8, %rcx
movq %rcx, 0x18(%rsp)
incl %r13d
cmpl %r14d, %r13d
jne 0x13b2f
addq $0x18, %rbp
cmpq 0x30(%rsp), %rbp
jne 0x13b19
movl 0xc(%rsp), %eax
testl %eax, %eax
jle 0x13d2c
movl %eax, %ebx
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %rdx
xorl %r12d, %r12d
leaq 0x58(%rsp), %r14
movq %rsp, %r15
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
leaq 0x3f(%rcx), %rbp
movq %rax, %rcx
subq %rax, %rdx
je 0x13d1d
shrq $0x3, %rdx
decl %edx
movl $0x0, (%rsp)
movl %edx, 0x4(%rsp)
movq %r15, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x15c08
movq 0x28(%rsp), %rcx
movq (%rcx), %rcx
leaq (%r12,%r12,2), %rdi
movslq %eax, %rdx
movq 0x10(%rsp), %rax
leaq 0x8(%rax,%rdx,8), %rsi
movslq -0x8(%rsi), %r8
movq (%rcx,%rdi,8), %rdi
leaq (%r8,%r8,4), %r8
movslq -0x4(%rsi), %rcx
leal 0x3f(%rcx), %r9d
testq %rcx, %rcx
cmovnsl %ecx, %r9d
sarl $0x6, %r9d
movslq %r9d, %r9
shlq $0x3, %r9
addq (%rdi,%r8,8), %r9
movq %rcx, %rdi
andq %rbp, %rdi
xorl %r8d, %r8d
movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000
cmpq %r10, %rdi
setbe %r8b
movl $0x1, %edi
shlq %cl, %rdi
orq %rdi, -0x8(%r9,%r8,8)
movq 0x18(%rsp), %rcx
cmpq %rcx, %rsi
je 0x13d14
movq %rcx, %rdi
subq %rsi, %rdi
sarq $0x3, %rdi
testq %rdi, %rdi
jle 0x13d14
incq %rdi
leaq (%rax,%rdx,8), %rdx
addq $0xc, %rdx
movq -0x4(%rdx), %rsi
movq %rsi, -0xc(%rdx)
decq %rdi
addq $0x8, %rdx
cmpq $0x1, %rdi
ja 0x13cff
addq $-0x8, %rcx
movq %rcx, 0x18(%rsp)
incq %r12
movq %rcx, %rdx
cmpq %rbx, %r12
jne 0x13c46
leaq 0x58(%rsp), %rax
movq %rax, (%rsp)
movq 0x28(%rsp), %r13
movq (%r13), %r14
movq 0x8(%r13), %rbx
cmpq %rbx, %r14
je 0x13d86
movapd 0x40(%rsp), %xmm0
cvttsd2si %xmm0, %rax
movq %rax, %rcx
subsd 0x1386b(%rip), %xmm0    # 0x275c8
cvttsd2si %xmm0, %r15
sarq $0x3f, %rcx
andq %rcx, %r15
orq %rax, %r15
movq %rsp, %r12
movq %r12, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x15368
addq $0x18, %r14
cmpq %rbx, %r14
jne 0x13d6f
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x13d95
callq 0x4230
leaq 0x13e0(%rsp), %rdi
callq 0x4220
movq %r13, %rax
addq $0x2768, %rsp           # imm = 0x2768
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x15857(%rip), %rdi     # 0x29615
leaq 0x1585e(%rip), %rsi     # 0x29623
leaq 0x15869(%rip), %rcx     # 0x29635
movl $0x9c, %edx
callq 0x4160
leaq 0x158a3(%rip), %rdi     # 0x29680
leaq 0x1583f(%rip), %rsi     # 0x29623
leaq 0x1584a(%rip), %rcx     # 0x29635
movl $0x9d, %edx
callq 0x4160
leaq 0x15897(%rip), %rdi     # 0x29693
leaq 0x15820(%rip), %rsi     # 0x29623
leaq 0x1582b(%rip), %rcx     # 0x29635
movl $0xa0, %edx
callq 0x4160
jmp 0x13e69
movq %rax, %r14
jmp 0x13e54
jmp 0x13e35
jmp 0x13e35
movq %rax, %r14
leaq 0x10(%rsp), %rdi
callq 0x14654
jmp 0x13e4c
movq %rax, %r14
jmp 0x13e4c
jmp 0x13e35
movq %rax, %r14
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
movq 0x28(%rsp), %rbp
je 0x13e4c
callq 0x4230
movq %rbp, %rdi
callq 0x135fa
leaq 0x13e0(%rsp), %rdi
callq 0x4220
movq %r14, %rdi
callq 0x43e0
movq %rax, %rdi
callq 0x14607
nop