// File: wichtounet[P]cpp_utils_test/include/cpp_utils/parallel.hpp
// Function: void cpp::parallel_foreach<cpp::thread_pool<true>, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int>>>, DOCTEST_ANON_FUNC_2()::$_0>(cpp::thread_pool<true>&, __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_2()::$_0)
void parallel_foreach(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>) {
        auto n    = std::distance(first, last);
        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);
            }

            //Distribute the remainders

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

    thread_pool.wait();
}

// Assembly:
subq $0xc8, %rsp
movq %rsi, 0xc0(%rsp)
movq %rdx, 0xb8(%rsp)
movq %rcx, 0xb0(%rsp)
movq %rdi, 0xa8(%rsp)
movq 0xc0(%rsp), %rax
movq %rax, 0x98(%rsp)
movq 0xb8(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x98(%rsp), %rdi
movq 0x90(%rsp), %rsi
callq 0x30000
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0xa8(%rsp), %rdi
callq 0x50e20
movq %rax, %rcx
movq 0x30(%rsp), %rax
xorl %edx, %edx
divq %rcx
movq %rax, 0x88(%rsp)
cmpq $0x2, 0x88(%rsp)
jae 0x43a7f
jmp 0x43a10
leaq 0xc0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x1edd0
xorb $-0x1, %al
testb $0x1, %al
jne 0x43a2d
jmp 0x43a7a
movq 0xa8(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0xb0(%rsp), %rax
movq %rax, 0x80(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0x1ee50
movq 0x28(%rsp), %rdi
movl (%rax), %edx
movq 0x80(%rsp), %rsi
callq 0x43c30
leaq 0xc0(%rsp), %rdi
callq 0x1f180
jmp 0x43a10
jmp 0x43c0c
movq 0xb0(%rsp), %rax
movq %rax, 0x78(%rsp)
movq $0x0, 0x70(%rsp)
movq 0x70(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0xa8(%rsp), %rdi
callq 0x50e20
movq %rax, %rcx
movq 0x20(%rsp), %rax
cmpq %rcx, %rax
jae 0x43b44
movq 0xa8(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x78(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x70(%rsp), %rsi
imulq 0x88(%rsp), %rsi
leaq 0xc0(%rsp), %rdi
callq 0x50e30
movq %rax, 0x60(%rsp)
movq 0x70(%rsp), %rsi
addq $0x1, %rsi
imulq 0x88(%rsp), %rsi
leaq 0xc0(%rsp), %rdi
callq 0x50e30
movq 0x18(%rsp), %rdi
movq %rax, 0x58(%rsp)
movq 0x68(%rsp), %rsi
movq 0x60(%rsp), %rdx
movq 0x58(%rsp), %rcx
callq 0x43cb0
movq 0x70(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x70(%rsp)
jmp 0x43a95
movq 0xa0(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0xa8(%rsp), %rdi
callq 0x50e20
movq %rax, %rcx
movq 0x10(%rsp), %rax
xorl %edx, %edx
divq %rcx
movq %rdx, 0x50(%rsp)
cmpq $0x0, 0x50(%rsp)
jbe 0x43c0a
movq 0x50(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
callq 0x50e70
movq %rax, 0x48(%rsp)
leaq 0x48(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x50ee0
movb %al, 0x47(%rsp)
leaq 0x46(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x50f30
movzbl 0x47(%rsp), %edi
callq 0x50ec0
testb $0x1, %al
jne 0x43bc7
jmp 0x43c08
movq 0xa8(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0xb0(%rsp), %rax
movq %rax, 0x38(%rsp)
leaq 0x48(%rsp), %rdi
callq 0x1ee50
movq 0x8(%rsp), %rdi
movl (%rax), %edx
movq 0x38(%rsp), %rsi
callq 0x43c30
leaq 0x48(%rsp), %rdi
callq 0x1f180
jmp 0x43b93
jmp 0x43c0a
jmp 0x43c0c
movq 0xa8(%rsp), %rdi
callq 0x50f40
addq $0xc8, %rsp
retq
nopw %cs:(%rax,%rax)