// File: junhe[P]libpatterndetector/pattern.cpp
// Function: PatternUtil::findPattern(std::vector<long, std::allocator<long>>)
PatChain<PatternUnit> 
PatternUtil::findPattern( vector<off_t> deltas )
{
    // pointer(iterator) to the lookahead window, both should move together
//    mlog(IDX_WARN, "Entering %s", __FUNCTION__);
//    mlog(IDX_WARN, "deltas: %s", printVector(deltas).c_str());
    vector<off_t>::const_iterator p_lookahead_win;
    PatChain<PatternUnit> pattern_stack;

    p_lookahead_win = deltas.begin();
    pattern_stack.clear();

    while ( p_lookahead_win < deltas.end() ) {
        //lookahead window is not empty
//        mlog(IDX_WARN, "window position:%d", p_lookahead_win - deltas.begin());
        Tuple cur_tuple = searchNeighbor( deltas, p_lookahead_win );
        if ( cur_tuple.isRepeatingNeighbor() ) {
            if ( pattern_stack.isPopSafe( cur_tuple.length ) ) {
//                mlog(IDX_WARN, "SAFE" );
                //safe
                //pop out elements without breaking existing patterns
                pattern_stack.popElem( cur_tuple.length );

                vector<off_t>::const_iterator first, last;
                first = p_lookahead_win;
                last = p_lookahead_win + cur_tuple.length;

                PatternUnit pu;
                pu.seq.assign(first, last);
                pu.cnt = 2;

                pattern_stack.push( pu );
                p_lookahead_win += cur_tuple.length;
            } else {
                //unsafe
//                mlog(IDX_WARN, "UNSAFE" );
                PatternUnit pu = pattern_stack.top();

                if ( cur_tuple.length % pu.seq.size() == 0
                     && cur_tuple.length <= pu.seq.size() * pu.cnt ) {
//                    mlog(IDX_WARN, "-REPEATING LAST Pattern");
                    //the subseq in lookahead window repeats
                    //the top pattern in stack.
                    //initial remains the same.
                    pu.cnt += cur_tuple.length / pu.seq.size() ;
                    pattern_stack.popPattern();
                    pattern_stack.push(pu);

                    p_lookahead_win += cur_tuple.length;
                } else {
//                    mlog(IDX_WARN, "-Just Pust it in");
                    //cannot pop out cur_tuple.length elems without
                    //totally breaking any pattern.
                    //So we simply add one elem to the stack
                    PatternUnit pu;
                    pu.seq.push_back( *p_lookahead_win );
                    pu.cnt = 1;
                    pattern_stack.push(pu);
                    p_lookahead_win++;
                }
            }
        } else {
            //(0,0,x), nothing repeats
            PatternUnit pu;
            pu.seq.push_back(cur_tuple.next_symbol);
            pu.cnt = 1;

            pattern_stack.push(pu); 
            p_lookahead_win++;
        }
        pattern_stack.chain.back().compressRepeats();
//        mlog(IDX_WARN, "LOOP: %s", pattern_stack.show().c_str());
    }
   
//    mlog(IDX_WARN, "Leaving %s:%s", __FUNCTION__, pattern_stack.show().c_str());
    return pattern_stack;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x270, %rsp            # imm = 0x270
movq %rsi, -0x228(%rbp)
movq %rdi, -0x220(%rbp)
movq %rdi, %rax
movq %rax, -0x230(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x18(%rbp), %rdi
callq 0x6980
movq -0x220(%rbp), %rdi
movb $0x0, -0x19(%rbp)
callq 0x7390
movq -0x228(%rbp), %rdi
callq 0x69a0
movq %rax, -0x30(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x69d0
movq -0x220(%rbp), %rdi
movq -0x28(%rbp), %rax
movq %rax, -0x18(%rbp)
callq 0x7670
jmp 0x59c7
jmp 0x59c9
movq -0x228(%rbp), %rdi
callq 0x6a50
movq %rax, -0x48(%rbp)
leaq -0x18(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x7690
testb $0x1, %al
jne 0x59ef
jmp 0x5e9e
movq -0x228(%rbp), %rdi
movq -0x18(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rsi
callq 0x5ee0
movq %rdx, -0x240(%rbp)
movq %rax, -0x238(%rbp)
jmp 0x5a17
movq -0x240(%rbp), %rax
movq -0x238(%rbp), %rcx
movq %rcx, -0x58(%rbp)
movq %rax, -0x50(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x76d0
movb %al, -0x241(%rbp)
jmp 0x5a3e
movb -0x241(%rbp), %al
testb $0x1, %al
jne 0x5a4d
jmp 0x5dca
movq -0x220(%rbp), %rdi
movl -0x54(%rbp), %esi
callq 0x7700
movb %al, -0x242(%rbp)
jmp 0x5a64
movb -0x242(%rbp), %al
testb $0x1, %al
jne 0x5a73
jmp 0x5b9e
movq -0x220(%rbp), %rdi
movl -0x54(%rbp), %esi
callq 0x77c0
jmp 0x5a84
leaq -0x68(%rbp), %rdi
callq 0x6980
leaq -0x70(%rbp), %rdi
callq 0x6980
movq -0x18(%rbp), %rax
movq %rax, -0x68(%rbp)
movslq -0x54(%rbp), %rsi
leaq -0x18(%rbp), %rdi
callq 0x7890
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x70(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x7590
jmp 0x5ac5
leaq -0xa0(%rbp), %rdi
movq -0x68(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0xb0(%rbp), %rsi
movq -0xb8(%rbp), %rdx
callq 0x78d0
jmp 0x5af7
movq $0x2, -0x88(%rbp)
leaq -0xe8(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x7600
jmp 0x5b17
movq -0x220(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0x75d0
jmp 0x5b2c
leaq -0xe8(%rbp), %rdi
callq 0x2bf0
movslq -0x54(%rbp), %rsi
leaq -0x18(%rbp), %rdi
callq 0x7910
leaq -0xa8(%rbp), %rdi
callq 0x2bf0
jmp 0x5dc5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x5ec4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x5b8d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x2bf0
leaq -0xa8(%rbp), %rdi
callq 0x2bf0
jmp 0x5ec4
movq -0x220(%rbp), %rsi
leaq -0x118(%rbp), %rdi
callq 0x7930
jmp 0x5bb3
movslq -0x54(%rbp), %rax
movq %rax, -0x250(%rbp)
leaq -0x118(%rbp), %rdi
addq $0x8, %rdi
callq 0x6c70
movq %rax, %rcx
movq -0x250(%rbp), %rax
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
jne 0x5cdb
movslq -0x54(%rbp), %rax
movq %rax, -0x258(%rbp)
leaq -0x118(%rbp), %rdi
addq $0x8, %rdi
callq 0x6c70
movq %rax, %rcx
movq -0x258(%rbp), %rax
imulq -0xf8(%rbp), %rcx
cmpq %rcx, %rax
ja 0x5cdb
movslq -0x54(%rbp), %rax
movq %rax, -0x260(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x6c70
movq -0x220(%rbp), %rdi
movq %rax, %rcx
movq -0x260(%rbp), %rax
xorl %edx, %edx
divq %rcx
movq %rax, %rcx
movq -0xf8(%rbp), %rax
addq %rcx, %rax
movq %rax, -0xf8(%rbp)
callq 0x79b0
jmp 0x5c65
leaq -0x148(%rbp), %rdi
leaq -0x118(%rbp), %rsi
callq 0x7600
jmp 0x5c7a
movq -0x220(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0x75d0
jmp 0x5c8f
leaq -0x148(%rbp), %rdi
callq 0x2bf0
movslq -0x54(%rbp), %rsi
leaq -0x18(%rbp), %rdi
callq 0x7910
jmp 0x5da6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x5db4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x148(%rbp), %rdi
callq 0x2bf0
jmp 0x5db4
leaq -0x178(%rbp), %rdi
callq 0x7590
jmp 0x5ce9
leaq -0x170(%rbp), %rax
movq %rax, -0x268(%rbp)
leaq -0x18(%rbp), %rdi
callq 0x6a80
movq -0x268(%rbp), %rdi
movq %rax, %rsi
callq 0x6d70
jmp 0x5d11
movq $0x1, -0x158(%rbp)
leaq -0x1a8(%rbp), %rdi
leaq -0x178(%rbp), %rsi
callq 0x7600
jmp 0x5d31
movq -0x220(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x75d0
jmp 0x5d46
leaq -0x1a8(%rbp), %rdi
callq 0x2bf0
leaq -0x18(%rbp), %rdi
xorl %esi, %esi
callq 0x6aa0
movq %rax, -0x1b0(%rbp)
leaq -0x178(%rbp), %rdi
callq 0x2bf0
jmp 0x5da6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x5d98
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x1a8(%rbp), %rdi
callq 0x2bf0
leaq -0x178(%rbp), %rdi
callq 0x2bf0
jmp 0x5db4
leaq -0x118(%rbp), %rdi
callq 0x2bf0
jmp 0x5dc5
leaq -0x118(%rbp), %rdi
callq 0x2bf0
jmp 0x5ec4
jmp 0x5e7f
leaq -0x1e0(%rbp), %rdi
callq 0x7590
jmp 0x5dd8
leaq -0x1d8(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x6d70
jmp 0x5dea
movq $0x1, -0x1c0(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x1e0(%rbp), %rsi
callq 0x7600
jmp 0x5e0a
movq -0x220(%rbp), %rdi
leaq -0x210(%rbp), %rsi
callq 0x75d0
jmp 0x5e1f
leaq -0x210(%rbp), %rdi
callq 0x2bf0
leaq -0x18(%rbp), %rdi
xorl %esi, %esi
callq 0x6aa0
movq %rax, -0x218(%rbp)
leaq -0x1e0(%rbp), %rdi
callq 0x2bf0
jmp 0x5e7f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x5e71
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x210(%rbp), %rdi
callq 0x2bf0
leaq -0x1e0(%rbp), %rdi
callq 0x2bf0
jmp 0x5ec4
movq -0x220(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq %rax, %rdi
callq 0x49e0
jmp 0x5e99
jmp 0x59c9
movb $0x1, -0x19(%rbp)
testb $0x1, -0x19(%rbp)
jne 0x5eb4
movq -0x220(%rbp), %rdi
callq 0x2bd0
movq -0x230(%rbp), %rax
addq $0x270, %rsp            # imm = 0x270
popq %rbp
retq
movq -0x220(%rbp), %rdi
callq 0x2bd0
movq -0x38(%rbp), %rdi
callq 0x21a0
nopl (%rax)