// File: brc7[P]DiversitySampling/src/RACE.cpp
// Function: RACE::serialize(std::ostream&)
void RACE::serialize(std::ostream &out){
	/*
	Input: A BINARY ostream out. You can open a binary output stream
	with the flag: std::ios::binary | std::ios::out
	Format: (Big Endian) 
	magic_number (uint8_t); file_version_number (uint8_t); R (uint64_t); range (uint64_t);
	Then every element in the sketch, as a uint32_t
	*/

	// 0. Determine if system is big-endian or little-endian 
	// 1. Write magic numbers and parameters to file 
	// 2. For each element in sketch, cast element to standard-sized element 
	// 3. Depending on (1), bitflip so that it is big-endian (network order)
	// 4. Write to stream 

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

	// 0. Write magic number and file version. Dont worry about endianness, as these are bytes 
	out.write(reinterpret_cast <const char *>(&magic_number), sizeof(uint8_t));
	out.write(reinterpret_cast <const char *>(&file_version_number), sizeof(uint8_t));

	// 0. Write the parameters to the file 
	uint64_t sketch_param = _R; 
	if (is_little_endian)
		sketch_param = __builtin_bswap64(sketch_param);
    out.write(reinterpret_cast <char *>(&sketch_param), sizeof(uint64_t));
	
	sketch_param = _range; 
	if (is_little_endian)
		sketch_param = __builtin_bswap64(sketch_param);
    out.write(reinterpret_cast <char *>(&sketch_param), sizeof(uint64_t));

	// 2. For each element in sketch
	for (size_t r = 0; r < _R; r++){
		for (size_t i = 0; i < _range; i++){
			// 2. Cast element to standard-sized element
			uint32_t value = _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. Write to stream 
			out.write(reinterpret_cast <char *>(&value), sizeof(uint32_t));
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rsi
movq %rsi, -0x40(%rbp)
movl $0x1, -0x14(%rbp)
cmpb $0x0, -0x14(%rbp)
setne %al
andb $0x1, %al
movb %al, -0x15(%rbp)
movq -0x10(%rbp), %rdi
addq $0x18, %rsi
movl $0x1, %edx
callq 0x22c0
movq -0x40(%rbp), %rsi
movq -0x10(%rbp), %rdi
addq $0x19, %rsi
movl $0x1, %edx
callq 0x22c0
movq -0x40(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x20(%rbp)
testb $0x1, -0x15(%rbp)
je 0x378f
movq -0x20(%rbp), %rax
bswapq %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x20(%rbp), %rsi
movl $0x8, %edx
callq 0x22c0
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
testb $0x1, -0x15(%rbp)
je 0x37be
movq -0x20(%rbp), %rax
bswapq %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x20(%rbp), %rsi
movl $0x8, %edx
callq 0x22c0
movq $0x0, -0x28(%rbp)
movq -0x40(%rbp), %rcx
movq -0x28(%rbp), %rax
cmpq (%rcx), %rax
jae 0x3854
movq $0x0, -0x30(%rbp)
movq -0x40(%rbp), %rcx
movq -0x30(%rbp), %rax
cmpq 0x8(%rcx), %rax
jae 0x3844
movq -0x40(%rbp), %rdx
movq 0x10(%rdx), %rax
movq -0x28(%rbp), %rcx
imulq 0x8(%rdx), %rcx
addq -0x30(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x34(%rbp)
testb $0x1, -0x15(%rbp)
je 0x3824
movl -0x34(%rbp), %eax
bswapl %eax
movl %eax, -0x34(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x34(%rbp), %rsi
movl $0x4, %edx
callq 0x22c0
movq -0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
jmp 0x37ed
jmp 0x3846
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x37d8
addq $0x40, %rsp
popq %rbp
retq
nopw (%rax,%rax)