// File: btbujiangjun[P]abcdl/example/cnn.cpp
// Function: main
int main(int argc, char** argv){
    abcdl::utils::log::set_min_log_level(abcdl::utils::log::INFO);
    abcdl::utils::log::initialize_log(argc, argv);

    const std::string path = "./data/cnn.model";

    std::vector<abcdl::cnn::Layer*> layers;
    layers.push_back(new abcdl::cnn::InputLayer(28, 28));
    layers.push_back(new abcdl::cnn::ConvolutionLayer(3, 1, 5, new abcdl::framework::SigmoidActivateFunc()));
    layers.push_back(new abcdl::cnn::SubSamplingLayer(2, new abcdl::framework::MeanPooling()));
    layers.push_back(new abcdl::cnn::ConvolutionLayer(3, 1, 5, new abcdl::framework::SigmoidActivateFunc()));
//    layers.push_back(new abcdl::cnn::SubSamplingLayer(2, new abcdl::cnn::MeanPooling()));
    layers.push_back(new abcdl::cnn::OutputLayer(10, new abcdl::framework::SigmoidActivateFunc(), new abcdl::framework::CrossEntropyCost()));

    abcdl::cnn::CNN cnn;
    cnn.set_layers(layers);
	cnn.set_batch_size(1);
	cnn.set_alpha(0.1);

    //abcdl::utils::FashionMnistReader<real> helper("data");
    abcdl::utils::MnistReader<real> helper("data");
    const size_t train_size = 60000;
    const size_t test_size  = 10000;

    abcdl::algebra::MatSet train_data;
    helper.read_train_images(train_data, train_size, 30);

    abcdl::algebra::MatSet train_label;
    helper.read_train_vec_labels(train_label, train_size);

    abcdl::algebra::MatSet test_data;
    helper.read_test_images(test_data, test_size);

    abcdl::algebra::MatSet test_label;
    helper.read_test_vec_labels(test_label, test_size);

    cnn.train(train_data, train_label, test_data, test_label);
}

