// File: btbujiangjun[P]abcdl/src/fnn/FNN.cpp
// Function: abcdl::fnn::FNN::evaluate(abcdl::algebra::Matrix<float> const&, abcdl::algebra::Matrix<float> const&, float*)
size_t FNN::evaluate(const abcdl::algebra::Mat& test_data,
                     const abcdl::algebra::Mat& test_label,
                     real* loss){
    CHECK(test_data.rows() > 0);
    CHECK(test_data.cols() == _layers[0]->get_input_dim());
    CHECK(test_data.rows() == test_label.rows());
    CHECK(test_label.cols() == _layers[_layers.size() - 1]->get_output_dim());

    auto now = []{return std::chrono::system_clock::now();};
    auto start_time = now();
    
    size_t rows = test_data.rows();
    size_t predict_num = 0;
    abcdl::algebra::Mat mat;

    real total_loss = 0;
    std::vector<std::pair<real, real>> auc_evaluate_vec;

    for(size_t i = 0; i < rows; i++){
        predict(mat, test_data.get_row(i));
		if(mat.argmax() == test_label.get_row(i).argmax()){
            ++ predict_num; 
        }
        auc_evaluate_vec.push_back(std::make_pair(test_label.get_row(i).argmax(), mat.argmax()));
        total_loss += _loss->loss(test_label.get_row(i), mat);
    }

    *loss = total_loss / rows;
    double auc_score = auc(auc_evaluate_vec); 
    LOG(INFO) << "evaluate auc[" << auc_score << "] loss[" << *loss << "] ["<< predict_num <<"/" << rows << "] rate[" << predict_num/(real)rows << "]";
    auto predict_time = now();
    printf("evaluate auc[%lf] loss[%f] rate[%f] [%zu/%zu]predict run time:[%lld]ms\n", auc_score, *loss, predict_num/(real)rows, predict_num, rows, (long long int)std::chrono::duration_cast<std::chrono::milliseconds>(predict_time - start_time).count());
    return predict_num;
}

