#include <stdio.h>
#include "Queue.cuh"

Queue** createQueue(int width, int height){
	Queue** queue=(Queue**)calloc(1, sizeof(Queue*));
	
	*queue=(Queue*)calloc(1, sizeof(Queue));

	(*queue)->width=width;
	(*queue)->height=height;
	(*queue)->entries=0;

	(*queue)->queue=(int**)calloc(height, sizeof(int*));
	for(int entry=0; entry<height; entry++){
		(*queue)->queue[entry]=(int*)calloc(width, sizeof(int));
	}

	return queue;
}

void copyValuesBetweenQueues(Queue** queue1, Queue** queue2){
	for(int entry=0; entry<(*queue1)->height; entry++){
		for(int value=0; value<(*queue1)->width; value++){
			(*queue2)->queue[entry][value]=(*queue1)->queue[entry][value];
		}
	}

	(*queue2)->entries=(*queue1)->entries;
}

void freeQueue(Queue** queue){
	for(int entry=0; entry<(*queue)->height; entry++){
		free((*queue)->queue[entry]);
	}
	free((*queue)->queue);
	free(*queue);
	free(queue);
}

void extendQueue(Queue** queue, int newWidth, int newHeight){
	Queue** queueHolder=createQueue(newWidth, newHeight);
	copyValuesBetweenQueues(queue, queueHolder);
	*queue=*queueHolder;
	free(queueHolder);
}

void freeEntryFromQueue(int* entry){
	free(entry);
}

int isEmpty(Queue** queue){
	return (*queue)->entries==0;
}

void insertToQueue(Queue** queue, int* entry){
	if((*queue)->entries==(*queue)->height){
		extendQueue(queue, (*queue)->width, (*queue)->height*2);
	}

	for(int value=0; value<(*queue)->width; value++){
		(*queue)->queue[(*queue)->entries][value]=entry[value];
	}
	(*queue)->entries++;

	freeEntryFromQueue(entry);
}

int* peekFromQueue(Queue** queue, int entryNum){
	return (*queue)->queue[entryNum];
}

int* popFromQueue(Queue** queue, int entryNum){
	int* returnedEntry=(int*)calloc((*queue)->width, sizeof(int));
	for(int value=0; value<(*queue)->width; value++){
		returnedEntry[value]=(*queue)->queue[entryNum][value];
	}
	
	(*queue)->entries--;
	for(int entry=entryNum; entry<(*queue)->entries; entry++){
		for(int value=0; value<(*queue)->width; value++){
			(*queue)->queue[entry][value]=(*queue)->queue[entry+1][value];
		}
	}

	return returnedEntry;
}

int* popRandomEntryFromQueue(Queue** queue){
	int entry=(int)((((double)rand())/(RAND_MAX+1))*(*queue)->entries);
	return popFromQueue(queue, entry);
}

void printQueueData(Queue** queue){
	printf("Width %d, Height %d, entries %d\n", (*queue)->width, (*queue)->height, (*queue)->entries);

	for(int entry=0; entry<(*queue)->height; entry++){
		printf("Entry %d \t", entry);
		for(int value=0; value<(*queue)->width; value++){
			printf("%d ", (*queue)->queue[entry][value]);
		}
		printf("\n");
	}
}

	.file	"tmpxft_002a513c_00000000-6_Queue.cudafe1.cpp"
	.text
#APP

#NO_APP
	.type	_ZL26__cudaUnregisterBinaryUtilv, @function
_ZL26__cudaUnregisterBinaryUtilv:
.LFB2040:
	.cfi_startproc
	endbr64
	movq	_ZL20__cudaFatCubinHandle(%rip), %rdi
	jmp	__cudaUnregisterFatBinary@PLT
	.cfi_endproc
.LFE2040:
	.size	_ZL26__cudaUnregisterBinaryUtilv, .-_ZL26__cudaUnregisterBinaryUtilv
	.globl	_Z11createQueueii
	.type	_Z11createQueueii, @function
_Z11createQueueii:
.LFB2027:
	.cfi_startproc
	endbr64
	pushq	%r14
	.cfi_def_cfa_offset 16
	.cfi_offset 14, -16
	pushq	%r13
	.cfi_def_cfa_offset 24
	.cfi_offset 13, -24
	pushq	%r12
	.cfi_def_cfa_offset 32
	.cfi_offset 12, -32
	movl	%esi, %r12d
	movl	$8, %esi
	pushq	%rbp
	.cfi_def_cfa_offset 40
	.cfi_offset 6, -40
	movslq	%edi, %rbp
	movl	$1, %edi
	pushq	%rbx
	.cfi_def_cfa_offset 48
	.cfi_offset 3, -48
	call	calloc@PLT
	movl	$24, %esi
	movl	$1, %edi
	movq	%rax, %r13
	call	calloc@PLT
	xorl	%edx, %edx
	movslq	%r12d, %rdi
	movl	$8, %esi
	movq	%rax, 0(%r13)
	movq	%rax, %rbx
	movl	%ebp, 4(%rax)
	movl	%r12d, (%rax)
	movl	%edx, 16(%rax)
	call	calloc@PLT
	movq	%rax, 8(%rbx)
	movq	%rax, %r14
	xorl	%ebx, %ebx
