#include <cmath>

#include "RNG.cuh"

using namespace std;


// Constructor and destructor
__device__ __host__ RNG_Tausworthe::RNG_Tausworthe(){
	_Seed = 129;
}
__device__ __host__ RNG_Tausworthe::RNG_Tausworthe(const unsigned int seed){
	_Seed = seed;
}

// Private functions
__device__ __host__ unsigned int RNG_Tausworthe::TausStep(){
	int S1 = 23, S2 = 5, S3 = 29;
	unsigned int M = 4294967240UL;
	unsigned int z = this->_Seed;
	
	unsigned b = (((z << S1) ^ z) >> S2);

	this->_Seed = (((z & M) << S3) ^ b);
	return _Seed;		
}

// Virtual functions from base class
__device__ __host__ void RNG_Tausworthe::ResetSeed(){
	_Seed = 129;	
}

__device__ __host__ unsigned int RNG_Tausworthe::GetUnsignedInt(){
	return this->TausStep();
}

__device__ __host__ double RNG_Tausworthe::GetUniform(){
	return 2.3283064365387e-10 * this->GetUnsignedInt();	
}

__device__ __host__ double RNG_Tausworthe::GetGauss(){
	double u = this->GetUniform();
	double v = this->GetUniform();

	return sqrt(-2.*log(u)) * cos(2.*M_PI*v);	
}

__device__ __host__ double RNG_Tausworthe::GetBimodal(){
	double gaussian;

	do{
		gaussian = this->GetGauss();
		
		if(gaussian > 0.)
			return 1.;
		else if(gaussian < 0.)
			return -1.;
	}while(gaussian == 0.);
	
	return -1000.;
}

__device__ __host__ void RNG_Tausworthe::SetInternalState(RNG* supportGenerator){
	unsigned int seed;
	
	do
		seed = supportGenerator->GetUnsignedInt();
	while(seed < 129);
	
	this->_Seed = seed;
}



__device__ __host__ RNG_CombinedGenerator::RNG_CombinedGenerator(const unsigned int seed1, const unsigned int seed2, const unsigned int seed3, const unsigned int seed4){
	this->_SeedLCGS = seed1;
	this->_SeedTaus1 = seed2;
	this->_SeedTaus2 = seed3;
	this->_SeedTaus3 = seed4;
}

__device__ __host__ RNG_CombinedGenerator::RNG_CombinedGenerator(){
	this->_SeedLCGS = 0;
	this->_SeedTaus1 = 129;
	this->_SeedTaus2 = 130;
	this->_SeedTaus3 = 131;
}

__device__ __host__ unsigned int RNG_CombinedGenerator::TausStep1(){
	int S1 = 13, S2 = 19, S3 = 12;
	unsigned int M = 4294967294UL;
	unsigned int z = this->_SeedTaus1;
	
	unsigned b = (((z << S1) ^ z) >> S2);
	
	this->_SeedTaus1 = (((z & M) << S3) ^ b);
	return _SeedTaus1;
}

__device__ __host__ unsigned int RNG_CombinedGenerator::TausStep2(){
	int S1 = 2, S2 = 25, S3 = 4;
	unsigned int M = 4294967288UL;
	unsigned int z = this->_SeedTaus2;
	
	unsigned b = (((z << S1) ^ z) >> S2);

	this->_SeedTaus2 = (((z & M) << S3) ^ b);
	return _SeedTaus2;
}
__device__ __host__ unsigned int RNG_CombinedGenerator::TausStep3(){
	int S1 = 3, S2 = 11, S3 = 17;
	unsigned int M = 4294967280UL;
	unsigned int z = this->_SeedTaus3;
	
	unsigned b = (((z << S1) ^ z) >> S2);

	this->_SeedTaus3 = (((z & M) << S3) ^ b);
	return _SeedTaus3;
}

__device__ __host__ unsigned int RNG_CombinedGenerator::LCGStep(){
	unsigned int z = this->_SeedLCGS;
	unsigned int A = 1664525;
	unsigned int C = 1013904223UL;
	this->_SeedLCGS = (A*z + C);
	return _SeedLCGS;
}

__device__ __host__ unsigned int RNG_CombinedGenerator::HybridTausGenerator(){
	return (
		this->TausStep1() ^
		this->TausStep2() ^
		this->TausStep3() ^
		this->LCGStep()
	);
}

__device__ __host__ void RNG_CombinedGenerator::ResetSeed(){
	this->_SeedLCGS = 0;
	this->_SeedTaus1 = 129;
	this->_SeedTaus2 = 130;
	this->_SeedTaus3 = 131;
}

__device__ __host__ unsigned int RNG_CombinedGenerator::GetUnsignedInt(){
	return this->HybridTausGenerator();
}

