// File: redpony[P]cpyp/crp_test.cc
// Function: main
int main() {
  cpyp::MT19937 eng;
  double tot = 0;
  double xt = 0;
  cpyp::crp<int> crp(0.5, 1.0);
  unsigned cust = 10;
  vector<int> hist(cust + 1, 0);
  for (unsigned i = 0; i < cust; ++i) { crp.increment(1, 1.0, eng); }
  const int samples = 200000;
  const bool simulate = true;
  for (int k = 0; k < samples; ++k) {
  if (!simulate) {
    crp.clear();
    for (unsigned i = 0; i < cust; ++i) { crp.increment(1, 1.0, eng); }
  } else {
    unsigned da = cpyp::sample_uniform01<double>(eng) * cust;
    bool a = cpyp::sample_uniform01<double>(eng) < 0.5;
    if (a) {
      for (unsigned i = 0; i < da; ++i) { crp.increment(1, 1.0, eng); }
      for (unsigned i = 0; i < da; ++i) { crp.decrement(1, eng); }
      xt += 1.0;
    } else {
      for (unsigned i = 0; i < da; ++i) { crp.decrement(1, eng); }
      for (unsigned i = 0; i < da; ++i) { crp.increment(1, 1.0, eng); }
    }
  }
  int c = crp.num_tables(1);
  ++hist[c];
  tot += c;
  }
  assert(cust == crp.num_customers());
  cerr << crp << endl;
  cerr << crp.log_likelihood() << endl;
  cerr << "P(a) = " << (xt / samples) << endl;
  cerr << "mean num tables = " << (tot / samples) << endl;
  double error = fabs((tot / samples) - 5.4);
  cerr << "  error = " << error << endl;
  for (unsigned i = 1; i <= cust; ++i)
  cerr << i << ' ' << (hist[i]) << endl;
  if (error > 0.1) {
    cerr << "*** error is too big = " << error << endl;
    return 1;
  }
  test_mh1();
  test_mh1a();
  test_mh2();
  test_mfcrp();
  return 0;
}

