// File: brc7[P]DiversitySampling/src/RACE.cpp
// Function: RACE::deserialize(std::istream&)
void RACE::deserialize(std::istream& in){
  	/*   
	Input: A BINARY istream in. You can open a binary input stream
	with the flag: std::ios::binary | std::ios::in

	beware: frees sketch
	*/

	// 0. Determine if system is little-endian
	uint32_t n = 1;
	bool is_little_endian = *(uint8_t*)(&n);

	uint8_t magic, version;
	uint64_t R, range;

	in.read(reinterpret_cast<char *>(&magic), sizeof(uint8_t)); 
	in.read(reinterpret_cast<char *>(&version), sizeof(uint8_t)); 
	
	if (magic != magic_number)
		return;

	in.read(reinterpret_cast<char *>(&R), sizeof(uint64_t));
	in.read(reinterpret_cast<char *>(&range), sizeof(uint64_t));

	// fix endian-ness of parameters
	if (is_little_endian){
		R = __builtin_bswap64(R); 
		range = __builtin_bswap64(range);
	}

	_R = R; _range = range; 
	uint32_t* recovered_sketch = new uint32_t[_R*_range]; 

	// now read the sketch into recovered_sketch
	in.read(reinterpret_cast <char *>(recovered_sketch), _R*_range*sizeof(uint32_t));

	delete[] _sketch;
	_sketch = new unsigned int[_R *_range];

	for (size_t r = 0; r < _R; r++){
		for (size_t i = 0; i < _range; i++){
			uint32_t value = recovered_sketch[r*_range + i];
			// 3. Depending on (1), bitflip so that it is big-endian (network order)
			if (is_little_endian)
				value = __builtin_bswap32(value);
			// 4. Save to our sketch 
			_sketch[r*_range + i] = value;
		}
	}
	delete[] recovered_sketch; 
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x50(%rbp)
movl $0x1, -0x14(%rbp)
cmpb $0x0, -0x14(%rbp)
setne %al
andb $0x1, %al
movb %al, -0x15(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x16(%rbp), %rsi
movl $0x1, %edx
callq 0x2290
movq -0x10(%rbp), %rdi
leaq -0x17(%rbp), %rsi
movl $0x1, %edx
callq 0x2290
movq -0x50(%rbp), %rcx
movzbl -0x16(%rbp), %eax
movzbl 0x18(%rcx), %ecx
cmpl %ecx, %eax
je 0x38c4
jmp 0x3a5e
movq -0x10(%rbp), %rdi
leaq -0x20(%rbp), %rsi
movl $0x8, %edx
callq 0x2290
movq -0x10(%rbp), %rdi
leaq -0x28(%rbp), %rsi
movl $0x8, %edx
callq 0x2290
testb $0x1, -0x15(%rbp)
je 0x3904
movq -0x20(%rbp), %rax
bswapq %rax
movq %rax, -0x20(%rbp)
movq -0x28(%rbp), %rax
bswapq %rax
movq %rax, -0x28(%rbp)
movq -0x50(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rax, (%rcx)
movq -0x28(%rbp), %rax
movq %rax, 0x8(%rcx)
movq (%rcx), %rax
imulq 0x8(%rcx), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq -0x50(%rbp), %rax
movq %rcx, -0x30(%rbp)
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq (%rax), %rdx
imulq 0x8(%rax), %rdx
shlq $0x2, %rdx
callq 0x2290
movq -0x50(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x58(%rbp)
cmpq $0x0, %rax
je 0x397f
movq -0x58(%rbp), %rdi
callq 0x22b0
movq -0x50(%rbp), %rcx
movq (%rcx), %rax
imulq 0x8(%rcx), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq -0x50(%rbp), %rax
movq %rcx, 0x10(%rax)
movq $0x0, -0x38(%rbp)
movq -0x50(%rbp), %rcx
movq -0x38(%rbp), %rax
cmpq (%rcx), %rax
jae 0x3a47
movq $0x0, -0x40(%rbp)
movq -0x50(%rbp), %rcx
movq -0x40(%rbp), %rax
cmpq 0x8(%rcx), %rax
jae 0x3a34
movq -0x50(%rbp), %rdx
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
imulq 0x8(%rdx), %rcx
addq -0x40(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x44(%rbp)
testb $0x1, -0x15(%rbp)
je 0x3a0b
movl -0x44(%rbp), %eax
bswapl %eax
movl %eax, -0x44(%rbp)
movq -0x50(%rbp), %rsi
movl -0x44(%rbp), %edx
movq 0x10(%rsi), %rax
movq -0x38(%rbp), %rcx
imulq 0x8(%rsi), %rcx
addq -0x40(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x40(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x40(%rbp)
jmp 0x39d4
jmp 0x3a36
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x39bf
movq -0x30(%rbp), %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, %rax
je 0x3a5e
movq -0x60(%rbp), %rdi
callq 0x22b0
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)