// File: /workspace/github_cpp_makefile_star2_O1/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, %r15
movl %ecx, %ebp
movq %rdx, %r14
movq %rdi, %rbx
movq $0x0, (%r8)
leaq 0x8(%rsp), %r12
movq %r12, %rdi
callq 0x93a0
movq %r12, %rdi
movq %r14, %rsi
movl $0xe, %edx
callq 0x9300
movq 0x8(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x28(%rsp,%rax)
je 0x12321
movq 0x45d01(%rip), %rdi     # 0x57fc8
leaq 0x27f55(%rip), %rsi     # 0x3a223
movl $0x10, %edx
callq 0x93b0
movq (%r14), %rsi
movq 0x8(%r14), %rdx
movq 0x45ce2(%rip), %rdi     # 0x57fc8
callq 0x93b0
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x9360
movsbl %al, %esi
movq %r14, %rdi
callq 0x9040
movq %rax, %rdi
callq 0x9210
movq $0x0, (%rbx)
jmp 0x124e8
leaq 0x8(%rsp), %rdi
callq 0x95b0
movq %rax, %r12
testq %rax, %rax
movq $-0x1, %rdi
cmovnsq %rax, %rdi
callq 0x9030
movq %rax, %r14
leaq 0x8(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x9440
leaq 0x8(%rsp), %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x93f0
leaq 0x8(%rsp), %rdi
callq 0x9090
movl (%r14), %ecx
movl %ecx, %eax
andl $0xffffff, %eax         # imm = 0xFFFFFF
bswapl %eax
sarl $0x18, %ecx
orl %eax, %ecx
cmpl %ebp, %ecx
jne 0x1242e
movl 0x4(%r14), %eax
movl %eax, %edx
andl $0xffffff, %edx         # imm = 0xFFFFFF
bswapl %edx
sarl $0x18, %eax
orl %edx, %eax
cmpl $0x801, %ecx            # imm = 0x801
je 0x1247d
cmpl $0x803, %ecx            # imm = 0x803
jne 0x124d0
movl 0x8(%r14), %ecx
movl 0xc(%r14), %edx
movl $0xffffff, %esi         # imm = 0xFFFFFF
movl %ecx, %edi
andl %esi, %edi
bswapl %edi
sarl $0x18, %ecx
orl %edi, %ecx
andl %edx, %esi
bswapl %esi
sarl $0x18, %edx
orl %esi, %edx
imull %eax, %ecx
imull %edx, %ecx
addl $0x10, %ecx
movslq %ecx, %rcx
cmpq %rcx, %r12
jge 0x124d0
movq 0x45bdb(%rip), %r15     # 0x57fc8
leaq 0x27e70(%rip), %rsi     # 0x3a264
movl $0xf, %edx
movq %r15, %rdi
callq 0x93b0
movq (%r15), %rax
addq -0x18(%rax), %r15
movq %r15, %rdi
movl $0xa, %esi
callq 0x9360
movsbl %al, %esi
movq 0x45ba9(%rip), %rdi     # 0x57fc8
callq 0x9040
movq %rax, %rdi
callq 0x9210
jmp 0x12474
movq 0x45b93(%rip), %r15     # 0x57fc8
leaq 0x27df8(%rip), %rsi     # 0x3a234
movl $0x2f, %edx
movq %r15, %rdi
callq 0x93b0
movq (%r15), %rax
addq -0x18(%rax), %r15
movq %r15, %rdi
movl $0xa, %esi
callq 0x9360
movsbl %al, %esi
movq 0x45b61(%rip), %rdi     # 0x57fc8
callq 0x9040
movq %rax, %rdi
callq 0x9210
movq $0x0, (%rbx)
jmp 0x124db
leal 0x8(%rax), %ecx
movslq %ecx, %rcx
cmpq %rcx, %r12
jge 0x124d0
movq 0x45b39(%rip), %r15     # 0x57fc8
leaq 0x27dce(%rip), %rsi     # 0x3a264
movl $0xf, %edx
movq %r15, %rdi
callq 0x93b0
movq (%r15), %rax
addq -0x18(%rax), %r15
movq %r15, %rdi
movl $0xa, %esi
callq 0x9360
movsbl %al, %esi
movq 0x45b07(%rip), %rdi     # 0x57fc8
callq 0x9040
movq %rax, %rdi
callq 0x9210
jmp 0x12474
cltq
movq %rax, (%r15)
movq %r14, (%rbx)
xorl %r14d, %r14d
testq %r14, %r14
je 0x124e8
movq %r14, %rdi
callq 0x9420
leaq 0x8(%rsp), %rdi
callq 0x90b0
movq %rbx, %rax
addq $0x210, %rsp            # imm = 0x210
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
jmp 0x1250f
jmp 0x1250f
jmp 0x1251c
jmp 0x1251c
jmp 0x1250f
movq %rax, %rbx
movq %r14, %rdi
callq 0x9420
jmp 0x1251f
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x90b0
movq %rbx, %rdi
callq 0x95d0
nop