// File: /workspace/github_cpp_makefile_star2_O2/j-faria[P]kima/src/RVmodel.cpp
// Function: RVmodel::log_likelihood() const
double RVmodel::log_likelihood() const
{
    auto data = Data::get_instance();
    int N = data.N();
    auto y = data.get_y();
    auto sig = data.get_sig();
    auto obsi = data.get_obsi();

    double logL = 0.;

    #if TIMING
    auto begin = std::chrono::high_resolution_clock::now();  // start timing
    #endif

    if(GP)
    {
        /** The following code calculates the log likelihood in the case of a GP model */
        // residual vector (observed y minus model y)
        VectorXd residual(y.size());
        for(size_t i=0; i<y.size(); i++)
            residual(i) = y[i] - mu[i];

        switch (kernel)
        {
            case standard:
            {
                // perform the cholesky decomposition of C
                Eigen::LLT<Eigen::MatrixXd> cholesky = C.llt();
                // get the lower triangular matrix L
                MatrixXd L = cholesky.matrixL();

                double logDeterminant = 0.;
                for(size_t i=0; i<y.size(); i++)
                    logDeterminant += 2.*log(L(i,i));

                VectorXd solution = cholesky.solve(residual);

                // y*solution
                double exponent = 0.;
                for(size_t i=0; i<y.size(); i++)
                    exponent += residual(i)*solution(i);

                logL = -0.5*y.size()*log(2*M_PI)
                        - 0.5*logDeterminant - 0.5*exponent;

                break;
            }

            case celerite:
            {
                logL = -0.5 * (solver.dot_solve(residual) +
                    solver.log_determinant() +
                    y.size()*log(2*M_PI)); 
    
                break;
            }
        
            default:
                break;
        }

    }
    else
    {
        if (studentt){
            // The following code calculates the log likelihood 
            // in the case of a t-Student model
            double var, jit;
            for(size_t i=0; i<N; i++)
            {
                if(multi_instrument)
                {
                    jit = jitters[obsi[i]-1];
                    var = sig[i]*sig[i] + jit*jit;
                }
                else
                    var = sig[i]*sig[i] + extra_sigma*extra_sigma;

                logL += std::lgamma(0.5*(nu + 1.)) - std::lgamma(0.5*nu)
                        - 0.5*log(M_PI*nu) - 0.5*log(var)
                        - 0.5*(nu + 1.)*log(1. + pow(y[i] - mu[i], 2)/var/nu);
            }

        }

        else{
            // The following code calculates the log likelihood
            // in the case of a Gaussian likelihood
            double var, jit;
            for(size_t i=0; i<N; i++)
            {
                if(multi_instrument)
                {
                    jit = jitters[obsi[i]-1];
                    var = sig[i]*sig[i] + jit*jit;
                }
                else
                    var = sig[i]*sig[i] + extra_sigma*extra_sigma;

                logL += - halflog2pi - 0.5*log(var)
                        - 0.5*(pow(y[i] - mu[i], 2)/var);
            }
        }

    }

    #if TIMING
    auto end = std::chrono::high_resolution_clock::now();
    cout << "Likelihood took " << std::chrono::duration_cast<std::chrono::nanoseconds>(end-begin).count()*1E-6 << " ms" << std::endl;
    #endif

    if(std::isnan(logL) || std::isinf(logL))
    {
        logL = std::numeric_limits<double>::infinity();
    }
    return logL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x260, %rsp            # imm = 0x260
movq %rdi, %rbx
leaq 0x54907(%rip), %rsi     # 0x64580
leaq 0x158(%rsp), %r14
movq %r14, %rdi
callq 0x11aa2
movq 0x8(%r14), %r15
subq (%r14), %r15
leaq 0x170(%rsp), %rsi
leaq 0x38(%rsp), %rdi
callq 0xb866
leaq 0x188(%rsp), %rsi
leaq 0x70(%rsp), %rdi
callq 0xb866
leaq 0x1a0(%rsp), %rsi
leaq 0xf0(%rsp), %rdi
callq 0x122a0
leaq 0x3733c(%rip), %rax     # 0x4700c
cmpb $0x1, (%rax)
jne 0xfd6c
movq 0x40(%rsp), %rax
subq 0x38(%rsp), %rax
sarq $0x3, %rax
leaq 0x120(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x50(%rsp), %rdi
callq 0x11efc
xorl %r12d, %r12d
leaq 0x50(%rsp), %r14
xorl %r15d, %r15d
movq 0x38(%rsp), %rax
movq 0x40(%rsp), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %rcx, %r15
jae 0xff4b
movsd (%rax,%r15,8), %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0x380(%rbx), %rax
fldt (%rax,%r12)
fstpt 0x20(%rsp)
movq %r14, %rdi
movq %r15, %rsi
callq 0x11f2c
movsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x98(%rsp)
fldt 0x20(%rsp)
fsubrl 0x98(%rsp)
fstpl (%rax)
incq %r15
addq $0x10, %r12
jmp 0xfd07
leaq 0x372a9(%rip), %rax     # 0x4701c
shrq $0x3, %r15
movslq %r15d, %r14
leaq 0x37293(%rip), %rcx     # 0x47014
movb (%rcx), %bpl
xorpd %xmm0, %xmm0
cmpb $0x0, (%rax)
je 0xffe6
movapd %xmm0, 0x10(%rsp)
xorl %r15d, %r15d
subq $0x1, %r14
jb 0x10289
testb $0x1, %bpl
je 0xfdd0
movq 0xf0(%rsp), %rax
movslq (%rax,%r15,2), %rax
movq 0x140(%rbx), %rcx
movsd -0x8(%rcx,%rax,8), %xmm0
movq 0x70(%rsp), %rax
movsd (%rax,%r15,4), %xmm1
jmp 0xfde3
movq 0x70(%rsp), %rax
movsd (%rax,%r15,4), %xmm1
movsd 0x198(%rbx), %xmm0
mulsd %xmm0, %xmm0
mulsd %xmm1, %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x20(%rsp)
movsd 0x1a0(%rbx), %xmm0
movsd 0x2c22b(%rip), %xmm1    # 0x3c030
addsd %xmm1, %xmm0
movsd 0x2c387(%rip), %xmm1    # 0x3c198
mulsd %xmm1, %xmm0
callq 0x6380
movsd %xmm0, 0x30(%rsp)
movsd 0x1a0(%rbx), %xmm0
mulsd 0x2c368(%rip), %xmm0    # 0x3c198
callq 0x6380
movsd %xmm0, 0x90(%rsp)
movsd 0x1a0(%rbx), %xmm0
mulsd 0x2c83a(%rip), %xmm0    # 0x3c688
callq 0x63b0
movsd %xmm0, 0x88(%rsp)
movsd 0x20(%rsp), %xmm0
callq 0x63b0
movsd 0x1a0(%rbx), %xmm1
movq 0x38(%rsp), %rax
movq 0x380(%rbx), %rcx
fldt (%rcx,%r15,8)
fsubrl (%rax,%r15,4)
fmul %st, %st(0)
movapd %xmm1, %xmm2
addsd 0x2c19f(%rip), %xmm2    # 0x3c030
movsd 0x2c19f(%rip), %xmm3    # 0x3c038
mulsd %xmm3, %xmm2
movsd %xmm2, 0xb0(%rsp)
movsd 0x30(%rsp), %xmm2
subsd 0x90(%rsp), %xmm2
movsd 0x88(%rsp), %xmm4
mulsd %xmm3, %xmm4
addsd %xmm2, %xmm4
mulsd %xmm3, %xmm0
addsd %xmm4, %xmm0
movsd %xmm0, 0xa8(%rsp)
movsd 0x20(%rsp), %xmm0
movsd %xmm0, 0xc8(%rsp)
fdivl 0xc8(%rsp)
movsd %xmm1, 0xb8(%rsp)
fdivl 0xb8(%rsp)
fld1
faddp %st, %st(1)
fstpt (%rsp)
callq 0x61e0
fmull 0xb0(%rsp)
faddl 0xa8(%rsp)
movaps 0x10(%rsp), %xmm0
movsd %xmm0, 0xc0(%rsp)
faddl 0xc0(%rsp)
fstpl 0xa0(%rsp)
movsd 0xa0(%rsp), %xmm0
movapd %xmm0, 0x10(%rsp)
addq $0x2, %r15
jmp 0xfd9a
movl 0x1a8(%rbx), %eax
testl %eax, %eax
je 0x100e1
xorpd %xmm0, %xmm0
movapd %xmm0, 0x10(%rsp)
cmpl $0x1, %eax
jne 0x1027f
addq $0x220, %rbx            # imm = 0x220
leaq 0x50(%rsp), %rsi
movq %rbx, %rdi
callq 0x12336
movsd %xmm0, 0x10(%rsp)
movq %rbx, %rdi
callq 0x13e8a
movq 0x40(%rsp), %rax
subq 0x38(%rsp), %rax
sarq $0x3, %rax
movq %rax, %xmm1
punpckldq 0x2c067(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x2c06f(%rip), %xmm1    # 0x3c020
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
mulsd 0x2c6e3(%rip), %xmm2    # 0x3c6a8
movsd 0x10(%rsp), %xmm1
addsd %xmm0, %xmm1
addsd %xmm1, %xmm2
mulsd 0x2c05d(%rip), %xmm2    # 0x3c038
movapd %xmm2, 0x10(%rsp)
jmp 0x1027f
movapd %xmm0, 0x10(%rsp)
xorl %r15d, %r15d
subq $0x1, %r14
jb 0x10289
testb $0x1, %bpl
je 0x10025
movq 0xf0(%rsp), %rax
movslq (%rax,%r15,2), %rax
movq 0x140(%rbx), %rcx
movsd -0x8(%rcx,%rax,8), %xmm1
movq 0x70(%rsp), %rax
movsd (%rax,%r15,4), %xmm0
jmp 0x10038
movq 0x70(%rsp), %rax
movsd (%rax,%r15,4), %xmm0
movsd 0x198(%rbx), %xmm1
mulsd %xmm1, %xmm1
mulsd %xmm0, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x30(%rsp)
movsd 0x5463e(%rip), %xmm1    # 0x64690
movsd %xmm1, 0x20(%rsp)
callq 0x63b0
movq 0x38(%rsp), %rax
movq 0x380(%rbx), %rcx
fldt (%rcx,%r15,8)
fsubrl (%rax,%r15,4)
fmul %st, %st(0)
mulsd 0x2bfbd(%rip), %xmm0    # 0x3c038
subsd 0x20(%rsp), %xmm0
movsd %xmm0, 0xd8(%rsp)
movsd 0x30(%rsp), %xmm0
movsd %xmm0, 0xe8(%rsp)
fdivl 0xe8(%rsp)
fmuls 0x2c6aa(%rip)           # 0x3c750
faddl 0xd8(%rsp)
movaps 0x10(%rsp), %xmm0
movsd %xmm0, 0xe0(%rsp)
faddl 0xe0(%rsp)
fstpl 0xd0(%rsp)
movsd 0xd0(%rsp), %xmm0
movapd %xmm0, 0x10(%rsp)
addq $0x2, %r15
jmp 0xffef
addq $0x398, %rbx            # imm = 0x398
leaq 0x120(%rsp), %rdi
movq %rbx, %rsi
callq 0x15e1a
leaq 0x120(%rsp), %rdi
callq 0x122ee
leaq 0x60(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x108(%rsp), %rdi
callq 0x1c21e
xorpd %xmm0, %xmm0
movsd %xmm0, 0x20(%rsp)
xorl %ebx, %ebx
leaq 0x108(%rsp), %r14
movq 0x40(%rsp), %rax
subq 0x38(%rsp), %rax
sarq $0x3, %rax
cmpq %rax, %rbx
jae 0x10171
movq %r14, %rdi
movq %rbx, %rsi
movq %rbx, %rdx
callq 0x11dc0
movsd (%rax), %xmm0
callq 0x63b0
addsd %xmm0, %xmm0
movsd 0x20(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x20(%rsp)
incq %rbx
jmp 0x1012e
leaq 0x120(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x12318
leaq 0x148(%rsp), %rsi
movq %rax, (%rsi)
movq %rdx, 0x8(%rsi)
leaq 0x60(%rsp), %rdi
callq 0x1c488
xorpd %xmm0, %xmm0
movapd %xmm0, 0x10(%rsp)
xorl %ebx, %ebx
leaq 0x50(%rsp), %r14
leaq 0x60(%rsp), %r15
movq 0x40(%rsp), %rax
subq 0x38(%rsp), %rax
sarq $0x3, %rax
cmpq %rax, %rbx
jae 0x10204
movq %r14, %rdi
movq %rbx, %rsi
callq 0x11f2c
movsd (%rax), %xmm0
movsd %xmm0, 0x30(%rsp)
movq %r15, %rdi
movq %rbx, %rsi
callq 0x11f2c
movsd 0x30(%rsp), %xmm1
mulsd (%rax), %xmm1
movapd 0x10(%rsp), %xmm0
addsd %xmm1, %xmm0
movapd %xmm0, 0x10(%rsp)
incq %rbx
jmp 0x101b2
movq %rax, %xmm0
punpckldq 0x2bdff(%rip), %xmm0 # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0x2be07(%rip), %xmm0    # 0x3c020
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
movsd 0x2be0b(%rip), %xmm0    # 0x3c038
mulsd %xmm0, %xmm1
movsd 0x20(%rsp), %xmm2
mulsd %xmm0, %xmm2
mulsd 0x2c465(%rip), %xmm1    # 0x3c6a8
addsd %xmm2, %xmm1
movapd 0x10(%rsp), %xmm2
mulsd %xmm0, %xmm2
addsd %xmm1, %xmm2
movapd %xmm2, 0x10(%rsp)
movq 0x60(%rsp), %rdi
callq 0x64a0
movq 0x108(%rsp), %rdi
callq 0x64a0
movq 0x120(%rsp), %rdi
callq 0x64a0
movq 0x50(%rsp), %rdi
callq 0x64a0
movdqa 0x10(%rsp), %xmm0
movq %xmm0, %rax
btrq $0x3f, %rax
movabsq $0x7ff0000000000000, %rcx # imm = 0x7FF0000000000000
cmpq %rcx, %rax
jl 0x102b0
movq 0x2c400(%rip), %xmm0    # 0x3c6b0
movdqa %xmm0, 0x10(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0xb5f6
leaq 0x70(%rsp), %rdi
callq 0x716e
leaq 0x38(%rsp), %rdi
callq 0x716e
leaq 0x158(%rsp), %rdi
callq 0xb0be
movaps 0x10(%rsp), %xmm0
addq $0x260, %rsp            # imm = 0x260
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
jmp 0x10346
jmp 0x10318
movq %rax, %rbx
jmp 0x10337
jmp 0x10346
movq %rax, %rbx
jmp 0x10353
movq %rax, %rbx
jmp 0x10360
movq %rax, %rbx
jmp 0x1036a
movq %rax, %rbx
jmp 0x10374
movq %rax, %rbx
jmp 0x1032a
movq %rax, %rbx
movq 0x60(%rsp), %rdi
callq 0x64a0
movq 0x108(%rsp), %rdi
callq 0x64a0
movq 0x120(%rsp), %rdi
callq 0x64a0
jmp 0x10349
movq %rax, %rbx
movq 0x50(%rsp), %rdi
callq 0x64a0
leaq 0xf0(%rsp), %rdi
callq 0xb5f6
leaq 0x70(%rsp), %rdi
callq 0x716e
leaq 0x38(%rsp), %rdi
callq 0x716e
leaq 0x158(%rsp), %rdi
callq 0xb0be
movq %rbx, %rdi
callq 0x66e0
nop