__device__ __host__ double RNG_CombinedGenerator::GetUniform(){
	return 2.3283064365387e-10 * this->GetUnsignedInt();
}

__device__ __host__ double RNG_CombinedGenerator::GetGauss(){
	double u = this->GetUniform();
	double v = this->GetUniform();

	return sqrt(-2.*log(u)) * cos(2.*M_PI*v);
}

__device__ __host__ double RNG_CombinedGenerator::GetBimodal(){
	double gaussian;

	do{
		gaussian = this->GetGauss();
		
		if(gaussian > 0.)
			return 1.;
		else if(gaussian < 0.)
			return -1.;
	}while(gaussian == 0.);

	return -1000.;
}

__device__ __host__ void RNG_CombinedGenerator::SetInternalState(RNG* supportGenerator){
	this->_SeedLCGS = supportGenerator->GetUnsignedInt();
	
	unsigned int seedTaus1, seedTaus2, seedTaus3;
	
	do
		seedTaus1 = supportGenerator->GetUnsignedInt();
	while(seedTaus1 < 129);
	
	do
		seedTaus2 = supportGenerator->GetUnsignedInt();
	while(seedTaus2 < 129);
	
	do
		seedTaus3 = supportGenerator->GetUnsignedInt();
	while(seedTaus3 < 129);
	
	this->_SeedTaus1 = seedTaus1;
	this->_SeedTaus2 = seedTaus2;
	this->_SeedTaus3 = seedTaus3;
}

	.file	"tmpxft_002b38d3_00000000-6_RNG.cudafe1.cpp"
	.text
#APP

#NO_APP
	.align 2
	.globl	_ZN14RNG_Tausworthe9ResetSeedEv
	.type	_ZN14RNG_Tausworthe9ResetSeedEv, @function
_ZN14RNG_Tausworthe9ResetSeedEv:
.LFB2018:
	.cfi_startproc
	endbr64
	movl	$129, 8(%rdi)
	ret
	.cfi_endproc
.LFE2018:
	.size	_ZN14RNG_Tausworthe9ResetSeedEv, .-_ZN14RNG_Tausworthe9ResetSeedEv
	.align 2
	.globl	_ZN14RNG_Tausworthe10GetUniformEv
	.type	_ZN14RNG_Tausworthe10GetUniformEv, @function
_ZN14RNG_Tausworthe10GetUniformEv:
.LFB2020:
	.cfi_startproc
	endbr64
	pushq	%rax
	.cfi_def_cfa_offset 16
	movq	(%rdi), %rax
	call	*8(%rax)
	movl	%eax, %eax
	cvtsi2sdq	%rax, %xmm0
	mulsd	.LC0(%rip), %xmm0
	popq	%rdx
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2020:
	.size	_ZN14RNG_Tausworthe10GetUniformEv, .-_ZN14RNG_Tausworthe10GetUniformEv
	.align 2
	.globl	_ZN14RNG_Tausworthe10GetBimodalEv
	.type	_ZN14RNG_Tausworthe10GetBimodalEv, @function
_ZN14RNG_Tausworthe10GetBimodalEv:
.LFB2022:
	.cfi_startproc
	endbr64
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	movq	%rdi, %rbx
.L8:
	movq	(%rbx), %rax
	movq	%rbx, %rdi
	call	*24(%rax)
	xorps	%xmm1, %xmm1
	comisd	%xmm1, %xmm0
	ja	.L10
	comisd	%xmm0, %xmm1
	ja	.L11
	ucomisd	%xmm1, %xmm0
	jp	.L12
	je	.L8
.L12:
	movsd	.LC3(%rip), %xmm0
	jmp	.L6
.L10:
	movsd	.LC1(%rip), %xmm0
	jmp	.L6
.L11:
	movsd	.LC2(%rip), %xmm0
.L6:
	popq	%rbx
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2022:
	.size	_ZN14RNG_Tausworthe10GetBimodalEv, .-_ZN14RNG_Tausworthe10GetBimodalEv
	.align 2
	.globl	_ZN14RNG_Tausworthe16SetInternalStateEP3RNG
	.type	_ZN14RNG_Tausworthe16SetInternalStateEP3RNG, @function
_ZN14RNG_Tausworthe16SetInternalStateEP3RNG:
.LFB2023:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rdi, %rbp
	pushq	%rbx
	.cfi_def_cfa_offset 24
	.cfi_offset 3, -24
	movq	%rsi, %rbx
	pushq	%rdx
	.cfi_def_cfa_offset 32
