// File: /workspace/github_cpp_makefile_star2_O2/robertomaldonado[P]HypercubeTopologyRouting/links.cpp
// Function: main
int main(int argc, char * argv[]){
    //Check arguments for right input
    if ( !isArgCountCorrect ( argc ) ) return 1;
    total_nodes = std::stoi(argv[1]);
    if ( !isPowerOfTwo(total_nodes) ) return 1;
    string routing_model = argv[2];
    if ( !isValidOption(routing_model) ) return 1;
    bits_for_node = log2(total_nodes);

    //Create a vector to hold a binary representation
    map<int, vector<int> > nodes_map;
    create_map( nodes_map );
    printf("%s", map_to_bin_str( nodes_map, total_nodes).c_str() );

    //TO-DO: Get source and destination from the console*/
    int source = 1, destination = 30, path = 10;

    if( routing_model == "dim" ){

        // int len = dim_order_routing(source, destination, &path );
        printf("Dimensional order routing\n");
        while(1){
            printf("input src dst : ");
            cin >> source; cin >> destination; 

            int bits_to_change =  source^destination;

            vector<bool> vector_src = int_to_bin_vector( bits_for_node, source);
            vector<bool> xor_guide = int_to_bin_vector( bits_for_node, bits_to_change);
            vector<int> dim_ord_route;
            int current;
            dim_ord_route.push_back( source );

            for(int i = 0 ; i < xor_guide.size() ; i++){
                if(xor_guide[i]) {
                    vector_src[i] = !vector_src[i];
                    current = bin_vector_to_int( bits_for_node, vector_src);
                    dim_ord_route.push_back( current );
                }
            }
            printf("path from %d to %d: ", source, destination);
            print_single_route(bits_for_node, dim_ord_route);
        
            if( (source > (total_nodes - 1)) ||  (destination > (total_nodes - 1)) ){
                printf( "dim_order_routing: src %d, dst %d, out of bound 0..%d",
                source, destination, total_nodes);
                return 1;
            }
        }

    }else if(routing_model == "all"){

        // int allpath[MAX_PATH][MAXZ_PATH_LEN];
        // int allpath_routing(source, destination, allpath);
        printf("All shortest path routing\n");

        while(1){
            printf("input src dst : ");
            cin >> source; cin >> destination;  

            //XOR to get a get a guide on which bits need to be changed
            int bits_to_change =  source^destination;
            //Convert source and guide to vector of bits
            vector<bool> vector_src = int_to_bin_vector( bits_for_node, source);
            vector<bool> vector_dst = int_to_bin_vector( bits_for_node, destination);
            vector<bool> xor_guide = int_to_bin_vector( bits_for_node, bits_to_change);
            vector<int> all_ord_route;
            //The structure of neighbors is hold in a map.
            //To store here the path for each route found.
            map<int, vector<int> > paths_map;

            int current;
            //The source is the first node
            all_ord_route.push_back( source );
            //For each  bit changed on on the guide, flip the bit
            recursive_flip(vector_src, vector_dst, xor_guide);

            paths_map[ 0 ] = all_ord_route;
            paths_map[ 1 ] = all_ord_route;

            map<int, vector<int> >::iterator it = paths_map.begin();
            int counter = 0;
            for (int i = 0; i < xor_guide.size(); i++ )
                if( xor_guide[i] )
                    counter++;

            printf("%d shortest paths from %d to %d: \n", factorial(counter), source, destination);
            print_multiple_routes(paths_map);

            if( (source > (total_nodes - 1)) ||  (destination > (total_nodes - 1)) ){
                printf( "dim_order_routing: src %d, dst %d, out of bound 0..%d",
                source, destination, total_nodes);
                return 1;
            }
        }
    }
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1e8, %rsp            # imm = 0x1E8
movq %rsi, %rbx
callq 0x3dc0
pushq $0x1
popq %r14
testl %eax, %eax
je 0x29ec
movq 0x8(%rbx), %rsi
leaq -0x100(%rbp), %rdi
leaq -0xb8(%rbp), %rdx
callq 0x20a0
leaq -0x100(%rbp), %rdi
pushq $0xa
popq %rdx
xorl %esi, %esi
callq 0x30f8
movl %eax, 0x5cee(%rip)      # 0x8170
leaq -0x100(%rbp), %rdi
callq 0x20c0
movl 0x5cdc(%rip), %edi      # 0x8170
callq 0x3dec
testl %eax, %eax
je 0x29ec
movq 0x10(%rbx), %rsi
leaq -0x120(%rbp), %rdi
leaq -0x100(%rbp), %rdx
callq 0x20a0
leaq -0x168(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x21b0
leaq -0x168(%rbp), %rdi
callq 0x3e45
movl %eax, %ebx
leaq -0x168(%rbp), %rdi
callq 0x20c0
testl %ebx, %ebx
je 0x29e0
movl 0x5c7d(%rip), %edi      # 0x8170
callq 0x3119
cvttsd2si %xmm0, %eax
movl %eax, 0x5c72(%rip)      # 0x8174
leaq -0xf8(%rbp), %rax
andl $0x0, (%rax)
andq $0x0, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
andq $0x0, 0x20(%rax)
leaq -0x100(%rbp), %rdi
callq 0x2b2b
movl 0x5c40(%rip), %edx      # 0x8170
leaq -0xb8(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0x3e9c
leaq -0xb8(%rbp), %rbx
movq (%rbx), %rsi
leaq 0x2acc(%rip), %rdi      # 0x5020
xorl %eax, %eax
callq 0x2040
movq %rbx, %rdi
callq 0x20c0
movl $0x1, -0x2c(%rbp)
movl $0x1e, -0x30(%rbp)
leaq 0x2aab(%rip), %rsi      # 0x5023
leaq -0x120(%rbp), %rdi
callq 0x3127
testb %al, %al
je 0x274f
leaq 0x2b8c(%rip), %rdi      # 0x511f
callq 0x2200
movq 0x5a41(%rip), %rbx      # 0x7fe0
leaq -0xb8(%rbp), %r13
leaq -0x208(%rbp), %r14
movl $0x0, -0x34(%rbp)
leaq 0x2a6c(%rip), %rdi      # 0x5027
xorl %eax, %eax
callq 0x2040
movq %rbx, %rdi
leaq -0x2c(%rbp), %rsi
callq 0x2100
movq %rbx, %rdi
leaq -0x30(%rbp), %rsi
callq 0x2100
movl -0x2c(%rbp), %r12d
movl -0x30(%rbp), %r15d
movl 0x5b8c(%rip), %esi      # 0x8174
movq %r13, %rdi
movl %r12d, %edx
callq 0x4207
xorl %r12d, %r15d
movl 0x5b78(%rip), %esi      # 0x8174
leaq -0x88(%rbp), %rdi
movl %r15d, %edx
callq 0x4207
xorpd %xmm0, %xmm0
movapd %xmm0, -0x60(%rbp)
andq $0x0, -0x50(%rbp)
leaq -0x60(%rbp), %rdi
leaq -0x2c(%rbp), %rsi
callq 0x3138
xorl %r15d, %r15d
movq -0x78(%rbp), %rax
movl -0x70(%rbp), %ecx
subq -0x88(%rbp), %rax
leaq (%rcx,%rax,8), %rax
cmpq %r15, %rax
jbe 0x26ca
leaq -0x88(%rbp), %rdi
movq %r15, %rsi
callq 0x315e
testq %rdx, (%rax)
je 0x26c2
movq %r13, %rdi
movq %r15, %rsi
callq 0x315e
movq %rdx, %r12
movq (%rax), %rbx
movq %r13, %rdi
movq %r15, %rsi
callq 0x315e
testq %r12, %rbx
je 0x2681
notq %rdx
andq (%rax), %rdx
jmp 0x2684
orq (%rax), %rdx
movq %rdx, (%rax)
movl 0x5ae6(%rip), %r12d     # 0x8174
movq %r14, %rdi
movq %r13, %rsi
callq 0x3180
movl %r12d, %edi
movq %r14, %rsi
callq 0x418c
movl %eax, -0x148(%rbp)
movq %r14, %rdi
callq 0x31fe
leaq -0x60(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0x3138
incq %r15
jmp 0x2629
movl -0x2c(%rbp), %esi
movl -0x30(%rbp), %edx
leaq 0x2961(%rip), %rdi      # 0x5038
xorl %eax, %eax
callq 0x2040
movl 0x5a90(%rip), %edi      # 0x8174
leaq -0x60(%rbp), %rsi
callq 0x2cc4
movl -0x2c(%rbp), %esi
movl 0x5a7a(%rip), %ecx      # 0x8170
cmpl %ecx, %esi
setl %al
movl -0x30(%rbp), %edx
cmpl %ecx, %edx
setl %r15b
andb %al, %r15b
jne 0x271d
leaq 0x293d(%rip), %rdi      # 0x504d
xorl %eax, %eax
callq 0x2040
pushq $0x1
popq %rax
movl %eax, -0x34(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x35fc
leaq -0x88(%rbp), %rdi
callq 0x31fe
movq %r13, %rdi
callq 0x31fe
testb %r15b, %r15b
movq 0x589c(%rip), %rbx      # 0x7fe0
jne 0x25b4
jmp 0x29d0
movl $0x0, -0x34(%rbp)
leaq 0x2926(%rip), %rsi      # 0x5083
leaq -0x120(%rbp), %rdi
callq 0x3127
testb %al, %al
je 0x29d0
leaq 0x298d(%rip), %rdi      # 0x5105
callq 0x2200
movq 0x585c(%rip), %r13      # 0x7fe0
leaq -0x2c(%rbp), %r12
leaq -0x148(%rbp), %r15
leaq -0x190(%rbp), %rbx
movl $0x0, -0x34(%rbp)
leaq 0x2883(%rip), %rdi      # 0x5027
xorl %eax, %eax
callq 0x2040
movq %r13, %rdi
movq %r12, %rsi
callq 0x2100
movq %r13, %rdi
leaq -0x30(%rbp), %rsi
callq 0x2100
movl -0x2c(%rbp), %edx
movl -0x30(%rbp), %r14d
xorl %edx, %r14d
movl 0x59a2(%rip), %esi      # 0x8174
leaq -0x88(%rbp), %rdi
callq 0x4207
movl 0x5990(%rip), %esi      # 0x8174
movl -0x30(%rbp), %edx
leaq -0x60(%rbp), %rdi
callq 0x4207
movl 0x597e(%rip), %esi      # 0x8174
movq %r15, %rdi
movl %r14d, %edx
callq 0x4207
andq $0x0, -0xc0(%rbp)
xorpd %xmm0, %xmm0
movapd %xmm0, -0xd0(%rbp)
andl $0x0, -0xb0(%rbp)
andq $0x0, -0xa8(%rbp)
leaq -0xb0(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq %rax, -0x98(%rbp)
andq $0x0, -0x90(%rbp)
leaq -0xd0(%rbp), %r14
movq %r14, %rdi
movq %r12, %rsi
callq 0x3138
movq %rbx, %rdi
leaq -0x88(%rbp), %rsi
callq 0x3180
leaq -0x1e0(%rbp), %r12
movq %r12, %rdi
leaq -0x60(%rbp), %rsi
callq 0x3180
leaq -0x1b8(%rbp), %r13
movq %r13, %rdi
movq %r15, %rsi
callq 0x3180
movq %rbx, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0x2d56
movq %r13, %rdi
callq 0x31fe
movq %r12, %rdi
callq 0x31fe
movq %rbx, %rdi
callq 0x31fe
andl $0x0, -0x38(%rbp)
leaq -0xb8(%rbp), %rbx
movq %rbx, %rdi
leaq -0x38(%rbp), %rsi
callq 0x3212
movq %rax, %rdi
movq %r14, %rsi
callq 0x3264
movq 0x570a(%rip), %r12      # 0x7fe0
movl $0x1, -0x38(%rbp)
movq %rbx, %rdi
leaq -0x38(%rbp), %rsi
callq 0x3212
movq %rax, %rdi
movq %r14, %rsi
callq 0x3264
xorl %r14d, %r14d
xorl %r13d, %r13d
movq -0x138(%rbp), %rax
movl -0x130(%rbp), %ecx
subq -0x148(%rbp), %rax
leaq (%rcx,%rax,8), %rax
cmpq %r14, %rax
jbe 0x2932
movq %r15, %rdi
movq %r14, %rsi
callq 0x315e
andq (%rax), %rdx
cmpq $0x1, %rdx
sbbl $-0x1, %r13d
incq %r14
jmp 0x28fa
movl %r13d, %edi
callq 0x3071
movl -0x2c(%rbp), %edx
movl -0x30(%rbp), %ecx
leaq 0x2740(%rip), %rdi      # 0x5087
movl %eax, %esi
xorl %eax, %eax
callq 0x2040
movq %rbx, %rdi
callq 0x3087
movl -0x2c(%rbp), %esi
movl 0x580f(%rip), %ecx      # 0x8170
cmpl %ecx, %esi
setl %al
movl -0x30(%rbp), %edx
cmpl %ecx, %edx
setl %r14b
andb %al, %r14b
movq %r12, %r13
jne 0x298b
leaq 0x26cf(%rip), %rdi      # 0x504d
xorl %eax, %eax
callq 0x2040
pushq $0x1
popq %rax
movl %eax, -0x34(%rbp)
movq %rbx, %rdi
callq 0x3550
leaq -0xd0(%rbp), %rdi
callq 0x35fc
movq %r15, %rdi
callq 0x31fe
leaq -0x60(%rbp), %rdi
callq 0x31fe
leaq -0x88(%rbp), %rdi
callq 0x31fe
testb %r14b, %r14b
leaq -0x2c(%rbp), %r12
leaq -0x190(%rbp), %rbx
jne 0x279d
leaq -0x100(%rbp), %rdi
callq 0x3550
movl -0x34(%rbp), %r14d
leaq -0x120(%rbp), %rdi
callq 0x20c0
movl %r14d, %eax
addq $0x1e8, %rsp            # imm = 0x1E8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2a92
jmp 0x2a92
movq %rax, %rbx
leaq -0x168(%rbp), %rdi
callq 0x20c0
jmp 0x2b17
movq %rax, %rbx
jmp 0x2b17
jmp 0x2a38
movq %rax, %rbx
leaq -0x100(%rbp), %rdi
jmp 0x2b1e
movq %rax, %rbx
jmp 0x2b23
jmp 0x2a97
jmp 0x2a92
movq %rax, %rbx
jmp 0x2ac7
movq %rax, %rbx
jmp 0x2abe
movq %rax, %rbx
jmp 0x2a73
movq %rax, %rbx
jmp 0x2a67
movq %rax, %rbx
leaq -0x1b8(%rbp), %rdi
callq 0x31fe
leaq -0x1e0(%rbp), %rdi
callq 0x31fe
leaq -0x190(%rbp), %rdi
callq 0x31fe
jmp 0x2a9a
jmp 0x2a92
movq %rax, %rbx
jmp 0x2aff
jmp 0x2a97
jmp 0x2a97
jmp 0x2a92
jmp 0x2a97
jmp 0x2ae7
movq %rax, %rbx
jmp 0x2b0b
movq %rax, %rbx
leaq -0xb8(%rbp), %rdi
callq 0x3550
leaq -0xd0(%rbp), %rdi
callq 0x35fc
leaq -0x148(%rbp), %rdi
callq 0x31fe
leaq -0x60(%rbp), %rdi
callq 0x31fe
leaq -0x88(%rbp), %rdi
jmp 0x2b06
jmp 0x2ae7
movq %rax, %rbx
leaq -0x208(%rbp), %rdi
callq 0x31fe
jmp 0x2aea
jmp 0x2ae7
jmp 0x2ae7
movq %rax, %rbx
leaq -0x60(%rbp), %rdi
callq 0x35fc
leaq -0x88(%rbp), %rdi
callq 0x31fe
leaq -0xb8(%rbp), %rdi
callq 0x31fe
leaq -0x100(%rbp), %rdi
callq 0x3550
leaq -0x120(%rbp), %rdi
callq 0x20c0
movq %rbx, %rdi
callq 0x2250