// File: /workspace/github_cpp_makefile_star2_O2/btbujiangjun[P]abcdl/include/utils/MnistHelper.h
// Function: abcdl::utils::MnistHelper<float>::read_mnist_file(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, int, unsigned long*)
inline std::unique_ptr<char[]> MnistHelper<T>::read_mnist_file(const std::string& path,
                                                               const int key,
                                                               size_t* out_rows){

    *out_rows = 0;

    std::ifstream file;
    file.open(path, std::ios::in | std::ios::binary | std::ios::ate);

    if(!file){
        std::cout << "Can't open file:" << path << std::endl;
        return {};
    }

    auto size = file.tellg();
    std::unique_ptr<char[]> buffer(new char[size]);

    //read the entire file to buffer
    file.seekg(0, std::ios::beg);
    file.read(buffer.get(), size);
    file.close();

    auto magic_num = read_header(buffer, 0);

    if(magic_num != key){
        std::cout << "Invalid magic number, probably not a MNIST file" << std::endl;
        return {};
    }

    auto count = read_header(buffer, 1);

    if(magic_num == 0x803){
        auto rows = read_header(buffer, 2);
        auto cols = read_header(buffer, 3);

        if(size < count * rows * cols + 16){
            std::cout << "File size ERROR" << std::endl;
            return {};
        }
    }else if( magic_num == 0x801){
        if(size < count + 8){
            std::cout << "File size ERROR" << std::endl;
            return {};
        }
    }

    *out_rows = count;

    return std::move(buffer);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x210, %rsp            # imm = 0x210
movq %r8, %r14
movl %ecx, %ebp
movq %rdx, %r15
movq %rdi, %rbx
andq $0x0, (%r8)
leaq 0x8(%rsp), %r12
movq %r12, %rdi
callq 0x93a0
pushq $0xe
popq %rdx
movq %r12, %rdi
movq %r15, %rsi
callq 0x9300
movq 0x8(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x28(%rsp,%rax)
je 0x10fe0
movq 0x3e000(%rip), %rdi     # 0x4efb8
leaq 0x1f264(%rip), %rsi     # 0x30223
callq 0x9370
movq %rax, %rdi
movq %r15, %rsi
callq 0x9320
movq %rax, %rdi
callq 0x9180
andq $0x0, (%rbx)
jmp 0x1111a
leaq 0x8(%rsp), %rdi
callq 0x95c0
movq %rax, %r15
testq %rax, %rax
pushq $-0x1
popq %rdi
cmovnsq %rax, %rdi
callq 0x9030
movq %rax, %r12
movq %rax, (%rsp)
leaq 0x8(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x9450
leaq 0x8(%rsp), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x93f0
leaq 0x8(%rsp), %rdi
callq 0x9080
movq (%rsp), %rax
movl (%rax), %ecx
movl %ecx, %edx
andl $0xffffff, %edx         # imm = 0xFFFFFF
bswapl %edx
sarl $0x18, %ecx
orl %edx, %ecx
cmpl %ebp, %ecx
jne 0x110bb
movl 0x4(%rax), %ecx
movl %ecx, %edx
andl $0xffffff, %edx         # imm = 0xFFFFFF
bswapl %edx
sarl $0x18, %ecx
orl %edx, %ecx
cmpl $0x801, %ebp            # imm = 0x801
je 0x110dc
cmpl $0x803, %ebp            # imm = 0x803
jne 0x11104
movl 0x8(%rax), %edx
movl 0xc(%rax), %esi
movl $0xffffff, %edi         # imm = 0xFFFFFF
movl %edx, %r8d
andl %edi, %r8d
bswapl %r8d
sarl $0x18, %edx
orl %r8d, %edx
andl %esi, %edi
bswapl %edi
sarl $0x18, %esi
orl %edi, %esi
imull %ecx, %edx
imull %esi, %edx
addl $0x10, %edx
movslq %edx, %rdx
cmpq %rdx, %r15
jge 0x11104
movq 0x3df13(%rip), %rdi     # 0x4efb8
leaq 0x1f1b8(%rip), %rsi     # 0x30264
callq 0x9370
movq %rax, %rdi
callq 0x9180
jmp 0x110d6
movq 0x3def6(%rip), %rdi     # 0x4efb8
leaq 0x1f16b(%rip), %rsi     # 0x30234
callq 0x9370
movq %rax, %rdi
callq 0x9180
andq $0x0, (%rbx)
jmp 0x11112
leal 0x8(%rcx), %edx
movslq %edx, %rdx
cmpq %rdx, %r15
jge 0x11104
movq 0x3deca(%rip), %rdi     # 0x4efb8
leaq 0x1f16f(%rip), %rsi     # 0x30264
callq 0x9370
movq %rax, %rdi
callq 0x9180
jmp 0x110d6
movslq %ecx, %rcx
movq %rcx, (%r14)
movq %rax, (%rbx)
andq $0x0, (%rsp)
movq %rsp, %rdi
callq 0x111be
leaq 0x8(%rsp), %rdi
callq 0x90a0
movq %rbx, %rax
addq $0x210, %rsp            # imm = 0x210
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
jmp 0x11141
jmp 0x11141
jmp 0x11141
jmp 0x1114e
jmp 0x1114e
movq %rax, %rbx
movq %rsp, %rdi
callq 0x111be
jmp 0x11151
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x90a0
movq %rbx, %rdi
callq 0x95e0
nop