// File: sisong[P]ApkDiffPatch/HDiffPatch/libHDiffPatch/HDiff/private_diff/limit_mem_diff/digest_matcher.cpp
// Function: unsigned long const* hdiff_private::getBestMatchi<unsigned long>(unsigned long const*, unsigned long, unsigned long const**, unsigned long const**, hdiff_private::TNewStreamCache&, hpatch_TCover const&, unsigned long*)
static const TIndex* getBestMatchi(const adler_uint_t* blocksBase,size_t blocksSize,
                                   const TIndex** _left,const TIndex** _right,
                                   TNewStreamCache& newStream,const TCover& lastCover,
                                   size_t* _digests_eq_n){
    const size_t kMatchBlockSize=newStream.kMatchBlockSize;
    size_t max_digests_n=upperCount(kMinTrustMatchedLength,kMatchBlockSize);
    size_t _data_max_digests_n=newStream.dataLength()/kMatchBlockSize;
    if (max_digests_n>_data_max_digests_n) max_digests_n=_data_max_digests_n;
    
    const TIndex* best=0;
    const TIndex*& left=*_left;
    const TIndex*& right=*_right;
    size_t& digests_eq_n=*_digests_eq_n;
    digests_eq_n=1;
    //缩小[left best right)范围,留下最多2个(因为签名匹配并不保证一定相等,2个的话应该就够了?);
    if (right-left>1){
        //寻找最长的签名匹配位置(也就是最有可能的最长匹配位置);
        TDigest_comp_i comp_i(blocksBase,blocksSize);
        newStream.toBestDataLength();
        const unsigned char* bdata=newStream.data()+kMatchBlockSize;
        for (; (digests_eq_n<max_digests_n)&&(right-left>1);++digests_eq_n,bdata+=kMatchBlockSize){
            adler_uint_t digest=adler_start(bdata,kMatchBlockSize);
            typename TDigest_comp::TDigest digest_value(digest);
            comp_i.i=digests_eq_n;
            std::pair<const TIndex*,const TIndex*> i_range=
                std::equal_range(left,right,digest_value,comp_i);
            size_t rn=i_range.second-i_range.first;
            if (rn==0){
                break;
            }else if (rn==1){
                best=i_range.first;
                break;
            }else{
                left=i_range.first;
                right=i_range.second;
            }
        }
    }else{
        best=left;
    }
    //best==0 说明有>2个位置都是最好位置,还需要继续寻找;
    
    //assert(newStream.pos()>lastCover.newPos);
    hpatch_StreamPos_t linkOldPos=newStream.pos()+lastCover.oldPos-lastCover.newPos;
    TIndex linkIndex=(TIndex)posToBlockIndex(linkOldPos,kMatchBlockSize,blocksSize);
    //找到lastCover附近的位置当作比较好的best默认值,以利于link或压缩;
    if (best==0){
        TIndex_comp comp(blocksBase,blocksSize,max_digests_n);
        size_t findCount=(right-left)*2+1;
        if (findCount>kMaxLinkIndexFindCount) findCount=kMaxLinkIndexFindCount;
        for (TIndex inc=1;(inc<=findCount);++inc) { //linkIndex附近找;
            TIndex fi;  TIndex s=(inc>>1);
            if (inc&1){
                if (linkIndex<s) continue;
                fi=linkIndex-s;
            }else{
                if (linkIndex+s>=blocksSize) continue;
                fi=linkIndex+s;
            }
            std::pair<const TIndex*,const TIndex*> i_range=std::equal_range(left,right,fi,comp);
            if (i_range.first!=i_range.second){
                best=i_range.first+(i_range.second-i_range.first)/2;
                for (const TIndex* ci=best;ci<i_range.second; ++ci) {
                    if (*ci==fi) { best=ci; break;  } //找到;
                }
                break;
            }
        }
    }
    if(best==0){ //继续找;
        best=left+(right-left)/2;
        hpatch_StreamPos_t _best_distance=hpatch_kNullStreamPos;
        const TIndex* end=(left+kBestMatchRange>=right)?right:(left+kBestMatchRange);
        for (const TIndex* it=left;it<end; ++it) {
            hpatch_StreamPos_t oldIndex=(*it);
            hpatch_StreamPos_t distance=(oldIndex<linkIndex)?(linkIndex-oldIndex):(oldIndex-linkIndex);
            if (distance<_best_distance){ //找最近;
                best=it;
                _best_distance=distance;
            }
        }
    }
    return best;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1b0, %rsp            # imm = 0x1B0
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rsi
movl $0x4000, %edi           # imm = 0x4000
callq 0x3eaf0
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rdi
callq 0x49800
xorl %ecx, %ecx
movl %ecx, %edx
divq -0x38(%rbp)
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rax
cmpq -0x48(%rbp), %rax
jbe 0x40dec
movq -0x48(%rbp), %rax
movq %rax, -0x40(%rbp)
movq $0x0, -0x50(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x60(%rbp)
movq 0x10(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movq $0x1, (%rax)
movq -0x60(%rbp), %rax
movq (%rax), %rax
movq -0x58(%rbp), %rcx
movq (%rcx), %rcx
subq %rcx, %rax
sarq $0x3, %rax
cmpq $0x1, %rax
jle 0x40fd3
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rdx
leaq -0x80(%rbp), %rdi
callq 0x49d50
movq -0x28(%rbp), %rdi
callq 0x49d90
movq -0x28(%rbp), %rdi
callq 0x425f0
addq -0x38(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x68(%rbp), %rax
movq (%rax), %rcx
xorl %eax, %eax
cmpq -0x40(%rbp), %rcx
movb %al, -0x169(%rbp)
jae 0x40e9b
movq -0x60(%rbp), %rax
movq (%rax), %rax
movq -0x58(%rbp), %rcx
movq (%rcx), %rcx
subq %rcx, %rax
sarq $0x3, %rax
cmpq $0x1, %rax
setg %al
movb %al, -0x169(%rbp)
movb -0x169(%rbp), %al
testb $0x1, %al
jne 0x40eaa
jmp 0x40fd1
movq -0x88(%rbp), %rsi
movq -0x38(%rbp), %rdx
movl $0x1, %edi
callq 0x51790
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rsi
leaq -0x98(%rbp), %rdi
callq 0x49720
movq -0x68(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x70(%rbp)
movq -0x58(%rbp), %rax
movq (%rax), %rdi
movq -0x60(%rbp), %rax
movq (%rax), %rsi
movq -0x80(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0x98(%rbp), %rdx
leaq -0xc0(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x49e10
movq %rax, -0xa8(%rbp)
movq %rdx, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
movq -0xa8(%rbp), %rcx
subq %rcx, %rax
sarq $0x3, %rax
movq %rax, -0xc8(%rbp)
cmpq $0x0, -0xc8(%rbp)
jne 0x40f75
jmp 0x40fd1
cmpq $0x1, -0xc8(%rbp)
jne 0x40f8c
movq -0xa8(%rbp), %rax
movq %rax, -0x50(%rbp)
jmp 0x40fd1
movq -0xa8(%rbp), %rcx
movq -0x58(%rbp), %rax
movq %rcx, (%rax)
movq -0xa0(%rbp), %rcx
movq -0x60(%rbp), %rax
movq %rcx, (%rax)
jmp 0x40faa
jmp 0x40fac
movq -0x68(%rbp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movq -0x38(%rbp), %rax
addq -0x88(%rbp), %rax
movq %rax, -0x88(%rbp)
jmp 0x40e64
jmp 0x40fde
movq -0x58(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x28(%rbp), %rdi
callq 0x497d0
movq -0x30(%rbp), %rcx
addq (%rcx), %rax
movq -0x30(%rbp), %rcx
subq 0x8(%rcx), %rax
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rdi
movq -0x38(%rbp), %rsi
movq -0x10(%rbp), %rdx
callq 0x417e0
movq %rax, -0xd8(%rbp)
cmpq $0x0, -0x50(%rbp)
jne 0x41244
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rdx
movq -0x40(%rbp), %rcx
leaq -0xf0(%rbp), %rdi
callq 0x426a0
movq -0x60(%rbp), %rax
movq (%rax), %rax
movq -0x58(%rbp), %rcx
movq (%rcx), %rcx
subq %rcx, %rax
sarq $0x3, %rax
shlq %rax
addq $0x1, %rax
movq %rax, -0xf8(%rbp)
cmpq $0x40, -0xf8(%rbp)
jbe 0x41073
movq $0x40, -0xf8(%rbp)
movq $0x1, -0x100(%rbp)
movq -0x100(%rbp), %rax
cmpq -0xf8(%rbp), %rax
ja 0x41242
movq -0x100(%rbp), %rax
shrq %rax
movq %rax, -0x110(%rbp)
movq -0x100(%rbp), %rax
andq $0x1, %rax
cmpq $0x0, %rax
je 0x410e0
movq -0xd8(%rbp), %rax
cmpq -0x110(%rbp), %rax
jae 0x410c9
jmp 0x4122b
movq -0xd8(%rbp), %rax
subq -0x110(%rbp), %rax
movq %rax, -0x108(%rbp)
jmp 0x4110e
movq -0xd8(%rbp), %rax
addq -0x110(%rbp), %rax
cmpq -0x10(%rbp), %rax
jb 0x410f9
jmp 0x4122b
movq -0xd8(%rbp), %rax
addq -0x110(%rbp), %rax
movq %rax, -0x108(%rbp)
movq -0x58(%rbp), %rax
movq (%rax), %rdi
movq -0x60(%rbp), %rax
movq (%rax), %rsi
movq -0xf0(%rbp), %rax
movq %rax, -0x138(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0x130(%rbp)
movq -0xe0(%rbp), %rax
movq %rax, -0x128(%rbp)
leaq -0x108(%rbp), %rdx
leaq -0x138(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x49f10
movq %rax, -0x120(%rbp)
movq %rdx, -0x118(%rbp)
movq -0x120(%rbp), %rax
cmpq -0x118(%rbp), %rax
je 0x41229
movq -0x120(%rbp), %rax
movq %rax, -0x178(%rbp)
movq -0x118(%rbp), %rax
movq -0x120(%rbp), %rcx
subq %rcx, %rax
sarq $0x3, %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x178(%rbp), %rax
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rax
cmpq -0x118(%rbp), %rax
jae 0x41227
movq -0x140(%rbp), %rax
movq (%rax), %rax
cmpq -0x108(%rbp), %rax
jne 0x41211
movq -0x140(%rbp), %rax
movq %rax, -0x50(%rbp)
jmp 0x41227
jmp 0x41213
movq -0x140(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x140(%rbp)
jmp 0x411e1
jmp 0x41242
jmp 0x4122b
movq -0x100(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x100(%rbp)
jmp 0x4107e
jmp 0x41244
cmpq $0x0, -0x50(%rbp)
jne 0x413a5
movq -0x58(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x180(%rbp)
movq -0x60(%rbp), %rax
movq (%rax), %rax
movq -0x58(%rbp), %rcx
movq (%rcx), %rcx
subq %rcx, %rax
sarq $0x3, %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x180(%rbp), %rax
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq $-0x1, -0x148(%rbp)
movq -0x58(%rbp), %rax
movq (%rax), %rax
addq $0x80000, %rax          # imm = 0x80000
movq -0x60(%rbp), %rcx
cmpq (%rcx), %rax
jb 0x412c2
movq -0x60(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x188(%rbp)
jmp 0x412d6
movq -0x58(%rbp), %rax
movq (%rax), %rax
addq $0x80000, %rax          # imm = 0x80000
movq %rax, -0x188(%rbp)
movq -0x188(%rbp), %rax
movq %rax, -0x150(%rbp)
movq -0x58(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x158(%rbp)
movq -0x158(%rbp), %rax
cmpq -0x150(%rbp), %rax
jae 0x413a3
movq -0x158(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x160(%rbp)
movq -0x160(%rbp), %rax
cmpq -0xd8(%rbp), %rax
jae 0x4133e
movq -0xd8(%rbp), %rax
subq -0x160(%rbp), %rax
movq %rax, -0x190(%rbp)
jmp 0x41353
movq -0x160(%rbp), %rax
subq -0xd8(%rbp), %rax
movq %rax, -0x190(%rbp)
movq -0x190(%rbp), %rax
movq %rax, -0x168(%rbp)
movq -0x168(%rbp), %rax
cmpq -0x148(%rbp), %rax
jae 0x4138a
movq -0x158(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x168(%rbp), %rax
movq %rax, -0x148(%rbp)
jmp 0x4138c
movq -0x158(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x158(%rbp)
jmp 0x412f2
jmp 0x413a5
movq -0x50(%rbp), %rax
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbp
retq
nopw %cs:(%rax,%rax)