// File: derekzwy[P]an-optimal-tcam-encoding-algorithm-for-packet-classification/cps-tss.cc
// Function: tuples_num(std::vector<pc_rule*, std::allocator<pc_rule*>>&)
void tuples_num(vector<pc_rule*> &pc) 
{ 
    array<int, MAXDIMENSIONS> tuple;
    map<array<int, MAXDIMENSIONS>, int> tuple_map;


    for(auto rule = pc.begin(); rule != pc.end(); rule++) {
        for(int i = 0; i< MAXDIMENSIONS; i++) {
            int prefixlen;
            if(i == 0 || i == 1) 
                prefixlen = 32 - __builtin_popcount((*rule)->field[i].high - (*rule)->field[i].low);
            if(i == 2 || i == 3)
                prefixlen = 16 - __builtin_popcount((*rule)->field[i].high - (*rule)->field[i].low);
            if( i == 4) 
                prefixlen = 8 - __builtin_popcount((*rule)->field[i].high - (*rule)->field[i].low);
            tuple[i] = prefixlen;
        }

        tuple_map[tuple] ++;
    }

    cout <<"tuple numbers: "<< tuple_map.size()<< endl;

    /*for(auto tuple_pair = tuple_map.begin(); tuple_pair != tuple_map.end(); tuple_pair ++) {
        for_each(tuple_pair->first.begin(), tuple_pair->first.end(), [](int i ){cout<<i<<" ";});
        cout<< "  " << tuple_pair->second<<endl;
    }*/
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x3440
movq -0x8(%rbp), %rdi
callq 0x3460
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rdi
callq 0x34d0
movq %rax, -0x60(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x3490
testb $0x1, %al
jne 0x27f8
jmp 0x2a52
movl $0x0, -0x64(%rbp)
cmpl $0x5, -0x64(%rbp)
jge 0x2a03
cmpl $0x0, -0x64(%rbp)
je 0x2819
cmpl $0x1, -0x64(%rbp)
jne 0x28a5
leaq -0x58(%rbp), %rdi
callq 0x3500
movq (%rax), %rax
addq $0x8, %rax
movslq -0x64(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0x88(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x3500
movq %rax, %rcx
movq -0x88(%rbp), %rax
movq (%rcx), %rcx
addq $0x8, %rcx
movslq -0x64(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
subq (%rcx), %rax
movl %eax, %ecx
movl %ecx, %eax
shrl %eax
andl $0x55555555, %eax       # imm = 0x55555555
subl %eax, %ecx
movl %ecx, %eax
andl $0x33333333, %eax       # imm = 0x33333333
shrl $0x2, %ecx
andl $0x33333333, %ecx       # imm = 0x33333333
addl %ecx, %eax
movl %eax, %ecx
shrl $0x4, %ecx
addl %ecx, %eax
andl $0xf0f0f0f, %eax        # imm = 0xF0F0F0F
imull $0x1010101, %eax, %ecx  # imm = 0x1010101
shrl $0x18, %ecx
movl $0x20, %eax
subl %ecx, %eax
movl %eax, -0x68(%rbp)
cmpl $0x2, -0x64(%rbp)
je 0x28b5
cmpl $0x3, -0x64(%rbp)
jne 0x2941
leaq -0x58(%rbp), %rdi
callq 0x3500
movq (%rax), %rax
addq $0x8, %rax
movslq -0x64(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0x90(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x3500
movq %rax, %rcx
movq -0x90(%rbp), %rax
movq (%rcx), %rcx
addq $0x8, %rcx
movslq -0x64(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
subq (%rcx), %rax
movl %eax, %ecx
movl %ecx, %eax
shrl %eax
andl $0x55555555, %eax       # imm = 0x55555555
subl %eax, %ecx
movl %ecx, %eax
andl $0x33333333, %eax       # imm = 0x33333333
shrl $0x2, %ecx
andl $0x33333333, %ecx       # imm = 0x33333333
addl %ecx, %eax
movl %eax, %ecx
shrl $0x4, %ecx
addl %ecx, %eax
andl $0xf0f0f0f, %eax        # imm = 0xF0F0F0F
imull $0x1010101, %eax, %ecx  # imm = 0x1010101
shrl $0x18, %ecx
movl $0x10, %eax
subl %ecx, %eax
movl %eax, -0x68(%rbp)
cmpl $0x4, -0x64(%rbp)
jne 0x29d7
leaq -0x58(%rbp), %rdi
callq 0x3500
movq (%rax), %rax
addq $0x8, %rax
movslq -0x64(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0x98(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x3500
movq %rax, %rcx
movq -0x98(%rbp), %rax
movq (%rcx), %rcx
addq $0x8, %rcx
movslq -0x64(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
subq (%rcx), %rax
movl %eax, %ecx
movl %ecx, %eax
shrl %eax
andl $0x55555555, %eax       # imm = 0x55555555
subl %eax, %ecx
movl %ecx, %eax
andl $0x33333333, %eax       # imm = 0x33333333
shrl $0x2, %ecx
andl $0x33333333, %ecx       # imm = 0x33333333
addl %ecx, %eax
movl %eax, %ecx
shrl $0x4, %ecx
addl %ecx, %eax
andl $0xf0f0f0f, %eax        # imm = 0xF0F0F0F
imull $0x1010101, %eax, %ecx  # imm = 0x1010101
shrl $0x18, %ecx
movl $0x8, %eax
subl %ecx, %eax
movl %eax, -0x68(%rbp)
movl -0x68(%rbp), %eax
movl %eax, -0x9c(%rbp)
movslq -0x64(%rbp), %rsi
leaq -0x1c(%rbp), %rdi
callq 0x3520
movl -0x9c(%rbp), %ecx
movl %ecx, (%rax)
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x27ff
leaq -0x50(%rbp), %rdi
leaq -0x1c(%rbp), %rsi
callq 0x3550
movq %rax, -0xa8(%rbp)
jmp 0x2a19
movq -0xa8(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
leaq -0x58(%rbp), %rdi
xorl %esi, %esi
callq 0x3630
movq %rax, -0x80(%rbp)
jmp 0x27d5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x3690
jmp 0x2ab6
movq 0xf57f(%rip), %rdi      # 0x11fd8
leaq 0xa5ec(%rip), %rsi      # 0xd04c
callq 0x2110
movq %rax, -0xb0(%rbp)
jmp 0x2a6e
leaq -0x50(%rbp), %rdi
callq 0x3670
movq -0xb0(%rbp), %rdi
movq %rax, %rsi
callq 0x2060
movq %rax, -0xb8(%rbp)
jmp 0x2a8f
movq -0xb8(%rbp), %rdi
movq 0xf523(%rip), %rsi      # 0x11fc0
callq 0x2150
jmp 0x2aa4
leaq -0x50(%rbp), %rdi
callq 0x3690
addq $0xc0, %rsp
popq %rbp
retq
movq -0x70(%rbp), %rdi
callq 0x2220
nop