// File: junhe[P]libpatterndetector/pattern.cpp
// Function: PatternUtil::getPatChainFromSeq(std::vector<long, std::allocator<long>>)
PatChain<PatternUnit>
PatternUtil::getPatChainFromSeq( vector<off_t> inits )
{
    //mlog(IDX_WARN, "Entering %s. inits: %s", 
    //     __FUNCTION__, printVector(inits).c_str());
    vector<off_t> deltas = buildDeltas(inits);
    PatChain<PatternUnit> pattern, patterntrim;

    pattern = findPattern( deltas ); // find repeating pattern in deltas

    // Put the init back into the patterns
    int pos = 0;
    vector<PatternUnit>::iterator it;
    for ( it = pattern.chain.begin() ;
          it != pattern.chain.end() ;
          it++ )
    {
        it->init = inits[pos];
        pos += it->seq.size() * it->cnt;
    }


    // handle the missing last
    if ( ! inits.empty() ) {
        if ( ! pattern.chain.empty() 
             && pattern.chain.back().seq.size() == 1 
             && pattern.chain.back().init + 
                pattern.chain.back().seq[0] * pattern.chain.back().cnt 
                 == inits.back() ) 
        {
            pattern.chain.back().cnt++;
        } else {        
            PatternUnit punit;
            punit.init = inits.back();
            punit.cnt = 1;
            pattern.push(punit);
        }
    }

    // combine the unecessary single patterns
    for ( it = pattern.chain.begin() ;
          it != pattern.chain.end() ;
          it++ )
    {
        ostringstream oss;
        oss << it->show() ;
//        mlog(IDX_WARN, "TRIM:%s", oss.str().c_str());
        
        if ( it != pattern.chain.begin()
             && it->cnt * it->seq.size() <= 1
             && patterntrim.chain.back().seq.size() == 1
             && patterntrim.chain.back().cnt > 1
             && patterntrim.chain.back().init
                + patterntrim.chain.back().seq[0]
                * patterntrim.chain.back().cnt == it->init
             ) 
        {
            // it can be represented by the last pattern.
//            mlog(IDX_WARN, "in back++");
            patterntrim.chain.back().cnt++;
        } else {
//            mlog(IDX_WARN, "in push");
            patterntrim.push(*it);
        }
    }
   
    
    /*
    ostringstream oss;
    oss << pattern.show() << endl; 
    mlog(IDX_WARN, "Leaving %s:{%s}", __FUNCTION__, oss.str().c_str());
    */

    return patterntrim;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x390, %rsp            # imm = 0x390
movq %rsi, -0x340(%rbp)
movq %rdi, -0x338(%rbp)
movq %rdi, %rax
movq %rax, -0x330(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x40(%rbp), %rdi
movq %rdi, -0x328(%rbp)
callq 0x6f90
movq -0x328(%rbp), %rsi
leaq -0x28(%rbp), %rdi
callq 0x4170
jmp 0x526d
leaq -0x40(%rbp), %rdi
callq 0x3220
leaq -0x70(%rbp), %rdi
callq 0x7390
jmp 0x5281
movq -0x338(%rbp), %rdi
movb $0x0, -0x71(%rbp)
callq 0x7390
jmp 0x5293
leaq -0xb0(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0x6f90
jmp 0x52a5
leaq -0x98(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x5950
jmp 0x52ba
leaq -0x70(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x72f0
leaq -0x98(%rbp), %rdi
callq 0x2bd0
leaq -0xb0(%rbp), %rdi
callq 0x3220
movl $0x0, -0xb4(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x73d0
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x3050
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0xc0(%rbp)
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x3100
movq %rax, -0xd0(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x73f0
testb $0x1, %al
jne 0x534a
jmp 0x5449
movq -0x340(%rbp), %rdi
movslq -0xb4(%rbp), %rsi
callq 0x6d30
movq (%rax), %rax
movq %rax, -0x350(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x7430
movq -0x350(%rbp), %rcx
movq %rcx, 0x28(%rax)
leaq -0xc0(%rbp), %rdi
callq 0x7430
movq %rax, %rdi
addq $0x8, %rdi
callq 0x6c70
movq %rax, -0x348(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x7430
movq -0x348(%rbp), %rcx
imulq 0x20(%rax), %rcx
movslq -0xb4(%rbp), %rax
addq %rcx, %rax
movl %eax, -0xb4(%rbp)
leaq -0xc0(%rbp), %rdi
xorl %esi, %esi
callq 0x7450
movq %rax, -0xd8(%rbp)
jmp 0x531a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x3220
jmp 0x5939
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x5930
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x5927
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x591b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x3220
jmp 0x591b
movq -0x340(%rbp), %rdi
callq 0x7490
testb $0x1, %al
jne 0x55e3
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x74d0
testb $0x1, %al
jne 0x553a
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq %rax, %rdi
addq $0x8, %rdi
callq 0x6c70
cmpq $0x1, %rax
jne 0x553a
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq 0x28(%rax), %rax
movq %rax, -0x360(%rbp)
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq %rax, %rdi
addq $0x8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x6d30
movq (%rax), %rax
movq %rax, -0x368(%rbp)
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq -0x368(%rbp), %rcx
movq -0x340(%rbp), %rdi
movq %rax, %rdx
movq -0x360(%rbp), %rax
imulq 0x20(%rdx), %rcx
addq %rcx, %rax
movq %rax, -0x358(%rbp)
callq 0x7550
movq %rax, %rcx
movq -0x358(%rbp), %rax
cmpq (%rcx), %rax
jne 0x553a
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq 0x20(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x20(%rax)
jmp 0x55e1
leaq -0x108(%rbp), %rdi
callq 0x7590
jmp 0x5548
movq -0x340(%rbp), %rdi
callq 0x7550
movq (%rax), %rax
movq %rax, -0xe0(%rbp)
movq $0x1, -0xe8(%rbp)
leaq -0x138(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x7600
jmp 0x557e
leaq -0x70(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0x75d0
jmp 0x5590
leaq -0x138(%rbp), %rdi
callq 0x2bf0
leaq -0x108(%rbp), %rdi
callq 0x2bf0
jmp 0x55e1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x55d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x138(%rbp), %rdi
callq 0x2bf0
leaq -0x108(%rbp), %rdi
callq 0x2bf0
jmp 0x591b
jmp 0x55e3
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x3050
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rax
movq %rax, -0xc0(%rbp)
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x3100
movq %rax, -0x148(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0x73f0
testb $0x1, %al
jne 0x5635
jmp 0x58e3
leaq -0x2c0(%rbp), %rdi
callq 0x2140
jmp 0x5643
leaq -0xc0(%rbp), %rdi
callq 0x7430
movq %rax, %rsi
movq (%rsi), %rax
movq (%rax), %rax
leaq -0x2e0(%rbp), %rdi
callq *%rax
jmp 0x5663
leaq -0x2c0(%rbp), %rdi
leaq -0x2e0(%rbp), %rsi
callq 0x20e0
jmp 0x5678
leaq -0x2e0(%rbp), %rdi
callq 0x2090
leaq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x3050
movq %rax, -0x2e8(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0x2e8(%rbp), %rsi
callq 0x73f0
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x369(%rbp)
jne 0x56bf
jmp 0x57fa
leaq -0xc0(%rbp), %rdi
callq 0x7430
movq 0x20(%rax), %rax
movq %rax, -0x378(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x7430
movq %rax, %rdi
addq $0x8, %rdi
callq 0x6c70
movq -0x378(%rbp), %rcx
imulq %rax, %rcx
xorl %eax, %eax
cmpq $0x1, %rcx
movb %al, -0x369(%rbp)
ja 0x57fa
movq -0x338(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq %rax, %rdi
addq $0x8, %rdi
callq 0x6c70
movq %rax, %rcx
xorl %eax, %eax
cmpq $0x1, %rcx
movb %al, -0x369(%rbp)
jne 0x57fa
movq -0x338(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq %rax, %rcx
xorl %eax, %eax
cmpq $0x1, 0x20(%rcx)
movb %al, -0x369(%rbp)
jle 0x57fa
movq -0x338(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq -0x338(%rbp), %rdi
movq 0x28(%rax), %rax
movq %rax, -0x388(%rbp)
addq $0x8, %rdi
callq 0x7510
movq %rax, %rdi
addq $0x8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x6d30
movq -0x338(%rbp), %rdi
movq (%rax), %rax
movq %rax, -0x390(%rbp)
addq $0x8, %rdi
callq 0x7510
movq -0x390(%rbp), %rcx
movq %rax, %rdx
movq -0x388(%rbp), %rax
imulq 0x20(%rdx), %rcx
addq %rcx, %rax
movq %rax, -0x380(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x7430
movq %rax, %rcx
movq -0x380(%rbp), %rax
cmpq 0x28(%rcx), %rax
sete %al
movb %al, -0x369(%rbp)
movb -0x369(%rbp), %al
testb $0x1, %al
jne 0x5806
jmp 0x5855
movq -0x338(%rbp), %rdi
addq $0x8, %rdi
callq 0x7510
movq 0x20(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x20(%rax)
jmp 0x58af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x58d5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x2e0(%rbp), %rdi
callq 0x2090
jmp 0x58d5
leaq -0xc0(%rbp), %rdi
callq 0x7650
movq %rax, %rsi
leaq -0x318(%rbp), %rdi
callq 0x7600
jmp 0x5872
movq -0x338(%rbp), %rdi
leaq -0x318(%rbp), %rsi
callq 0x75d0
jmp 0x5887
leaq -0x318(%rbp), %rdi
callq 0x2bf0
jmp 0x58af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x318(%rbp), %rdi
callq 0x2bf0
jmp 0x58d5
leaq -0x2c0(%rbp), %rdi
callq 0x2040
leaq -0xc0(%rbp), %rdi
xorl %esi, %esi
callq 0x7450
movq %rax, -0x320(%rbp)
jmp 0x5605
leaq -0x2c0(%rbp), %rdi
callq 0x2040
jmp 0x591b
movb $0x1, -0x71(%rbp)
testb $0x1, -0x71(%rbp)
jne 0x58f9
movq -0x338(%rbp), %rdi
callq 0x2bd0
leaq -0x70(%rbp), %rdi
callq 0x2bd0
leaq -0x28(%rbp), %rdi
callq 0x3220
movq -0x330(%rbp), %rax
addq $0x390, %rsp            # imm = 0x390
popq %rbp
retq
movq -0x338(%rbp), %rdi
callq 0x2bd0
leaq -0x70(%rbp), %rdi
callq 0x2bd0
leaq -0x28(%rbp), %rdi
callq 0x3220
movq -0x48(%rbp), %rdi
callq 0x21a0
nopw %cs:(%rax,%rax)