// Assembly:
subq $0x238, %rsp            # imm = 0x238
movl %edi, 0x234(%rsp)
movq %rsi, 0x228(%rsp)
xorl %edi, %edi
callq 0x861e0
movl 0x234(%rsp), %edi
movq 0x228(%rsp), %rsi
callq 0x85cd0
leaq 0x207(%rsp), %rdi
movq %rdi, 0x78(%rsp)
callq 0x95e0
movq 0x78(%rsp), %rdx
leaq 0x81281(%rip), %rsi     # 0x8b0a0
leaq 0x208(%rsp), %rdi
callq 0x94b0
jmp 0x9e2e
leaq 0x207(%rsp), %rdi
callq 0x93e0
leaq 0x1d8(%rsp), %rdi
callq 0x15990
movl $0xd0, %edi
callq 0x93a0
movq %rax, 0x70(%rsp)
jmp 0x9e59
movq 0x70(%rsp), %rdi
movl $0x1c, %edx
movq %rdx, %rsi
callq 0x159d0
jmp 0x9e6d
movq 0x70(%rsp), %rax
movq %rax, 0x1d0(%rsp)
leaq 0x1d8(%rsp), %rdi
leaq 0x1d0(%rsp), %rsi
callq 0x159a0
jmp 0x9e91
movl $0xe8, %edi
callq 0x93a0
movq %rax, 0x68(%rsp)
jmp 0x9ea2
movl $0x18, %edi
callq 0x93a0
movq %rax, 0x60(%rsp)
jmp 0x9eb3
movq 0x60(%rsp), %rdi
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
callq 0x15a20
jmp 0x9ecd
movq 0x60(%rsp), %r8
movq 0x68(%rsp), %rdi
movl $0x3, %esi
movl $0x1, %edx
movl $0x5, %ecx
callq 0x15a50
jmp 0x9eed
movq 0x68(%rsp), %rax
movq %rax, 0x1c8(%rsp)
leaq 0x1d8(%rsp), %rdi
leaq 0x1c8(%rsp), %rsi
callq 0x159a0
jmp 0x9f11
movl $0xe0, %edi
callq 0x93a0
movq %rax, 0x58(%rsp)
jmp 0x9f22
movl $0x8, %edi
callq 0x93a0
movq %rax, 0x50(%rsp)
jmp 0x9f33
movq 0x50(%rsp), %rdi
movq $0x0, (%rdi)
callq 0x15ad0
movq 0x58(%rsp), %rdi
movq 0x50(%rsp), %rdx
movl $0x2, %esi
callq 0x15b00
jmp 0x9f5a
movq 0x58(%rsp), %rax
movq %rax, 0x1c0(%rsp)
leaq 0x1d8(%rsp), %rdi
leaq 0x1c0(%rsp), %rsi
callq 0x159a0
jmp 0x9f7e
movl $0xe8, %edi
callq 0x93a0
movq %rax, 0x48(%rsp)
jmp 0x9f8f
movl $0x18, %edi
callq 0x93a0
movq %rax, 0x40(%rsp)
jmp 0x9fa0
movq 0x40(%rsp), %rdi
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
callq 0x15a20
jmp 0x9fba
movq 0x40(%rsp), %r8
movq 0x48(%rsp), %rdi
movl $0x3, %esi
movl $0x1, %edx
movl $0x5, %ecx
callq 0x15a50
jmp 0x9fda
movq 0x48(%rsp), %rax
movq %rax, 0x1b8(%rsp)
leaq 0x1d8(%rsp), %rdi
leaq 0x1b8(%rsp), %rsi
callq 0x159a0
jmp 0x9ffe
movl $0x138, %edi            # imm = 0x138
callq 0x93a0
movq %rax, 0x38(%rsp)
jmp 0xa00f
movl $0x18, %edi
callq 0x93a0
movq %rax, 0x30(%rsp)
jmp 0xa020
movq 0x30(%rsp), %rdi
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
callq 0x15a20
jmp 0xa03a
movl $0x18, %edi
callq 0x93a0
movq %rax, 0x28(%rsp)
jmp 0xa04b
movq 0x28(%rsp), %rdi
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
callq 0x15b70
jmp 0xa065
movq 0x28(%rsp), %rcx
movq 0x30(%rsp), %rdx
movq 0x38(%rsp), %rdi
movl $0xa, %esi
callq 0x15ba0
jmp 0xa080
movq 0x38(%rsp), %rax
movq %rax, 0x1b0(%rsp)
leaq 0x1d8(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
callq 0x159a0
jmp 0xa0a4
leaq 0x180(%rsp), %rdi
callq 0x15c80
jmp 0xa0b3
leaq 0x168(%rsp), %rdi
leaq 0x1d8(%rsp), %rsi
callq 0x15cb0
jmp 0xa0ca
leaq 0x180(%rsp), %rdi
leaq 0x168(%rsp), %rsi
callq 0x2b1e0
jmp 0xa0e1
leaq 0x168(%rsp), %rdi
callq 0x15db0
leaq 0x180(%rsp), %rdi
movl $0x1, %esi
callq 0x15e10
jmp 0xa102
leaq 0x180(%rsp), %rdi
movss 0x80ef2(%rip), %xmm0    # 0x8b004
callq 0x15e30
jmp 0xa119
leaq 0xf7(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x95e0
movq 0x20(%rsp), %rdx
leaq 0x80f7a(%rip), %rsi     # 0x8b0b1
leaq 0xf8(%rsp), %rdi
callq 0x94b0
jmp 0xa146
leaq 0x118(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0x15e50
jmp 0xa15d
leaq 0xf8(%rsp), %rdi
callq 0x91e0
leaq 0xf7(%rsp), %rdi
callq 0x93e0
movq $0xea60, 0xe8(%rsp) # imm = 0xEA60
movq $0x2710, 0xe0(%rsp) # imm = 0x2710
leaq 0xc8(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x15f20
movq 0x18(%rsp), %rsi
leaq 0x118(%rsp), %rdi
movl $0xea60, %edx           # imm = 0xEA60
movl $0x1e, %ecx
callq 0x15f30
jmp 0xa1bf
leaq 0xb0(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x15f20
movq 0x10(%rsp), %rsi
leaq 0x118(%rsp), %rdi
movl $0xea60, %edx           # imm = 0xEA60
movl $0xa, %ecx
callq 0x16070
jmp 0xa1ef
leaq 0x98(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x15f20
movq 0x8(%rsp), %rsi
xorl %eax, %eax
movl %eax, %ecx
leaq 0x118(%rsp), %rdi
movl $0x2710, %edx           # imm = 0x2710
callq 0x161b0
jmp 0xa21e
leaq 0x80(%rsp), %rdi
movq %rdi, (%rsp)
callq 0x15f20
movq (%rsp), %rsi
leaq 0x118(%rsp), %rdi
movl $0x2710, %edx           # imm = 0x2710
movl $0xa, %ecx
callq 0x162f0
jmp 0xa24c
leaq 0x180(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
leaq 0xb0(%rsp), %rdx
leaq 0x98(%rsp), %rcx
leaq 0x80(%rsp), %r8
callq 0x2b400
jmp 0xa27b
leaq 0x80(%rsp), %rdi
callq 0x16430
leaq 0x98(%rsp), %rdi
callq 0x16430
leaq 0xb0(%rsp), %rdi
callq 0x16430
leaq 0xc8(%rsp), %rdi
callq 0x16430
leaq 0x118(%rsp), %rdi
callq 0x16440
leaq 0x180(%rsp), %rdi
callq 0x16480
leaq 0x1d8(%rsp), %rdi
callq 0x15db0
leaq 0x208(%rsp), %rdi
callq 0x91e0
xorl %eax, %eax
addq $0x238, %rsp            # imm = 0x238
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
leaq 0x207(%rsp), %rdi
callq 0x93e0
jmp 0xa5a1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0xa587
movq 0x70(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
callq 0x9380
jmp 0xa587
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0xa383
movq 0x60(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
callq 0x9380
movq 0x68(%rsp), %rdi
callq 0x9380
jmp 0xa587
movq 0x58(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
callq 0x9380
jmp 0xa587
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0xa3e9
movq 0x40(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
callq 0x9380
movq 0x48(%rsp), %rdi
callq 0x9380
jmp 0xa587
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0xa44c
movq 0x30(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
callq 0x9380
jmp 0xa44c
movq 0x28(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
callq 0x9380
movq 0x38(%rsp), %rdi
callq 0x9380
jmp 0xa587
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0xa57a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
leaq 0x168(%rsp), %rdi
callq 0x15db0
jmp 0xa57a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0xa4d1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
leaq 0xf8(%rsp), %rdi
callq 0x91e0
leaq 0xf7(%rsp), %rdi
callq 0x93e0
jmp 0xa57a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0xa560
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0xa553
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0xa546
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
leaq 0x80(%rsp), %rdi
callq 0x16430
leaq 0x98(%rsp), %rdi
callq 0x16430
leaq 0xb0(%rsp), %rdi
callq 0x16430
leaq 0xc8(%rsp), %rdi
callq 0x16430
leaq 0x118(%rsp), %rdi
callq 0x16440
leaq 0x180(%rsp), %rdi
callq 0x16480
leaq 0x1d8(%rsp), %rdi
callq 0x15db0
leaq 0x208(%rsp), %rdi
callq 0x91e0
movq 0x1f8(%rsp), %rdi
callq 0x95d0
nop