// File: twekkel[P]mzpq/libzpaq.cpp
// Function: libzpaq::Predictor::update0(int)
void Predictor::update0(int y) {
  assert(initTables);
  assert(y==0 || y==1);
  assert(c8>=1 && c8<=255);
  assert(hmap4>=1 && hmap4<=511);

  // Update components
  const U8* cp=&z.header[7];
  int n=z.header[6];
  assert(n>=1 && n<=255);
  assert(cp[-1]==n);
  for (int i=0; i<n; ++i) {
    Component& cr=comp[i];
    switch(cp[0]) {
      case CONS:  // c
        break;
      case CM:  // sizebits limit
        train(cr, y);
        break;
      case ICM: { // sizebits: cxt=ht[b]=bh, ht[c][0..15]=bh row, cxt=bh
        cr.ht[cr.c+(hmap4&15)]=st.next(cr.ht[cr.c+(hmap4&15)], y);
        U32& pn=cr.cm(cr.cxt);
        pn+=int(y*32767-(pn>>8))>>2;
      }
        break;
      case MATCH: // sizebits bufbits:
                  //   a=len, b=offset, c=bit, cm=index, cxt=bitpos
                  //   ht=buf, limit=pos
      {
        assert(cr.a<=255);
        assert(cr.c==0 || cr.c==1);
        assert(cr.cxt<8);
        assert(cr.cm.size()==(size_t(1)<<cp[1]));
        assert(cr.ht.size()==(size_t(1)<<cp[2]));
        assert(cr.limit<cr.ht.size());
        if (int(cr.c)!=y) cr.a=0;  // mismatch?
        cr.ht(cr.limit)+=cr.ht(cr.limit)+y;
        if (++cr.cxt==8) {
          cr.cxt=0;
          ++cr.limit;
          cr.limit&=(1<<cp[2])-1;
          if (cr.a==0) {  // look for a match
            cr.b=cr.limit-cr.cm(h[i]);
            if (cr.b&(cr.ht.size()-1))
              while (cr.a<255
                     && cr.ht(cr.limit-cr.a-1)==cr.ht(cr.limit-cr.a-cr.b-1))
                ++cr.a;
          }
          else cr.a+=cr.a<255;
          cr.cm(h[i])=cr.limit;
        }
      }
        break;
      case AVG:  // j k wt
        break;
      case MIX2: { // sizebits j k rate mask
                   // cm=wt[size], cxt=input
        assert(cr.a16.size()==cr.c);
        assert(cr.cxt<cr.a16.size());
        int err=(y*32767-squash(p[i]))*cp[4]>>5;
        int w=cr.a16[cr.cxt];
        w+=(err*(p[cp[2]]-p[cp[3]])+(1<<12))>>13;
        if (w<0) w=0;
        if (w>65535) w=65535;
        cr.a16[cr.cxt]=w;
      }
        break;
      case MIX: {   // sizebits j m rate mask
                    // cm=wt[size][m], cxt=input
        int m=cp[3];
        assert(m>0 && m<=i);
        assert(cr.cm.size()==m*cr.c);
        assert(cr.cxt+m<=cr.cm.size());
        int err=(y*32767-squash(p[i]))*cp[4]>>4;
        int* wt=(int*)&cr.cm[cr.cxt];
        for (int j=0; j<m; ++j)
          wt[j]=clamp512k(wt[j]+((err*p[cp[2]+j]+(1<<12))>>13));
      }
        break;
      case ISSE: { // sizebits j  -- c=hi, cxt=bh
        assert(cr.cxt==cr.ht[cr.c+(hmap4&15)]);
        int err=y*32767-squash(p[i]);
        int *wt=(int*)&cr.cm[cr.cxt*2];
        wt[0]=clamp512k(wt[0]+((err*p[cp[2]]+(1<<12))>>13));
        wt[1]=clamp512k(wt[1]+((err+16)>>5));
        cr.ht[cr.c+(hmap4&15)]=st.next(cr.cxt, y);
      }
        break;
      case SSE:  // sizebits j start limit
        train(cr, y);
        break;
      default:
        assert(0);
    }
    cp+=compsize[cp[0]];
    assert(cp>=&z.header[7] && cp<&z.header[z.cend] 
           && cp<&z.header[z.header.isize()-8]);
  }
  assert(cp[0]==NONE);

  // Save bit y in c8, hmap4
  c8+=c8+y;
  if (c8>=256) {
    z.run(c8-256);
    hmap4=1;
    c8=1;
    for (int i=0; i<n; ++i) h[i]=z.H(i);
  }
  else if (c8>=16 && c8<32)
    hmap4=(hmap4&0xf)<<5|y<<4|1;
  else
    hmap4=(hmap4&0x1f0)|(((hmap4&0xf)*2+y)&0xf);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x68(%rbp)
movq 0x808(%rax), %rdi
addq $0x10, %rdi
movl $0x7, %esi
callq 0x30630
movq %rax, %rcx
movq -0x68(%rbp), %rax
movq %rcx, -0x18(%rbp)
movq 0x808(%rax), %rdi
addq $0x10, %rdi
movl $0x6, %esi
callq 0x30630
movzbl (%rax), %eax
movl %eax, -0x1c(%rbp)
movl $0x0, -0x20(%rbp)
movl -0x20(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x131e5
movq -0x68(%rbp), %rax
movslq -0x20(%rbp), %rcx
imulq $0x70, %rcx, %rcx
leaq 0x810(%rax,%rcx), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x70(%rbp)
subl $0x8, %eax
ja 0x131b4
movq -0x70(%rbp), %rax
leaq 0x21bc5(%rip), %rcx     # 0x347e8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x131b6
movq -0x68(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl -0xc(%rbp), %edx
callq 0x30d80
jmp 0x131b6
movq -0x68(%rbp), %rax
movq %rax, %rcx
addq $0x1ac14, %rcx          # imm = 0x1AC14
movq %rcx, -0x80(%rbp)
movq -0x28(%rbp), %rdi
addq $0x40, %rdi
movq -0x28(%rbp), %rcx
movq 0x20(%rcx), %rsi
movl 0x4(%rax), %eax
andl $0xf, %eax
cltq
addq %rax, %rsi
callq 0x30630
movq -0x80(%rbp), %rdi
movzbl (%rax), %esi
movl -0xc(%rbp), %edx
callq 0x30e30
movl %eax, %ecx
movq -0x68(%rbp), %rax
movb %cl, -0x71(%rbp)
movq -0x28(%rbp), %rdi
addq $0x40, %rdi
movq -0x28(%rbp), %rcx
movq 0x20(%rcx), %rsi
movl 0x4(%rax), %eax
andl $0xf, %eax
cltq
addq %rax, %rsi
callq 0x30630
movb -0x71(%rbp), %cl
movb %cl, (%rax)
movq -0x28(%rbp), %rdi
addq $0x28, %rdi
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x30970
movq %rax, -0x30(%rbp)
imull $0x7fff, -0xc(%rbp), %ecx # imm = 0x7FFF
movq -0x30(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
subl %eax, %ecx
sarl $0x2, %ecx
movq -0x30(%rbp), %rax
addl (%rax), %ecx
movl %ecx, (%rax)
jmp 0x131b6
movq -0x28(%rbp), %rax
movq 0x20(%rax), %rax
cmpl -0xc(%rbp), %eax
je 0x12d09
movq -0x28(%rbp), %rax
movq $0x0, 0x10(%rax)
movq -0x28(%rbp), %rdi
addq $0x40, %rdi
movq -0x28(%rbp), %rax
movq (%rax), %rsi
callq 0x30940
movzbl (%rax), %eax
addl -0xc(%rbp), %eax
movl %eax, -0x84(%rbp)
movq -0x28(%rbp), %rdi
addq $0x40, %rdi
movq -0x28(%rbp), %rax
movq (%rax), %rsi
callq 0x30940
movl -0x84(%rbp), %edx
movzbl (%rax), %ecx
addl %edx, %ecx
movb %cl, (%rax)
movq -0x28(%rbp), %rcx
movq 0x8(%rcx), %rax
addq $0x1, %rax
movq %rax, 0x8(%rcx)
cmpq $0x8, %rax
jne 0x12f1d
movq -0x28(%rbp), %rax
movq $0x0, 0x8(%rax)
movq -0x28(%rbp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %ecx
movl $0x1, %eax
shll %cl, %eax
subl $0x1, %eax
movslq %eax, %rcx
movq -0x28(%rbp), %rax
andq (%rax), %rcx
movq %rcx, (%rax)
movq -0x28(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x12ec8
movq -0x68(%rbp), %rax
movq -0x28(%rbp), %rcx
movq (%rcx), %rcx
movq %rcx, -0x98(%rbp)
movq -0x28(%rbp), %rdi
addq $0x28, %rdi
movslq -0x20(%rbp), %rcx
movl 0x408(%rax,%rcx,4), %eax
movl %eax, %esi
callq 0x30970
movq -0x98(%rbp), %rcx
movl (%rax), %eax
subq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x28(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x90(%rbp)
movq -0x28(%rbp), %rdi
addq $0x40, %rdi
callq 0x30610
movq %rax, %rcx
movq -0x90(%rbp), %rax
subq $0x1, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
je 0x12ec6
jmp 0x12e25
movq -0x28(%rbp), %rcx
xorl %eax, %eax
cmpq $0xff, 0x10(%rcx)
movb %al, -0x99(%rbp)
jae 0x12ea3
movq -0x28(%rbp), %rdi
addq $0x40, %rdi
movq -0x28(%rbp), %rax
movq (%rax), %rsi
movq -0x28(%rbp), %rax
subq 0x10(%rax), %rsi
subq $0x1, %rsi
callq 0x30940
movzbl (%rax), %eax
movl %eax, -0xa0(%rbp)
movq -0x28(%rbp), %rdi
addq $0x40, %rdi
movq -0x28(%rbp), %rax
movq (%rax), %rsi
movq -0x28(%rbp), %rax
subq 0x10(%rax), %rsi
movq -0x28(%rbp), %rax
subq 0x18(%rax), %rsi
subq $0x1, %rsi
callq 0x30940
movq %rax, %rcx
movl -0xa0(%rbp), %eax
movzbl (%rcx), %ecx
cmpl %ecx, %eax
sete %al
movb %al, -0x99(%rbp)
movb -0x99(%rbp), %al
testb $0x1, %al
jne 0x12eaf
jmp 0x12ec4
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x10(%rax)
jmp 0x12e25
jmp 0x12ec6
jmp 0x12eea
movq -0x28(%rbp), %rax
cmpq $0xff, 0x10(%rax)
setb %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, %ecx
movq -0x28(%rbp), %rax
addq 0x10(%rax), %rcx
movq %rcx, 0x10(%rax)
movq -0x68(%rbp), %rax
movq -0x28(%rbp), %rcx
movq (%rcx), %rcx
movl %ecx, -0xa4(%rbp)
movq -0x28(%rbp), %rdi
addq $0x28, %rdi
movslq -0x20(%rbp), %rcx
movl 0x408(%rax,%rcx,4), %eax
movl %eax, %esi
callq 0x30970
movl -0xa4(%rbp), %ecx
movl %ecx, (%rax)
jmp 0x131b6
jmp 0x131b6
movq -0x68(%rbp), %rdi
imull $0x7fff, -0xc(%rbp), %eax # imm = 0x7FFF
movl %eax, -0xa8(%rbp)
movslq -0x20(%rbp), %rax
movl 0x8(%rdi,%rax,4), %esi
callq 0x30d10
movl %eax, %ecx
movl -0xa8(%rbp), %eax
subl %ecx, %eax
movq -0x18(%rbp), %rcx
movzbl 0x4(%rcx), %ecx
imull %ecx, %eax
sarl $0x5, %eax
movl %eax, -0x34(%rbp)
movq -0x28(%rbp), %rdi
addq $0x58, %rdi
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x30c90
movq -0x68(%rbp), %rdx
movzwl (%rax), %eax
movl %eax, -0x38(%rbp)
movl -0x34(%rbp), %eax
movq -0x18(%rbp), %rcx
movzbl 0x2(%rcx), %ecx
movl 0x8(%rdx,%rcx,4), %ecx
movq -0x18(%rbp), %rsi
movzbl 0x3(%rsi), %esi
subl 0x8(%rdx,%rsi,4), %ecx
imull %ecx, %eax
addl $0x1000, %eax           # imm = 0x1000
sarl $0xd, %eax
addl -0x38(%rbp), %eax
movl %eax, -0x38(%rbp)
cmpl $0x0, -0x38(%rbp)
jge 0x12fb8
movl $0x0, -0x38(%rbp)
cmpl $0xffff, -0x38(%rbp)    # imm = 0xFFFF
jle 0x12fc8
movl $0xffff, -0x38(%rbp)    # imm = 0xFFFF
movl -0x38(%rbp), %eax
movw %ax, -0xaa(%rbp)
movq -0x28(%rbp), %rdi
addq $0x58, %rdi
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x30c90
movw -0xaa(%rbp), %cx
movw %cx, (%rax)
jmp 0x131b6
movq -0x68(%rbp), %rdi
movq -0x18(%rbp), %rax
movzbl 0x3(%rax), %eax
movl %eax, -0x3c(%rbp)
imull $0x7fff, -0xc(%rbp), %eax # imm = 0x7FFF
movl %eax, -0xb0(%rbp)
movslq -0x20(%rbp), %rax
movl 0x8(%rdi,%rax,4), %esi
callq 0x30d10
movl %eax, %ecx
movl -0xb0(%rbp), %eax
subl %ecx, %eax
movq -0x18(%rbp), %rcx
movzbl 0x4(%rcx), %ecx
imull %ecx, %eax
sarl $0x4, %eax
movl %eax, -0x40(%rbp)
movq -0x28(%rbp), %rdi
addq $0x28, %rdi
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x30880
movq %rax, -0x48(%rbp)
movl $0x0, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jge 0x130ae
movq -0x68(%rbp), %rdi
movq -0x48(%rbp), %rax
movslq -0x4c(%rbp), %rcx
movl (%rax,%rcx,4), %esi
movl -0x40(%rbp), %eax
movq -0x18(%rbp), %rcx
movzbl 0x2(%rcx), %ecx
addl -0x4c(%rbp), %ecx
movslq %ecx, %rcx
imull 0x8(%rdi,%rcx,4), %eax
addl $0x1000, %eax           # imm = 0x1000
sarl $0xd, %eax
addl %eax, %esi
callq 0x30cb0
movl %eax, %edx
movq -0x48(%rbp), %rax
movslq -0x4c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x1305a
jmp 0x131b6
movq -0x68(%rbp), %rdi
imull $0x7fff, -0xc(%rbp), %eax # imm = 0x7FFF
movl %eax, -0xb8(%rbp)
movslq -0x20(%rbp), %rax
movl 0x8(%rdi,%rax,4), %esi
callq 0x30d10
movl %eax, %ecx
movl -0xb8(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x50(%rbp)
movq -0x28(%rbp), %rdi
addq $0x28, %rdi
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rsi
shlq %rsi
callq 0x30880
movq -0x68(%rbp), %rdi
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movl (%rax), %esi
movl -0x50(%rbp), %eax
movq -0x18(%rbp), %rcx
movzbl 0x2(%rcx), %ecx
imull 0x8(%rdi,%rcx,4), %eax
addl $0x1000, %eax           # imm = 0x1000
sarl $0xd, %eax
addl %eax, %esi
callq 0x30cb0
movq -0x68(%rbp), %rdi
movl %eax, %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
movq -0x58(%rbp), %rax
movl 0x4(%rax), %esi
movl -0x50(%rbp), %eax
addl $0x10, %eax
sarl $0x5, %eax
addl %eax, %esi
callq 0x30cb0
movq -0x68(%rbp), %rdi
movl %eax, %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0x4(%rax)
addq $0x1ac14, %rdi          # imm = 0x1AC14
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movl %eax, %esi
movl -0xc(%rbp), %edx
callq 0x30e30
movl %eax, %ecx
movq -0x68(%rbp), %rax
movb %cl, -0xb1(%rbp)
movq -0x28(%rbp), %rdi
addq $0x40, %rdi
movq -0x28(%rbp), %rcx
movq 0x20(%rcx), %rsi
movl 0x4(%rax), %eax
andl $0xf, %eax
cltq
addq %rax, %rsi
callq 0x30630
movb -0xb1(%rbp), %cl
movb %cl, (%rax)
jmp 0x131b6
movq -0x68(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl -0xc(%rbp), %edx
callq 0x30d80
jmp 0x131b6
jmp 0x131b6
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
movl %eax, %ecx
leaq 0x219fa(%rip), %rax     # 0x34bc0
movl (%rax,%rcx,4), %ecx
movq -0x18(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x18(%rbp)
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x12bdc
movq -0x68(%rbp), %rax
movl (%rax), %ecx
addl -0xc(%rbp), %ecx
addl (%rax), %ecx
movl %ecx, (%rax)
cmpl $0x100, (%rax)          # imm = 0x100
jl 0x13263
movq -0x68(%rbp), %rax
movq 0x808(%rax), %rdi
movl (%rax), %esi
subl $0x100, %esi            # imm = 0x100
callq 0x132c0
movq -0x68(%rbp), %rax
movl $0x1, 0x4(%rax)
movl $0x1, (%rax)
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x13261
movq -0x68(%rbp), %rax
movq 0x808(%rax), %rdi
movl -0x5c(%rbp), %esi
callq 0x30e60
movl %eax, %edx
movq -0x68(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl %edx, 0x408(%rax,%rcx,4)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x1322a
jmp 0x132b4
movq -0x68(%rbp), %rax
cmpl $0x10, (%rax)
jl 0x13292
movq -0x68(%rbp), %rax
cmpl $0x20, (%rax)
jge 0x13292
movq -0x68(%rbp), %rax
movl 0x4(%rax), %ecx
andl $0xf, %ecx
shll $0x5, %ecx
movl -0xc(%rbp), %edx
shll $0x4, %edx
orl %edx, %ecx
orl $0x1, %ecx
movl %ecx, 0x4(%rax)
jmp 0x132b2
movq -0x68(%rbp), %rax
movl 0x4(%rax), %ecx
andl $0x1f0, %ecx            # imm = 0x1F0
movl 0x4(%rax), %edx
andl $0xf, %edx
shll %edx
addl -0xc(%rbp), %edx
andl $0xf, %edx
orl %edx, %ecx
movl %ecx, 0x4(%rax)
jmp 0x132b4
addq $0xc0, %rsp
popq %rbp
retq
nopl (%rax)