// File: wichtounet[P]cpp_utils_test/include/cpp_utils/parallel.hpp
// Function: void cpp::parallel_foreach_it<cpp::default_thread_pool<std::deque>, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int>>>, DOCTEST_ANON_FUNC_36()::$_0>(cpp::default_thread_pool<std::deque>&, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int>>>, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int>>>, DOCTEST_ANON_FUNC_36()::$_0)
void parallel_foreach_it(TP& thread_pool, Iterator first, Iterator last, Functor fun) {
    if constexpr (std::is_same_v<typename std::iterator_traits<Iterator>::iterator_category, std::random_access_iterator_tag>) {
        const auto n    = std::distance(first, last);
        const auto part = n / thread_pool.size();

        if (part < 2) {
            for (; first != last; ++first) {
                thread_pool.do_task(fun, first);
            }
        } else {
            auto batch_functor = [fun](Iterator first, Iterator last) {
                for (Iterator it = first; it != last; ++it) {
                    fun(it);
                }
            };

            // Distribute evenly the batches

            for (std::size_t t = 0; t < thread_pool.size(); ++t) {
                thread_pool.do_task(batch_functor, first + t * part, first + (t + 1) * part);
            }

            // Compute the remainders
            if (auto rem = n % thread_pool.size(); rem > 0) {
                for (Iterator it = last - rem; it < last; ++it) {
                    fun(it);
                }
            }
        }
    } else {
        for (; first != last; ++first) {
            thread_pool.do_task(fun, first);
        }
    }

    thread_pool.wait();
}

// Assembly:
subq $0xb8, %rsp
movq %rsi, 0xb0(%rsp)
movq %rdx, 0xa8(%rsp)
movq %rdi, 0x98(%rsp)
movq 0xb0(%rsp), %rax
movq %rax, 0x88(%rsp)
movq 0xa8(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x88(%rsp), %rdi
movq 0x80(%rsp), %rsi
callq 0x30000
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x98(%rsp), %rdi
callq 0x50e20
movq %rax, %rcx
movq 0x18(%rsp), %rax
xorl %edx, %edx
divq %rcx
movq %rax, 0x78(%rsp)
cmpq $0x2, 0x78(%rsp)
jae 0x85622
jmp 0x855d2
leaq 0xb0(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x1edd0
xorb $-0x1, %al
testb $0x1, %al
jne 0x855ef
jmp 0x8561d
movq 0x98(%rsp), %rdi
movq 0xb0(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rsi
callq 0x85790
leaq 0xb0(%rsp), %rdi
callq 0x1f180
jmp 0x855d2
jmp 0x85772
movq $0x0, 0x58(%rsp)
movq 0x58(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x98(%rsp), %rdi
callq 0x50e20
movq %rax, %rcx
movq 0x10(%rsp), %rax
cmpq %rcx, %rax
jae 0x856c9
movq 0x98(%rsp), %rax
movq %rax, 0x8(%rsp)
movb 0x67(%rsp), %al
movb %al, 0x57(%rsp)
movq 0x58(%rsp), %rsi
imulq 0x78(%rsp), %rsi
leaq 0xb0(%rsp), %rdi
callq 0x50e30
movq %rax, 0x48(%rsp)
movq 0x58(%rsp), %rsi
addq $0x1, %rsi
imulq 0x78(%rsp), %rsi
leaq 0xb0(%rsp), %rdi
callq 0x50e30
movq 0x8(%rsp), %rdi
movq %rax, 0x40(%rsp)
movq 0x48(%rsp), %rsi
movq 0x40(%rsp), %rdx
callq 0x85800
movq 0x58(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x58(%rsp)
jmp 0x8562b
movq 0x90(%rsp), %rax
movq %rax, (%rsp)
movq 0x98(%rsp), %rdi
callq 0x50e20
movq %rax, %rcx
movq (%rsp), %rax
xorl %edx, %edx
divq %rcx
movq %rdx, 0x38(%rsp)
cmpq $0x0, 0x38(%rsp)
jbe 0x85770
movq 0x38(%rsp), %rsi
leaq 0xa8(%rsp), %rdi
callq 0x50e70
movq %rax, 0x30(%rsp)
leaq 0x30(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x50ee0
movb %al, 0x2f(%rsp)
leaq 0x2e(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x50f30
movzbl 0x2f(%rsp), %edi
callq 0x50ec0
testb $0x1, %al
jne 0x85746
jmp 0x8576e
movq 0x30(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rsi
leaq 0xa7(%rsp), %rdi
callq 0x85890
leaq 0x30(%rsp), %rdi
callq 0x1f180
jmp 0x85712
jmp 0x85770
jmp 0x85772
movq 0x98(%rsp), %rdi
callq 0x50f40
addq $0xb8, %rsp
retq
nopw (%rax,%rax)