// File: btbujiangjun[P]abcdl/example/fnn.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/fnn.model";

    abcdl::fnn::FNN fnn;
    fnn.set_alpha(0.1);
	fnn.set_batch_size(64);

    std::vector<abcdl::fnn::Layer*> layers;
    layers.push_back(new abcdl::fnn::InputLayer(784));
    //layers.push_back(new abcdl::fnn::FullConnLayer(784, 30, new abcdl::framework::SigmoidActivateFunc()));
    layers.push_back(new abcdl::fnn::FullConnLayer(784, 32, new abcdl::framework::ReluActivateFunc()));
    layers.push_back(new abcdl::fnn::OutputLayer(32, 10, new abcdl::framework::SigmoidActivateFunc(), new abcdl::framework::CrossEntropyCost()));
    fnn.set_layers(layers);

    const int train_size = -1;
    const int test_size = -1;
    
    //abcdl::utils::FashionMnistReader<real> helper("data");
    abcdl::utils::MnistReader<real> helper("data");
    abcdl::algebra::Mat train_data;
    helper.read_train_image(&train_data, train_size);
    abcdl::algebra::Mat train_label;
    helper.read_train_vec_label(&train_label, train_size);

    abcdl::algebra::Mat test_data;
    helper.read_test_image(&test_data, test_size);
    abcdl::algebra::Mat test_label;
    helper.read_test_vec_label(&test_label, test_size);
    real loss = 0;
	int epoch = 100;
    for(int i = 1; i <= epoch; i++){
		printf("Epoch:[%d/%d]\n", i, epoch);
        fnn.train(train_data, train_label);
        fnn.evaluate(test_data, test_label, &loss);
        fnn.write_model(path);
    }
}