.L17:
	movq	(%rbx), %rax
	movq	%rbx, %rdi
	call	*8(%rax)
	cmpl	$128, %eax
	jbe	.L17
	movl	%eax, 8(%rbp)
	popq	%rax
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2023:
	.size	_ZN14RNG_Tausworthe16SetInternalStateEP3RNG, .-_ZN14RNG_Tausworthe16SetInternalStateEP3RNG
	.align 2
	.globl	_ZN21RNG_CombinedGenerator9ResetSeedEv
	.type	_ZN21RNG_CombinedGenerator9ResetSeedEv, @function
_ZN21RNG_CombinedGenerator9ResetSeedEv:
.LFB2035:
	.cfi_startproc
	endbr64
	movl	$129, %eax
	salq	$32, %rax
	movq	%rax, 8(%rdi)
	movabsq	$562640715906, %rax
	movq	%rax, 16(%rdi)
	ret
	.cfi_endproc
.LFE2035:
	.size	_ZN21RNG_CombinedGenerator9ResetSeedEv, .-_ZN21RNG_CombinedGenerator9ResetSeedEv
	.align 2
	.globl	_ZN21RNG_CombinedGenerator10GetUniformEv
	.type	_ZN21RNG_CombinedGenerator10GetUniformEv, @function
_ZN21RNG_CombinedGenerator10GetUniformEv:
.LFB2037:
	.cfi_startproc
	endbr64
	pushq	%rax
	.cfi_def_cfa_offset 16
	movq	(%rdi), %rax
	call	*8(%rax)
	movl	%eax, %eax
	cvtsi2sdq	%rax, %xmm0
	mulsd	.LC0(%rip), %xmm0
	popq	%rdx
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2037:
	.size	_ZN21RNG_CombinedGenerator10GetUniformEv, .-_ZN21RNG_CombinedGenerator10GetUniformEv
	.align 2
	.globl	_ZN21RNG_CombinedGenerator10GetBimodalEv
	.type	_ZN21RNG_CombinedGenerator10GetBimodalEv, @function
_ZN21RNG_CombinedGenerator10GetBimodalEv:
.LFB2039:
	.cfi_startproc
	endbr64
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	movq	%rdi, %rbx
.L27:
	movq	(%rbx), %rax
	movq	%rbx, %rdi
	call	*24(%rax)
	xorps	%xmm1, %xmm1
	comisd	%xmm1, %xmm0
	ja	.L29
	comisd	%xmm0, %xmm1
	ja	.L30
	ucomisd	%xmm1, %xmm0
	jp	.L31
	je	.L27
.L31:
	movsd	.LC3(%rip), %xmm0
	jmp	.L25
.L29:
	movsd	.LC1(%rip), %xmm0
	jmp	.L25
.L30:
	movsd	.LC2(%rip), %xmm0
.L25:
	popq	%rbx
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2039:
	.size	_ZN21RNG_CombinedGenerator10GetBimodalEv, .-_ZN21RNG_CombinedGenerator10GetBimodalEv
	.align 2
	.globl	_ZN21RNG_CombinedGenerator16SetInternalStateEP3RNG
	.type	_ZN21RNG_CombinedGenerator16SetInternalStateEP3RNG, @function
_ZN21RNG_CombinedGenerator16SetInternalStateEP3RNG:
.LFB2040:
	.cfi_startproc
	endbr64
	pushq	%r13
	.cfi_def_cfa_offset 16
	.cfi_offset 13, -16
	pushq	%r12
	.cfi_def_cfa_offset 24
	.cfi_offset 12, -24
	pushq	%rbp
	.cfi_def_cfa_offset 32
	.cfi_offset 6, -32
	movq	%rdi, %rbp
	movq	%rsi, %rdi
	pushq	%rbx
	.cfi_def_cfa_offset 40
	.cfi_offset 3, -40
	movq	%rsi, %rbx
	pushq	%rdx
	.cfi_def_cfa_offset 48
	movq	(%rsi), %rax
	call	*8(%rax)
	movl	%eax, 8(%rbp)
.L35:
	movq	(%rbx), %rax
	movq	%rbx, %rdi
	call	*8(%rax)
	movl	%eax, %r13d
	cmpl	$128, %eax
	jbe	.L35
.L36:
	movq	(%rbx), %rax
	movq	%rbx, %rdi
	call	*8(%rax)
	movl	%eax, %r12d
	cmpl	$128, %eax
	jbe	.L36
.L37:
	movq	(%rbx), %rax
	movq	%rbx, %rdi
	call	*8(%rax)
	cmpl	$128, %eax
	jbe	.L37
	movl	%r13d, 12(%rbp)
	movl	%r12d, 16(%rbp)
	movl	%eax, 20(%rbp)
	popq	%rax
	.cfi_def_cfa_offset 40
	popq	%rbx
	.cfi_def_cfa_offset 32
	popq	%rbp
	.cfi_def_cfa_offset 24
	popq	%r12
	.cfi_def_cfa_offset 16
	popq	%r13
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2040:
	.size	_ZN21RNG_CombinedGenerator16SetInternalStateEP3RNG, .-_ZN21RNG_CombinedGenerator16SetInternalStateEP3RNG
	.align 2
	.globl	_ZN14RNG_Tausworthe8GetGaussEv
	.type	_ZN14RNG_Tausworthe8GetGaussEv, @function
