// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x268, %rsp            # imm = 0x268
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x88(%rsp), %rbp
movq %rbp, %rdi
callq 0x3b94
leaq 0x28(%rsp), %rdi
movq %rbp, %rsi
callq 0x294b
leaq 0x88(%rsp), %rdi
callq 0x2666
xorps %xmm0, %xmm0
andq $0x0, 0x20(%rsp)
movups %xmm0, 0x10(%rsp)
leaq 0x4c78(%rip), %rax      # 0x7d98
movq %rax, 0x8(%rsp)
movups %xmm0, 0x8(%rbx)
andq $0x0, 0x18(%rbx)
movq %rax, (%rbx)
leaq 0x40(%rsp), %rdi
leaq 0x28(%rsp), %rbp
movq %rbp, %rsi
callq 0x3b94
leaq 0xf0(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x33fa
leaq 0x10(%rsp), %r13
leaq 0x8(%rbx), %r15
leaq 0xf8(%rsp), %rsi
movq %r13, %rdi
callq 0x3f32
leaq 0xf0(%rsp), %rdi
callq 0x250e
leaq 0x40(%rsp), %rdi
callq 0x2666
movq (%r13), %r12
movq 0x8(%r13), %rax
xorl %edx, %edx
movq %r12, %rcx
cmpq %rax, %rcx
je 0x31bf
movslq %edx, %rsi
movq (%r14), %rdx
movq (%rdx,%rsi,8), %rdx
movq %rdx, 0x28(%rcx)
movq 0x10(%rcx), %rdx
subq 0x8(%rcx), %rdx
sarq $0x3, %rdx
imulq 0x20(%rcx), %rdx
addq %rsi, %rdx
addq $0x30, %rcx
jmp 0x3192
movq 0x8(%r14), %rcx
cmpq %rcx, (%r14)
je 0x3261
cmpq %rax, %r12
je 0x3200
movq -0x28(%rax), %rsi
movq -0x20(%rax), %rdx
subq %rsi, %rdx
cmpq $0x8, %rdx
jne 0x3200
movq -0x10(%rax), %rdx
movq (%rsi), %rsi
imulq %rdx, %rsi
addq -0x8(%rax), %rsi
cmpq -0x8(%rcx), %rsi
jne 0x3200
incq %rdx
movq %rdx, -0x10(%rax)
jmp 0x3261
xorps %xmm0, %xmm0
leaq 0xf0(%rsp), %rsi
movups %xmm0, 0x8(%rsi)
andq $0x0, 0x18(%rsi)
leaq 0x4b4d(%rip), %rax      # 0x7d68
movq %rax, (%rsi)
movq -0x8(%rcx), %rax
movq %rax, 0x28(%rsi)
movq $0x1, 0x20(%rsi)
leaq 0x58(%rsp), %rdi
callq 0x3c62
leaq 0x58(%rsp), %rsi
movq %r13, %rdi
callq 0x48b6
leaq 0x58(%rsp), %rdi
callq 0x2522
leaq 0xf0(%rsp), %rdi
callq 0x2522
movq 0x10(%rsp), %r12
leaq 0xf0(%rsp), %r13
leaq 0xa0(%rsp), %rbp
leaq 0xc0(%rsp), %r14
cmpq 0x18(%rsp), %r12
je 0x3335
movq %r13, %rdi
callq 0x2140
movq (%r12), %rax
movq %rbp, %rdi
movq %r12, %rsi
callq *(%rax)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x20f0
movq %rbp, %rdi
callq 0x2080
cmpq 0x10(%rsp), %r12
je 0x3306
movq 0x10(%r12), %rax
subq 0x8(%r12), %rax
sarq $0x3, %rax
imulq 0x20(%r12), %rax
cmpq $0x1, %rax
ja 0x3306
movq 0x10(%rbx), %rax
movq -0x28(%rax), %rdx
movq -0x20(%rax), %rcx
subq %rdx, %rcx
cmpq $0x8, %rcx
jne 0x3306
movq -0x10(%rax), %rcx
cmpq $0x2, %rcx
jl 0x3306
movq (%rdx), %rdx
imulq %rcx, %rdx
addq -0x8(%rax), %rdx
cmpq 0x28(%r12), %rdx
jne 0x3306
incq %rcx
movq %rcx, -0x10(%rax)
jmp 0x3324
movq %r14, %rdi
movq %r12, %rsi
callq 0x3c62
movq %r15, %rdi
movq %r14, %rsi
callq 0x48b6
movq %r14, %rdi
callq 0x2522
movq %r13, %rdi
callq 0x2040
addq $0x30, %r12
jmp 0x3279
leaq 0x8(%rsp), %rdi
callq 0x250e
leaq 0x28(%rsp), %rdi
callq 0x2666
movq %rbx, %rax
addq $0x268, %rsp            # imm = 0x268
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
leaq 0x58(%rsp), %rdi
callq 0x2522
jmp 0x3370
movq %rax, %r14
leaq 0xf0(%rsp), %rdi
callq 0x2522
jmp 0x33d8
movq %rax, %r14
leaq 0x40(%rsp), %rdi
callq 0x2666
jmp 0x33d8
movq %rax, %r14
jmp 0x33d8
movq %rax, %r14
jmp 0x33ea
movq %rax, %r14
leaq 0xc0(%rsp), %rdi
callq 0x2522
jmp 0x33c6
jmp 0x33b1
movq %rax, %r14
jmp 0x33d3
movq %rax, %r14
jmp 0x33c6
movq %rax, %r14
leaq 0xa0(%rsp), %rdi
callq 0x2080
leaq 0xf0(%rsp), %rdi
callq 0x2040
leaq 0x28(%rsp), %rbp
movq %rbx, %rdi
callq 0x250e
leaq 0x8(%rsp), %rdi
callq 0x250e
movq %rbp, %rdi
callq 0x2666
movq %r14, %rdi
callq 0x21a0