// Assembly:
subq $0x278, %rsp            # imm = 0x278
movl $0x0, 0x274(%rsp)
movl %edi, 0x270(%rsp)
movq %rsi, 0x268(%rsp)
xorl %edi, %edi
callq 0x897d0
movl 0x270(%rsp), %edi
movq 0x268(%rsp), %rsi
callq 0x892c0
leaq 0x247(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x9710
movq 0x48(%rsp), %rdx
leaq 0x8415a(%rip), %rsi     # 0x8e0a4
leaq 0x248(%rsp), %rdi
callq 0x9580
jmp 0x9f59
leaq 0x247(%rsp), %rdi
callq 0x9470
leaq 0x1c0(%rsp), %rdi
callq 0x15a20
jmp 0x9f75
leaq 0x1c0(%rsp), %rdi
movss 0x8407f(%rip), %xmm0    # 0x8e004
callq 0x15b50
jmp 0x9f8c
leaq 0x1c0(%rsp), %rdi
movl $0x40, %esi
callq 0x15b70
jmp 0x9fa0
leaq 0x1a8(%rsp), %rdi
callq 0x15b90
movl $0x168, %edi            # imm = 0x168
callq 0x9430
movq %rax, 0x40(%rsp)
jmp 0x9fbe
movq 0x40(%rsp), %rdi
movl $0x310, %esi            # imm = 0x310
callq 0x15bd0
jmp 0x9fcf
movq 0x40(%rsp), %rax
movq %rax, 0x1a0(%rsp)
leaq 0x1a8(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
callq 0x15ba0
jmp 0x9ff3
movl $0x170, %edi            # imm = 0x170
callq 0x9430
movq %rax, 0x38(%rsp)
jmp 0xa004
movl $0x18, %edi
callq 0x9430
movq %rax, 0x30(%rsp)
jmp 0xa015
movq 0x30(%rsp), %rdi
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
callq 0x15c10
jmp 0xa02f
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rdi
movl $0x0, 0x194(%rsp)
movl $0x3f000000, 0x190(%rsp) # imm = 0x3F000000
movl $0x310, %esi            # imm = 0x310
movl $0x20, %edx
leaq 0x194(%rsp), %r8
leaq 0x190(%rsp), %r9
callq 0x15c40
jmp 0xa070
movq 0x38(%rsp), %rax
movq %rax, 0x198(%rsp)
leaq 0x1a8(%rsp), %rdi
leaq 0x198(%rsp), %rsi
callq 0x15ba0
jmp 0xa094
movl $0x1a0, %edi            # imm = 0x1A0
callq 0x9430
movq %rax, 0x28(%rsp)
jmp 0xa0a5
movl $0x18, %edi
callq 0x9430
movq %rax, 0x20(%rsp)
jmp 0xa0b6
movq 0x20(%rsp), %rdi
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
callq 0x15d50
jmp 0xa0d0
movl $0x18, %edi
callq 0x9430
movq %rax, 0x18(%rsp)
jmp 0xa0e1
movq 0x18(%rsp), %rdi
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
callq 0x15d80
jmp 0xa0fb
movq 0x18(%rsp), %r8
movq 0x20(%rsp), %rcx
movq 0x28(%rsp), %rdi
movl $0x0, 0x184(%rsp)
movl $0x3f000000, 0x180(%rsp) # imm = 0x3F000000
movq %rsp, %rax
leaq 0x180(%rsp), %rdx
movq %rdx, (%rax)
movl $0x20, %esi
movl $0xa, %edx
leaq 0x184(%rsp), %r9
callq 0x15db0
jmp 0xa147
movq 0x28(%rsp), %rax
movq %rax, 0x188(%rsp)
leaq 0x1a8(%rsp), %rdi
leaq 0x188(%rsp), %rsi
callq 0x15ba0
jmp 0xa16b
leaq 0x1c0(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
callq 0x15f00
jmp 0xa182
movl $0xffffffff, 0x17c(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x178(%rsp) # imm = 0xFFFFFFFF
leaq 0x107(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x9710
movq 0x10(%rsp), %rdx
leaq 0x83eff(%rip), %rsi     # 0x8e0b5
leaq 0x108(%rsp), %rdi
callq 0x9580
jmp 0xa1c5
leaq 0x128(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x161f0
jmp 0xa1dc
leaq 0x108(%rsp), %rdi
callq 0x9260
leaq 0x107(%rsp), %rdi
callq 0x9470
leaq 0xd8(%rsp), %rdi
callq 0x33a40
jmp 0xa205
xorl %eax, %eax
movl %eax, %ecx
leaq 0x128(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x162c0
jmp 0xa225
leaq 0xb0(%rsp), %rdi
callq 0x33a40
jmp 0xa234
leaq 0x128(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0xa, %ecx
callq 0x16400
jmp 0xa255
leaq 0x88(%rsp), %rdi
callq 0x33a40
jmp 0xa264
xorl %eax, %eax
movl %eax, %ecx
leaq 0x128(%rsp), %rdi
leaq 0x88(%rsp), %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x16540
jmp 0xa284
leaq 0x60(%rsp), %rdi
callq 0x33a40
jmp 0xa290
leaq 0x128(%rsp), %rdi
leaq 0x60(%rsp), %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0xa, %ecx
callq 0x16680
jmp 0xa2ae
xorps %xmm0, %xmm0
movss %xmm0, 0x5c(%rsp)
movl $0x64, 0x58(%rsp)
movl $0x1, 0x54(%rsp)
movl 0x54(%rsp), %eax
cmpl 0x58(%rsp), %eax
jg 0xa55d
movl 0x54(%rsp), %esi
movl 0x58(%rsp), %edx
leaq 0x83dd6(%rip), %rdi     # 0x8e0ba
xorl %eax, %eax
callq 0x9060
jmp 0xa2ed
leaq 0x1c0(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
leaq 0xb0(%rsp), %rdx
callq 0x27f90
jmp 0xa30c
leaq 0x1c0(%rsp), %rdi
leaq 0x88(%rsp), %rsi
leaq 0x60(%rsp), %rdx
leaq 0x5c(%rsp), %rcx
callq 0x28d60
jmp 0xa32d
leaq 0x1c0(%rsp), %rdi
leaq 0x248(%rsp), %rsi
callq 0x2a470
jmp 0xa344
jmp 0xa346
movl 0x54(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x54(%rsp)
jmp 0xa2c7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
leaq 0x247(%rsp), %rdi
callq 0x9470
jmp 0xa62c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa61f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa612
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa605
movq 0x40(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
callq 0x9410
jmp 0xa605
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa41e
movq 0x30(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
callq 0x9410
movq 0x38(%rsp), %rdi
callq 0x9410
jmp 0xa605
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa481
movq 0x20(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
callq 0x9410
jmp 0xa481
movq 0x18(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
callq 0x9410
movq 0x28(%rsp), %rdi
callq 0x9410
jmp 0xa605
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa4c7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x9260
leaq 0x107(%rsp), %rdi
callq 0x9470
jmp 0xa605
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa5f8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa5eb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa5de
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
jmp 0xa5d1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x238(%rsp)
movl %eax, 0x234(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x33e80
jmp 0xa5d1
leaq 0x60(%rsp), %rdi
callq 0x33e80
leaq 0x88(%rsp), %rdi
callq 0x33e80
leaq 0xb0(%rsp), %rdi
callq 0x33e80
leaq 0xd8(%rsp), %rdi
callq 0x33e80
leaq 0x128(%rsp), %rdi
callq 0x167c0
leaq 0x1a8(%rsp), %rdi
callq 0x16800
leaq 0x1c0(%rsp), %rdi
callq 0x16860
leaq 0x248(%rsp), %rdi
callq 0x9260
movl 0x274(%rsp), %eax
addq $0x278, %rsp            # imm = 0x278
retq
leaq 0x88(%rsp), %rdi
callq 0x33e80
leaq 0xb0(%rsp), %rdi
callq 0x33e80
leaq 0xd8(%rsp), %rdi
callq 0x33e80
leaq 0x128(%rsp), %rdi
callq 0x167c0
leaq 0x1a8(%rsp), %rdi
callq 0x16800
leaq 0x1c0(%rsp), %rdi
callq 0x16860
leaq 0x248(%rsp), %rdi
callq 0x9260
movq 0x238(%rsp), %rdi
callq 0x9700
nopl (%rax)