_ZN14RNG_Tausworthe8GetGaussEv:
.LFB2021:
	.cfi_startproc
	endbr64
	pushq	%r14
	.cfi_def_cfa_offset 16
	.cfi_offset 14, -16
	pushq	%rbx
	.cfi_def_cfa_offset 24
	.cfi_offset 3, -24
	subq	$24, %rsp
	.cfi_def_cfa_offset 48
	movq	(%rdi), %rax
	movq	%rdi, 8(%rsp)
	call	*16(%rax)
	movq	8(%rsp), %rdi
	movq	%xmm0, %r14
	movq	(%rdi), %rax
	call	*16(%rax)
	movq	%xmm0, %rbx
	movq	%r14, %xmm0
	call	log@PLT
	mulsd	.LC5(%rip), %xmm0
	call	sqrt@PLT
	movsd	%xmm0, 8(%rsp)
	movq	%rbx, %xmm0
	mulsd	.LC6(%rip), %xmm0
	call	cos@PLT
	mulsd	8(%rsp), %xmm0
	addq	$24, %rsp
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%r14
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2021:
	.size	_ZN14RNG_Tausworthe8GetGaussEv, .-_ZN14RNG_Tausworthe8GetGaussEv
	.align 2
	.globl	_ZN21RNG_CombinedGenerator8GetGaussEv
	.type	_ZN21RNG_CombinedGenerator8GetGaussEv, @function
_ZN21RNG_CombinedGenerator8GetGaussEv:
.LFB2038:
	.cfi_startproc
	endbr64
	pushq	%r14
	.cfi_def_cfa_offset 16
	.cfi_offset 14, -16
	pushq	%rbx
	.cfi_def_cfa_offset 24
	.cfi_offset 3, -24
	subq	$24, %rsp
	.cfi_def_cfa_offset 48
	movq	(%rdi), %rax
	movq	%rdi, 8(%rsp)
	call	*16(%rax)
	movq	8(%rsp), %rdi
	movq	%xmm0, %r14
	movq	(%rdi), %rax
	call	*16(%rax)
	movq	%xmm0, %rbx
	movq	%r14, %xmm0
	call	log@PLT
	mulsd	.LC5(%rip), %xmm0
	call	sqrt@PLT
	movsd	%xmm0, 8(%rsp)
	movq	%rbx, %xmm0
	mulsd	.LC6(%rip), %xmm0
	call	cos@PLT
	mulsd	8(%rsp), %xmm0
	addq	$24, %rsp
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%r14
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2038:
	.size	_ZN21RNG_CombinedGenerator8GetGaussEv, .-_ZN21RNG_CombinedGenerator8GetGaussEv
	.type	_ZL26__cudaUnregisterBinaryUtilv, @function
_ZL26__cudaUnregisterBinaryUtilv:
.LFB2043:
	.cfi_startproc
	endbr64
	movq	_ZL20__cudaFatCubinHandle(%rip), %rdi
	jmp	__cudaUnregisterFatBinary@PLT
	.cfi_endproc
.LFE2043:
	.size	_ZL26__cudaUnregisterBinaryUtilv, .-_ZL26__cudaUnregisterBinaryUtilv
	.align 2
	.globl	_ZN14RNG_TauswortheC2Ev
	.type	_ZN14RNG_TauswortheC2Ev, @function
_ZN14RNG_TauswortheC2Ev:
.LFB2012:
	.cfi_startproc
	endbr64
	leaq	16+_ZTV14RNG_Tausworthe(%rip), %rax
	movl	$129, 8(%rdi)
	movq	%rax, (%rdi)
	ret
	.cfi_endproc
.LFE2012:
	.size	_ZN14RNG_TauswortheC2Ev, .-_ZN14RNG_TauswortheC2Ev
	.globl	_ZN14RNG_TauswortheC1Ev
	.set	_ZN14RNG_TauswortheC1Ev,_ZN14RNG_TauswortheC2Ev
	.align 2
	.globl	_ZN14RNG_TauswortheC2Ej
	.type	_ZN14RNG_TauswortheC2Ej, @function
_ZN14RNG_TauswortheC2Ej:
.LFB2015:
	.cfi_startproc
	endbr64
	leaq	16+_ZTV14RNG_Tausworthe(%rip), %rax
	movl	%esi, 8(%rdi)
	movq	%rax, (%rdi)
	ret
	.cfi_endproc