.L3:
	cmpl	%ebx, %r12d
	jle	.L7
	movl	$4, %esi
	movq	%rbp, %rdi
	call	calloc@PLT
	movq	%rax, (%r14,%rbx,8)
	incq	%rbx
	jmp	.L3
.L7:
	popq	%rbx
	.cfi_def_cfa_offset 40
	movq	%r13, %rax
	popq	%rbp
	.cfi_def_cfa_offset 32
	popq	%r12
	.cfi_def_cfa_offset 24
	popq	%r13
	.cfi_def_cfa_offset 16
	popq	%r14
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2027:
	.size	_Z11createQueueii, .-_Z11createQueueii
	.globl	_Z23copyValuesBetweenQueuesPP1qS1_
	.type	_Z23copyValuesBetweenQueuesPP1qS1_, @function
_Z23copyValuesBetweenQueuesPP1qS1_:
.LFB2028:
	.cfi_startproc
	endbr64
	movq	(%rdi), %rdx
	xorl	%ecx, %ecx
.L9:
	cmpl	%ecx, (%rdx)
	movq	(%rsi), %rdi
	jle	.L11
	leaq	0(,%rcx,8), %r8
	xorl	%eax, %eax
.L12:
	cmpl	%eax, 4(%rdx)
	jle	.L13
	movq	8(%rdx), %r9
	movq	(%r9,%r8), %r9
	movl	(%r9,%rax,4), %r10d
	movq	8(%rdi), %r9
	movq	(%r9,%r8), %r9
	movl	%r10d, (%r9,%rax,4)
	incq	%rax
	jmp	.L12
.L13:
	incq	%rcx
	jmp	.L9
.L11:
	movl	16(%rdx), %eax
	movl	%eax, 16(%rdi)
	ret
	.cfi_endproc
.LFE2028:
	.size	_Z23copyValuesBetweenQueuesPP1qS1_, .-_Z23copyValuesBetweenQueuesPP1qS1_
	.globl	_Z9freeQueuePP1q
	.type	_Z9freeQueuePP1q, @function
_Z9freeQueuePP1q:
.LFB2029:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	xorl	%ebp, %ebp
	pushq	%rbx
	.cfi_def_cfa_offset 24
	.cfi_offset 3, -24
	movq	%rdi, %rbx
	pushq	%rdx
	.cfi_def_cfa_offset 32
.L15:
	movq	(%rbx), %rax
	movq	8(%rax), %rdi
	cmpl	%ebp, (%rax)
	jle	.L18
	movq	(%rdi,%rbp,8), %rdi
	incq	%rbp
	call	free@PLT
	jmp	.L15
.L18:
	call	free@PLT
	movq	(%rbx), %rdi
	call	free@PLT
	popq	%rax
	.cfi_def_cfa_offset 24
	movq	%rbx, %rdi
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	jmp	free@PLT
	.cfi_endproc
.LFE2029:
	.size	_Z9freeQueuePP1q, .-_Z9freeQueuePP1q
	.globl	_Z11extendQueuePP1qii
	.type	_Z11extendQueuePP1qii, @function
_Z11extendQueuePP1qii:
.LFB2030:
	.cfi_startproc
	endbr64
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	movq	%rdi, %rbx
	movl	%esi, %edi
	movl	%edx, %esi
	call	_Z11createQueueii
	movq	%rbx, %rdi
	movq	%rax, %rsi
	call	_Z23copyValuesBetweenQueuesPP1qS1_
	movq	(%rsi), %rax
	movq	%rsi, %rdi
	movq	%rax, (%rbx)
	popq	%rbx
	.cfi_def_cfa_offset 8
	jmp	free@PLT
	.cfi_endproc
.LFE2030:
	.size	_Z11extendQueuePP1qii, .-_Z11extendQueuePP1qii
	.globl	_Z18freeEntryFromQueuePi
	.type	_Z18freeEntryFromQueuePi, @function
_Z18freeEntryFromQueuePi:
.LFB2031:
	.cfi_startproc
	endbr64
	jmp	free@PLT
	.cfi_endproc
