// File: /workspace/github_cpp_makefile_star2_O2/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 $0xc8, %rsp
movq %rsi, %r14
movq %rdi, 0x68(%rsp)
leaq 0xa8(%rsp), %rbx
movq %rbx, %rdi
callq 0x4350
movl 0xc8(%r14), %eax
movl %eax, 0x10(%rsp)
movq %r14, 0x70(%rsp)
movl 0xcc(%r14), %r15d
movq 0x8(%rbx), %rbp
movslq %r15d, %rdi
pushq $0x8
popq %rsi
callq 0x4190
testq %rax, %rax
je 0x551a
movq %rax, %rbx
movslq %ebp, %r12
xorl %r14d, %r14d
testl %r15d, %r15d
cmovlel %r14d, %r15d
pushq $0x4
popq %r13
cmpq %r14, %r15
je 0x4f51
movq %r12, %rdi
movq %r13, %rsi
callq 0x4190
movq %rax, (%rbx,%r14,8)
incq %r14
testq %rax, %rax
jne 0x4f12
movq 0xe093(%rip), %rax      # 0x12fc8
movq (%rax), %rcx
leaq 0x815d(%rip), %rdi      # 0xd09c
pushq $0x26
popq %rsi
pushq $0x1
popq %rdx
callq 0x44c0
xorl %edi, %edi
callq 0x42d0
movq %rbp, 0x18(%rsp)
leaq 0x90(%rsp), %r12
andq $0x0, 0x10(%r12)
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
xorl %ebp, %ebp
movl 0x10(%rsp), %eax
testl %eax, %eax
movl $0x0, %ecx
cmovgl %eax, %ecx
movl %ecx, 0x14(%rsp)
leaq 0x20(%rsp), %r13
movq 0x70(%rsp), %r14
cmpl %ebp, 0x14(%rsp)
je 0x4faf
movq %r14, %rsi
movl %ebp, %edx
callq 0x4e00
movss %xmm0, 0x20(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0x4c80
incl %ebp
jmp 0x4f8a
leaq 0x28(%rsp), %rax
andl $0x0, (%rax)
andq $0x0, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
andq $0x0, 0x20(%rax)
leaq 0xc(%rsp), %rsi
movb $0x41, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d958106, (%rax)     # imm = 0x3D958106
leaq 0xc(%rsp), %rsi
movb $0x43, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movq 0x18(%rsp), %r12
movl $0x3ccccccd, (%rax)     # imm = 0x3CCCCCCD
leaq 0xc(%rsp), %rsi
movb $0x44, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d4ccccd, (%rax)     # imm = 0x3D4CCCCD
leaq 0xc(%rsp), %rsi
movb $0x45, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d79db23, (%rax)     # imm = 0x3D79DB23
leaq 0xc(%rsp), %rsi
movb $0x46, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d2c0831, (%rax)     # imm = 0x3D2C0831
leaq 0xc(%rsp), %rsi
movb $0x47, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d9374bc, (%rax)     # imm = 0x3D9374BC
leaq 0xc(%rsp), %rsi
movb $0x48, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3cbc6a7f, (%rax)     # imm = 0x3CBC6A7F
leaq 0xc(%rsp), %rsi
movb $0x49, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d591687, (%rax)     # imm = 0x3D591687
leaq 0xc(%rsp), %rsi
movb $0x4b, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d83126f, (%rax)     # imm = 0x3D83126F
leaq 0xc(%rsp), %rsi
movb $0x4c, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3db645a2, (%rax)     # imm = 0x3DB645A2
leaq 0xc(%rsp), %rsi
movb $0x4d, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3cbc6a7f, (%rax)     # imm = 0x3CBC6A7F
leaq 0xc(%rsp), %rsi
movb $0x4e, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d3020c5, (%rax)     # imm = 0x3D3020C5
leaq 0xc(%rsp), %rsi
movb $0x50, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d54fdf4, (%rax)     # imm = 0x3D54FDF4
leaq 0xc(%rsp), %rsi
movb $0x51, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d23d70a, (%rax)     # imm = 0x3D23D70A
leaq 0xc(%rsp), %rsi
movb $0x52, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d54fdf4, (%rax)     # imm = 0x3D54FDF4
leaq 0xc(%rsp), %rsi
movb $0x53, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d958106, (%rax)     # imm = 0x3D958106
leaq 0xc(%rsp), %rsi
movb $0x54, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d656042, (%rax)     # imm = 0x3D656042
leaq 0xc(%rsp), %rsi
movb $0x56, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d810625, (%rax)     # imm = 0x3D810625
leaq 0xc(%rsp), %rsi
movb $0x57, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movq %r15, 0x50(%rsp)
movl $0x3c54fdf4, (%rax)     # imm = 0x3C54FDF4
leaq 0xc(%rsp), %rsi
movb $0x59, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x5590
movl $0x3d072b02, (%rax)     # imm = 0x3D072B02
xorl %eax, %eax
testl %r12d, %r12d
movl $0x0, %r15d
cmovgl %r12d, %r15d
movl 0x14(%rsp), %ecx
shlq $0x2, %rcx
movsd 0x7e8e(%rip), %xmm0     # 0xd060
xorps %xmm1, %xmm1
cmpq 0x50(%rsp), %rax
je 0x529e
xorl %esi, %esi
xorl %edx, %edx
cmpq %r15, %rsi
je 0x524d
movq 0x38(%r14), %rdi
movq 0xa8(%rsp), %r8
movq 0x90(%rsp), %r9
xorl %r10d, %r10d
cmpq %r10, %rcx
je 0x522f
movq (%rdi,%r10,8), %r11
movb (%r11,%rax), %r11b
cmpb (%r8,%rsi), %r11b
jne 0x5229
movss (%r9,%r10), %xmm2
movq (%rbx,%rax,8), %r11
addss (%r11,%rsi,4), %xmm2
movss %xmm2, (%r11,%rsi,4)
addq $0x4, %r10
jmp 0x5200
movq (%rbx,%rax,8), %rdi
movss (%rdi,%rsi,4), %xmm2
ucomiss %xmm1, %xmm2
jne 0x5248
jp 0x5248
movl $0x358637bd, (%rdi,%rsi,4) # imm = 0x358637BD
incl %edx
incq %rsi
jmp 0x51e4
cvtsi2ss %edx, %xmm2
cvtss2sd %xmm2, %xmm2
mulsd %xmm0, %xmm2
movl %r12d, %esi
subl %edx, %esi
cvtsi2ss %esi, %xmm3
cvtss2sd %xmm3, %xmm3
divsd %xmm3, %xmm2
cvtsd2ss %xmm2, %xmm2
xorl %edx, %edx
cmpq %rdx, %r15
je 0x5296
movq (%rbx,%rax,8), %rsi
movss (%rsi,%rdx,4), %xmm3
cvtss2sd %xmm3, %xmm4
ucomisd %xmm0, %xmm4
jbe 0x5291
subss %xmm2, %xmm3
movss %xmm3, (%rsi,%rdx,4)
incq %rdx
jmp 0x5270
incq %rax
jmp 0x51d5
addq $0x8, 0x68(%rsp)
cvtsi2ssl 0x10(%rsp), %xmm0
movss %xmm0, 0x5c(%rsp)
xorl %ebp, %ebp
leaq 0x20(%rsp), %r14
movabsq $0x280000200001, %r13   # imm = 0x280000200001
cmpq 0x50(%rsp), %rbp
je 0x54c1
xorps %xmm0, %xmm0
movss %xmm0, 0x14(%rsp)
xorl %r12d, %r12d
movss %xmm0, 0x10(%rsp)
movq %rbp, 0x78(%rsp)
cmpq %r12, %r15
je 0x5446
movq 0xa8(%rsp), %rax
movzbl (%rax,%r12), %eax
movb %al, 0xc(%rsp)
addl $-0x2d, %eax
cmpl $0x2d, %eax
ja 0x5310
btq %rax, %r13
jae 0x5310
incq %r12
jmp 0x52e3
movq (%rbx,%rbp,8), %rbp
movss (%rbp,%r12,4), %xmm0
movss %xmm0, 0x18(%rsp)
movq %r14, %rdi
movq %r14, %r13
leaq 0xc(%rsp), %r14
movq %r14, %rsi
callq 0x55de
movss 0x18(%rsp), %xmm0
cvtss2sd %xmm0, %xmm2
mulss 0x7d12(%rip), %xmm0     # 0xd058
cvtss2sd %xmm0, %xmm0
cvtss2sd (%rax), %xmm1
mulsd 0x7d12(%rip), %xmm1     # 0xd068
addsd %xmm0, %xmm1
movsd %xmm2, 0x18(%rsp)
movaps %xmm2, %xmm0
divsd %xmm1, %xmm0
callq 0x4200
movsd %xmm0, 0x88(%rsp)
movq %r13, %rdi
movq %r14, %rsi
callq 0x55de
cvtss2sd (%rax), %xmm0
movsd %xmm0, 0x80(%rsp)
movq %r13, %rdi
movq %r14, %rsi
callq 0x55de
movss (%rax), %xmm0
movss %xmm0, 0x64(%rsp)
movss (%rbp,%r12,4), %xmm0
movss %xmm0, 0x60(%rsp)
movq %r13, %rdi
movq %r14, %rsi
callq 0x55de
cvtss2sd 0x14(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
mulsd 0x88(%rsp), %xmm1
addsd %xmm0, %xmm1
cvtsd2ss %xmm1, %xmm0
movss %xmm0, 0x14(%rsp)
movss 0x60(%rsp), %xmm0
mulss 0x7c6d(%rip), %xmm0     # 0xd058
cvtss2sd %xmm0, %xmm1
cvtss2sd (%rax), %xmm2
cvtss2sd 0x64(%rsp), %xmm0
mulsd 0x7c67(%rip), %xmm2     # 0xd068
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
callq 0x4200
cvtss2sd 0x10(%rsp), %xmm1
movsd 0x80(%rsp), %xmm2
mulsd %xmm0, %xmm2
addsd %xmm1, %xmm2
cvtsd2ss %xmm2, %xmm0
movss %xmm0, 0x10(%rsp)
movq 0x78(%rsp), %rbp
movq %r13, %r14
movabsq $0x280000200001, %r13   # imm = 0x280000200001
jmp 0x530b
movq 0x70(%rsp), %rdi
movl %ebp, %esi
callq 0x9c0c
leaq 0xc(%rsp), %rsi
cvtss2sd 0x10(%rsp), %xmm0
movss 0x14(%rsp), %xmm1
mulss 0x7bed(%rip), %xmm1     # 0xd058
cvtss2sd %xmm1, %xmm1
mulsd 0x7bf1(%rip), %xmm0     # 0xd068
addsd %xmm1, %xmm0
movsd 0x7bed(%rip), %xmm1     # 0xd070
subsd %xmm0, %xmm1
cvtsi2ss %eax, %xmm0
divss 0x5c(%rsp), %xmm0
movss 0x7bbb(%rip), %xmm2     # 0xd054
subss %xmm0, %xmm2
cvtss2sd %xmm2, %xmm0
mulsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0xc(%rsp)
movq 0x68(%rsp), %rdi
callq 0x4c80
incq %rbp
jmp 0x52c1
xorl %r14d, %r14d
movq 0x50(%rsp), %r15
cmpq %r14, %r15
je 0x54dc
movq (%rbx,%r14,8), %rdi
callq 0x42c0
incq %r14
jmp 0x54c9
movq %rbx, %rdi
callq 0x42c0
leaq 0x20(%rsp), %rdi
callq 0x5642
leaq 0x90(%rsp), %rdi
callq 0x49cc
leaq 0xa8(%rsp), %rdi
callq 0x4110
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0xdaa7(%rip), %rax      # 0x12fc8
movq (%rax), %rcx
leaq 0x7b4d(%rip), %rdi      # 0xd078
pushq $0x23
jmp 0x4f41
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
jmp 0x5561
movq %rax, %rbx
jmp 0x556e
jmp 0x5561
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x5642
leaq 0x90(%rsp), %rdi
callq 0x49cc
leaq 0xa8(%rsp), %rdi
callq 0x4110
movq %rbx, %rdi
callq 0x4430