.LFE2015:
	.size	_ZN14RNG_TauswortheC2Ej, .-_ZN14RNG_TauswortheC2Ej
	.globl	_ZN14RNG_TauswortheC1Ej
	.set	_ZN14RNG_TauswortheC1Ej,_ZN14RNG_TauswortheC2Ej
	.align 2
	.globl	_ZN14RNG_Tausworthe8TausStepEv
	.type	_ZN14RNG_Tausworthe8TausStepEv, @function
_ZN14RNG_Tausworthe8TausStepEv:
.LFB2017:
	.cfi_startproc
	endbr64
	movl	8(%rdi), %edx
	movl	%edx, %eax
	sall	$23, %eax
	xorl	%edx, %eax
	shrl	$5, %eax
	movl	%eax, 8(%rdi)
	ret
	.cfi_endproc
.LFE2017:
	.size	_ZN14RNG_Tausworthe8TausStepEv, .-_ZN14RNG_Tausworthe8TausStepEv
	.align 2
	.globl	_ZN14RNG_Tausworthe14GetUnsignedIntEv
	.type	_ZN14RNG_Tausworthe14GetUnsignedIntEv, @function
_ZN14RNG_Tausworthe14GetUnsignedIntEv:
.LFB2019:
	.cfi_startproc
	endbr64
	jmp	_ZN14RNG_Tausworthe8TausStepEv
	.cfi_endproc
.LFE2019:
	.size	_ZN14RNG_Tausworthe14GetUnsignedIntEv, .-_ZN14RNG_Tausworthe14GetUnsignedIntEv
	.align 2
	.globl	_ZN21RNG_CombinedGeneratorC2Ejjjj
	.type	_ZN21RNG_CombinedGeneratorC2Ejjjj, @function
_ZN21RNG_CombinedGeneratorC2Ejjjj:
.LFB2025:
	.cfi_startproc
	endbr64
	leaq	16+_ZTV21RNG_CombinedGenerator(%rip), %rax
	movl	%esi, 8(%rdi)
	movq	%rax, (%rdi)
	movl	%edx, 12(%rdi)
	movl	%ecx, 16(%rdi)
	movl	%r8d, 20(%rdi)
	ret
	.cfi_endproc
.LFE2025:
	.size	_ZN21RNG_CombinedGeneratorC2Ejjjj, .-_ZN21RNG_CombinedGeneratorC2Ejjjj
	.globl	_ZN21RNG_CombinedGeneratorC1Ejjjj
	.set	_ZN21RNG_CombinedGeneratorC1Ejjjj,_ZN21RNG_CombinedGeneratorC2Ejjjj
	.align 2
	.globl	_ZN21RNG_CombinedGeneratorC2Ev
	.type	_ZN21RNG_CombinedGeneratorC2Ev, @function
_ZN21RNG_CombinedGeneratorC2Ev:
.LFB2028:
	.cfi_startproc
	endbr64
	leaq	16+_ZTV21RNG_CombinedGenerator(%rip), %rax
	movq	%rax, (%rdi)
	movl	$129, %eax
	salq	$32, %rax
	movq	%rax, 8(%rdi)
	movabsq	$562640715906, %rax
	movq	%rax, 16(%rdi)
	ret
	.cfi_endproc
.LFE2028:
	.size	_ZN21RNG_CombinedGeneratorC2Ev, .-_ZN21RNG_CombinedGeneratorC2Ev
	.globl	_ZN21RNG_CombinedGeneratorC1Ev
	.set	_ZN21RNG_CombinedGeneratorC1Ev,_ZN21RNG_CombinedGeneratorC2Ev
	.align 2
	.globl	_ZN21RNG_CombinedGenerator9TausStep1Ev
	.type	_ZN21RNG_CombinedGenerator9TausStep1Ev, @function
_ZN21RNG_CombinedGenerator9TausStep1Ev:
.LFB2030:
	.cfi_startproc
	endbr64
	movl	12(%rdi), %edx
	movl	%edx, %eax
	sall	$13, %eax
	xorl	%edx, %eax
	sall	$12, %edx
	shrl	$19, %eax
	andl	$-8192, %edx
	xorl	%edx, %eax
	movl	%eax, 12(%rdi)
	ret
	.cfi_endproc
.LFE2030:
	.size	_ZN21RNG_CombinedGenerator9TausStep1Ev, .-_ZN21RNG_CombinedGenerator9TausStep1Ev
	.align 2
	.globl	_ZN21RNG_CombinedGenerator9TausStep2Ev
	.type	_ZN21RNG_CombinedGenerator9TausStep2Ev, @function
_ZN21RNG_CombinedGenerator9TausStep2Ev:
.LFB2031:
	.cfi_startproc
	endbr64
	movl	16(%rdi), %edx
	leal	0(,%rdx,4), %eax
	xorl	%edx, %eax
	sall	$4, %edx
	shrl	$25, %eax
	andl	$-128, %edx
	xorl	%edx, %eax
	movl	%eax, 16(%rdi)
	ret
	.cfi_endproc
