// File: /workspace/github_cpp_makefile_star2_O3/gcollet[P]MstatX/src/jensen.cpp
// Function: JensenStat::calculate(Msa&)
void
JensenStat :: calculate(Msa & msa)
{
	/* Init size */
	string alphabet = msa.getAlphabet();
	int L = msa.getNcol();
	int N = msa.getNseq();
	int K = (int) alphabet.size();
	
	/* Allocate proba array */
	float **proba = (float **) calloc(L, sizeof(float*));
	if (proba == NULL){
		fprintf(stderr,"Cannot Allocate probability matrix\n");
		exit(0);
	}
	for (int i(0); i < L; i++){
		proba[i] = (float *) calloc(K, sizeof(float));
		if (proba[i] == NULL){
			fprintf(stderr,"Cannot Allocate probability submatrix\n");
			exit(0);
		}
	}

	/* Calculate Sequence Weights */
	vector<float> w;
	for (int seq(0); seq < N; ++seq){
		w.push_back(calcSeqWeight(msa,seq));
	}

	/* Background distribution of amino acids 
	 * These background frequencies are used in sca paper
	 */
	map<char,float> q;
	q['A'] = 0.073;
	q['C'] = 0.025;
	q['D'] = 0.050;
	q['E'] = 0.061;
	q['F'] = 0.042;
	q['G'] = 0.072;
	q['H'] = 0.023;
	q['I'] = 0.053;
	q['K'] = 0.064;
	q['L'] = 0.089;
	q['M'] = 0.023;
	q['N'] = 0.043;
	q['P'] = 0.052;
	q['Q'] = 0.040;
	q['R'] = 0.052;
	q['S'] = 0.073;
	q['T'] = 0.056;
	q['V'] = 0.063;
	q['W'] = 0.013;
	q['Y'] = 0.033;
	
	/* Calculate aa proba by columns */
	float lambda = 0.5;
	
  for (int x(0); x < L; ++x){
		int nb_abs = 0;
		for (int a(0); a < K; a++){
		  for (int j(0); j < N; ++j){
				if(msa.getSymbol(j, x) == alphabet[a]){
					proba[x][a] += w[j];
				}
			}
			if (proba[x][a] == 0.0){
				proba[x][a] = pow(10.0,-6.0);
				nb_abs++;
			}
		}
		/* reduce by the pseudo counts in order to have sum-of-proba = 1 */
		float pseudo_counts = (float) nb_abs * pow(10.0,-6.0) / (float) (K - nb_abs);
		for (int a(0); a < K; a++){
			if (proba[x][a] > pow(10.0,-6.0)){
				proba[x][a] -= pseudo_counts;
			}
		}
	}
	
	/* Calculate conservation score by columns */
	for (int x(0); x < L; ++x){
		float score_left = 0.0;
		float score_right = 0.0;
		for (int a(0); a < K; a++){
			char aa = alphabet[a];
			if (aa != '-' && aa != 'X' && aa != 'Z' && aa != 'B'){
				score_left  += proba[x][a] * log(proba[x][a] / (lambda * proba[x][a] + (1.0 - lambda) * q[aa]));
				score_right += q[aa] * log(q[aa] / (lambda * proba[x][a] + (1.0 - lambda) * q[aa]));
			}
		}
		col_stat.push_back((1 - (lambda * score_left + (1.0 - lambda) * score_right)) * (1 - ((float) msa.getGap(x) / (float) N)));
	}
	
	/* Add Side columns effect */
	/*int window = Options::Get().window;
	for (int x(0); x < L; ++x){
		float score = col_stat[x];
		float side_score = 0.0;
		for (int i(x-1); i >= 0 && i >= x - window; i--) {
			side_score += col_stat[i];
		}
		for (int i(x+1); i < L && i <= x + window; i++) {
			side_score += col_stat[i];
		}
		side_score /= (2 * window);
		cout << 0.5 * (score + side_score) <<"\n";
		col_stat[x] = 0.5 * (score + side_score);
	}*/
	
	for (int i(0); i < L; ++i) {
		free (proba[i]);	
	}
	free(proba);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movq %rsi, %r13
movq %rdi, 0x30(%rsp)
leaq 0xb0(%rsp), %r15
movq %r15, -0x10(%r15)
movq (%rsi), %rsi
movq 0x8(%r13), %rdx
addq %rsi, %rdx
leaq 0xa0(%rsp), %r14
movq %r14, %rdi
callq 0x5cca
movslq 0xcc(%r13), %rbx
movq %r13, 0x68(%rsp)
movl 0xc8(%r13), %r13d
movq 0x8(%r14), %rax
movq %rax, 0x8(%rsp)
movl $0x8, %esi
movq %rbx, %rdi
callq 0x4170
movq %rax, 0x10(%rsp)
testq %rax, %rax
je 0x5b40
movq %rbx, 0x28(%rsp)
testl %ebx, %ebx
movq 0x30(%rsp), %r12
jle 0x546a
movslq 0x8(%rsp), %r14
xorl %ebx, %ebx
movl $0x4, %esi
movq %r14, %rdi
callq 0x4170
movq 0x10(%rsp), %rcx
movq %rax, (%rcx,%rbx,8)
testq %rax, %rax
je 0x5b3b
incq %rbx
cmpq %rbx, 0x28(%rsp)
jne 0x5441
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movq $0x0, 0x90(%rsp)
testl %r13d, %r13d
jle 0x54dd
xorl %ebp, %ebp
leaq 0x80(%rsp), %r14
leaq 0x38(%rsp), %rbx
movq 0x68(%rsp), %rsi
movl %ebp, %edx
callq 0x530c
movss %xmm0, 0x38(%rsp)
movq 0x88(%rsp), %rsi
cmpq 0x90(%rsp), %rsi
je 0x54cb
movss %xmm0, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x88(%rsp)
jmp 0x54d6
movq %r14, %rdi
movq %rbx, %rdx
callq 0x51cc
incl %ebp
cmpl %ebp, %r13d
jne 0x5495
leaq 0x40(%rsp), %rax
movl $0x0, (%rax)
xorl %ecx, %ecx
movq %rcx, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
movq %rcx, 0x20(%rax)
leaq 0x4(%rsp), %rsi
movb $0x41, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d958106, (%rax)     # imm = 0x3D958106
leaq 0x4(%rsp), %rsi
movb $0x43, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movq 0x28(%rsp), %r15
movl $0x3ccccccd, (%rax)     # imm = 0x3CCCCCCD
leaq 0x4(%rsp), %rsi
movb $0x44, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d4ccccd, (%rax)     # imm = 0x3D4CCCCD
leaq 0x4(%rsp), %rsi
movb $0x45, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d79db23, (%rax)     # imm = 0x3D79DB23
leaq 0x4(%rsp), %rsi
movb $0x46, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d2c0831, (%rax)     # imm = 0x3D2C0831
leaq 0x4(%rsp), %rsi
movb $0x47, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d9374bc, (%rax)     # imm = 0x3D9374BC
leaq 0x4(%rsp), %rsi
movb $0x48, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3cbc6a7f, (%rax)     # imm = 0x3CBC6A7F
leaq 0x4(%rsp), %rsi
movb $0x49, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d591687, (%rax)     # imm = 0x3D591687
leaq 0x4(%rsp), %rsi
movb $0x4b, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d83126f, (%rax)     # imm = 0x3D83126F
leaq 0x4(%rsp), %rsi
movb $0x4c, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3db645a2, (%rax)     # imm = 0x3DB645A2
leaq 0x4(%rsp), %rsi
movb $0x4d, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3cbc6a7f, (%rax)     # imm = 0x3CBC6A7F
leaq 0x4(%rsp), %rsi
movb $0x4e, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d3020c5, (%rax)     # imm = 0x3D3020C5
leaq 0x4(%rsp), %rsi
movb $0x50, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d54fdf4, (%rax)     # imm = 0x3D54FDF4
leaq 0x4(%rsp), %rsi
movb $0x51, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d23d70a, (%rax)     # imm = 0x3D23D70A
leaq 0x4(%rsp), %rsi
movb $0x52, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d54fdf4, (%rax)     # imm = 0x3D54FDF4
leaq 0x4(%rsp), %rsi
movb $0x53, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d958106, (%rax)     # imm = 0x3D958106
leaq 0x4(%rsp), %rsi
movb $0x54, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d656042, (%rax)     # imm = 0x3D656042
leaq 0x4(%rsp), %rsi
movb $0x56, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d810625, (%rax)     # imm = 0x3D810625
leaq 0x4(%rsp), %rsi
movb $0x57, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3c54fdf4, (%rax)     # imm = 0x3C54FDF4
leaq 0x4(%rsp), %rsi
movb $0x59, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bcc
movl $0x3d072b02, (%rax)     # imm = 0x3D072B02
testl %r15d, %r15d
movq 0x10(%rsp), %rbp
jle 0x5ad5
movq 0x8(%rsp), %rax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
leaq (,%r13,4), %rcx
xorl %edx, %edx
xorps %xmm0, %xmm0
movsd 0xa954(%rip), %xmm1     # 0x10060
movl $0x0, %esi
cmpl $0x0, 0x8(%rsp)
jle 0x5793
movq 0x68(%rsp), %rsi
movq 0x38(%rsi), %rdi
movq 0xa0(%rsp), %r8
movq 0x10(%rsp), %rsi
movq (%rsi,%rdx,8), %r9
xorl %r10d, %r10d
xorl %esi, %esi
testl %r13d, %r13d
jle 0x576f
movq 0x80(%rsp), %r11
xorl %ebx, %ebx
movq (%rdi,%rbx,8), %r14
movb (%r14,%rdx), %bpl
cmpb (%r8,%r10), %bpl
jne 0x5766
movss (%r11,%rbx), %xmm2
addss (%r9,%r10,4), %xmm2
movss %xmm2, (%r9,%r10,4)
addq $0x4, %rbx
cmpq %rbx, %rcx
jne 0x5746
movss (%r9,%r10,4), %xmm2
ucomiss %xmm0, %xmm2
jne 0x5786
jp 0x5786
movl $0x358637bd, (%r9,%r10,4) # imm = 0x358637BD
incl %esi
movq 0x30(%rsp), %r12
incq %r10
cmpq %rax, %r10
jne 0x5737
xorps %xmm2, %xmm2
cvtsi2ss %esi, %xmm2
cvtss2sd %xmm2, %xmm2
mulsd %xmm1, %xmm2
cmpl $0x0, 0x8(%rsp)
jle 0x57f1
movq 0x8(%rsp), %rdi
subl %esi, %edi
xorps %xmm3, %xmm3
cvtsi2ss %edi, %xmm3
cvtss2sd %xmm3, %xmm3
divsd %xmm3, %xmm2
cvtsd2ss %xmm2, %xmm2
movq 0x10(%rsp), %rsi
movq (%rsi,%rdx,8), %rsi
xorl %edi, %edi
movss (%rsi,%rdi,4), %xmm3
xorps %xmm4, %xmm4
cvtss2sd %xmm3, %xmm4
ucomisd %xmm1, %xmm4
jbe 0x57e9
subss %xmm2, %xmm3
movss %xmm3, (%rsi,%rdi,4)
incq %rdi
cmpq %rdi, %rax
jne 0x57ce
incq %rdx
cmpq %r15, %rdx
jne 0x570c
testl %r15d, %r15d
movq 0x10(%rsp), %rbp
jle 0x5ad5
xorps %xmm0, %xmm0
cvtsi2ss %r13d, %xmm0
movss %xmm0, 0x70(%rsp)
leaq 0x8(%r12), %rax
movq %rax, 0xc0(%rsp)
movq 0x8(%rsp), %r15
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
movq %rbp, %r13
xorl %ebp, %ebp
leaq 0x4(%rsp), %rbx
cmpl $0x0, 0x8(%rsp)
jle 0x5a0f
xorps %xmm0, %xmm0
xorl %r14d, %r14d
xorpd %xmm1, %xmm1
movss %xmm1, 0x20(%rsp)
leaq 0x38(%rsp), %r12
movabsq $0x280000200001, %rcx   # imm = 0x280000200001
movq 0xa0(%rsp), %rax
movzbl (%rax,%r14), %eax
movb %al, 0x4(%rsp)
addl $-0x2d, %eax
cmpl $0x2d, %eax
ja 0x5892
btq %rax, %rcx
jae 0x5892
incq %r14
cmpq %r14, %r15
jne 0x5866
jmp 0x59e1
movss %xmm0, 0x7c(%rsp)
movq (%r13,%rbp,8), %r13
movss (%r13,%r14,4), %xmm0
movss %xmm0, 0x18(%rsp)
movq %r12, %rdi
leaq 0x4(%rsp), %rbx
movq %rbx, %rsi
callq 0x5c32
movss 0x18(%rsp), %xmm0
xorps %xmm2, %xmm2
cvtss2sd %xmm0, %xmm2
mulss 0xa789(%rip), %xmm0     # 0x10058
cvtss2sd %xmm0, %xmm0
xorps %xmm1, %xmm1
cvtss2sd (%rax), %xmm1
mulsd 0xa786(%rip), %xmm1     # 0x10068
addsd %xmm0, %xmm1
movsd %xmm2, 0x18(%rsp)
movaps %xmm2, %xmm0
divsd %xmm1, %xmm0
callq 0x41d0
movsd %xmm0, 0xd0(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x5c32
xorps %xmm0, %xmm0
cvtss2sd (%rax), %xmm0
movsd %xmm0, 0xc8(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x5c32
movss (%rax), %xmm0
movss %xmm0, 0x78(%rsp)
movss (%r13,%r14,4), %xmm0
movss %xmm0, 0x74(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x5c32
xorps %xmm0, %xmm0
cvtss2sd 0x20(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
mulsd 0xd0(%rsp), %xmm1
addsd %xmm0, %xmm1
xorps %xmm0, %xmm0
cvtsd2ss %xmm1, %xmm0
movss %xmm0, 0x20(%rsp)
movss 0x74(%rsp), %xmm0
mulss 0xa6d8(%rip), %xmm0     # 0x10058
xorps %xmm1, %xmm1
cvtss2sd %xmm0, %xmm1
xorps %xmm2, %xmm2
cvtss2sd (%rax), %xmm2
xorps %xmm0, %xmm0
cvtss2sd 0x78(%rsp), %xmm0
mulsd 0xa6c9(%rip), %xmm2     # 0x10068
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
callq 0x41d0
xorps %xmm1, %xmm1
cvtss2sd 0x7c(%rsp), %xmm1
movsd 0xc8(%rsp), %xmm2
mulsd %xmm0, %xmm2
addsd %xmm1, %xmm2
xorps %xmm0, %xmm0
cvtsd2ss %xmm2, %xmm0
movq 0x10(%rsp), %r13
movabsq $0x280000200001, %rcx   # imm = 0x280000200001
jmp 0x5885
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x18(%rsp)
movss 0x20(%rsp), %xmm0
mulss 0xa65f(%rip), %xmm0     # 0x10058
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x30(%rsp), %r12
leaq 0x4(%rsp), %rbx
jmp 0x5a1e
xorps %xmm0, %xmm0
movsd %xmm0, 0x20(%rsp)
movsd %xmm0, 0x18(%rsp)
movq 0x68(%rsp), %rdi
movl %ebp, %esi
callq 0xc094
movsd 0x18(%rsp), %xmm2
mulsd 0xa630(%rip), %xmm2     # 0x10068
addsd 0x20(%rsp), %xmm2
movsd 0xa62a(%rip), %xmm0     # 0x10070
xorps %xmm1, %xmm1
cvtsi2ss %eax, %xmm1
subsd %xmm2, %xmm0
divss 0x70(%rsp), %xmm1
movss 0xa5f5(%rip), %xmm2     # 0x10054
subss %xmm1, %xmm2
xorps %xmm1, %xmm1
cvtss2sd %xmm2, %xmm1
mulsd %xmm0, %xmm1
xorps %xmm0, %xmm0
cvtsd2ss %xmm1, %xmm0
movss %xmm0, 0x4(%rsp)
movq 0x10(%r12), %rsi
cmpq 0x18(%r12), %rsi
je 0x5a96
movss %xmm0, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x10(%r12)
jmp 0x5aa6
movq 0xc0(%rsp), %rdi
movq %rbx, %rdx
callq 0x51cc
incq %rbp
cmpq 0x28(%rsp), %rbp
jne 0x583c
movq 0x28(%rsp), %r14
testl %r14d, %r14d
movq %r13, %rbp
jle 0x5ad5
xorl %ebx, %ebx
movq (%rbp,%rbx,8), %rdi
callq 0x42d0
incq %rbx
cmpq %rbx, %r14
jne 0x5ac3
movq %rbp, %rdi
callq 0x42d0
leaq 0x38(%rsp), %rdi
callq 0x5d60
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x5b04
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x4250
movq 0xa0(%rsp), %rdi
leaq 0xb0(%rsp), %rax
cmpq %rax, %rdi
je 0x5b29
movq 0xb0(%rsp), %rsi
incq %rsi
callq 0x4250
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x4566
callq 0x458a
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
jmp 0x5b74
movq %rax, %rbx
jmp 0x5b89
jmp 0x5b74
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x5d60
leaq 0xb0(%rsp), %r15
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x5ba6
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x4250
movq 0xa0(%rsp), %rdi
cmpq %r15, %rdi
je 0x5bc3
movq 0xb0(%rsp), %rsi
incq %rsi
callq 0x4250
movq %rbx, %rdi
callq 0x4440
nop