// File: /workspace/github_c_makefile_star2_O0/ijleesw[P]data-compression/src/tunstall/tunstall.hpp
// Function: Tunstall::createDecodingTables()
void Tunstall::createDecodingTables() {
	int n_symbols = probabilities.size();
	if(n_symbols <= 1) return;

	vector<deque<TSymbol> > queues(n_symbols);
	vector<unsigned char> buffer;

	//initialize adding all symbols to queues
	for(int i = 0; i < n_symbols; i++) {
		TSymbol s;
		s.probability = (uint32_t)(probabilities[i].probability<<8);
		s.offset = buffer.size();
		s.length = 1;

		queues[i].push_back(s);
		buffer.push_back(probabilities[i].symbol);
	}
	int dictionary_size = 1<<wordsize;
	int n_words = n_symbols;
	int table_length = n_symbols;
	while(n_words < dictionary_size - n_symbols +1) {
		//find highest probability word
		int best = 0;
		float max_prob = 0;
		for(int i = 0; i < n_symbols; i++) {
			float p = queues[i].front().probability ;
			if(p > max_prob) {
				best = i;
				max_prob = p;
			}
		}

		TSymbol symbol = queues[best].front();
		//split word.
		int pos = buffer.size();
		buffer.resize(pos + n_symbols*(symbol.length + 1));
		for(int i = 0; i < n_symbols; i++) {
			uint32_t p = probabilities[i].probability;
			TSymbol s;
			//TODO check performances with +1 and without.
			s.probability = ( ( symbol.probability * (unsigned int)(p<<8) )>>16); //probabilities[i].probability*symbol.probability;
			s.offset = pos;
			s.length = symbol.length + 1;

			memcpy(&buffer[pos], &buffer[symbol.offset], symbol.length);
			pos += symbol.length;
			buffer[pos++] = probabilities[i].symbol;
			queues[i].push_back(s);
		}
		table_length += (n_symbols-1)*(symbol.length + 1) +1;
		n_words += n_symbols -1;
		queues[best].pop_front();
	}
	index.clear();
	lengths.clear();
	table.clear();

	//build table and index
	index.resize(n_words);
	lengths.resize(n_words);
	table.resize(table_length);
	int word = 0;
	int pos = 0;
	for(size_t i = 0; i < queues.size(); i++) {
		deque<TSymbol> &queue = queues[i];
		for(size_t k = 0; k < queue.size(); k++) {
			TSymbol &s = queue[k];
			index[word] = pos;
			lengths[word] = s.length;
			word++;
			memcpy(&table[pos], &buffer[s.offset], s.length);
			pos += s.length;
		}
	}
	assert((int)index.size() <= dictionary_size);
}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x130(%rsp)
movq 0x130(%rsp), %rdi
movq %rdi, 0x60(%rsp)
addq $0x10, %rdi
callq 0x6120
movl %eax, 0x12c(%rsp)
cmpl $0x1, 0x12c(%rsp)
jg 0x353b
jmp 0x3c51
movslq 0x12c(%rsp), %rax
movq %rax, 0x50(%rsp)
leaq 0x10f(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x6400
movq 0x50(%rsp), %rsi
movq 0x58(%rsp), %rdx
leaq 0x110(%rsp), %rdi
callq 0x6410
jmp 0x3573
leaq 0x10f(%rsp), %rdi
callq 0x6490
leaq 0xe0(%rsp), %rdi
callq 0x64a0
movl $0x0, 0xdc(%rsp)
movl 0xdc(%rsp), %eax
cmpl 0x12c(%rsp), %eax
jge 0x36be
leaq 0xd0(%rsp), %rdi
callq 0x64b0
jmp 0x35bb
movq 0x60(%rsp), %rdi
addq $0x10, %rdi
movslq 0xdc(%rsp), %rsi
callq 0x6320
movzbl 0x1(%rax), %eax
shll $0x8, %eax
movl %eax, 0xd8(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x6380
movl %eax, 0xd0(%rsp)
movl $0x1, 0xd4(%rsp)
movslq 0xdc(%rsp), %rsi
leaq 0x110(%rsp), %rdi
callq 0x64c0
movq %rax, %rdi
leaq 0xd0(%rsp), %rsi
callq 0x64e0
jmp 0x3625
movq 0x60(%rsp), %rdi
addq $0x10, %rdi
movslq 0xdc(%rsp), %rsi
callq 0x6320
movq %rax, %rsi
leaq 0xe0(%rsp), %rdi
callq 0x6540
jmp 0x364d
jmp 0x364f
movl 0xdc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xdc(%rsp)
jmp 0x3598
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x100(%rsp)
movl %eax, 0xfc(%rsp)
leaq 0x10f(%rsp), %rdi
callq 0x6490
jmp 0x3c59
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x100(%rsp)
movl %eax, 0xfc(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x6700
leaq 0x110(%rsp), %rdi
callq 0x6760
jmp 0x3c59
movq 0x60(%rsp), %rax
movl 0x4(%rax), %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, 0xcc(%rsp)
movl 0x12c(%rsp), %eax
movl %eax, 0xc8(%rsp)
movl 0x12c(%rsp), %eax
movl %eax, 0xc4(%rsp)
movl 0xc8(%rsp), %eax
movl 0xcc(%rsp), %ecx
subl 0x12c(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jge 0x39f9
movl $0x0, 0xc0(%rsp)
xorps %xmm0, %xmm0
movss %xmm0, 0xbc(%rsp)
movl $0x0, 0xb8(%rsp)
movl 0xb8(%rsp), %eax
cmpl 0x12c(%rsp), %eax
jge 0x37bb
movslq 0xb8(%rsp), %rsi
leaq 0x110(%rsp), %rdi
callq 0x64c0
movq %rax, %rdi
callq 0x65b0
movl 0x8(%rax), %eax
cvtsi2ss %rax, %xmm0
movss %xmm0, 0xb4(%rsp)
movss 0xb4(%rsp), %xmm0
ucomiss 0xbc(%rsp), %xmm0
jbe 0x37a3
movl 0xb8(%rsp), %eax
movl %eax, 0xc0(%rsp)
movss 0xb4(%rsp), %xmm0
movss %xmm0, 0xbc(%rsp)
jmp 0x37a5
movl 0xb8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb8(%rsp)
jmp 0x3732
movslq 0xc0(%rsp), %rsi
leaq 0x110(%rsp), %rdi
callq 0x64c0
movq %rax, %rdi
callq 0x65b0
movl 0x8(%rax), %ecx
movl %ecx, 0xb0(%rsp)
movq (%rax), %rax
movq %rax, 0xa8(%rsp)
leaq 0xe0(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x6380
movq 0x48(%rsp), %rdi
movl %eax, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
movl 0x12c(%rsp), %ecx
movl 0xac(%rsp), %edx
incl %edx
imull %edx, %ecx
addl %ecx, %eax
movslq %eax, %rsi
callq 0x6280
jmp 0x3831
movl $0x0, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
cmpl 0x12c(%rsp), %eax
jge 0x3997
movq 0x60(%rsp), %rdi
addq $0x10, %rdi
movslq 0xa0(%rsp), %rsi
callq 0x6320
movzbl 0x1(%rax), %eax
movl %eax, 0x9c(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x64b0
jmp 0x3880
movl 0xb0(%rsp), %ecx
movl 0x9c(%rsp), %eax
imull %ecx, %eax
shrl $0x8, %eax
movzwl %ax, %eax
movl %eax, 0x98(%rsp)
movl 0xa4(%rsp), %eax
movl %eax, 0x90(%rsp)
movl 0xac(%rsp), %eax
incl %eax
movl %eax, 0x94(%rsp)
movslq 0xa4(%rsp), %rsi
leaq 0xe0(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x6340
movq 0x38(%rsp), %rdi
movq %rax, 0x30(%rsp)
movslq 0xa8(%rsp), %rsi
callq 0x6340
movq 0x30(%rsp), %rdi
movq %rax, %rsi
movslq 0xac(%rsp), %rdx
callq 0x2100
movq 0x60(%rsp), %rdi
movl 0xac(%rsp), %ecx
movl 0xa4(%rsp), %eax
addl %ecx, %eax
movl %eax, 0xa4(%rsp)
addq $0x10, %rdi
movslq 0xa0(%rsp), %rsi
callq 0x6320
movq 0x38(%rsp), %rdi
movb (%rax), %al
movb %al, 0x47(%rsp)
movslq 0xa4(%rsp), %rsi
movl %esi, %eax
incl %eax
movl %eax, 0xa4(%rsp)
callq 0x6340
movb 0x47(%rsp), %cl
movb %cl, (%rax)
movslq 0xa0(%rsp), %rsi
leaq 0x110(%rsp), %rdi
callq 0x64c0
movq %rax, %rdi
leaq 0x90(%rsp), %rsi
callq 0x64e0
jmp 0x397f
jmp 0x3981
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x383c
movl 0x12c(%rsp), %eax
subl $0x1, %eax
movl 0xac(%rsp), %ecx
addl $0x1, %ecx
imull %ecx, %eax
addl $0x1, %eax
addl 0xc4(%rsp), %eax
movl %eax, 0xc4(%rsp)
movl 0x12c(%rsp), %eax
subl $0x1, %eax
addl 0xc8(%rsp), %eax
movl %eax, 0xc8(%rsp)
movslq 0xc0(%rsp), %rsi
leaq 0x110(%rsp), %rdi
callq 0x64c0
movq %rax, %rdi
callq 0x65e0
jmp 0x36f0
movq 0x60(%rsp), %rdi
addq $0x28, %rdi
movq %rdi, 0x28(%rsp)
callq 0x6650
movq 0x60(%rsp), %rdi
addq $0x40, %rdi
callq 0x6650
movq 0x60(%rsp), %rdi
addq $0x58, %rdi
callq 0x6670
movq 0x28(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0x61e0
jmp 0x3a3c
movq 0x60(%rsp), %rdi
addq $0x40, %rdi
movslq 0xc8(%rsp), %rsi
callq 0x61e0
jmp 0x3a54
movq 0x60(%rsp), %rdi
addq $0x58, %rdi
movslq 0xc4(%rsp), %rsi
callq 0x6280
jmp 0x3a6c
movl $0x0, 0x8c(%rsp)
movl $0x0, 0x88(%rsp)
movq $0x0, 0x80(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0x20(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x6690
movq %rax, %rcx
movq 0x20(%rsp), %rax
cmpq %rcx, %rax
jae 0x3bff
movq 0x80(%rsp), %rsi
leaq 0x110(%rsp), %rdi
callq 0x64c0
movq %rax, 0x78(%rsp)
movq $0x0, 0x70(%rsp)
movq 0x70(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x78(%rsp), %rdi
callq 0x66b0
movq %rax, %rcx
movq 0x18(%rsp), %rax
cmpq %rcx, %rax
jae 0x3be4
movq 0x78(%rsp), %rdi
movq 0x70(%rsp), %rsi
callq 0x66d0
movq 0x60(%rsp), %rdi
movq %rax, 0x68(%rsp)
movl 0x88(%rsp), %eax
movl %eax, 0x8(%rsp)
addq $0x28, %rdi
movslq 0x8c(%rsp), %rsi
callq 0x5fc0
movl 0x8(%rsp), %ecx
movq 0x60(%rsp), %rdi
movl %ecx, (%rax)
movq 0x68(%rsp), %rax
movl 0x4(%rax), %eax
movl %eax, 0xc(%rsp)
addq $0x40, %rdi
movslq 0x8c(%rsp), %rsi
callq 0x5fc0
movl 0xc(%rsp), %ecx
movq 0x60(%rsp), %rdi
movl %ecx, (%rax)
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
addq $0x58, %rdi
movslq 0x88(%rsp), %rsi
callq 0x6340
movq %rax, 0x10(%rsp)
movq 0x68(%rsp), %rax
movslq (%rax), %rsi
leaq 0xe0(%rsp), %rdi
callq 0x6340
movq 0x10(%rsp), %rdi
movq %rax, %rsi
movq 0x68(%rsp), %rax
movslq 0x4(%rax), %rdx
callq 0x2100
movq 0x68(%rsp), %rax
movl 0x4(%rax), %eax
addl 0x88(%rsp), %eax
movl %eax, 0x88(%rsp)
movq 0x70(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x70(%rsp)
jmp 0x3adc
jmp 0x3be6
movq 0x80(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x80(%rsp)
jmp 0x3a8e
movq 0x60(%rsp), %rdi
addq $0x28, %rdi
callq 0x5fe0
cmpl 0xcc(%rsp), %eax
jg 0x3c18
jmp 0x3c37
leaq 0xa464(%rip), %rdi      # 0xe083
leaq 0xa3f0(%rip), %rsi      # 0xe016
movl $0x1d1, %edx            # imm = 0x1D1
leaq 0xa476(%rip), %rcx      # 0xe0a8
callq 0x20d0
leaq 0xe0(%rsp), %rdi
callq 0x6700
leaq 0x110(%rsp), %rdi
callq 0x6760
addq $0x138, %rsp            # imm = 0x138
retq
movq 0x100(%rsp), %rdi
callq 0x2280
nopw %cs:(%rax,%rax)