.LFE2031:
	.size	_Z18freeEntryFromQueuePi, .-_Z18freeEntryFromQueuePi
	.globl	_Z7isEmptyPP1q
	.type	_Z7isEmptyPP1q, @function
_Z7isEmptyPP1q:
.LFB2032:
	.cfi_startproc
	endbr64
	movq	(%rdi), %rax
	cmpl	$0, 16(%rax)
	sete	%al
	movzbl	%al, %eax
	ret
	.cfi_endproc
.LFE2032:
	.size	_Z7isEmptyPP1q, .-_Z7isEmptyPP1q
	.globl	_Z13insertToQueuePP1qPi
	.type	_Z13insertToQueuePP1qPi, @function
_Z13insertToQueuePP1qPi:
.LFB2033:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsi, %rbp
	pushq	%rbx
	.cfi_def_cfa_offset 24
	.cfi_offset 3, -24
	movq	%rdi, %rbx
	pushq	%rdx
	.cfi_def_cfa_offset 32
	movq	(%rdi), %rax
	movl	(%rax), %edx
	cmpl	%edx, 16(%rax)
	jne	.L24
	movl	4(%rax), %esi
	addl	%edx, %edx
	call	_Z11extendQueuePP1qii
.L24:
	movq	(%rbx), %rcx
	xorl	%edx, %edx
.L25:
	movslq	16(%rcx), %rax
	cmpl	%edx, 4(%rcx)
	jle	.L28
	movq	8(%rcx), %rdi
	movl	0(%rbp,%rdx,4), %esi
	movq	(%rdi,%rax,8), %rax
	movl	%esi, (%rax,%rdx,4)
	incq	%rdx
	jmp	.L25
.L28:
	incl	%eax
	movq	%rbp, %rdi
	movl	%eax, 16(%rcx)
	popq	%rax
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	jmp	free@PLT
	.cfi_endproc
.LFE2033:
	.size	_Z13insertToQueuePP1qPi, .-_Z13insertToQueuePP1qPi
	.globl	_Z13peekFromQueuePP1qi
	.type	_Z13peekFromQueuePP1qi, @function
_Z13peekFromQueuePP1qi:
.LFB2034:
	.cfi_startproc
	endbr64
	movq	(%rdi), %rax
	movslq	%esi, %rsi
	movq	8(%rax), %rax
	movq	(%rax,%rsi,8), %rax
	ret
	.cfi_endproc
.LFE2034:
	.size	_Z13peekFromQueuePP1qi, .-_Z13peekFromQueuePP1qi
	.globl	_Z12popFromQueuePP1qi
	.type	_Z12popFromQueuePP1qi, @function
_Z12popFromQueuePP1qi:
.LFB2035:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movl	%esi, %ebp
	movl	$4, %esi
	pushq	%rbx
	.cfi_def_cfa_offset 24
	.cfi_offset 3, -24
	pushq	%rcx
	.cfi_def_cfa_offset 32
	movq	(%rdi), %rbx
	movslq	4(%rbx), %rdi
	call	calloc@PLT
	movslq	%ebp, %rdx
	xorl	%ecx, %ecx
	salq	$3, %rdx
.L31:
	cmpl	%ecx, 4(%rbx)
	jle	.L38
	movq	8(%rbx), %rsi
	movq	(%rsi,%rdx), %rsi
	movl	(%rsi,%rcx,4), %esi
	movl	%esi, (%rax,%rcx,4)
	incq	%rcx
	jmp	.L31
.L38:
	decl	16(%rbx)
.L33:
	cmpl	%ebp, 16(%rbx)
	jle	.L30
	leaq	8(%rdx), %rsi
	xorl	%ecx, %ecx
.L36:
	cmpl	%ecx, 4(%rbx)
	jle	.L39
	movq	8(%rbx), %rdi
	movq	(%rdi,%rsi), %r8
	movq	(%rdi,%rdx), %rdi
	movl	(%r8,%rcx,4), %r8d
	movl	%r8d, (%rdi,%rcx,4)
	incq	%rcx
	jmp	.L36
.L39:
	incl	%ebp
	movq	%rsi, %rdx
	jmp	.L33
.L30:
	popq	%rdx
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2035:
	.size	_Z12popFromQueuePP1qi, .-_Z12popFromQueuePP1qi
	.globl	_Z23popRandomEntryFromQueuePP1q
	.type	_Z23popRandomEntryFromQueuePP1q, @function
