// File: /workspace/github_cpp_makefile_star2_O2/maramire[P]SP_PSO/parallel_main.cpp
// Function: particle_function(void*)
void* particle_function(void* arg){
    
    long p = (long)arg;

    random_device rd;
    mt19937 gen(rd());
    uniform_real_distribution<> dis(0, 1);//uniform distribution between 0 and 1
    
    /* Each thread run */
    /* Particle movement */
    vector<float> new_permutation(n_items);
    iota(begin(new_permutation), end(new_permutation), 1);

    for (int i = 0; i < swarm[p].permutation.size(); i++)
    {
    
        float r1 = dis(gen);
        float r2 = dis(gen);

        float pfactor = swarm[p].pbest[i] - swarm[p].permutation[i];
        float gfactor = gbest.permutation[i] - swarm[p].permutation[i];                

        float current_velocity = omega*swarm[p].permutation[i] + r1*c1*pfactor + r2*c2*gfactor;

        if (current_velocity < velocity_min)
        {
            current_velocity = velocity_min;

        }else if(current_velocity > velocity_max)
        {
            current_velocity = velocity_max;
        }

        swarm[p].velocity[i] = current_velocity;
    
        new_permutation[i] = swarm[p].permutation[i] + swarm[p].velocity[i];
        
    }

    /* Discretize Movement */
    vector<float> assignments = new_permutation;
    sort(assignments.begin(),assignments.end());

    for (int i = 0; i < new_permutation.size(); i++)
    {
        for (int j = 0; j < assignments.size(); j++)
        {
            if (new_permutation[j]==assignments[i])
            {
                swarm[p].permutation[i] = j+1;
            }   
        }
    }

    /* Evaluate particle */
    Strip s = {};
    s.height = max_height;
    s.width = strip_width;

    s.x_position = 0;
    s.y_position = 0;

    HR(items,s,n_items,swarm[p]); 


    /* Update personal best */
    if (swarm[p].fitness < swarm[p].pbest_fitness)
    {
        swarm[p].pbest = swarm[p].permutation;
        swarm[p].pbest_fitness = swarm[p].fitness;
    }

    
    /* Update global best, using mutex */

    if (swarm[p].pbest_fitness < gbest.fitness)
    {
        pthread_mutex_lock(&mutex);
        gbest.fitness = swarm[p].pbest_fitness;
        gbest.permutation = swarm[p].pbest;
        pthread_mutex_unlock (&mutex);
    } 

    pthread_exit((void*) 0);   

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x2770, %rsp           # imm = 0x2770
movq %rdi, %rbx
leaq -0x2788(%rbp), %r14
movq %r14, %rdi
callq 0x3650
movq %r14, %rdi
callq 0x2230
movl %eax, %esi
leaq -0x1400(%rbp), %rdi
callq 0x4740
andq $0x0, -0x68(%rbp)
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, -0x60(%rbp)
movslq 0x850b(%rip), %rsi      # 0xb368
leaq -0x38(%rbp), %rdi
leaq -0x50(%rbp), %rdx
callq 0x3b0c
movq -0x38(%rbp), %rdi
movq -0x30(%rbp), %rsi
pushq $0x1
popq %rdx
callq 0x3b5d
movq 0x83af(%rip), %rax      # 0xb230
imulq $0x58, %rbx, %r15
movq (%rax,%r15), %rcx
xorl %r12d, %r12d
leaq -0x68(%rbp), %rbx
leaq -0x1400(%rbp), %r14
movq 0x8(%rax,%r15), %rax
subq %rcx, %rax
sarq $0x2, %rax
cmpq %r12, %rax
jbe 0x2f73
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3b78
movsd %xmm0, -0x58(%rbp)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3b78
movq 0x8362(%rip), %rax      # 0xb230
movq (%rax,%r15), %rcx
movq 0x20(%rax,%r15), %rdx
movl (%rdx,%r12,4), %edx
movl (%rcx,%r12,4), %esi
subl %esi, %edx
cvtsi2ss %edx, %xmm2
cvtsd2ss -0x58(%rbp), %xmm3
movq 0x82e7(%rip), %rdx      # 0xb1d8
movl (%rdx,%r12,4), %edx
subl %esi, %edx
cvtsi2ss %edx, %xmm4
cvtsi2ss %esi, %xmm1
cvtsd2ss %xmm0, %xmm0
mulss 0x8465(%rip), %xmm3     # 0xb370
mulss %xmm2, %xmm3
movss 0x8455(%rip), %xmm2     # 0xb36c
mulss %xmm1, %xmm2
addss %xmm3, %xmm2
mulss 0x844d(%rip), %xmm0     # 0xb374
mulss %xmm4, %xmm0
addss %xmm2, %xmm0
movss 0x844d(%rip), %xmm2     # 0xb384
ucomiss %xmm0, %xmm2
ja 0x2f4f
movss 0x843c(%rip), %xmm3     # 0xb380
ucomiss %xmm3, %xmm0
movaps %xmm0, %xmm2
jbe 0x2f4f
movaps %xmm3, %xmm2
leaq (%rax,%r15), %rdx
movq 0x40(%rdx), %rdx
movss %xmm2, (%rdx,%r12,4)
addss %xmm2, %xmm1
movq -0x38(%rbp), %rdx
movss %xmm1, (%rdx,%r12,4)
incq %r12
jmp 0x2e97
leaq -0x50(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x3b86
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
callq 0x50d2
movq -0x38(%rbp), %rax
movq -0x30(%rbp), %rcx
subq %rax, %rcx
sarq $0x2, %rcx
movq -0x50(%rbp), %rdx
movq -0x48(%rbp), %rsi
subq %rdx, %rsi
sarq $0x2, %rsi
xorl %edi, %edi
cmpq %rcx, %rdi
je 0x2fe7
movq 0x8277(%rip), %r8       # 0xb230
addq %r15, %r8
xorl %r9d, %r9d
cmpq %r9, %rsi
je 0x2fe2
movss (%rax,%r9,4), %xmm0
ucomiss (%rdx,%rdi,4), %xmm0
jne 0x2fdd
jp 0x2fdd
movq (%r8), %r10
leal 0x1(%r9), %r11d
movl %r11d, (%r10,%rdi,4)
incq %r9
jmp 0x2fbf
incq %rdi
jmp 0x2fad
movl 0x839f(%rip), %eax      # 0xb38c
leaq -0x78(%rbp), %rsi
movl %eax, (%rsi)
movl 0x838f(%rip), %eax      # 0xb388
movl %eax, 0x4(%rsi)
andq $0x0, 0x8(%rsi)
movq 0x8228(%rip), %rcx      # 0xb230
addq %r15, %rcx
leaq 0x837e(%rip), %rdi      # 0xb390
callq 0x2ad2
movq 0x8212(%rip), %rsi      # 0xb230
movl 0x18(%rsi,%r15), %eax
cmpl 0x38(%rsi,%r15), %eax
jge 0x3047
addq %r15, %rsi
leaq 0x20(%rsi), %rdi
callq 0x3822
movq 0x81f3(%rip), %rsi      # 0xb230
movl 0x18(%rsi,%r15), %eax
movl %eax, 0x38(%rsi,%r15)
movl 0x38(%rsi,%r15), %eax
cmpl 0x819e(%rip), %eax      # 0xb1f0
jge 0x3090
leaq 0x82e5(%rip), %rdi      # 0xb340
callq 0x2250
movq 0x81c9(%rip), %rax      # 0xb230
leaq (%rax,%r15), %rsi
addq $0x20, %rsi
movl 0x18(%rsi), %eax
movl %eax, 0x8178(%rip)      # 0xb1f0
leaq 0x8159(%rip), %rdi      # 0xb1d8
callq 0x3822
leaq 0x82b5(%rip), %rdi      # 0xb340
callq 0x2130
xorl %edi, %edi
callq 0x2300
jmp 0x3099
movq %rax, %rbx
leaq -0x50(%rbp), %rdi
callq 0x3d62
jmp 0x30ae
jmp 0x30ab
jmp 0x30ab
movq %rax, %rbx
leaq -0x38(%rbp), %rdi
callq 0x3d62
jmp 0x30be
jmp 0x30bb
movq %rax, %rbx
leaq -0x2788(%rbp), %rdi
callq 0x3a66
movq %rbx, %rdi
callq 0x22f0