.LFE2031:
	.size	_ZN21RNG_CombinedGenerator9TausStep2Ev, .-_ZN21RNG_CombinedGenerator9TausStep2Ev
	.align 2
	.globl	_ZN21RNG_CombinedGenerator9TausStep3Ev
	.type	_ZN21RNG_CombinedGenerator9TausStep3Ev, @function
_ZN21RNG_CombinedGenerator9TausStep3Ev:
.LFB2032:
	.cfi_startproc
	endbr64
	movl	20(%rdi), %edx
	leal	0(,%rdx,8), %eax
	xorl	%edx, %eax
	sall	$17, %edx
	shrl	$11, %eax
	andl	$-2097152, %edx
	xorl	%edx, %eax
	movl	%eax, 20(%rdi)
	ret
	.cfi_endproc
.LFE2032:
	.size	_ZN21RNG_CombinedGenerator9TausStep3Ev, .-_ZN21RNG_CombinedGenerator9TausStep3Ev
	.align 2
	.globl	_ZN21RNG_CombinedGenerator7LCGStepEv
	.type	_ZN21RNG_CombinedGenerator7LCGStepEv, @function
_ZN21RNG_CombinedGenerator7LCGStepEv:
.LFB2033:
	.cfi_startproc
	endbr64
	imull	$1664525, 8(%rdi), %eax
	addl	$1013904223, %eax
	movl	%eax, 8(%rdi)
	ret
	.cfi_endproc
.LFE2033:
	.size	_ZN21RNG_CombinedGenerator7LCGStepEv, .-_ZN21RNG_CombinedGenerator7LCGStepEv
	.align 2
	.globl	_ZN21RNG_CombinedGenerator19HybridTausGeneratorEv
	.type	_ZN21RNG_CombinedGenerator19HybridTausGeneratorEv, @function
_ZN21RNG_CombinedGenerator19HybridTausGeneratorEv:
.LFB2034:
	.cfi_startproc
	endbr64
	call	_ZN21RNG_CombinedGenerator9TausStep1Ev
	movl	%eax, %ecx
	call	_ZN21RNG_CombinedGenerator9TausStep2Ev
	xorl	%eax, %ecx
	call	_ZN21RNG_CombinedGenerator9TausStep3Ev
	movl	%eax, %edx
	imull	$1664525, 8(%rdi), %eax
	addl	$1013904223, %eax
	xorl	%eax, %ecx
	movl	%eax, 8(%rdi)
	movl	%ecx, %eax
	xorl	%edx, %eax
	ret
	.cfi_endproc
.LFE2034:
	.size	_ZN21RNG_CombinedGenerator19HybridTausGeneratorEv, .-_ZN21RNG_CombinedGenerator19HybridTausGeneratorEv
	.align 2
	.globl	_ZN21RNG_CombinedGenerator14GetUnsignedIntEv
	.type	_ZN21RNG_CombinedGenerator14GetUnsignedIntEv, @function
_ZN21RNG_CombinedGenerator14GetUnsignedIntEv:
.LFB2036:
	.cfi_startproc
	endbr64
	jmp	_ZN21RNG_CombinedGenerator19HybridTausGeneratorEv
	.cfi_endproc
.LFE2036:
	.size	_ZN21RNG_CombinedGenerator14GetUnsignedIntEv, .-_ZN21RNG_CombinedGenerator14GetUnsignedIntEv
	.section	.text.startup,"ax",@progbits
	.type	_ZL24__sti____cudaRegisterAllv, @function
_ZL24__sti____cudaRegisterAllv:
.LFB2066:
	.cfi_startproc
	endbr64
	pushq	%rax
	.cfi_def_cfa_offset 16
	leaq	_ZL15__fatDeviceText(%rip), %rdi
	call	__cudaRegisterFatBinary@PLT
	movq	%rax, %rdi
	movq	%rax, _ZL20__cudaFatCubinHandle(%rip)
	call	__cudaRegisterFatBinaryEnd@PLT
	leaq	_ZL26__cudaUnregisterBinaryUtilv(%rip), %rdi
	popq	%rdx
	.cfi_def_cfa_offset 8
	jmp	atexit@PLT
	.cfi_endproc
.LFE2066:
	.size	_ZL24__sti____cudaRegisterAllv, .-_ZL24__sti____cudaRegisterAllv
	.section	.init_array,"aw"
	.align 8
	.quad	_ZL24__sti____cudaRegisterAllv
	.weak	_ZTS3RNG
	.section	.rodata._ZTS3RNG,"aG",@progbits,_ZTS3RNG,comdat
	.type	_ZTS3RNG, @object
	.size	_ZTS3RNG, 5
