// File: /workspace/github_cpp_makefile_star2_O3/mburhanpurkar[P]fast_xorshift_plus/test_rng.cpp
// Function: test_xorshift(int)
inline bool test_xorshift(int niter=10000)
{
    random_device rd;
    uint64_t rn1 = rng_helpers::rd64(rd);
    uint64_t rn2 = rng_helpers::rd64(rd);
    uint64_t rn3 = rng_helpers::rd64(rd);
    uint64_t rn4 = rng_helpers::rd64(rd);
    uint64_t rn5 = rng_helpers::rd64(rd);
    uint64_t rn6 = rng_helpers::rd64(rd);
    uint64_t rn7 = rng_helpers::rd64(rd);
    uint64_t rn8 = rng_helpers::rd64(rd);
          
    fast_rng::vec_xorshift_plus a(_mm256_setr_epi64x(rn1, rn3, rn5, rn7), _mm256_setr_epi64x(rn2, rn4, rn6, rn8));
    float vrn_vec[8];
    rng_helpers::xorshift_plus b(rn1, rn2, rn3, rn4, rn5, rn6, rn7, rn8);
    float srn_vec[8];

    for (int iter=0; iter < niter; iter++)
    {
        __m256 vrn = a.gen_floats();
	_mm256_storeu_ps(&vrn_vec[0], vrn);
	b.gen_floats(srn_vec);
	
	for (int i=0; i<8; i++)
	{
	    if (srn_vec[i] != vrn_vec[i])
	    {
	        cout << "S code outputs: ";
		print_vec(srn_vec);
		cout << "V code outputs: ";
		print_vec(vrn_vec);
		cout << "rng test failed: scalar and vectorized prngs are out of sync on iter " << i << "!" << endl;
		return false;
	    }
	}
    }

    // Check that array generation is working
    int n = 10000;
    float *big_scalar = new float[n];
    float *big_vector = new float[n];

    a.gen_arr(big_vector, n);

    for (int i = 0; i < n; i += 8)
        b.gen_floats(big_scalar + i);
	  
    for (int i = 0; i < n; i++)
    {
        if (big_scalar[i] < -1 || big_scalar[i] > 1 || big_vector[i] < -1 || big_vector[i] > 1)
	{
	    cout << "Oh no, something isn't outputting a floating point number between (-1, 1). This is very bad!" << endl;
	}
        if (big_scalar[i] != big_vector[i])
	{
	    cout << "The output of vec_xorshift_plus: gen_arr diverged from the scalar implementation at iteration " << i << endl;
	    return false;
	}
    }
	  
    cout << "All rng tests passed." << endl;
    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1478, %rsp           # imm = 0x1478
leaq 0xf0(%rsp), %rbx
movl %edi, 0x1c(%rsp)
movq %rbx, %rdi
callq 0x302a
movq %rbx, %rdi
callq 0x2160
movl %eax, 0x20(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2160
leaq 0xf0(%rsp), %rdi
movl %eax, %r14d
callq 0x2160
leaq 0xf0(%rsp), %rdi
movl %eax, %r15d
callq 0x2160
leaq 0xf0(%rsp), %rdi
movl %eax, %r12d
callq 0x2160
movl %eax, 0x40(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2160
leaq 0xf0(%rsp), %rdi
movl %eax, %ebx
callq 0x2160
movl %eax, 0x18(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2160
leaq 0xf0(%rsp), %rdi
movl %eax, %ebp
callq 0x2160
movl %eax, 0x14(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2160
leaq 0xf0(%rsp), %rdi
movl %eax, %r13d
callq 0x2160
movl %eax, 0x10(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2160
movq %rax, 0x70(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2160
movl %eax, 0xc(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2160
movq %rax, 0x68(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2160
movl %eax, 0x8(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2160
movq %rbp, %rcx
movl 0x18(%rsp), %ebp
shlq $0x20, %rcx
movl 0x20(%rsp), %edx
shlq $0x20, %r14
movl %r15d, %edi
movl 0x40(%rsp), %r15d
shlq $0x20, %r12
shlq $0x20, %rbx
shlq $0x20, %rax
leaq 0xb0(%rsp), %rsi
orq %r12, %rdi
movl 0xc(%rsp), %r12d
movq %rdi, 0x20(%rsp)
orq %rcx, %rbp
movq %r13, %rcx
movl 0x14(%rsp), %r13d
shlq $0x20, %rcx
orq %r14, %rdx
movl 0x10(%rsp), %r14d
orq %rbx, %r15
movl 0x8(%rsp), %ebx
movq %rdx, (%rsi)
movq %rdi, 0x8(%rsi)
movq %r15, 0x10(%rsi)
movq %rdx, 0x40(%rsp)
movq %rbp, 0x18(%rsi)
orq %rcx, %r13
movq 0x70(%rsp), %rcx
orq %rax, %rbx
movq %r13, 0x20(%rsi)
shlq $0x20, %rcx
orq %rcx, %r14
movq 0x68(%rsp), %rcx
movq %r14, 0x28(%rsi)
shlq $0x20, %rcx
orq %rcx, %r12
movq %r12, 0x30(%rsi)
movq %rbx, 0x38(%rsi)
leaq 0x78(%rsp), %rdi
leaq 0x7(%rsp), %rcx
movl $0x8, %edx
callq 0x3134
vmovq 0x20(%rsp), %xmm2
vmovq 0x40(%rsp), %xmm3
vmovq %rbx, %xmm0
vmovq %r14, %xmm1
movl 0x1c(%rsp), %edx
vpunpcklqdq %xmm0, %xmm1, %xmm0 # xmm0 = xmm1[0],xmm0[0]
vmovq %rbp, %xmm1
vpunpcklqdq %xmm1, %xmm2, %xmm1 # xmm1 = xmm2[0],xmm1[0]
vinserti128 $0x1, %xmm0, %ymm1, %ymm0
vmovq %r13, %xmm1
vmovdqu %ymm0, 0x20(%rsp)
vmovq %r12, %xmm0
vpunpcklqdq %xmm0, %xmm1, %xmm0 # xmm0 = xmm1[0],xmm0[0]
vmovq %r15, %xmm1
vpunpcklqdq %xmm1, %xmm3, %xmm1 # xmm1 = xmm3[0],xmm1[0]
vinserti128 $0x1, %xmm0, %ymm1, %ymm5
testl %edx, %edx
jle 0x2b3f
movq 0x78(%rsp), %rax
vbroadcastss 0x18c5(%rip), %ymm1 # 0x4180
vbroadcastsd 0x18ac(%rip), %ymm3 # 0x4170
vpmovsxbq 0x18aa(%rip), %zmm2 # 0x4178
vmovapd 0x1828(%rip), %zmm4     # 0x4100
xorl %ecx, %ecx
vmovdqu64 (%rax), %zmm0
vmovdqu 0x20(%rsp), %ymm8
vpsllq $0x17, %ymm5, %ymm6
xorl %r14d, %r14d
vpxor %ymm5, %ymm6, %ymm5
vpsrlq $0x11, %ymm5, %ymm6
vpsrlq $0x1a, %ymm8, %ymm7
vmovdqu %ymm8, 0x40(%rsp)
vpxor %ymm6, %ymm7, %ymm6
vpternlogq $0x96, %ymm8, %ymm5, %ymm6
vpaddq %ymm6, %ymm8, %ymm5
vmovdqu %ymm6, 0x20(%rsp)
vcvtdq2ps %ymm5, %ymm5
vmulps %ymm1, %ymm5, %ymm5
vmovups %ymm5, 0x90(%rsp)
vextracti64x4 $0x1, %zmm0, %ymm5
vpunpcklqdq %ymm5, %ymm0, %ymm6 # ymm6 = ymm0[0],ymm5[0],ymm0[2],ymm5[2]
vpunpckhqdq %ymm5, %ymm0, %ymm5 # ymm5 = ymm0[1],ymm5[1],ymm0[3],ymm5[3]
vpermq $0xd8, %ymm6, %ymm6     # ymm6 = ymm6[0,2,1,3]
vpermq $0xd8, %ymm5, %ymm5     # ymm5 = ymm5[0,2,1,3]
vpsllq $0x17, %ymm6, %ymm7
vpsrlq $0x1a, %ymm5, %ymm8
vpxor %ymm6, %ymm7, %ymm6
vpsrlq $0x11, %ymm6, %ymm7
vpxor %ymm7, %ymm8, %ymm7
vpternlogq $0x96, %ymm5, %ymm6, %ymm7
vpaddq %ymm5, %ymm7, %ymm5
vpermt2q %zmm7, %zmm2, %zmm0
vpmovqd %ymm5, %xmm6
vpsrlq $0x20, %ymm5, %ymm5
vpmovqd %ymm5, %xmm5
vcvtdq2ps %xmm6, %xmm6
vcvtdq2ps %xmm5, %xmm5
vcvtps2pd %xmm6, %ymm6
vcvtps2pd %xmm5, %ymm5
vmulpd %ymm3, %ymm6, %ymm6
vmulpd %ymm3, %ymm5, %ymm5
vinsertf64x4 $0x1, %ymm6, %zmm6, %zmm6
vinsertf64x4 $0x1, %ymm5, %zmm5, %zmm5
vpermt2pd %zmm5, %zmm4, %zmm6
vcvtpd2ps %zmm6, %ymm5
vmovups %ymm5, 0xb0(%rsp)
vmovss 0xb0(%rsp,%r14,4), %xmm5
vucomiss 0x90(%rsp,%r14,4), %xmm5
jne 0x29f4
jp 0x29f4
incq %r14
cmpq $0x8, %r14
jne 0x29b8
vmovdqu 0x40(%rsp), %ymm5
incl %ecx
cmpl %edx, %ecx
jne 0x28e0
vmovdqu64 %zmm0, (%rax)
jmp 0x2b45
vmovdqu64 %zmm0, (%rax)
movq 0x35cf(%rip), %rdi      # 0x5fd0
leaq 0x1820(%rip), %rsi      # 0x4228
movl $0x10, %edx
vzeroupper
callq 0x2150
movq 0x35b4(%rip), %rbx      # 0x5fd0
leaq 0x1814(%rip), %r15      # 0x4237
xorl %r12d, %r12d
vcvtss2sd 0xb0(%rsp,%r12,4), %xmm9, %xmm0
movq %rbx, %rdi
callq 0x2190
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x2150
incq %r12
cmpq $0x8, %r12
jne 0x2a26
movq 0x3578(%rip), %rdi      # 0x5fd0
leaq 0x1934(%rip), %rsi      # 0x4393
movl $0x2, %edx
callq 0x2150
movq 0x3560(%rip), %rdi      # 0x5fd0
leaq 0x17c2(%rip), %rsi      # 0x4239
movl $0x10, %edx
callq 0x2150
movq 0x3548(%rip), %rbx      # 0x5fd0
leaq 0x17a8(%rip), %r15      # 0x4237
xorl %r12d, %r12d
vcvtss2sd 0x90(%rsp,%r12,4), %xmm9, %xmm0
movq %rbx, %rdi
callq 0x2190
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x2150
incq %r12
cmpq $0x8, %r12
jne 0x2a92
movq 0x350c(%rip), %rdi      # 0x5fd0
leaq 0x18c8(%rip), %rsi      # 0x4393
movl $0x2, %edx
callq 0x2150
movq 0x34f4(%rip), %rdi      # 0x5fd0
leaq 0x1767(%rip), %rsi      # 0x424a
movl $0x45, %edx
callq 0x2150
movq 0x34dc(%rip), %rdi      # 0x5fd0
movl %r14d, %esi
callq 0x21e0
leaq 0x17e8(%rip), %rsi      # 0x42eb
movl $0x1, %edx
movq %rax, %rdi
movq %rax, %rbx
callq 0x2150
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20b0
jmp 0x2ddc
vmovdqu %ymm5, 0x40(%rsp)
movl $0x9c40, %edi           # imm = 0x9C40
vzeroupper
callq 0x2030
movl $0x9c40, %edi           # imm = 0x9C40
movq %rax, %rbx
callq 0x2030
vbroadcastss 0x1618(%rip), %ymm0 # 0x4180
vmovdqu 0x20(%rsp), %ymm3
vmovdqu 0x40(%rsp), %ymm2
movq %rax, %r14
movq $-0x8, %rax
vpsllq $0x17, %ymm2, %ymm1
vpxor %ymm2, %ymm1, %ymm1
vmovdqa %ymm3, %ymm2
vpsrlq $0x1a, %ymm2, %ymm4
vpsrlq $0x11, %ymm1, %ymm3
vpxor %ymm3, %ymm4, %ymm3
vpternlogq $0x96, %ymm2, %ymm1, %ymm3
vpaddq %ymm2, %ymm3, %ymm1
vcvtdq2ps %ymm1, %ymm1
vmulps %ymm0, %ymm1, %ymm1
vmovups %ymm1, 0x20(%r14,%rax,4)
addq $0x8, %rax
cmpq $0x2708, %rax           # imm = 0x2708
jb 0x2b7e
movq 0x78(%rsp), %rax
vbroadcastsd 0x15a3(%rip), %ymm2 # 0x4170
vpmovsxbq 0x15a1(%rip), %zmm1 # 0x4178
vmovapd 0x151f(%rip), %zmm3     # 0x4100
movq $-0x8, %rcx
vmovdqu64 (%rax), %zmm0
vextracti64x4 $0x1, %zmm0, %ymm4
vpunpcklqdq %ymm4, %ymm0, %ymm5 # ymm5 = ymm0[0],ymm4[0],ymm0[2],ymm4[2]
vpunpckhqdq %ymm4, %ymm0, %ymm4 # ymm4 = ymm0[1],ymm4[1],ymm0[3],ymm4[3]
vpermq $0xd8, %ymm5, %ymm5     # ymm5 = ymm5[0,2,1,3]
vpermq $0xd8, %ymm4, %ymm4     # ymm4 = ymm4[0,2,1,3]
vpsllq $0x17, %ymm5, %ymm6
vpsrlq $0x1a, %ymm4, %ymm7
vpxor %ymm5, %ymm6, %ymm5
vpsrlq $0x11, %ymm5, %ymm6
vpxor %ymm6, %ymm7, %ymm6
vpternlogq $0x96, %ymm4, %ymm5, %ymm6
vpaddq %ymm4, %ymm6, %ymm4
vpermt2q %zmm6, %zmm1, %zmm0
vpmovqd %ymm4, %xmm5
vpsrlq $0x20, %ymm4, %ymm4
vpmovqd %ymm4, %xmm4
vcvtdq2ps %xmm5, %xmm5
vcvtdq2ps %xmm4, %xmm4
vcvtps2pd %xmm5, %ymm5
vcvtps2pd %xmm4, %ymm4
vmulpd %ymm2, %ymm5, %ymm5
vmulpd %ymm2, %ymm4, %ymm4
vinsertf64x4 $0x1, %ymm5, %zmm5, %zmm5
vinsertf64x4 $0x1, %ymm4, %zmm4, %zmm4
vpermt2pd %zmm4, %zmm3, %zmm5
vcvtpd2ps %zmm5, %ymm4
vmovupd %ymm4, 0x20(%rbx,%rcx,4)
addq $0x8, %rcx
cmpq $0x2708, %rcx           # imm = 0x2708
jb 0x2bee
movq 0x333e(%rip), %r12      # 0x5fd0
leaq 0x15f7(%rip), %r13      # 0x4290
xorl %r15d, %r15d
vmovdqu64 %zmm0, (%rax)
vmovss (%rbx,%r15,4), %xmm0
vmovaps %xmm0, 0x20(%rsp)
vandps 0x14cc(%rip){1to4}, %xmm0, %xmm0 # 0x4184
vucomiss 0x14c8(%rip), %xmm0     # 0x4188
ja 0x2cdc
vmovss (%r14,%r15,4), %xmm0
vandps 0x14b2(%rip){1to4}, %xmm0, %xmm1 # 0x4184
vucomiss 0x14ae(%rip), %xmm1     # 0x4188
jbe 0x2d1d
movl $0x5c, %edx
movq %r12, %rdi
movq %r13, %rsi
vzeroupper
callq 0x2150
movq (%r12), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %r12, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20b0
vmovss (%r14,%r15,4), %xmm0
vmovaps 0x20(%rsp), %xmm1
vucomiss %xmm0, %xmm1
jne 0x2d88
jp 0x2d88
incq %r15
cmpq $0x2710, %r15           # imm = 0x2710
jne 0x2ca2
movq 0x328e(%rip), %rbx      # 0x5fd0
leaq 0x1603(%rip), %rsi      # 0x434c
movl $0x15, %edx
movq %rbx, %rdi
vzeroupper
callq 0x2150
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movl $0xa, %esi
movq %rbx, %rdi
callq 0x2130
movq 0x325c(%rip), %rdi      # 0x5fd0
movsbl %al, %esi
callq 0x2040
movb $0x1, %bl
movq %rax, %rdi
callq 0x20b0
jmp 0x2dde
movq 0x3241(%rip), %rdi      # 0x5fd0
leaq 0x1557(%rip), %rsi      # 0x42ed
movl $0x5e, %edx
vzeroupper
callq 0x2150
movq 0x3226(%rip), %rdi      # 0x5fd0
movl %r15d, %esi
callq 0x21e0
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20b0
xorl %ebx, %ebx
movq 0x78(%rsp), %rdi
testq %rdi, %rdi
je 0x2ded
callq 0x2120
leaq 0xf0(%rsp), %rdi
callq 0x2110
movl %ebx, %eax
addq $0x1478, %rsp           # imm = 0x1478
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2e31
jmp 0x2e31
jmp 0x2e58
jmp 0x2e26
jmp 0x2e31
jmp 0x2e26
jmp 0x2e26
jmp 0x2e26
jmp 0x2e26
jmp 0x2e26
jmp 0x2e26
jmp 0x2e26
movq %rax, %rbx
jmp 0x2e43
jmp 0x2e31
jmp 0x2e31
jmp 0x2e31
movq 0x78(%rsp), %rdi
movq %rax, %rbx
testq %rdi, %rdi
je 0x2e43
callq 0x2120
leaq 0xf0(%rsp), %rdi
callq 0x2110
movq %rbx, %rdi
callq 0x21f0
movq %rax, %rdi
callq 0x3129