// File: Gammelkebab[P]GameOfLife/src/world/world.cpp
// Function: World::World(int, int, int, int, double)
World::World(int width, int height, int proc_amt, int total_rounds, double worker_share) : width(width), height(height), total_rounds(total_rounds)
{
    width_byte = width / 8 + (width % 8 == 0 ? 0 : 1);

    // Never have noone or everyone at work
    int worker_amt_tmp = btw(proc_amt * worker_share, 1, proc_amt - 1);

    // Distributes rows and columns proportionally to the overall pixel aspect ratio
    float rows_tmp = sqrt(worker_amt_tmp * ((float)height / width));
    rows = floor(rows_tmp);
    cols = floor(worker_amt_tmp / rows_tmp);

    // Try to create one more row or column (Might be possible due to flooring)
    int r1 = (rows + 1) * cols;
    int c1 = rows * (cols + 1);
    if (r1 <= proc_amt && c1 <= proc_amt)
    {
        if (r1 > c1)
        {
            rows++;
        }
        else
        {
            cols++;
        }
    }
    else if (r1 <= proc_amt)
    {
        rows++;
    }
    else if (c1 <= proc_amt)
    {
        cols++;
    }

    block_amt = rows * cols;
    worker_amt = block_amt; // There is one worker for every block
    writer_amt = proc_amt - worker_amt;

    // TODO
    // This enables scattering the writers amongst cores,
    // as long as the processor-core-distribution is known
    writer_nums = new int[writer_amt];
    for (int w = 0; w < writer_amt; w++)
    {
        writer_nums[w] = w + worker_amt; // Put writers behind workers
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl %ecx, -0x14(%rbp)
movl %r8d, -0x18(%rbp)
movsd %xmm0, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x40(%rbp)
movl -0xc(%rbp), %ecx
movl %ecx, (%rax)
movl -0x10(%rbp), %ecx
movl %ecx, 0x4(%rax)
movl -0x18(%rbp), %ecx
movl %ecx, 0x28(%rax)
movl -0xc(%rbp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0xc(%rbp), %eax
movl $0x8, %esi
cltd
idivl %esi
movq -0x40(%rbp), %rax
movl %edx, %edi
movl $0x1, %edx
xorl %esi, %esi
cmpl $0x0, %edi
cmovel %esi, %edx
addl %edx, %ecx
movl %ecx, 0x8(%rax)
cvtsi2sdl -0x14(%rbp), %xmm0
mulsd -0x20(%rbp), %xmm0
cvttsd2si %xmm0, %edi
movl -0x14(%rbp), %edx
subl $0x1, %edx
movl $0x1, %esi
callq 0x10020
movl %eax, -0x24(%rbp)
cvtsi2ssl -0x24(%rbp), %xmm0
cvtsi2ssl -0x10(%rbp), %xmm1
cvtsi2ssl -0xc(%rbp), %xmm2
divss %xmm2, %xmm1
mulss %xmm1, %xmm0
callq 0x10050
movss %xmm0, -0x28(%rbp)
movss -0x28(%rbp), %xmm0
callq 0x10070
movq -0x40(%rbp), %rax
cvttss2si %xmm0, %ecx
movl %ecx, 0xc(%rax)
cvtsi2ssl -0x24(%rbp), %xmm0
divss -0x28(%rbp), %xmm0
callq 0x10070
movq -0x40(%rbp), %rcx
cvttss2si %xmm0, %eax
movl %eax, 0x10(%rcx)
movl 0xc(%rcx), %eax
addl $0x1, %eax
imull 0x10(%rcx), %eax
movl %eax, -0x2c(%rbp)
movl 0xc(%rcx), %eax
movl 0x10(%rcx), %ecx
addl $0x1, %ecx
imull %ecx, %eax
movl %eax, -0x30(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x14(%rbp), %eax
jg 0xfcfa
movl -0x30(%rbp), %eax
cmpl -0x14(%rbp), %eax
jg 0xfcfa
movl -0x2c(%rbp), %eax
cmpl -0x30(%rbp), %eax
jle 0xfceb
movq -0x40(%rbp), %rax
movl 0xc(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0xc(%rax)
jmp 0xfcf8
movq -0x40(%rbp), %rax
movl 0x10(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x10(%rax)
jmp 0xfd2a
movl -0x2c(%rbp), %eax
cmpl -0x14(%rbp), %eax
jg 0xfd11
movq -0x40(%rbp), %rax
movl 0xc(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0xc(%rax)
jmp 0xfd28
movl -0x30(%rbp), %eax
cmpl -0x14(%rbp), %eax
jg 0xfd26
movq -0x40(%rbp), %rax
movl 0x10(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x10(%rax)
jmp 0xfd28
jmp 0xfd2a
movq -0x40(%rbp), %rax
movl 0xc(%rax), %ecx
imull 0x10(%rax), %ecx
movl %ecx, 0x14(%rax)
movl 0x14(%rax), %ecx
movl %ecx, 0x18(%rax)
movl -0x14(%rbp), %ecx
subl 0x18(%rax), %ecx
movl %ecx, 0x1c(%rax)
movslq 0x1c(%rax), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x8030
movq %rax, %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x20(%rax)
movl $0x0, -0x34(%rbp)
movq -0x40(%rbp), %rcx
movl -0x34(%rbp), %eax
cmpl 0x1c(%rcx), %eax
jge 0xfdaa
movq -0x40(%rbp), %rax
movl -0x34(%rbp), %edx
addl 0x18(%rax), %edx
movq 0x20(%rax), %rax
movslq -0x34(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0xfd7e
addq $0x40, %rsp
popq %rbp
retq