_ZTS3RNG:
	.string	"3RNG"
	.weak	_ZTI3RNG
	.section	.data.rel.ro._ZTI3RNG,"awG",@progbits,_ZTI3RNG,comdat
	.align 8
	.type	_ZTI3RNG, @object
	.size	_ZTI3RNG, 16
_ZTI3RNG:
	.quad	_ZTVN10__cxxabiv117__class_type_infoE+16
	.quad	_ZTS3RNG
	.weak	_ZTS14RNG_Tausworthe
	.section	.rodata._ZTS14RNG_Tausworthe,"aG",@progbits,_ZTS14RNG_Tausworthe,comdat
	.align 16
	.type	_ZTS14RNG_Tausworthe, @object
	.size	_ZTS14RNG_Tausworthe, 17
_ZTS14RNG_Tausworthe:
	.string	"14RNG_Tausworthe"
	.weak	_ZTI14RNG_Tausworthe
	.section	.data.rel.ro._ZTI14RNG_Tausworthe,"awG",@progbits,_ZTI14RNG_Tausworthe,comdat
	.align 8
	.type	_ZTI14RNG_Tausworthe, @object
	.size	_ZTI14RNG_Tausworthe, 24
_ZTI14RNG_Tausworthe:
	.quad	_ZTVN10__cxxabiv120__si_class_type_infoE+16
	.quad	_ZTS14RNG_Tausworthe
	.quad	_ZTI3RNG
	.weak	_ZTS21RNG_CombinedGenerator
	.section	.rodata._ZTS21RNG_CombinedGenerator,"aG",@progbits,_ZTS21RNG_CombinedGenerator,comdat
	.align 16
	.type	_ZTS21RNG_CombinedGenerator, @object
	.size	_ZTS21RNG_CombinedGenerator, 24
_ZTS21RNG_CombinedGenerator:
	.string	"21RNG_CombinedGenerator"
	.weak	_ZTI21RNG_CombinedGenerator
	.section	.data.rel.ro._ZTI21RNG_CombinedGenerator,"awG",@progbits,_ZTI21RNG_CombinedGenerator,comdat
	.align 8
	.type	_ZTI21RNG_CombinedGenerator, @object
	.size	_ZTI21RNG_CombinedGenerator, 24
_ZTI21RNG_CombinedGenerator:
	.quad	_ZTVN10__cxxabiv120__si_class_type_infoE+16
	.quad	_ZTS21RNG_CombinedGenerator
	.quad	_ZTI3RNG
	.weak	_ZTV14RNG_Tausworthe
	.section	.data.rel.ro.local._ZTV14RNG_Tausworthe,"awG",@progbits,_ZTV14RNG_Tausworthe,comdat
	.align 8
	.type	_ZTV14RNG_Tausworthe, @object
	.size	_ZTV14RNG_Tausworthe, 64
_ZTV14RNG_Tausworthe:
	.quad	0
	.quad	_ZTI14RNG_Tausworthe
	.quad	_ZN14RNG_Tausworthe9ResetSeedEv
	.quad	_ZN14RNG_Tausworthe14GetUnsignedIntEv
	.quad	_ZN14RNG_Tausworthe10GetUniformEv
	.quad	_ZN14RNG_Tausworthe8GetGaussEv
	.quad	_ZN14RNG_Tausworthe10GetBimodalEv
	.quad	_ZN14RNG_Tausworthe16SetInternalStateEP3RNG
	.weak	_ZTV21RNG_CombinedGenerator
	.section	.data.rel.ro.local._ZTV21RNG_CombinedGenerator,"awG",@progbits,_ZTV21RNG_CombinedGenerator,comdat
	.align 8
	.type	_ZTV21RNG_CombinedGenerator, @object
	.size	_ZTV21RNG_CombinedGenerator, 64
_ZTV21RNG_CombinedGenerator:
	.quad	0
	.quad	_ZTI21RNG_CombinedGenerator
	.quad	_ZN21RNG_CombinedGenerator9ResetSeedEv
	.quad	_ZN21RNG_CombinedGenerator14GetUnsignedIntEv
	.quad	_ZN21RNG_CombinedGenerator10GetUniformEv
	.quad	_ZN21RNG_CombinedGenerator8GetGaussEv
	.quad	_ZN21RNG_CombinedGenerator10GetBimodalEv
	.quad	_ZN21RNG_CombinedGenerator16SetInternalStateEP3RNG
	.section	.nvFatBinSegment,"aw"
	.align 8
	.type	_ZL15__fatDeviceText, @object
	.size	_ZL15__fatDeviceText, 24
