// File: /workspace/github_c_makefile_star2_O0/ijleesw[P]data-compression/src/tunstall/tunstall.hpp
// Function: Tunstall::createEncodingTables()
void Tunstall::createEncodingTables() {

	int n_symbols = probabilities.size();
	if(n_symbols <= 1) return; //not much to compress
	//we need to reverse the table and index
	int lookup_table_size = 1;
	for(int i = 0; i < lookup_size; i++)
		lookup_table_size *= n_symbols;

	remap.resize(256, 0);
	for(int i = 0; i < n_symbols; i++) {
		Symbol &s = probabilities[i];
		remap[s.symbol] = i;
	}

	if(probabilities[0].probability > rle_limit) return;


	offsets.clear();
	offsets.resize(lookup_table_size, 0xffffff); //this is enough for quite large tables.
	for(size_t i = 0; i < index.size(); i++) {
		int low, high;
		int offset = 0; //keeps track of how far we are in the word.
		int table_offset = 0;
		while(1) {
			wordCode(&table[index[i] + offset], lengths[i] - offset, low, high);
			if(lengths[i] - offset <= lookup_size) {
				for(int k = low; k < high; k++) {
					offsets[table_offset + k] = i;
				}
				break;
			}

			//word is too long
			//check if some other word already did this:
			int w = offsets[table_offset + low];
			//if w = 0xfffff (another incomplete word with same starting was found
			// if w >= 0 (another complete word) we extend the table still pointing to w,
			//    but will be overwritten by longer words.
			if(w >= 0) { //add
				offsets[table_offset + low] = -offsets.size();
				offsets.resize(offsets.size() + lookup_table_size, w);
			}
			table_offset = -offsets[table_offset + low];
			offset += lookup_size;
		}
	}
}