// Assembly:
subq $0x1568, %rsp           # imm = 0x1568
movl $0x0, 0x1564(%rsp)
leaq 0x1d8(%rsp), %rdi
callq 0x5e30
movq $0x0, 0x1d0(%rsp)
movq $0x0, 0x1c8(%rsp)
leaq 0x150(%rsp), %rdi
movsd 0xfa61(%rip), %xmm0     # 0x15008
movsd 0xfa61(%rip), %xmm1     # 0x15010
callq 0x5f10
movl $0xa, 0x14c(%rsp)
movl 0x14c(%rsp), %eax
incl %eax
movq %rax, 0x98(%rsp)
movl $0x0, 0x12c(%rsp)
leaq 0x12b(%rsp), %rdi
movq %rdi, 0xa0(%rsp)
callq 0x5fd0
movq 0x98(%rsp), %rsi
movq 0xa0(%rsp), %rcx
leaq 0x130(%rsp), %rdi
leaq 0x12c(%rsp), %rdx
callq 0x5fe0
jmp 0x5617
leaq 0x12b(%rsp), %rdi
callq 0x6060
movl $0x0, 0x118(%rsp)
movl 0x118(%rsp), %eax
cmpl 0x14c(%rsp), %eax
jae 0x56e8
movl $0x1, 0x114(%rsp)
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, 0x108(%rsp)
leaq 0x150(%rsp), %rdi
leaq 0x114(%rsp), %rsi
leaq 0x108(%rsp), %rdx
leaq 0x1d8(%rsp), %rcx
callq 0x6390
jmp 0x5687
jmp 0x5689
movl 0x118(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x118(%rsp)
jmp 0x562f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x120(%rsp)
movl %eax, 0x11c(%rsp)
leaq 0x12b(%rsp), %rdi
callq 0x6060
jmp 0x5d3a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x120(%rsp)
movl %eax, 0x11c(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x66e0
jmp 0x5d3a
movl $0x30d40, 0x104(%rsp) # imm = 0x30D40
movb $0x1, 0x103(%rsp)
movl $0x0, 0xfc(%rsp)
cmpl $0x30d40, 0xfc(%rsp) # imm = 0x30D40
jge 0x59e4
leaq 0x1d8(%rsp), %rdi
callq 0x6510
movsd %xmm0, 0x90(%rsp)
jmp 0x572f
movsd 0x90(%rsp), %xmm0
movl 0x14c(%rsp), %eax
cvtsi2sd %rax, %xmm1
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movl %eax, 0xf8(%rsp)
leaq 0x1d8(%rsp), %rdi
callq 0x6510
movsd %xmm0, 0x88(%rsp)
jmp 0x576c
movsd 0x88(%rsp), %xmm1
movsd 0xf88b(%rip), %xmm0     # 0x15008
ucomisd %xmm1, %xmm0
seta %al
andb $0x1, %al
movb %al, 0xf7(%rsp)
testb $0x1, 0xf7(%rsp)
je 0x588c
movl $0x0, 0xf0(%rsp)
movl 0xf0(%rsp), %eax
cmpl 0xf8(%rsp), %eax
jae 0x580f
movl $0x1, 0xec(%rsp)
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, 0xe0(%rsp)
leaq 0x150(%rsp), %rdi
leaq 0xec(%rsp), %rsi
leaq 0xe0(%rsp), %rdx
leaq 0x1d8(%rsp), %rcx
callq 0x6390
jmp 0x57fa
jmp 0x57fc
movl 0xf0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf0(%rsp)
jmp 0x57a6
movl $0x0, 0xdc(%rsp)
movl 0xdc(%rsp), %eax
cmpl 0xf8(%rsp), %eax
jae 0x586d
movl $0x1, 0xd8(%rsp)
xorl %eax, %eax
movl %eax, %ecx
leaq 0x150(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
leaq 0x1d8(%rsp), %rdx
callq 0x60d0
jmp 0x5858
jmp 0x585a
movl 0xdc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xdc(%rsp)
jmp 0x581a
movsd 0xf79b(%rip), %xmm0     # 0x15010
addsd 0x1c8(%rsp), %xmm0
movsd %xmm0, 0x1c8(%rsp)
jmp 0x5960
movl $0x0, 0xd4(%rsp)
movl 0xd4(%rsp), %eax
cmpl 0xf8(%rsp), %eax
jae 0x58ea
movl $0x1, 0xd0(%rsp)
xorl %eax, %eax
movl %eax, %ecx
leaq 0x150(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
leaq 0x1d8(%rsp), %rdx
callq 0x60d0
jmp 0x58d5
jmp 0x58d7
movl 0xd4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd4(%rsp)
jmp 0x5897
movl $0x0, 0xcc(%rsp)
movl 0xcc(%rsp), %eax
cmpl 0xf8(%rsp), %eax
jae 0x595e
movl $0x1, 0xc8(%rsp)
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, 0xc0(%rsp)
leaq 0x150(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
leaq 0x1d8(%rsp), %rcx
callq 0x6390
jmp 0x5949
jmp 0x594b
movl 0xcc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xcc(%rsp)
jmp 0x58f5
jmp 0x5960
movl $0x1, 0xb8(%rsp)
leaq 0x150(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x5db0
movl %eax, 0x84(%rsp)
jmp 0x5989
movl 0x84(%rsp), %eax
movl %eax, 0xbc(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x130(%rsp), %rdi
callq 0x65c0
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
cvtsi2sdl 0xbc(%rsp), %xmm0
addsd 0x1d0(%rsp), %xmm0
movsd %xmm0, 0x1d0(%rsp)
movl 0xfc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xfc(%rsp)
jmp 0x5706
movl 0x14c(%rsp), %eax
movl %eax, 0x7c(%rsp)
leaq 0x150(%rsp), %rdi
callq 0x7480
movl %eax, 0x80(%rsp)
jmp 0x5a05
movl 0x7c(%rsp), %eax
movl 0x80(%rsp), %ecx
cmpl %ecx, %eax
jne 0x5a16
jmp 0x5a35
leaq 0xfaba(%rip), %rdi      # 0x154d7
leaq 0xfa24(%rip), %rsi      # 0x15448
movl $0x13b, %edx            # imm = 0x13B
leaq 0xfac3(%rip), %rcx      # 0x154f3
callq 0x20e0
movq 0x185b4(%rip), %rdi     # 0x1dff0
leaq 0x150(%rsp), %rsi
callq 0x7490
movq %rax, 0x70(%rsp)
jmp 0x5a50
movq 0x70(%rsp), %rdi
movq 0x1856c(%rip), %rsi     # 0x1dfc8
callq 0x21a0
jmp 0x5a63
leaq 0x150(%rsp), %rdi
callq 0x5d90
movsd %xmm0, 0x68(%rsp)
jmp 0x5a78
movsd 0x68(%rsp), %xmm0
movq 0x1856b(%rip), %rdi     # 0x1dff0
callq 0x2290
movq %rax, 0x60(%rsp)
jmp 0x5a91
movq 0x60(%rsp), %rdi
movq 0x1852b(%rip), %rsi     # 0x1dfc8
callq 0x21a0
jmp 0x5aa4
movq 0x18545(%rip), %rdi     # 0x1dff0
leaq 0xfa4c(%rip), %rsi      # 0x154fe
callq 0x2180
movq %rax, 0x58(%rsp)
jmp 0x5abe
movq 0x58(%rsp), %rdi
movsd 0x1c8(%rsp), %xmm0
movsd 0xf574(%rip), %xmm1     # 0x15048
divsd %xmm1, %xmm0
callq 0x2290
movq %rax, 0x50(%rsp)
jmp 0x5ae4
movq 0x50(%rsp), %rdi
movq 0x184d8(%rip), %rsi     # 0x1dfc8
callq 0x21a0
jmp 0x5af7
movq 0x184f2(%rip), %rdi     # 0x1dff0
leaq 0xfa01(%rip), %rsi      # 0x15506
callq 0x2180
movq %rax, 0x48(%rsp)
jmp 0x5b11
movq 0x48(%rsp), %rdi
movsd 0x1d0(%rsp), %xmm0
movsd 0xf521(%rip), %xmm1     # 0x15048
divsd %xmm1, %xmm0
callq 0x2290
movq %rax, 0x40(%rsp)
jmp 0x5b37
movq 0x40(%rsp), %rdi
movq 0x18485(%rip), %rsi     # 0x1dfc8
callq 0x21a0
jmp 0x5b4a
movsd 0x1d0(%rsp), %xmm0
movsd 0xf4ed(%rip), %xmm1     # 0x15048
divsd %xmm1, %xmm0
movsd 0xf4e9(%rip), %xmm1     # 0x15050
addsd %xmm1, %xmm0
movaps 0xf50e(%rip), %xmm1     # 0x15080
pand %xmm1, %xmm0
movlpd %xmm0, 0xb0(%rsp)
movq 0x1846a(%rip), %rdi     # 0x1dff0
leaq 0xf98c(%rip), %rsi      # 0x15519
callq 0x2180
movq %rax, 0x38(%rsp)
jmp 0x5b99
movq 0x38(%rsp), %rdi
movsd 0xb0(%rsp), %xmm0
callq 0x2290
movq %rax, 0x30(%rsp)
jmp 0x5bb3
movq 0x30(%rsp), %rdi
movq 0x18409(%rip), %rsi     # 0x1dfc8
callq 0x21a0
jmp 0x5bc6
movl $0x1, 0xac(%rsp)
movl 0xac(%rsp), %eax
cmpl 0x14c(%rsp), %eax
ja 0x5c69
movl 0xac(%rsp), %esi
movq 0x183fd(%rip), %rdi     # 0x1dff0
callq 0x2200
movq %rax, 0x28(%rsp)
jmp 0x5bff
movq 0x28(%rsp), %rdi
movl $0x20, %esi
callq 0x21c0
movq %rax, 0x20(%rsp)
jmp 0x5c15
movl 0xac(%rsp), %eax
movl %eax, %esi
leaq 0x130(%rsp), %rdi
callq 0x65c0
movq 0x20(%rsp), %rdi
movl (%rax), %esi
callq 0x2250
movq %rax, 0x18(%rsp)
jmp 0x5c3e
movq 0x18(%rsp), %rdi
movq 0x1837e(%rip), %rsi     # 0x1dfc8
callq 0x21a0
jmp 0x5c51
jmp 0x5c53
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x5bd1
movsd 0xb0(%rsp), %xmm0
movsd 0xf3de(%rip), %xmm1     # 0x15058
ucomisd %xmm1, %xmm0
jbe 0x5cdf
movq 0x18369(%rip), %rdi     # 0x1dff0
leaq 0xf896(%rip), %rsi      # 0x15524
callq 0x2180
movq %rax, 0x10(%rsp)
jmp 0x5c9a
movq 0x10(%rsp), %rdi
movsd 0xb0(%rsp), %xmm0
callq 0x2290
movq %rax, 0x8(%rsp)
jmp 0x5cb4
movq 0x8(%rsp), %rdi
movq 0x18308(%rip), %rsi     # 0x1dfc8
callq 0x21a0
jmp 0x5cc7
movl $0x1, 0x1564(%rsp)
movl $0x1, 0xa8(%rsp)
jmp 0x5d11
callq 0x24a0
jmp 0x5ce6
callq 0x2d90
jmp 0x5ced
callq 0x3600
jmp 0x5cf4
callq 0x4910
jmp 0x5cfb
movl $0x0, 0x1564(%rsp)
movl $0x1, 0xa8(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x66e0
leaq 0x150(%rsp), %rdi
callq 0x65a0
movl 0x1564(%rsp), %eax
addq $0x1568, %rsp           # imm = 0x1568
retq
leaq 0x150(%rsp), %rdi
callq 0x65a0
movq 0x120(%rsp), %rdi
callq 0x2260
nopw %cs:(%rax,%rax)
nop