// File: /workspace/github_cpp_makefile_star2_O3/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 $0x14a8, %rsp           # imm = 0x14A8
leaq 0x53aa(%rip), %rsi      # 0x9328
leaq 0x120(%rsp), %rax
movl $0xb, %ecx
movq %rax, %rdi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x68(%rsp), %rdi
leaq 0xa8(%rsp), %rcx
movl $0xb, %edx
movq %rax, %rsi
callq 0x4c72
leaq 0x53ce(%rip), %rsi      # 0x9380
leaq 0x120(%rsp), %rax
movl $0xb, %ecx
movq %rax, %rdi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x50(%rsp), %rdi
leaq 0xa8(%rsp), %rcx
movl $0xb, %edx
movq %rax, %rsi
callq 0x4c72
leaq 0x120(%rsp), %rdi
callq 0x4bf4
movaps 0x5b4d(%rip), %xmm0     # 0x9b40
movaps %xmm0, 0x90(%rsp)
movaps 0x5b2e(%rip), %xmm0     # 0x9b30
movaps %xmm0, 0x80(%rsp)
movapd 0x510e(%rip), %xmm0     # 0x9120
movapd %xmm0, 0x40(%rsp)
movl $0x58, %edi
callq 0x21b0
xorpd %xmm0, %xmm0
movupd %xmm0, 0x40(%rax)
movupd %xmm0, 0x30(%rax)
movupd %xmm0, 0x20(%rax)
movupd %xmm0, 0x10(%rax)
movupd %xmm0, (%rax)
movq %rax, 0x38(%rsp)
movq $0x0, 0x50(%rax)
movl $0x58, %edi
callq 0x21b0
xorpd %xmm0, %xmm0
movupd %xmm0, 0x40(%rax)
movupd %xmm0, 0x30(%rax)
movupd %xmm0, 0x20(%rax)
movupd %xmm0, 0x10(%rax)
movupd %xmm0, (%rax)
movq %rax, 0x30(%rsp)
movq $0x0, 0x50(%rax)
xorl %r14d, %r14d
leaq 0xa8(%rsp), %r12
movsd 0x4f7f(%rip), %xmm1     # 0x9010
leaq 0xc(%rsp), %r13
leaq 0x120(%rsp), %rbx
movq %r14, 0x10(%rsp)
movq %r12, %rdi
movsd 0x4f5a(%rip), %xmm0     # 0x9008
callq 0x51c6
xorl %r14d, %r14d
movl $0xa, %r15d
xorl %ebp, %ebp
movl $0x0, 0xc(%rsp)
movq %r12, %rdi
movq %r13, %rsi
leaq 0x80(%rsp), %rdx
leaq 0x40(%rsp), %rcx
movq %rbx, %r8
callq 0x5230
movq %rax, %rcx
shrq $0x20, %rcx
je 0x40fd
testl %eax, %eax
movl %r14d, %ecx
cmovel %ebp, %ecx
incl %ecx
testl %eax, %eax
cmovel %ecx, %ebp
cmovnel %ecx, %r14d
decl %r15d
jne 0x40be
xorl %eax, %eax
movl %eax, (%rsp)
movl $0xa, %r15d
movl $0x0, 0xc(%rsp)
movq %r12, %rdi
movq %r13, %rsi
movq %rbx, %rdx
xorl %ecx, %ecx
callq 0x545a
movq %rax, %rcx
shrq $0x20, %rcx
je 0x4141
testl %eax, %eax
movl %r14d, %ecx
cmovel %ebp, %ecx
decl %ecx
testl %eax, %eax
cmovel %ecx, %ebp
cmovnel %ecx, %r14d
movq %r12, %rdi
movq %r13, %rsi
leaq 0x80(%rsp), %rdx
leaq 0x40(%rsp), %rcx
movq %rbx, %r8
callq 0x5230
movq %rax, %rcx
shrq $0x20, %rcx
je 0x4178
testl %eax, %eax
movl %r14d, %ecx
cmovel %ebp, %ecx
incl %ecx
testl %eax, %eax
cmovel %ecx, %ebp
cmovnel %ecx, %r14d
decl %r15d
jne 0x410d
movl (%rsp), %eax
incl %eax
cmpl $0x4, %eax
jne 0x4104
movslq %ebp, %rax
movq 0x30(%rsp), %rcx
movsd (%rcx,%rax,8), %xmm0
movsd 0x4e70(%rip), %xmm1     # 0x9010
addsd %xmm1, %xmm0
movsd %xmm0, (%rcx,%rax,8)
movslq %r14d, %rax
movq 0x38(%rsp), %rcx
movsd (%rcx,%rax,8), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rcx,%rax,8)
movq 0x10(%rsp), %r14
incl %r14d
leaq 0xb0(%rsp), %rdi
callq 0x5c98
movsd 0x4e34(%rip), %xmm1     # 0x9010
cmpl $0x30d40, %r14d         # imm = 0x30D40
jne 0x409e
movq 0x8e00(%rip), %rdi      # 0xcff0
leaq 0x5286(%rip), %rsi      # 0x947d
movl $0xa, %edx
callq 0x21c0
xorpd %xmm0, %xmm0
movsd %xmm0, (%rsp)
xorl %r14d, %r14d
movq 0x8ddc(%rip), %rbx      # 0xcff0
movsd %xmm0, 0x28(%rsp)
movq 0x38(%rsp), %rax
movsd (%rax,%r14), %xmm0
divsd 0x4e13(%rip), %xmm0     # 0x9040
movq 0x68(%rsp), %rax
subsd (%rax,%r14), %xmm0
movq %rbx, %rdi
movapd %xmm0, 0x10(%rsp)
callq 0x2230
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2190
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
movapd 0x10(%rsp), %xmm1
andpd 0x4e22(%rip), %xmm1     # 0x90a0
movsd (%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rsp)
maxsd 0x28(%rsp), %xmm1
addq $0x8, %r14
movapd %xmm1, %xmm0
cmpq $0x58, %r14
jne 0x4214
movapd %xmm1, 0x10(%rsp)
ucomisd 0x4d6e(%rip), %xmm1     # 0x9020
jbe 0x42cc
movq 0x8d35(%rip), %rdi      # 0xcff0
leaq 0x51cf(%rip), %rsi      # 0x9491
movl $0xb, %edx
callq 0x21c0
movq 0x8d1d(%rip), %rdi      # 0xcff0
leaq 0x51ae(%rip), %rsi      # 0x9488
movl $0x7, %edx
callq 0x21c0
movq 0x8d05(%rip), %rdi      # 0xcff0
movapd 0x10(%rsp), %xmm0
callq 0x2230
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2190
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
movsd (%rsp), %xmm0
divsd 0x4d1b(%rip), %xmm0     # 0x9048
movsd %xmm0, (%rsp)
ucomisd 0x4d16(%rip), %xmm0     # 0x9050
jbe 0x4354
movq 0x8cad(%rip), %rdi      # 0xcff0
leaq 0x5146(%rip), %rsi      # 0x9490
movl $0xc, %edx
callq 0x21c0
movq 0x8c95(%rip), %rdi      # 0xcff0
leaq 0x513b(%rip), %rsi      # 0x949d
movl $0x7, %edx
callq 0x21c0
movq 0x8c7d(%rip), %rdi      # 0xcff0
movsd (%rsp), %xmm0
callq 0x2230
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2190
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
movq 0x8c42(%rip), %rdi      # 0xcff0
leaq 0x50f0(%rip), %rsi      # 0x94a5
movl $0xc, %edx
callq 0x21c0
xorpd %xmm0, %xmm0
movsd %xmm0, 0x28(%rsp)
xorl %r14d, %r14d
movq 0x8c1d(%rip), %rbx      # 0xcff0
movsd %xmm0, (%rsp)
movq 0x30(%rsp), %rax
movsd (%rax,%r14), %xmm0
divsd 0x4c55(%rip), %xmm0     # 0x9040
movq 0x50(%rsp), %rax
subsd (%rax,%r14), %xmm0
movq %rbx, %rdi
movapd %xmm0, 0x10(%rsp)
callq 0x2230
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2190
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
movapd 0x10(%rsp), %xmm1
andpd 0x4c64(%rip), %xmm1     # 0x90a0
movsd (%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rsp)
maxsd 0x28(%rsp), %xmm1
addq $0x8, %r14
movsd %xmm1, 0x28(%rsp)
cmpq $0x58, %r14
jne 0x43d8
movapd %xmm1, 0x10(%rsp)
ucomisd 0x4bae(%rip), %xmm1     # 0x9020
jbe 0x448c
movq 0x8b75(%rip), %rdi      # 0xcff0
leaq 0x500f(%rip), %rsi      # 0x9491
movl $0xb, %edx
callq 0x21c0
movq 0x8b5d(%rip), %rdi      # 0xcff0
leaq 0x5018(%rip), %rsi      # 0x94b2
movl $0x9, %edx
callq 0x21c0
movq 0x8b45(%rip), %rdi      # 0xcff0
movapd 0x10(%rsp), %xmm0
callq 0x2230
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2190
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
movsd (%rsp), %xmm0
divsd 0x4b5b(%rip), %xmm0     # 0x9048
movsd %xmm0, (%rsp)
ucomisd 0x4b56(%rip), %xmm0     # 0x9050
jbe 0x4514
movq 0x8aed(%rip), %rdi      # 0xcff0
leaq 0x4f86(%rip), %rsi      # 0x9490
movl $0xc, %edx
callq 0x21c0
movq 0x8ad5(%rip), %rdi      # 0xcff0
leaq 0x4f9a(%rip), %rsi      # 0x94bc
movl $0x9, %edx
callq 0x21c0
movq 0x8abd(%rip), %rdi      # 0xcff0
movsd (%rsp), %xmm0
callq 0x2230
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2190
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
movq 0x30(%rsp), %rdi
callq 0x2180
movq 0x38(%rsp), %rdi
callq 0x2180
movq 0x50(%rsp), %rdi
testq %rdi, %rdi
je 0x458a
callq 0x2180
movq 0x68(%rsp), %rdi
testq %rdi, %rdi
je 0x4599
callq 0x2180
addq $0x14a8, %rsp           # imm = 0x14A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x45c6
movq %rax, %rbx
jmp 0x45e9
jmp 0x45b4
movq %rax, %rbx
jmp 0x45f3
movq %rax, %rbx
jmp 0x4602
jmp 0x45c6
jmp 0x45c6
jmp 0x45c6
jmp 0x45c6
movq %rax, %rbx
jmp 0x45df
jmp 0x45cf
jmp 0x45cf
movq %rax, %rbx
leaq 0xb0(%rsp), %rdi
callq 0x5c98
movq 0x30(%rsp), %rdi
callq 0x2180
movq 0x38(%rsp), %rdi
callq 0x2180
movq 0x50(%rsp), %rdi
testq %rdi, %rdi
je 0x4602
callq 0x2180
movq 0x68(%rsp), %rdi
testq %rdi, %rdi
je 0x4611
callq 0x2180
movq %rbx, %rdi
callq 0x2270