// Assembly:
subq $0x98, %rsp
movq %rdi, 0x90(%rsp)
movq 0x90(%rsp), %rdi
movq %rdi, 0x40(%rsp)
addq $0x10, %rdi
callq 0x6120
movl %eax, 0x8c(%rsp)
cmpl $0x1, 0x8c(%rsp)
jg 0x3cab
jmp 0x3fd7
movl $0x1, 0x88(%rsp)
movl $0x0, 0x84(%rsp)
movq 0x40(%rsp), %rcx
movl 0x84(%rsp), %eax
cmpl 0x70(%rcx), %eax
jge 0x3cfb
movl 0x8c(%rsp), %eax
imull 0x88(%rsp), %eax
movl %eax, 0x88(%rsp)
movl 0x84(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x84(%rsp)
jmp 0x3cc1
movq 0x40(%rsp), %rdi
addq $0x90, %rdi
movb $0x0, 0x83(%rsp)
movl $0x100, %esi            # imm = 0x100
leaq 0x83(%rsp), %rdx
callq 0x67c0
movl $0x0, 0x7c(%rsp)
movl 0x7c(%rsp), %eax
cmpl 0x8c(%rsp), %eax
jge 0x3d84
movq 0x40(%rsp), %rdi
addq $0x10, %rdi
movslq 0x7c(%rsp), %rsi
callq 0x6320
movq 0x40(%rsp), %rdi
movq %rax, 0x70(%rsp)
movl 0x7c(%rsp), %eax
movb %al, 0x3f(%rsp)
addq $0x90, %rdi
movq 0x70(%rsp), %rax
movzbl (%rax), %eax
movl %eax, %esi
callq 0x6340
movb 0x3f(%rsp), %cl
movb %cl, (%rax)
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x3d29
movq 0x40(%rsp), %rdi
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x6320
movq 0x40(%rsp), %rcx
movzbl 0x1(%rax), %eax
cmpl (%rcx), %eax
jle 0x3da8
jmp 0x3fd7
movq 0x40(%rsp), %rdi
addq $0x78, %rdi
callq 0x6650
movq 0x40(%rsp), %rdi
addq $0x78, %rdi
movslq 0x88(%rsp), %rsi
movl $0xffffff, 0x6c(%rsp)   # imm = 0xFFFFFF
leaq 0x6c(%rsp), %rdx
callq 0x6880
movq $0x0, 0x60(%rsp)
movq 0x40(%rsp), %rdi
movq 0x60(%rsp), %rax
movq %rax, 0x30(%rsp)
addq $0x28, %rdi
callq 0x5fe0
movq %rax, %rcx
movq 0x30(%rsp), %rax
cmpq %rcx, %rax
jae 0x3fd7
movl $0x0, 0x54(%rsp)
movl $0x0, 0x50(%rsp)
movq 0x40(%rsp), %rdi
movq %rdi, %rax
addq $0x58, %rax
movq %rax, 0x20(%rsp)
addq $0x28, %rdi
movq 0x60(%rsp), %rsi
callq 0x5fc0
movq 0x20(%rsp), %rdi
movl (%rax), %eax
addl 0x54(%rsp), %eax
movslq %eax, %rsi
callq 0x6340
movq 0x40(%rsp), %rdi
movq %rax, 0x28(%rsp)
addq $0x40, %rdi
movq 0x60(%rsp), %rsi
callq 0x5fc0
movq 0x28(%rsp), %rsi
movq 0x40(%rsp), %rdi
movl (%rax), %edx
subl 0x54(%rsp), %edx
leaq 0x5c(%rsp), %rcx
leaq 0x58(%rsp), %r8
callq 0x6940
movq 0x40(%rsp), %rdi
addq $0x40, %rdi
movq 0x60(%rsp), %rsi
callq 0x5fc0
movq 0x40(%rsp), %rcx
movl (%rax), %eax
subl 0x54(%rsp), %eax
cmpl 0x70(%rcx), %eax
jg 0x3ef3
movl 0x5c(%rsp), %eax
movl %eax, 0x4c(%rsp)
movl 0x4c(%rsp), %eax
cmpl 0x58(%rsp), %eax
jge 0x3eee
movq 0x40(%rsp), %rdi
movq 0x60(%rsp), %rax
movl %eax, 0x1c(%rsp)
addq $0x78, %rdi
movl 0x50(%rsp), %eax
addl 0x4c(%rsp), %eax
movslq %eax, %rsi
callq 0x5fc0
movl 0x1c(%rsp), %ecx
movl %ecx, (%rax)
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x3eaf
jmp 0x3fc2
movq 0x40(%rsp), %rdi
addq $0x78, %rdi
movl 0x50(%rsp), %eax
addl 0x5c(%rsp), %eax
movslq %eax, %rsi
callq 0x5fc0
movl (%rax), %eax
movl %eax, 0x48(%rsp)
cmpl $0x0, 0x48(%rsp)
jl 0x3f89
movq 0x40(%rsp), %rdi
addq $0x78, %rdi
callq 0x5fe0
movq 0x40(%rsp), %rdi
movq %rax, %rcx
xorl %eax, %eax
subq %rcx, %rax
movl %eax, 0xc(%rsp)
addq $0x78, %rdi
movl 0x50(%rsp), %eax
addl 0x5c(%rsp), %eax
movslq %eax, %rsi
callq 0x5fc0
movl 0xc(%rsp), %ecx
movq 0x40(%rsp), %rdi
movl %ecx, (%rax)
movq %rdi, %rax
addq $0x78, %rax
movq %rax, 0x10(%rsp)
addq $0x78, %rdi
callq 0x5fe0
movq 0x10(%rsp), %rdi
movq %rax, %rsi
movslq 0x88(%rsp), %rax
addq %rax, %rsi
leaq 0x48(%rsp), %rdx
callq 0x6880
movq 0x40(%rsp), %rdi
addq $0x78, %rdi
movl 0x50(%rsp), %eax
addl 0x5c(%rsp), %eax
movslq %eax, %rsi
callq 0x5fc0
movq %rax, %rdx
movq 0x40(%rsp), %rax
xorl %ecx, %ecx
subl (%rdx), %ecx
movl %ecx, 0x50(%rsp)
movl 0x70(%rax), %eax
addl 0x54(%rsp), %eax
movl %eax, 0x54(%rsp)
jmp 0x3e1b
jmp 0x3fc4
movq 0x60(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x60(%rsp)
jmp 0x3de2
addq $0x98, %rsp
retq
nop