// File: /workspace/github_cpp_makefile_star2_O2/redpony[P]cpyp/crp_test.cc
// Function: test_mfcrp()
void test_mfcrp() {
  vector<double> ref_up = {0.0152302, 0.0754287, 0.153957, 0.209485, 0.213071, 0.16726, 0.101233, 0.0460308, 0.0149256, 0.003075, 0.00030408};
  vector<double> ref_down = {0.185252, 0.32385, 0.271888, 0.145849, 0.0548223, 0.0149361, 0.00294062, 0.0004185, 4.074e-05, 2.3e-06, 4e-08};

  cpyp::MT19937 eng;
  long double p0[2]{1.0,1.0}; // pa(0), pb(0)
  double lam[2]{0.3,0.7};
  vector<double> hist_upstairs(11, 0);
  vector<double> hist_downstairs(11, 0);
  int c = 0;
  for (int n = 0; n < 200000; ++n) {
    cpyp::mf_crp<2, unsigned> crp(0.5, 1.0);
    int upstairs = 0;
    int downstairs = 0;
    for (int i = 0; i < 10; ++i) {
      unsigned obs = 0;
      pair<unsigned, int> floor_count = crp.increment(obs, p0, lam, eng);
      if (floor_count.second) (floor_count.first ? upstairs : downstairs)++;
    }
    // resample some stuff
    for (int j = 0; j < 4; ++j) {
      for (int i = 0; i < 10; ++i) {
        unsigned obs = 0;
        pair<unsigned, int> floor_count = crp.decrement(obs, eng);
        if (floor_count.second) (floor_count.first ? upstairs : downstairs)--;
        floor_count = crp.increment(obs, p0, lam, eng);
        if (floor_count.second) (floor_count.first ? upstairs : downstairs)++;
      }
    }
    hist_downstairs[downstairs] += 1.0;
    hist_upstairs[upstairs] += 1.0;
    ++c;
  }
  cerr << "Upstairs:\n";
  int j = 0;
  double max_up = 0;
  double tot_up = 0;
  for (auto& d : hist_upstairs) {
    double diff = d / c - ref_up[j++];
    cerr << diff << endl;
    if (fabs(diff) > max_up) max_up = fabs(diff);
    tot_up += fabs(diff);
  }
  if (max_up > 0.01) { cerr << "** TOO BIG "; }
  cerr << "max_up=" << max_up << endl;
  tot_up /= 11;
  if (tot_up > 0.005) { cerr << "*** TOO BIG "; }
  cerr << "avg_up=" << tot_up << endl;
  cerr << "Downstairs:\n";
  j = 0;
  double tot_down = 0;
  double max_down = 0;
  for (auto& d : hist_downstairs) {
    double diff = (d / c - ref_down[j++]);
    cerr << diff << endl;
    if (fabs(diff) > max_down) max_down = fabs(diff);
    tot_down += fabs(diff);
  }
  if (max_down > 0.01) { cerr << "** TOO BIG "; }
  cerr << "max_down=" << max_down << endl;
  tot_down /= 11;
  if (tot_down > 0.005) { cerr << "*** TOO BIG "; }
  cerr << "avg_down=" << tot_down << endl;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x14c8, %rsp           # imm = 0x14C8
leaq 0x5d44(%rip), %rsi      # 0x92f8
pushq $0xb
popq %rbx
leaq 0x140(%rsp), %rax
movq %rbx, %rcx
movq %rax, %rdi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x88(%rsp), %rdi
leaq 0xc8(%rsp), %rcx
movq %rax, %rsi
movq %rbx, %rdx
callq 0x3f4a
leaq 0x5d66(%rip), %rsi      # 0x9350
leaq 0x140(%rsp), %rax
movq %rbx, %rcx
movq %rax, %rdi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x70(%rsp), %rdi
leaq 0xc8(%rsp), %rcx
movq %rax, %rsi
movq %rbx, %rdx
callq 0x3f4a
leaq 0x140(%rsp), %rdi
callq 0x3f30
movaps 0x65a9(%rip), %xmm0     # 0x9bd0
movaps %xmm0, 0xb0(%rsp)
movaps 0x658a(%rip), %xmm0     # 0x9bc0
movaps %xmm0, 0xa0(%rsp)
movapd 0x5aaa(%rip), %xmm0     # 0x90f0
movapd %xmm0, 0x60(%rsp)
leaq 0xc8(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x48(%rsp), %rdi
pushq $0xb
popq %rsi
leaq 0x18(%rsp), %rcx
callq 0x4488
leaq 0xc8(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x18(%rsp), %rdi
pushq $0xb
popq %rsi
leaq 0x14(%rsp), %rcx
callq 0x4488
xorl %ebx, %ebx
leaq 0xc8(%rsp), %r14
leaq 0x14(%rsp), %r15
leaq 0x140(%rsp), %r12
cmpl $0x30d40, %ebx          # imm = 0x30D40
je 0x37e6
movq %rbx, 0x8(%rsp)
movq %r14, %rdi
movsd 0x594d(%rip), %xmm0     # 0x9008
movsd 0x594d(%rip), %xmm1     # 0x9010
callq 0x44de
xorl %r13d, %r13d
pushq $0xa
popq %rbp
xorl %ebx, %ebx
subl $0x1, %ebp
jb 0x3713
andl $0x0, 0x14(%rsp)
movq %r14, %rdi
movq %r15, %rsi
leaq 0xa0(%rsp), %rdx
leaq 0x60(%rsp), %rcx
movq %r12, %r8
callq 0x4546
movq %rax, %rcx
shrq $0x20, %rcx
je 0x36d0
testl %eax, %eax
movl %ebx, %ecx
cmovel %r13d, %ecx
incl %ecx
testl %eax, %eax
cmovel %ecx, %r13d
cmovnel %ecx, %ebx
jmp 0x36d0
xorl %eax, %eax
cmpl $0x4, %eax
je 0x3799
movl %eax, (%rsp)
pushq $0xa
popq %rbp
subl $0x1, %ebp
jb 0x378f
andl $0x0, 0x14(%rsp)
movq %r14, %rdi
movq %r15, %rsi
movq %r12, %rdx
xorl %ecx, %ecx
callq 0x46be
movq %rax, %rcx
shrq $0x20, %rcx
je 0x3756
testl %eax, %eax
movl %ebx, %ecx
cmovel %r13d, %ecx
decl %ecx
testl %eax, %eax
cmovel %ecx, %r13d
cmovnel %ecx, %ebx
movq %r14, %rdi
movq %r15, %rsi
leaq 0xa0(%rsp), %rdx
leaq 0x60(%rsp), %rcx
movq %r12, %r8
callq 0x4546
movq %rax, %rcx
shrq $0x20, %rcx
je 0x3720
testl %eax, %eax
movl %ebx, %ecx
cmovel %r13d, %ecx
incl %ecx
testl %eax, %eax
cmovel %ecx, %r13d
cmovnel %ecx, %ebx
jmp 0x3720
movl (%rsp), %eax
incl %eax
jmp 0x3715
movslq %r13d, %rax
movq 0x18(%rsp), %rcx
movsd (%rcx,%rax,8), %xmm0
movsd 0x5862(%rip), %xmm1     # 0x9010
addsd %xmm1, %xmm0
movsd %xmm0, (%rcx,%rax,8)
movslq %ebx, %rax
movq 0x48(%rsp), %rcx
movsd (%rcx,%rax,8), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rcx,%rax,8)
movq 0x8(%rsp), %rbx
incl %ebx
leaq 0xd0(%rsp), %rdi
callq 0x5024
jmp 0x369f
movq 0xa803(%rip), %rdi      # 0xdff0
leaq 0x5c5a(%rip), %rsi      # 0x944e
callq 0x2170
movq 0x48(%rsp), %r14
movq 0x50(%rsp), %r15
xorpd %xmm0, %xmm0
movsd %xmm0, 0x8(%rsp)
xorl %r12d, %r12d
movq 0xa7d9(%rip), %rbx      # 0xdff0
movsd %xmm0, (%rsp)
leaq (%r14,%r12), %rax
cmpq %r15, %rax
je 0x3883
movsd (%rax), %xmm0
divsd 0x580f(%rip), %xmm0     # 0x9040
movq 0x88(%rsp), %rax
subsd (%rax,%r12), %xmm0
movq %rbx, %rdi
movapd %xmm0, 0x30(%rsp)
callq 0x2200
movq %rax, %rdi
callq 0x2080
movapd 0x30(%rsp), %xmm1
andpd 0x583d(%rip), %xmm1     # 0x90a0
movsd (%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rsp)
maxsd 0x8(%rsp), %xmm1
addq $0x8, %r12
movsd %xmm1, 0x8(%rsp)
jmp 0x381c
movsd 0x8(%rsp), %xmm0
ucomisd 0x578f(%rip), %xmm0     # 0x9020
jbe 0x38a6
movq 0xa756(%rip), %rdi      # 0xdff0
leaq 0x5bc1(%rip), %rsi      # 0x9462
callq 0x2170
movq 0xa743(%rip), %rdi      # 0xdff0
leaq 0x5ba5(%rip), %rsi      # 0x9459
callq 0x2170
movq %rax, %rdi
movsd 0x8(%rsp), %xmm0
callq 0x2200
movq %rax, %rdi
callq 0x2080
movsd (%rsp), %xmm0
divsd 0x576c(%rip), %xmm0     # 0x9048
movsd %xmm0, (%rsp)
ucomisd 0x5767(%rip), %xmm0     # 0x9050
jbe 0x38fe
movq 0xa6fe(%rip), %rdi      # 0xdff0
leaq 0x5b68(%rip), %rsi      # 0x9461
callq 0x2170
movq 0xa6eb(%rip), %rdi      # 0xdff0
leaq 0x5b62(%rip), %rsi      # 0x946e
callq 0x2170
movq %rax, %rdi
movsd (%rsp), %xmm0
callq 0x2200
movq %rax, %rdi
callq 0x2080
movq 0xa6c3(%rip), %rdi      # 0xdff0
leaq 0x5b42(%rip), %rsi      # 0x9476
callq 0x2170
movq 0x18(%rsp), %r14
movq 0x20(%rsp), %r15
xorpd %xmm0, %xmm0
movsd %xmm0, (%rsp)
xorl %r12d, %r12d
movq 0xa69a(%rip), %rbx      # 0xdff0
movsd %xmm0, 0x8(%rsp)
leaq (%r14,%r12), %rax
cmpq %r15, %rax
je 0x39c0
movsd (%rax), %xmm0
divsd 0x56cf(%rip), %xmm0     # 0x9040
movq 0x70(%rsp), %rax
subsd (%rax,%r12), %xmm0
movq %rbx, %rdi
movapd %xmm0, 0x30(%rsp)
callq 0x2200
movq %rax, %rdi
callq 0x2080
movapd 0x30(%rsp), %xmm1
andpd 0x5700(%rip), %xmm1     # 0x90a0
movsd (%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rsp)
maxsd 0x8(%rsp), %xmm1
addq $0x8, %r12
movsd %xmm1, 0x8(%rsp)
jmp 0x395c
movsd 0x8(%rsp), %xmm0
ucomisd 0x5652(%rip), %xmm0     # 0x9020
jbe 0x39e3
movq 0xa619(%rip), %rdi      # 0xdff0
leaq 0x5a84(%rip), %rsi      # 0x9462
callq 0x2170
movq 0xa606(%rip), %rdi      # 0xdff0
leaq 0x5a92(%rip), %rsi      # 0x9483
callq 0x2170
movq %rax, %rdi
movsd 0x8(%rsp), %xmm0
callq 0x2200
movq %rax, %rdi
callq 0x2080
movsd (%rsp), %xmm0
divsd 0x562f(%rip), %xmm0     # 0x9048
movsd %xmm0, (%rsp)
ucomisd 0x562a(%rip), %xmm0     # 0x9050
jbe 0x3a3b
movq 0xa5c1(%rip), %rdi      # 0xdff0
leaq 0x5a2b(%rip), %rsi      # 0x9461
callq 0x2170
movq 0xa5ae(%rip), %rdi      # 0xdff0
leaq 0x5a44(%rip), %rsi      # 0x948d
callq 0x2170
movq %rax, %rdi
movsd (%rsp), %xmm0
callq 0x2200
movq %rax, %rdi
callq 0x2080
leaq 0x18(%rsp), %rdi
callq 0x59a8
leaq 0x48(%rsp), %rdi
callq 0x59a8
leaq 0x70(%rsp), %rdi
callq 0x59a8
leaq 0x88(%rsp), %rdi
callq 0x59a8
addq $0x14c8, %rsp           # imm = 0x14C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3abb
movq %rax, %r14
jmp 0x3ade
jmp 0x3aa9
movq %rax, %r14
jmp 0x3ae8
movq %rax, %r14
jmp 0x3af2
jmp 0x3abb
jmp 0x3abb
jmp 0x3abb
jmp 0x3abb
movq %rax, %r14
jmp 0x3ad4
jmp 0x3ac4
jmp 0x3ac4
movq %rax, %r14
leaq 0xd0(%rsp), %rdi
callq 0x5024
leaq 0x18(%rsp), %rdi
callq 0x59a8
leaq 0x48(%rsp), %rdi
callq 0x59a8
leaq 0x70(%rsp), %rdi
callq 0x59a8
leaq 0x88(%rsp), %rdi
callq 0x59a8
movq %r14, %rdi
callq 0x2240