_Z23popRandomEntryFromQueuePP1q:
.LFB2036:
	.cfi_startproc
	endbr64
	subq	$24, %rsp
	.cfi_def_cfa_offset 32
	movq	%rdi, 8(%rsp)
	call	rand@PLT
	movq	8(%rsp), %rdi
	cvtsi2sdl	%eax, %xmm1
	mulsd	.LC0(%rip), %xmm1
	movq	(%rdi), %rdx
	cvtsi2sdl	16(%rdx), %xmm0
	addq	$24, %rsp
	.cfi_def_cfa_offset 8
	mulsd	%xmm1, %xmm0
	cvttsd2sil	%xmm0, %esi
	jmp	_Z12popFromQueuePP1qi
	.cfi_endproc
.LFE2036:
	.size	_Z23popRandomEntryFromQueuePP1q, .-_Z23popRandomEntryFromQueuePP1q
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC1:
	.string	"Width %d, Height %d, entries %d\n"
.LC2:
	.string	"Entry %d \t"
.LC3:
	.string	"%d "
.LC4:
	.string	"\n"
	.text
	.globl	_Z14printQueueDataPP1q
	.type	_Z14printQueueDataPP1q, @function
_Z14printQueueDataPP1q:
.LFB2037:
	.cfi_startproc
	endbr64
	pushq	%r15
	.cfi_def_cfa_offset 16
	.cfi_offset 15, -16
	leaq	.LC1(%rip), %rsi
	pushq	%r14
	.cfi_def_cfa_offset 24
	.cfi_offset 14, -24
	pushq	%r13
	.cfi_def_cfa_offset 32
	.cfi_offset 13, -32
	leaq	.LC2(%rip), %r13
	pushq	%r12
	.cfi_def_cfa_offset 40
	.cfi_offset 12, -40
	pushq	%rbp
	.cfi_def_cfa_offset 48
	.cfi_offset 6, -48
	movq	%rdi, %rbp
	pushq	%rbx
	.cfi_def_cfa_offset 56
	.cfi_offset 3, -56
	xorl	%ebx, %ebx
	pushq	%rdx
	.cfi_def_cfa_offset 64
	movq	(%rdi), %rax
	movl	$2, %edi
	movl	4(%rax), %edx
	movl	16(%rax), %r8d
	movl	(%rax), %ecx
	xorl	%eax, %eax
	call	__printf_chk@PLT
.L43:
	movq	0(%rbp), %rax
	movl	%ebx, %edx
	cmpl	%ebx, (%rax)
	jle	.L48
	movq	%r13, %rsi
	movl	$2, %edi
	xorl	%eax, %eax
	xorl	%r12d, %r12d
	call	__printf_chk@PLT
	leaq	0(,%rbx,8), %r15
	leaq	.LC3(%rip), %r14
.L44:
	movq	0(%rbp), %rax
	cmpl	%r12d, 4(%rax)
	jle	.L49
	movq	8(%rax), %rax
	movq	%r14, %rsi
	movl	$2, %edi
	movq	(%rax,%r15), %rax
	movl	(%rax,%r12,4), %edx
	xorl	%eax, %eax
	incq	%r12
	call	__printf_chk@PLT
	jmp	.L44
.L49:
	leaq	.LC4(%rip), %rsi
	movl	$2, %edi
	xorl	%eax, %eax
	incq	%rbx
	call	__printf_chk@PLT
	jmp	.L43
.L48:
	popq	%rax
	.cfi_def_cfa_offset 56
	popq	%rbx
	.cfi_def_cfa_offset 48
	popq	%rbp
	.cfi_def_cfa_offset 40
	popq	%r12
	.cfi_def_cfa_offset 32
	popq	%r13
	.cfi_def_cfa_offset 24
	popq	%r14
	.cfi_def_cfa_offset 16
	popq	%r15
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2037:
	.size	_Z14printQueueDataPP1q, .-_Z14printQueueDataPP1q
	.section	.text.startup,"ax",@progbits
	.type	_ZL24__sti____cudaRegisterAllv, @function
_ZL24__sti____cudaRegisterAllv:
.LFB2063:
	.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
.LFE2063:
	.size	_ZL24__sti____cudaRegisterAllv, .-_ZL24__sti____cudaRegisterAllv
	.section	.init_array,"aw"
	.align 8
	.quad	_ZL24__sti____cudaRegisterAllv
	.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	0
	.long	-1107296256
	.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 QUEUE_CUH
#define QUEUE_CUH

typedef struct q{
	int height;
	int width;
	int** queue;
	int entries;
}Queue;

Queue** createQueue(int width, int height);

void freeQueue(Queue** queue);

void freeEntryFromQueue(int* entry);

int isEmpty(Queue** queue);

void insertToQueue(Queue** queue, int* entry);

int* peekFromQueue(Queue** queue, int entryNum);

int* popFromQueue(Queue** queue, int entryNum);

int* popRandomEntryFromQueue(Queue** queue);

void printQueueData(Queue** queue);

#endif

	.text
	.file	"Queue.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