// Assembly:
subq $0xaa8, %rsp            # imm = 0xAA8
movq %rdi, 0xaa0(%rsp)
movq %rsi, 0xa98(%rsp)
movq %rdx, 0xa90(%rsp)
movq %rcx, 0xa88(%rsp)
movq 0xaa0(%rsp), %rax
movq %rax, 0x168(%rsp)
movq 0xa98(%rsp), %rdi
callq 0x1a390
cmpq $0x0, %rax
seta %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x28db3
jmp 0x28e24
leaq 0x671f6(%rip), %rsi     # 0x8ffb0
leaq 0x900(%rsp), %rdi
movq %rdi, 0x160(%rsp)
movl $0x52, %edx
movl $0x3, %ecx
callq 0x89860
movq 0x160(%rsp), %rdi
leaq 0x67313(%rip), %rsi     # 0x900fb
callq 0x2c010
jmp 0x28def
leaq 0x900(%rsp), %rdi
callq 0x89c20
jmp 0x28e24
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
leaq 0x900(%rsp), %rdi
callq 0x89c20
jmp 0x298e2
movq 0xa98(%rsp), %rdi
callq 0x1a3a0
movq 0x168(%rsp), %rdi
movq %rax, 0x158(%rsp)
addq $0x30, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x17270
movq (%rax), %rdi
callq 0x17310
movq %rax, %rcx
movq 0x158(%rsp), %rax
cmpq %rcx, %rax
sete %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x28e6f
jmp 0x28ee0
leaq 0x6713a(%rip), %rsi     # 0x8ffb0
leaq 0x768(%rsp), %rdi
movq %rdi, 0x150(%rsp)
movl $0x53, %edx
movl $0x3, %ecx
callq 0x89860
movq 0x150(%rsp), %rdi
leaq 0x6727a(%rip), %rsi     # 0x9011e
callq 0x2c040
jmp 0x28eab
leaq 0x768(%rsp), %rdi
callq 0x89c20
jmp 0x28ee0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
leaq 0x768(%rsp), %rdi
callq 0x89c20
jmp 0x298e2
movq 0xa98(%rsp), %rdi
callq 0x1a390
movq %rax, 0x148(%rsp)
movq 0xa90(%rsp), %rdi
callq 0x1a390
movq %rax, %rcx
movq 0x148(%rsp), %rax
cmpq %rcx, %rax
sete %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x28f1b
jmp 0x28f8c
leaq 0x6708e(%rip), %rsi     # 0x8ffb0
leaq 0x5e0(%rsp), %rdi
movq %rdi, 0x140(%rsp)
movl $0x54, %edx
movl $0x3, %ecx
callq 0x89860
movq 0x140(%rsp), %rdi
leaq 0x6720c(%rip), %rsi     # 0x9015c
callq 0x2c070
jmp 0x28f57
leaq 0x5e0(%rsp), %rdi
callq 0x89c20
jmp 0x28f8c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
leaq 0x5e0(%rsp), %rdi
callq 0x89c20
jmp 0x298e2
movq 0xa90(%rsp), %rdi
callq 0x1a3a0
movq 0x168(%rsp), %rdi
movq %rax, 0x138(%rsp)
movq %rdi, %rax
addq $0x30, %rax
movq %rax, 0x130(%rsp)
addq $0x30, %rdi
callq 0x17250
movq 0x130(%rsp), %rdi
movq %rax, %rsi
subq $0x1, %rsi
callq 0x17270
movq (%rax), %rdi
callq 0x172d0
movq %rax, %rcx
movq 0x138(%rsp), %rax
cmpq %rcx, %rax
sete %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x28ff6
jmp 0x29067
leaq 0x66fb3(%rip), %rsi     # 0x8ffb0
leaq 0x458(%rsp), %rdi
movq %rdi, 0x128(%rsp)
movl $0x55, %edx
movl $0x3, %ecx
callq 0x89860
movq 0x128(%rsp), %rdi
leaq 0x67165(%rip), %rsi     # 0x90190
callq 0x2ba90
jmp 0x29032
leaq 0x458(%rsp), %rdi
callq 0x89c20
jmp 0x29067
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
leaq 0x458(%rsp), %rdi
callq 0x89c20
jmp 0x298e2
leaq 0x457(%rsp), %rdi
callq 0x298f0
movq %rax, 0x448(%rsp)
movq 0xa98(%rsp), %rdi
callq 0x1a390
movq %rax, 0x440(%rsp)
movq $0x0, 0x438(%rsp)
leaq 0x410(%rsp), %rdi
callq 0x33a40
xorps %xmm0, %xmm0
movss %xmm0, 0x40c(%rsp)
leaq 0x3f0(%rsp), %rdi
callq 0x2bac0
movq $0x0, 0x3e8(%rsp)
movq 0x3e8(%rsp), %rax
cmpq 0x440(%rsp), %rax
jae 0x29409
movq 0xa98(%rsp), %rsi
movq 0x3e8(%rsp), %rdx
leaq 0x3c0(%rsp), %rdi
movl $0x1, %ecx
callq 0x343d0
jmp 0x29109
movq 0x168(%rsp), %rdi
leaq 0x410(%rsp), %rsi
leaq 0x3c0(%rsp), %rdx
callq 0x29910
jmp 0x29128
leaq 0x3c0(%rsp), %rdi
callq 0x33e80
leaq 0x410(%rsp), %rdi
callq 0x5d440
movq %rax, 0x120(%rsp)
jmp 0x2914c
movq 0xa90(%rsp), %rsi
movq 0x3e8(%rsp), %rdx
leaq 0x398(%rsp), %rdi
movl $0x1, %ecx
callq 0x343d0
jmp 0x29170
leaq 0x398(%rsp), %rdi
callq 0x5d440
movq %rax, 0x118(%rsp)
jmp 0x29187
leaq 0x398(%rsp), %rdi
callq 0x33e80
movq 0x118(%rsp), %rcx
movq 0x120(%rsp), %rax
cmpq %rcx, %rax
jne 0x29224
movq 0x438(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x438(%rsp)
jmp 0x29224
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
jmp 0x298c8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
leaq 0x3c0(%rsp), %rdi
callq 0x33e80
jmp 0x298c8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
leaq 0x398(%rsp), %rdi
callq 0x33e80
jmp 0x298c8
movq 0xa90(%rsp), %rsi
movq 0x3e8(%rsp), %rdx
leaq 0x350(%rsp), %rdi
movl $0x1, %ecx
callq 0x343d0
jmp 0x29248
leaq 0x350(%rsp), %rdi
callq 0x5d440
movq %rax, 0x110(%rsp)
jmp 0x2925f
movq 0x110(%rsp), %rax
movq %rax, 0x378(%rsp)
leaq 0x410(%rsp), %rdi
callq 0x5d440
movq %rax, 0x108(%rsp)
jmp 0x29286
movq 0x108(%rsp), %rax
movq %rax, 0x348(%rsp)
leaq 0x378(%rsp), %rdi
leaq 0x348(%rsp), %rsi
callq 0x2bd00
movq %rdx, 0xf8(%rsp)
movq %rax, 0x100(%rsp)
jmp 0x292bd
movq 0xf8(%rsp), %rax
movq 0x100(%rsp), %rcx
movq %rcx, 0x380(%rsp)
movq %rax, 0x388(%rsp)
leaq 0x390(%rsp), %rdi
leaq 0x380(%rsp), %rsi
callq 0x2bd40
jmp 0x292f4
leaq 0x3f0(%rsp), %rdi
leaq 0x390(%rsp), %rsi
callq 0x2bcd0
jmp 0x2930b
leaq 0x350(%rsp), %rdi
callq 0x33e80
movq 0x168(%rsp), %rax
movq 0x48(%rax), %rax
movq %rax, 0xf0(%rsp)
movq 0xa90(%rsp), %rsi
movq 0x3e8(%rsp), %rdx
leaq 0x320(%rsp), %rdi
movl $0x1, %ecx
callq 0x343d0
jmp 0x29350
movq 0xf0(%rsp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
leaq 0x320(%rsp), %rsi
leaq 0x410(%rsp), %rdx
callq *%rax
movss %xmm0, 0xec(%rsp)
jmp 0x2937c
movss 0xec(%rsp), %xmm0
addss 0x40c(%rsp), %xmm0
movss %xmm0, 0x40c(%rsp)
leaq 0x320(%rsp), %rdi
callq 0x33e80
movq 0x3e8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x3e8(%rsp)
jmp 0x290cf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
leaq 0x350(%rsp), %rdi
callq 0x33e80
jmp 0x298c8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
leaq 0x320(%rsp), %rdi
callq 0x33e80
jmp 0x298c8
movss 0x40c(%rsp), %xmm0
movss %xmm0, 0xe0(%rsp)
movq 0x440(%rsp), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, 0xe4(%rsp)
testq %rax, %rax
movss %xmm0, 0xe8(%rsp)
js 0x29468
movss 0xe4(%rsp), %xmm0
movss %xmm0, 0xe8(%rsp)
movq 0x168(%rsp), %rdi
movss 0xe0(%rsp), %xmm0
movss 0xe8(%rsp), %xmm1
divss %xmm1, %xmm0
movq 0xa88(%rsp), %rax
movss %xmm0, (%rax)
leaq 0x3f0(%rsp), %rsi
callq 0x28bc0
movsd %xmm0, 0xd8(%rsp)
jmp 0x294aa
movsd 0xd8(%rsp), %xmm0
movsd %xmm0, 0x318(%rsp)
leaq 0x66aed(%rip), %rsi     # 0x8ffb0
leaq 0x190(%rsp), %rdi
movl $0x6c, %edx
xorl %ecx, %ecx
callq 0x89860
jmp 0x294d9
leaq 0x66d01(%rip), %rsi     # 0x901e1
leaq 0x190(%rsp), %rdi
callq 0x2c130
movq %rax, 0xd0(%rsp)
jmp 0x294f7
movq 0xd0(%rsp), %rdi
leaq 0x318(%rsp), %rsi
callq 0x2bef0
movq %rax, 0xc8(%rsp)
jmp 0x29516
movq 0xc8(%rsp), %rdi
leaq 0x66b85(%rip), %rsi     # 0x900aa
callq 0x2bf20
movq %rax, 0xc0(%rsp)
jmp 0x29534
movq 0xc0(%rsp), %rdi
movq 0xa88(%rsp), %rsi
callq 0x2c0d0
movq %rax, 0xb8(%rsp)
jmp 0x29553
movq 0xb8(%rsp), %rdi
leaq 0x66c8d(%rip), %rsi     # 0x901ef
callq 0x2be90
movq %rax, 0xb0(%rsp)
jmp 0x29571
movq 0xb0(%rsp), %rdi
leaq 0x438(%rsp), %rsi
callq 0x2c100
movq %rax, 0xa8(%rsp)
jmp 0x29590
movq 0xa8(%rsp), %rdi
leaq 0x64c5d(%rip), %rsi     # 0x8e1fc
callq 0x2c0a0
movq %rax, 0xa0(%rsp)
jmp 0x295ae
movq 0xa0(%rsp), %rdi
leaq 0x440(%rsp), %rsi
callq 0x2c100
movq %rax, 0x98(%rsp)
jmp 0x295cd
movq 0x98(%rsp), %rdi
leaq 0x66c17(%rip), %rsi     # 0x901f3
callq 0x2bf20
movq %rax, 0x90(%rsp)
jmp 0x295eb
movq 0x438(%rsp), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, 0x88(%rsp)
testq %rax, %rax
movss %xmm0, 0x8c(%rsp)
js 0x29638
movss 0x88(%rsp), %xmm0
movss %xmm0, 0x8c(%rsp)
movss 0x8c(%rsp), %xmm0
movss %xmm0, 0x7c(%rsp)
movq 0x440(%rsp), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, 0x80(%rsp)
testq %rax, %rax
movss %xmm0, 0x84(%rsp)
js 0x29694
movss 0x80(%rsp), %xmm0
movss %xmm0, 0x84(%rsp)
movq 0x90(%rsp), %rdi
movss 0x7c(%rsp), %xmm0
movss 0x84(%rsp), %xmm1
divss %xmm1, %xmm0
movss %xmm0, 0x18c(%rsp)
leaq 0x18c(%rsp), %rsi
callq 0x2c0d0
movq %rax, 0x70(%rsp)
jmp 0x296cc
movq 0x70(%rsp), %rdi
leaq 0x66d33(%rip), %rsi     # 0x9040b
callq 0x2c0a0
jmp 0x296df
leaq 0x190(%rsp), %rdi
callq 0x89c20
leaq 0x457(%rsp), %rdi
callq 0x298f0
movq %rax, 0x68(%rsp)
jmp 0x29700
movq 0x68(%rsp), %rax
movq %rax, 0x180(%rsp)
movsd 0x318(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
movq 0xa88(%rsp), %rax
movss (%rax), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x50(%rsp)
movq 0x438(%rsp), %rax
movq %rax, 0x58(%rsp)
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, 0x60(%rsp)
testq %rax, %rax
movss %xmm0, 0x64(%rsp)
js 0x29778
movss 0x60(%rsp), %xmm0
movss %xmm0, 0x64(%rsp)
movss 0x64(%rsp), %xmm0
movss %xmm0, 0x34(%rsp)
movq 0x440(%rsp), %rax
movq %rax, 0x38(%rsp)
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, 0x40(%rsp)
testq %rax, %rax
movss %xmm0, 0x44(%rsp)
js 0x297ca
movss 0x40(%rsp), %xmm0
movss %xmm0, 0x44(%rsp)
movss 0x34(%rsp), %xmm0
movss 0x44(%rsp), %xmm1
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x20(%rsp)
leaq 0x180(%rsp), %rdi
leaq 0x448(%rsp), %rsi
callq 0x2be30
movq %rax, 0x28(%rsp)
jmp 0x29800
movq 0x28(%rsp), %rax
movq %rax, 0x170(%rsp)
leaq 0x170(%rsp), %rdi
callq 0x2be00
movq %rax, 0x18(%rsp)
jmp 0x29821
movq 0x18(%rsp), %rax
movq %rax, 0x178(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x2be80
movq %rax, 0x10(%rsp)
jmp 0x29842
movq 0x10(%rsp), %rcx
movq 0x38(%rsp), %rdx
movq 0x58(%rsp), %rsi
movsd 0x20(%rsp), %xmm2
movsd 0x50(%rsp), %xmm1
movsd 0x48(%rsp), %xmm0
leaq 0x66991(%rip), %rdi     # 0x901fb
movb $0x3, %al
callq 0x9060
jmp 0x29873
movq 0x438(%rsp), %rax
movq %rax, 0x8(%rsp)
leaq 0x3f0(%rsp), %rdi
callq 0x2bf80
leaq 0x410(%rsp), %rdi
callq 0x33e80
movq 0x8(%rsp), %rax
addq $0xaa8, %rsp            # imm = 0xAA8
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x8f8(%rsp)
movl %eax, 0x8f4(%rsp)
leaq 0x190(%rsp), %rdi
callq 0x89c20
leaq 0x3f0(%rsp), %rdi
callq 0x2bf80
leaq 0x410(%rsp), %rdi
callq 0x33e80
movq 0x8f8(%rsp), %rdi
callq 0x9700
nop