// File: ekg[P]sgd2/src/sgd2.hpp
// Function: sgd2::bfs(unsigned long, unsigned long, unsigned long*, unsigned long*)
std::vector<term> bfs(uint64_t n, uint64_t m, uint64_t* I, uint64_t* J)
{
    auto graph = build_graph_unweighted(n, m, I, J);
        
    uint64_t nC2;
    if (n == 1) {
        nC2 = 1;
    } else {
        nC2 = (n*(n-1))/2;
    }
    std::vector<term> terms;
    terms.reserve(nC2);

    uint64_t terms_size_goal = 0; // to keep track of when to stop searching i<j

    for (uint64_t source=0; source<n-1; source++) // no need to do final vertex because i<j
    {
        std::vector<uint64_t> d(n, -1); // distances from source
        std::queue<uint64_t> q;
        
        d[source] = 0;
        q.push(source);

        terms_size_goal += n-source-1; // this is how many terms exist for i<j

        while (!q.empty() && terms.size() <= terms_size_goal)
        {
            uint64_t current = q.front();
            q.pop();
            for (uint64_t next : graph[current])
            {
                if (d[next] == -1)
                {
                    q.push(next);
                    uint64_t d_ij = d[current] + 1;
                    d[next] = d_ij;

                    if (source < next) // only add terms for i<j
                    {
                        double w_ij = 1.0 / ((double)d_ij*d_ij);
                        terms.push_back(term(source, next, d_ij, w_ij));
                    }
                }
            }
        }
        if (terms.size() != terms_size_goal)
        {
            throw "graph is not strongly connected, or is not indexed from zero";
        }
    }
    return terms;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x180, %rsp            # imm = 0x180
movq %rdi, -0x150(%rbp)
movq %rdi, %rax
movq %rax, -0x148(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %r8
leaq -0x40(%rbp), %rdi
callq 0x2880
cmpq $0x1, -0x10(%rbp)
jne 0x2bea
movq $0x1, -0x48(%rbp)
jmp 0x2c01
movq -0x10(%rbp), %rax
movq -0x10(%rbp), %rcx
subq $0x1, %rcx
imulq %rcx, %rax
shrq %rax
movq %rax, -0x48(%rbp)
movq -0x150(%rbp), %rdi
movb $0x0, -0x49(%rbp)
callq 0x9cd0
movq -0x150(%rbp), %rdi
movq -0x48(%rbp), %rsi
callq 0x9cf0
jmp 0x2c23
movq $0x0, -0x68(%rbp)
movq $0x0, -0x70(%rbp)
movq -0x70(%rbp), %rax
movq -0x10(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jae 0x2fee
movq -0x10(%rbp), %rax
movq %rax, -0x160(%rbp)
movq $-0x1, -0x90(%rbp)
leaq -0x91(%rbp), %rdi
movq %rdi, -0x158(%rbp)
callq 0x9df0
movq -0x160(%rbp), %rsi
movq -0x158(%rbp), %rcx
leaq -0x88(%rbp), %rdi
leaq -0x90(%rbp), %rdx
callq 0x9e10
jmp 0x2c94
leaq -0x91(%rbp), %rdi
callq 0x9e90
leaq -0xe8(%rbp), %rdi
callq 0x9eb0
jmp 0x2cae
movq -0x70(%rbp), %rsi
leaq -0x88(%rbp), %rdi
callq 0x9ee0
movq $0x0, (%rax)
leaq -0xe8(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x9f00
jmp 0x2cd7
movq -0x10(%rbp), %rax
subq -0x70(%rbp), %rax
subq $0x1, %rax
addq -0x68(%rbp), %rax
movq %rax, -0x68(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x9f30
movb %al, -0x161(%rbp)
jmp 0x2cff
movb -0x161(%rbp), %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x162(%rbp)
jne 0x2d2d
jmp 0x2d14
movq -0x150(%rbp), %rdi
callq 0x9f50
cmpq -0x68(%rbp), %rax
setbe %al
movb %al, -0x162(%rbp)
movb -0x162(%rbp), %al
testb $0x1, %al
jne 0x2d3c
jmp 0x2f79
leaq -0xe8(%rbp), %rdi
callq 0x9f70
movq %rax, -0x170(%rbp)
jmp 0x2d51
movq -0x170(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xf0(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x9f90
jmp 0x2d70
movq -0xf0(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0x9b80
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rdi
callq 0x9fb0
movq %rax, -0x100(%rbp)
movq -0xf8(%rbp), %rdi
callq 0x9fe0
movq %rax, -0x108(%rbp)
leaq -0x100(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0xa010
testb $0x1, %al
jne 0x2dc9
jmp 0x2f74
leaq -0x100(%rbp), %rdi
callq 0xa050
movq (%rax), %rax
movq %rax, -0x110(%rbp)
movq -0x110(%rbp), %rsi
leaq -0x88(%rbp), %rdi
callq 0x9ee0
cmpq $-0x1, (%rax)
jne 0x2f61
leaq -0xe8(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x9f00
jmp 0x2e11
movq -0xf0(%rbp), %rsi
leaq -0x88(%rbp), %rdi
callq 0x9ee0
movq (%rax), %rax
addq $0x1, %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rax
movq %rax, -0x178(%rbp)
movq -0x110(%rbp), %rsi
leaq -0x88(%rbp), %rdi
callq 0x9ee0
movq -0x178(%rbp), %rcx
movq %rcx, (%rax)
movq -0x70(%rbp), %rax
cmpq -0x110(%rbp), %rax
jae 0x2f5f
movq -0x118(%rbp), %xmm3
movaps 0x1b1c3(%rip), %xmm2    # 0x1e040
punpckldq %xmm2, %xmm3    # xmm3 = xmm3[0],xmm2[0],xmm3[1],xmm2[1]
movapd 0x1b1c7(%rip), %xmm1    # 0x1e050
subpd %xmm1, %xmm3
movaps %xmm3, %xmm0
unpckhpd %xmm3, %xmm3            # xmm3 = xmm3[1,1]
addsd %xmm0, %xmm3
mulsd %xmm3, %xmm3
movsd 0x1b164(%rip), %xmm0    # 0x1e008
divsd %xmm3, %xmm0
movsd %xmm0, -0x120(%rbp)
movq -0x70(%rbp), %rsi
movq -0x110(%rbp), %rdx
movq -0x118(%rbp), %xmm0
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd -0x120(%rbp), %xmm1
leaq -0x140(%rbp), %rdi
callq 0xa0a0
jmp 0x2eec
movq -0x150(%rbp), %rdi
leaq -0x140(%rbp), %rsi
callq 0xa070
jmp 0x2f01
jmp 0x2f5f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x301d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x91(%rbp), %rdi
callq 0x9e90
jmp 0x301d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x2fe0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0xa110
jmp 0x2fe0
jmp 0x2f61
jmp 0x2f63
leaq -0x100(%rbp), %rdi
callq 0xa0f0
jmp 0x2dad
jmp 0x2ceb
movq -0x150(%rbp), %rdi
callq 0x9f50
cmpq -0x68(%rbp), %rax
je 0x2fb7
movl $0x8, %edi
callq 0x2080
movq %rax, %rdi
leaq 0x1b0f2(%rip), %rax     # 0x1e091
movq %rax, (%rdi)
movq 0x2b017(%rip), %rsi     # 0x2dfc0
xorl %eax, %eax
movl %eax, %edx
callq 0x2290
jmp 0x303b
leaq -0xe8(%rbp), %rdi
callq 0xa110
leaq -0x88(%rbp), %rdi
callq 0xa130
movq -0x70(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x70(%rbp)
jmp 0x2c33
leaq -0x88(%rbp), %rdi
callq 0xa130
jmp 0x301d
movb $0x1, -0x49(%rbp)
testb $0x1, -0x49(%rbp)
jne 0x3004
movq -0x150(%rbp), %rdi
callq 0xa190
leaq -0x40(%rbp), %rdi
callq 0x9c10
movq -0x148(%rbp), %rax
addq $0x180, %rsp            # imm = 0x180
popq %rbp
retq
movq -0x150(%rbp), %rdi
callq 0xa190
leaq -0x40(%rbp), %rdi
callq 0x9c10
movq -0x58(%rbp), %rdi
callq 0x22a0
nopl (%rax,%rax)