// File: 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
subq $0x400, %rsp            # imm = 0x400
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl -0x8(%rbp), %edi
callq 0x8610
cmpl $0x0, %eax
jne 0x24d2
movl $0x1, -0x4(%rbp)
jmp 0x2ff8
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x340(%rbp)
leaq -0x31(%rbp), %rdi
movq %rdi, -0x338(%rbp)
callq 0x22a0
movq -0x340(%rbp), %rsi
movq -0x338(%rbp), %rdx
leaq -0x30(%rbp), %rdi
callq 0x2200
jmp 0x250a
xorl %eax, %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
movl $0xa, %edx
callq 0x3980
movl %eax, -0x344(%rbp)
jmp 0x2524
movl -0x344(%rbp), %eax
movl %eax, 0xdc68(%rip)      # 0x10198
leaq -0x30(%rbp), %rdi
callq 0x2120
leaq -0x31(%rbp), %rdi
callq 0x21e0
movl 0xdc50(%rip), %edi      # 0x10198
callq 0x8660
cmpl $0x0, %eax
jne 0x258f
movl $0x1, -0x4(%rbp)
jmp 0x2ff8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2581
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x2120
leaq -0x31(%rbp), %rdi
callq 0x21e0
jmp 0x3004
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x358(%rbp)
leaq -0x69(%rbp), %rdi
movq %rdi, -0x350(%rbp)
callq 0x22a0
movq -0x358(%rbp), %rsi
movq -0x350(%rbp), %rdx
leaq -0x68(%rbp), %rdi
callq 0x2200
jmp 0x25c7
leaq -0x69(%rbp), %rdi
callq 0x21e0
leaq -0x90(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x20c0
jmp 0x25e2
leaq -0x90(%rbp), %rdi
callq 0x86e0
movl %eax, -0x35c(%rbp)
jmp 0x25f6
movl -0x35c(%rbp), %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
movb %al, -0x35d(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x2120
movb -0x35d(%rbp), %al
testb $0x1, %al
jne 0x2622
jmp 0x2680
movl $0x1, -0x4(%rbp)
movl $0x1, -0x94(%rbp)
jmp 0x2fe2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x69(%rbp), %rdi
callq 0x21e0
jmp 0x3004
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2fed
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x2120
jmp 0x2fed
movl 0xdb12(%rip), %edi      # 0x10198
callq 0x39c0
movsd %xmm0, -0x368(%rbp)
jmp 0x2695
movsd -0x368(%rbp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xdaf5(%rip)      # 0x1019c
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x370(%rbp)
callq 0x39e0
movq -0x370(%rbp), %rdi
callq 0x3010
jmp 0x26c8
movl 0xdaca(%rip), %edx      # 0x10198
leaq -0xe8(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x8760
jmp 0x26e3
leaq -0xe8(%rbp), %rdi
callq 0x20b0
movq %rax, %rsi
leaq 0x890b(%rip), %rdi      # 0xb004
xorl %eax, %eax
callq 0x2040
jmp 0x2702
leaq -0xe8(%rbp), %rdi
callq 0x2120
movl $0x1, -0xec(%rbp)
movl $0x1e, -0xf0(%rbp)
movl $0xa, -0xf4(%rbp)
leaq 0x88d4(%rip), %rsi      # 0xb007
leaq -0x68(%rbp), %rdi
callq 0x3a00
movb %al, -0x371(%rbp)
jmp 0x2744
movb -0x371(%rbp), %al
testb $0x1, %al
jne 0x2753
jmp 0x2b2a
leaq 0x88b1(%rip), %rdi      # 0xb00b
xorl %eax, %eax
callq 0x2040
jmp 0x2763
jmp 0x2765
jmp 0x2767
leaq 0x88b8(%rip), %rdi      # 0xb026
xorl %eax, %eax
callq 0x2040
jmp 0x2777
movq 0xd862(%rip), %rdi      # 0xffe0
leaq -0xec(%rbp), %rsi
callq 0x2110
jmp 0x278c
movq 0xd84d(%rip), %rdi      # 0xffe0
leaq -0xf0(%rbp), %rsi
callq 0x2110
jmp 0x27a1
movl -0xec(%rbp), %eax
movl -0xf0(%rbp), %ecx
xorl %ecx, %eax
movl %eax, -0xf8(%rbp)
movl 0xd9e1(%rip), %esi      # 0x1019c
movl -0xec(%rbp), %edx
leaq -0x120(%rbp), %rdi
callq 0x8de0
jmp 0x27cf
movl 0xd9c7(%rip), %esi      # 0x1019c
movl -0xf8(%rbp), %edx
leaq -0x148(%rbp), %rdi
callq 0x8de0
jmp 0x27e9
leaq -0x160(%rbp), %rdi
movq %rdi, -0x380(%rbp)
callq 0x3a30
movq -0x380(%rbp), %rdi
leaq -0xec(%rbp), %rsi
callq 0x3a50
jmp 0x2811
movl $0x0, -0x168(%rbp)
movslq -0x168(%rbp), %rax
movq %rax, -0x388(%rbp)
leaq -0x148(%rbp), %rdi
callq 0x3ac0
movq %rax, %rcx
movq -0x388(%rbp), %rax
cmpq %rcx, %rax
jae 0x2a33
movslq -0x168(%rbp), %rsi
leaq -0x148(%rbp), %rdi
callq 0x3b40
movq %rdx, -0x398(%rbp)
movq %rax, -0x390(%rbp)
jmp 0x286b
movq -0x398(%rbp), %rax
movq -0x390(%rbp), %rcx
movq %rcx, -0x178(%rbp)
movq %rax, -0x170(%rbp)
leaq -0x178(%rbp), %rdi
callq 0x3ba0
testb $0x1, %al
jne 0x289c
jmp 0x2a1d
movslq -0x168(%rbp), %rsi
leaq -0x120(%rbp), %rdi
callq 0x3b40
movq %rdx, -0x3a8(%rbp)
movq %rax, -0x3a0(%rbp)
jmp 0x28bf
movq -0x3a8(%rbp), %rax
movq -0x3a0(%rbp), %rcx
movq %rcx, -0x188(%rbp)
movq %rax, -0x180(%rbp)
leaq -0x188(%rbp), %rdi
callq 0x3ba0
xorb $0x1, %al
movb %al, -0x3b9(%rbp)
movslq -0x168(%rbp), %rsi
leaq -0x120(%rbp), %rdi
callq 0x3b40
movq %rdx, -0x3b8(%rbp)
movq %rax, -0x3b0(%rbp)
jmp 0x2912
movb -0x3b9(%rbp), %al
movq -0x3b8(%rbp), %rcx
movq -0x3b0(%rbp), %rdx
movq %rdx, -0x198(%rbp)
movq %rcx, -0x190(%rbp)
movzbl %al, %esi
andl $0x1, %esi
leaq -0x198(%rbp), %rdi
callq 0x3bd0
movl 0xd850(%rip), %eax      # 0x1019c
movl %eax, -0x3c0(%rbp)
leaq -0x1c0(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x3c20
jmp 0x2967
movl -0x3c0(%rbp), %edi
leaq -0x1c0(%rbp), %rsi
callq 0x8d30
movl %eax, -0x3c4(%rbp)
jmp 0x2981
movl -0x3c4(%rbp), %eax
movl %eax, -0x164(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x3db0
leaq -0x160(%rbp), %rdi
leaq -0x164(%rbp), %rsi
callq 0x3a50
jmp 0x29ae
jmp 0x2a1d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2fd4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x2120
jmp 0x2fd4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2b19
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2b01
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x3db0
jmp 0x2b01
jmp 0x2a1f
movl -0x168(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x168(%rbp)
jmp 0x281b
movl -0xec(%rbp), %esi
movl -0xf0(%rbp), %edx
leaq 0x85f1(%rip), %rdi      # 0xb037
xorl %eax, %eax
callq 0x2040
jmp 0x2a4f
movl 0xd747(%rip), %edi      # 0x1019c
leaq -0x160(%rbp), %rsi
callq 0x3210
jmp 0x2a63
movl -0xec(%rbp), %eax
movl 0xd729(%rip), %ecx      # 0x10198
subl $0x1, %ecx
cmpl %ecx, %eax
jg 0x2a89
movl -0xf0(%rbp), %eax
movl 0xd716(%rip), %ecx      # 0x10198
subl $0x1, %ecx
cmpl %ecx, %eax
jle 0x2abe
movl -0xec(%rbp), %esi
movl -0xf0(%rbp), %edx
movl 0xd6fd(%rip), %ecx      # 0x10198
leaq 0x85aa(%rip), %rdi      # 0xb04c
xorl %eax, %eax
callq 0x2040
jmp 0x2aab
movl $0x1, -0x4(%rbp)
movl $0x1, -0x94(%rbp)
jmp 0x2ac8
movl $0x0, -0x94(%rbp)
leaq -0x160(%rbp), %rdi
callq 0x3dd0
leaq -0x148(%rbp), %rdi
callq 0x3db0
leaq -0x120(%rbp), %rdi
callq 0x3db0
movl -0x94(%rbp), %eax
testl %eax, %eax
jne 0x2fc6
jmp 0x2afc
jmp 0x2765
leaq -0x160(%rbp), %rdi
callq 0x3dd0
leaq -0x148(%rbp), %rdi
callq 0x3db0
leaq -0x120(%rbp), %rdi
callq 0x3db0
jmp 0x2fd4
leaq 0x8551(%rip), %rsi      # 0xb082
leaq -0x68(%rbp), %rdi
callq 0x3a00
movb %al, -0x3c5(%rbp)
jmp 0x2b42
movb -0x3c5(%rbp), %al
testb $0x1, %al
jne 0x2b51
jmp 0x2fb3
leaq 0x852e(%rip), %rdi      # 0xb086
xorl %eax, %eax
callq 0x2040
jmp 0x2b61
jmp 0x2b63
jmp 0x2b65
leaq 0x84ba(%rip), %rdi      # 0xb026
xorl %eax, %eax
callq 0x2040
jmp 0x2b75
movq 0xd464(%rip), %rdi      # 0xffe0
leaq -0xec(%rbp), %rsi
callq 0x2110
jmp 0x2b8a
movq 0xd44f(%rip), %rdi      # 0xffe0
leaq -0xf0(%rbp), %rsi
callq 0x2110
jmp 0x2b9f
movl -0xec(%rbp), %eax
movl -0xf0(%rbp), %ecx
xorl %ecx, %eax
movl %eax, -0x1c4(%rbp)
movl 0xd5e3(%rip), %esi      # 0x1019c
movl -0xec(%rbp), %edx
leaq -0x1f0(%rbp), %rdi
callq 0x8de0
jmp 0x2bcd
movl 0xd5c9(%rip), %esi      # 0x1019c
movl -0xf0(%rbp), %edx
leaq -0x218(%rbp), %rdi
callq 0x8de0
jmp 0x2be7
movl 0xd5af(%rip), %esi      # 0x1019c
movl -0x1c4(%rbp), %edx
leaq -0x240(%rbp), %rdi
callq 0x8de0
jmp 0x2c01
leaq -0x258(%rbp), %rdi
movq %rdi, -0x3d0(%rbp)
callq 0x3a30
leaq -0x288(%rbp), %rdi
callq 0x39e0
movq -0x3d0(%rbp), %rdi
leaq -0xec(%rbp), %rsi
callq 0x3a50
jmp 0x2c35
leaq -0x2b8(%rbp), %rdi
leaq -0x1f0(%rbp), %rsi
callq 0x3c20
jmp 0x2c4a
leaq -0x2e0(%rbp), %rdi
leaq -0x218(%rbp), %rsi
callq 0x3c20
jmp 0x2c5f
leaq -0x308(%rbp), %rdi
leaq -0x240(%rbp), %rsi
callq 0x3c20
jmp 0x2c74
leaq -0x2b8(%rbp), %rdi
leaq -0x2e0(%rbp), %rsi
leaq -0x308(%rbp), %rdx
callq 0x3300
jmp 0x2c90
leaq -0x308(%rbp), %rdi
callq 0x3db0
leaq -0x2e0(%rbp), %rdi
callq 0x3db0
leaq -0x2b8(%rbp), %rdi
callq 0x3db0
movl $0x0, -0x30c(%rbp)
leaq -0x288(%rbp), %rdi
leaq -0x30c(%rbp), %rsi
callq 0x3e30
movq %rax, -0x3d8(%rbp)
jmp 0x2cda
movq -0x3d8(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0x3f10
jmp 0x2cef
movl $0x1, -0x310(%rbp)
leaq -0x288(%rbp), %rdi
leaq -0x310(%rbp), %rsi
callq 0x3e30
movq %rax, -0x3e0(%rbp)
jmp 0x2d15
movq -0x3e0(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0x3f10
jmp 0x2d2a
leaq -0x288(%rbp), %rdi
callq 0x4160
movq %rax, -0x318(%rbp)
movl $0x0, -0x31c(%rbp)
movl $0x0, -0x320(%rbp)
movslq -0x320(%rbp), %rax
movq %rax, -0x3e8(%rbp)
leaq -0x240(%rbp), %rdi
callq 0x3ac0
movq %rax, %rcx
movq -0x3e8(%rbp), %rax
cmpq %rcx, %rax
jae 0x2e80
movslq -0x320(%rbp), %rsi
leaq -0x240(%rbp), %rdi
callq 0x3b40
movq %rdx, -0x3f8(%rbp)
movq %rax, -0x3f0(%rbp)
jmp 0x2da1
movq -0x3f8(%rbp), %rax
movq -0x3f0(%rbp), %rcx
movq %rcx, -0x330(%rbp)
movq %rax, -0x328(%rbp)
leaq -0x330(%rbp), %rdi
callq 0x3ba0
testb $0x1, %al
jne 0x2dd2
jmp 0x2e6a
movl -0x31c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x31c(%rbp)
jmp 0x2e6a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2fa5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2f99
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2f75
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2e59
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x2e4d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x308(%rbp), %rdi
callq 0x3db0
leaq -0x2e0(%rbp), %rdi
callq 0x3db0
leaq -0x2b8(%rbp), %rdi
callq 0x3db0
jmp 0x2f75
jmp 0x2e6c
movl -0x320(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x320(%rbp)
jmp 0x2d51
movl -0x31c(%rbp), %edi
callq 0x38b0
movl %eax, -0x3fc(%rbp)
jmp 0x2e93
movl -0x3fc(%rbp), %esi
movl -0xec(%rbp), %edx
movl -0xf0(%rbp), %ecx
leaq 0x81f5(%rip), %rdi      # 0xb0a1
xorl %eax, %eax
callq 0x2040
jmp 0x2eb5
leaq -0x288(%rbp), %rdi
callq 0x38e0
jmp 0x2ec3
movl -0xec(%rbp), %eax
movl 0xd2c9(%rip), %ecx      # 0x10198
subl $0x1, %ecx
cmpl %ecx, %eax
jg 0x2ee9
movl -0xf0(%rbp), %eax
movl 0xd2b6(%rip), %ecx      # 0x10198
subl $0x1, %ecx
cmpl %ecx, %eax
jle 0x2f1e
movl -0xec(%rbp), %esi
movl -0xf0(%rbp), %edx
movl 0xd29d(%rip), %ecx      # 0x10198
leaq 0x814a(%rip), %rdi      # 0xb04c
xorl %eax, %eax
callq 0x2040
jmp 0x2f0b
movl $0x1, -0x4(%rbp)
movl $0x1, -0x94(%rbp)
jmp 0x2f28
movl $0x0, -0x94(%rbp)
leaq -0x288(%rbp), %rdi
callq 0x4190
leaq -0x258(%rbp), %rdi
callq 0x3dd0
leaq -0x240(%rbp), %rdi
callq 0x3db0
leaq -0x218(%rbp), %rdi
callq 0x3db0
leaq -0x1f0(%rbp), %rdi
callq 0x3db0
movl -0x94(%rbp), %eax
testl %eax, %eax
jne 0x2fc6
jmp 0x2f70
jmp 0x2b63
leaq -0x288(%rbp), %rdi
callq 0x4190
leaq -0x258(%rbp), %rdi
callq 0x3dd0
leaq -0x240(%rbp), %rdi
callq 0x3db0
leaq -0x218(%rbp), %rdi
callq 0x3db0
leaq -0x1f0(%rbp), %rdi
callq 0x3db0
jmp 0x2fd4
jmp 0x2fb5
movl $0x0, -0x4(%rbp)
movl $0x1, -0x94(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x4190
jmp 0x2fe2
leaq -0xc8(%rbp), %rdi
callq 0x4190
jmp 0x2fed
leaq -0x68(%rbp), %rdi
callq 0x2120
jmp 0x2ff8
leaq -0x68(%rbp), %rdi
callq 0x2120
jmp 0x3004
movl -0x4(%rbp), %eax
addq $0x400, %rsp            # imm = 0x400
popq %rbp
retq
movq -0x40(%rbp), %rdi
callq 0x2290
nopl (%rax)