// File: mattcha[P]sgd-svm/sgd_svm_train.cpp
// Function: step_train(Instance const&, Weight&, Param&)
int step_train(const Instance &instance, Weight &weight, Param &param)
{
    uint32_t fea_size = instance.f_vec.size();
    // update eta
    param.eta = 1.0 / (param.lambda * sqrt(param.step));
    
    double y_score = inner_product(instance, weight);
    double y_label = instance.y_label;

    double loss = 1 - y_label * y_score;

    for (uint32_t fi=0; fi<fea_size; ++fi) {
        const Feature &fea = instance.f_vec[fi];
        double w_i = weight.w_vec[fea.idx];

        // compute l2 loss
        param.loss_l2 += param.lambda * w_i * w_i;

        // wrong classfy
        // iterate all instance feature
        // w = w - eta*(lambda*w - y_label*x)
        if (loss > 0) {
            w_i = w_i - param.eta*(param.lambda*w_i - y_label*fea.val);
        }
        // right classfy
        // as loss > 0
        // w = w - eta*lambda*w
        if (loss < 0) {
            w_i = w_i - param.eta*param.lambda*w_i;
        }

        weight.w_vec[fea.idx] = w_i;
    }

    if (loss > 0) {
        param.loss_hinge += loss;
    }

    if (loss <= 0) 
        return 1;
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x2fb0
movl %eax, -0x24(%rbp)
movq -0x20(%rbp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x20(%rbp), %rax
movl 0x18(%rax), %edi
callq 0x2fd0
movsd -0x60(%rbp), %xmm1
mulsd %xmm0, %xmm1
movsd 0x4899(%rip), %xmm0     # 0x7008
divsd %xmm1, %xmm0
movq -0x20(%rbp), %rax
movsd %xmm0, 0x10(%rax)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x5b10
movsd %xmm0, -0x30(%rbp)
movq -0x10(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x38(%rbp)
movsd -0x38(%rbp), %xmm0
movsd -0x30(%rbp), %xmm1
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm1, %xmm0
movsd 0x4840(%rip), %xmm1     # 0x7008
addsd %xmm1, %xmm0
movsd %xmm0, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0x24(%rbp), %eax
jae 0x2934
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
movl -0x44(%rbp), %eax
movl %eax, %esi
callq 0x2ff0
movq %rax, -0x50(%rbp)
movq -0x18(%rbp), %rdi
movq -0x50(%rbp), %rax
movl (%rax), %eax
movl %eax, %esi
callq 0x3010
movsd (%rax), %xmm0
movsd %xmm0, -0x58(%rbp)
movq -0x20(%rbp), %rax
movsd 0x8(%rax), %xmm0
mulsd -0x58(%rbp), %xmm0
movsd -0x58(%rbp), %xmm2
movq -0x20(%rbp), %rax
movsd 0x28(%rax), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x28(%rax)
movsd -0x40(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x28b8
movsd -0x58(%rbp), %xmm1
movq -0x20(%rbp), %rax
movsd 0x10(%rax), %xmm0
movq -0x20(%rbp), %rax
movsd 0x8(%rax), %xmm2
movsd -0x58(%rbp), %xmm4
movsd -0x38(%rbp), %xmm3
movq -0x50(%rbp), %rax
mulsd 0x8(%rax), %xmm3
movq %xmm3, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm3
mulsd %xmm4, %xmm2
addsd %xmm3, %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x58(%rbp)
xorps %xmm0, %xmm0
ucomisd -0x40(%rbp), %xmm0
jbe 0x2902
movsd -0x58(%rbp), %xmm1
movq -0x20(%rbp), %rax
movsd 0x10(%rax), %xmm0
movq -0x20(%rbp), %rax
mulsd 0x8(%rax), %xmm0
movsd -0x58(%rbp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x58(%rbp)
movsd -0x58(%rbp), %xmm0
movsd %xmm0, -0x68(%rbp)
movq -0x18(%rbp), %rdi
movq -0x50(%rbp), %rax
movl (%rax), %eax
movl %eax, %esi
callq 0x3010
movsd -0x68(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x27d8
movsd -0x40(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x2955
movsd -0x40(%rbp), %xmm0
movq -0x20(%rbp), %rax
addsd 0x20(%rax), %xmm0
movsd %xmm0, 0x20(%rax)
xorps %xmm0, %xmm0
ucomisd -0x40(%rbp), %xmm0
jb 0x2968
movl $0x1, -0x4(%rbp)
jmp 0x296f
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax,%rax)