_ZL15__fatDeviceText:
	.long	1180844977
	.long	1
	.quad	fatbinData
	.quad	0
	.local	_ZL20__cudaFatCubinHandle
	.comm	_ZL20__cudaFatCubinHandle,8,8
	.section	.rodata.cst8,"aM",@progbits,8
	.align 8
.LC0:
	.long	7
	.long	1039138816
	.align 8
.LC1:
	.long	0
	.long	1072693248
	.align 8
.LC2:
	.long	0
	.long	-1074790400
	.align 8
.LC3:
	.long	0
	.long	-1064353792
	.align 8
.LC5:
	.long	0
	.long	-1073741824
	.align 8
.LC6:
	.long	1413754136
	.long	1075388923
	.ident	"GCC: (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 8
	.long	1f - 0f
	.long	4f - 1f
	.long	5
0:
	.string	"GNU"
1:
	.align 8
	.long	0xc0000002
	.long	3f - 2f
2:
	.long	0x3
3:
	.align 8
4:

#ifndef _RNG__H
#define _RNG__H

class RNG{
	
	public:
		__device__ __host__ virtual void ResetSeed() = 0;
		__device__ __host__ virtual unsigned int GetUnsignedInt() = 0;
		__device__ __host__ virtual double GetUniform() = 0;
		__device__ __host__ virtual double GetGauss() = 0;
		__device__ __host__ virtual double GetBimodal() = 0;
		__device__ __host__ virtual void SetInternalState(RNG*) = 0;
		
};

class RNG_Tausworthe: public RNG{
	
	private:
		
		unsigned int _Seed;
		
		__device__ __host__ unsigned int TausStep();
	
	public:
	
		__device__ __host__ RNG_Tausworthe();
		__device__ __host__ RNG_Tausworthe(const unsigned int);
		__device__ __host__ ~RNG_Tausworthe() = default;	
		
		__device__ __host__ void ResetSeed();
		__device__ __host__ unsigned int GetUnsignedInt();
		__device__ __host__ double GetUniform();
		__device__ __host__ double GetGauss();
		__device__ __host__ double GetBimodal();
		__device__ __host__ void SetInternalState(RNG*);
		
};

class RNG_CombinedGenerator: public RNG{
	
	public:
	
		__device__ __host__ RNG_CombinedGenerator();
		__device__ __host__ RNG_CombinedGenerator(const unsigned int, const unsigned int, const unsigned int, const unsigned int);
		__device__ __host__ ~RNG_CombinedGenerator() = default;
		
		__device__ __host__ void ResetSeed();
		__device__ __host__ unsigned int GetUnsignedInt();
		__device__ __host__ double GetUniform();
		__device__ __host__ double GetGauss();
		__device__ __host__ double GetBimodal();


		__device__ __host__ void SetInternalState(RNG*);
	
	private:
		unsigned int _SeedLCGS;
		unsigned int _SeedTaus1;
		unsigned int _SeedTaus2;
		unsigned int _SeedTaus3;
		
		__device__ __host__ unsigned int LCGStep();
		__device__ __host__ unsigned int TausStep1();
		__device__ __host__ unsigned int TausStep2();
		__device__ __host__ unsigned int TausStep3();
		__device__ __host__ unsigned int HybridTausGenerator();
};

#endif

	.text
	.file	"RNG.hip"
	.type	__hip_cuid_,@object             # @__hip_cuid_
	.bss
	.globl	__hip_cuid_
__hip_cuid_:
	.byte	0                               # 0x0
	.size	__hip_cuid_, 1

	.ident	"AMD clang version 18.0.0git (https://github.com/RadeonOpenCompute/llvm-project roc-6.3.2 25012 e5bf7e55c91490b07c49d8960fa7983d864936c4)"
	.section	".note.GNU-stack","",@progbits
	.addrsig
	.addrsig_sym __hip_cuid_

	.text
	.p2alignl 7, 3214868480
	.fill 96, 4, 3214868480
	.type	__hip_cuid_,@object             ; @__hip_cuid_
	.section	.bss,"aw",@nobits
	.globl	__hip_cuid_
__hip_cuid_:
	.byte	0                               ; 0x0
	.size	__hip_cuid_, 1

	.ident	"AMD clang version 18.0.0git (https://github.com/RadeonOpenCompute/llvm-project roc-6.3.2 25012 e5bf7e55c91490b07c49d8960fa7983d864936c4)"
	.section	".note.GNU-stack","",@progbits
	.addrsig
	.addrsig_sym __hip_cuid_
	.amdgcn_target "amdgcn-amd-amdhsa--gfx1100"
	.amdgpu_metadata
---
amdhsa.kernels:  []
amdhsa.target:   amdgcn-amd-amdhsa--gfx1100
amdhsa.version:
  - 1
  - 2
...

	.end_amdgpu_metadata
