// File: /workspace/github_cpp_makefile_star2_O3/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 0x11ffb
movq 0x46027(%rip), %rdi     # 0x57fc8
leaq 0x2827b(%rip), %rsi     # 0x3a223
movl $0x10, %edx
callq 0x93b0
movq (%r14), %rsi
movq 0x8(%r14), %rdx
movq 0x46008(%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 0x121bb
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), %eax
movl %eax, %ecx
andl $0xffffff, %ecx         # imm = 0xFFFFFF
bswapl %ecx
sarl $0x18, %eax
orl %ecx, %eax
cmpl %ebp, %eax
jne 0x12109
movl 0x4(%r14), %eax
movl %eax, %ecx
andl $0xffffff, %ecx         # imm = 0xFFFFFF
bswapl %ecx
sarl $0x18, %eax
orl %ecx, %eax
cmpl $0x801, %ebp            # imm = 0x801
je 0x12160
cmpl $0x803, %ebp            # imm = 0x803
jne 0x121b3
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 0x121b3
movq 0x45f00(%rip), %r15     # 0x57fc8
leaq 0x28195(%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 0x45ece(%rip), %rdi     # 0x57fc8
callq 0x9040
movq %rax, %rdi
callq 0x9210
jmp 0x1214f
movq 0x45eb8(%rip), %r15     # 0x57fc8
leaq 0x2811d(%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 0x45e86(%rip), %rdi     # 0x57fc8
callq 0x9040
movq %rax, %rdi
callq 0x9210
movq $0x0, (%rbx)
movq %r14, %rdi
callq 0x9420
jmp 0x121bb
leal 0x8(%rax), %ecx
movslq %ecx, %rcx
cmpq %rcx, %r12
jge 0x121b3
movq 0x45e56(%rip), %r15     # 0x57fc8
leaq 0x280eb(%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 0x45e24(%rip), %rdi     # 0x57fc8
callq 0x9040
movq %rax, %rdi
callq 0x9210
jmp 0x1214f
cltq
movq %rax, (%r15)
movq %r14, (%rbx)
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 0x121e2
jmp 0x121e2
jmp 0x121ef
jmp 0x121ef
jmp 0x121e2
movq %rax, %rbx
movq %r14, %rdi
callq 0x9420
jmp 0x121f2
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x90b0
movq %rbx, %rdi
callq 0x95d0