// File: /workspace/github_cpp_makefile_star2_O1/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 $0xe8, %rsp
movq %rsi, %r12
movq %rdi, 0xa0(%rsp)
leaq 0xb8(%rsp), %r15
movq %r15, -0x10(%r15)
movq (%rsi), %rsi
movq 0x8(%r12), %rdx
addq %rsi, %rdx
leaq 0xa8(%rsp), %r14
movq %r14, %rdi
callq 0x5ccc
movslq 0xcc(%r12), %rbx
movq %r12, 0x68(%rsp)
movl 0xc8(%r12), %r13d
movq 0x8(%r14), %rax
movq %rax, 0x10(%rsp)
movl $0x8, %esi
movq %rbx, %rdi
callq 0x4170
testq %rax, %rax
je 0x5b46
movq %rax, %r14
movq %rbx, 0x18(%rsp)
testl %ebx, %ebx
jle 0x5464
movslq 0x10(%rsp), %r12
xorl %ebx, %ebx
movl $0x4, %esi
movq %r12, %rdi
callq 0x4170
movq %rax, (%r14,%rbx,8)
testq %rax, %rax
je 0x5b41
incq %rbx
cmpq %rbx, 0x18(%rsp)
jne 0x5440
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movq $0x0, 0x90(%rsp)
testl %r13d, %r13d
jle 0x54d7
xorl %ebp, %ebp
leaq 0x80(%rsp), %rbx
leaq 0x38(%rsp), %r12
movq 0x68(%rsp), %rsi
movl %ebp, %edx
callq 0x530c
movss %xmm0, 0x38(%rsp)
movq 0x88(%rsp), %rsi
cmpq 0x90(%rsp), %rsi
je 0x54c5
movss %xmm0, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x88(%rsp)
jmp 0x54d0
movq %rbx, %rdi
movq %r12, %rdx
callq 0x51ca
incl %ebp
cmpl %ebp, %r13d
jne 0x548f
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 0xc(%rsp), %rsi
movb $0x41, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d958106, (%rax)     # imm = 0x3D958106
leaq 0xc(%rsp), %rsi
movb $0x43, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3ccccccd, (%rax)     # imm = 0x3CCCCCCD
leaq 0xc(%rsp), %rsi
movb $0x44, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d4ccccd, (%rax)     # imm = 0x3D4CCCCD
leaq 0xc(%rsp), %rsi
movb $0x45, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d79db23, (%rax)     # imm = 0x3D79DB23
leaq 0xc(%rsp), %rsi
movb $0x46, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d2c0831, (%rax)     # imm = 0x3D2C0831
leaq 0xc(%rsp), %rsi
movb $0x47, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d9374bc, (%rax)     # imm = 0x3D9374BC
leaq 0xc(%rsp), %rsi
movb $0x48, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3cbc6a7f, (%rax)     # imm = 0x3CBC6A7F
leaq 0xc(%rsp), %rsi
movb $0x49, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d591687, (%rax)     # imm = 0x3D591687
leaq 0xc(%rsp), %rsi
movb $0x4b, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d83126f, (%rax)     # imm = 0x3D83126F
leaq 0xc(%rsp), %rsi
movb $0x4c, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3db645a2, (%rax)     # imm = 0x3DB645A2
leaq 0xc(%rsp), %rsi
movb $0x4d, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3cbc6a7f, (%rax)     # imm = 0x3CBC6A7F
leaq 0xc(%rsp), %rsi
movb $0x4e, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d3020c5, (%rax)     # imm = 0x3D3020C5
leaq 0xc(%rsp), %rsi
movb $0x50, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d54fdf4, (%rax)     # imm = 0x3D54FDF4
leaq 0xc(%rsp), %rsi
movb $0x51, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d23d70a, (%rax)     # imm = 0x3D23D70A
leaq 0xc(%rsp), %rsi
movb $0x52, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d54fdf4, (%rax)     # imm = 0x3D54FDF4
leaq 0xc(%rsp), %rsi
movb $0x53, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d958106, (%rax)     # imm = 0x3D958106
leaq 0xc(%rsp), %rsi
movb $0x54, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d656042, (%rax)     # imm = 0x3D656042
leaq 0xc(%rsp), %rsi
movb $0x56, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d810625, (%rax)     # imm = 0x3D810625
leaq 0xc(%rsp), %rsi
movb $0x57, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3c54fdf4, (%rax)     # imm = 0x3C54FDF4
leaq 0xc(%rsp), %rsi
movb $0x59, (%rsi)
leaq 0x38(%rsp), %rdi
callq 0x5bd2
movl $0x3d072b02, (%rax)     # imm = 0x3D072B02
cmpl $0x0, 0x18(%rsp)
jle 0x57e6
movq 0x10(%rsp), %rax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
leaq (,%r13,4), %rcx
xorl %edx, %edx
xorps %xmm0, %xmm0
movsd 0xa962(%rip), %xmm1     # 0x10060
movl $0x0, %esi
cmpl $0x0, 0x10(%rsp)
jle 0x577f
movq 0x68(%rsp), %rsi
movq 0x38(%rsi), %rdi
movq 0xa8(%rsp), %r8
movq (%r14,%rdx,8), %r9
xorl %r10d, %r10d
xorl %esi, %esi
testl %r13d, %r13d
jle 0x5760
movq 0x80(%rsp), %r11
xorl %ebx, %ebx
movq (%rdi,%rbx,8), %r15
movb (%r15,%rdx), %bpl
cmpb (%r8,%r10), %bpl
jne 0x5757
movss (%r11,%rbx), %xmm2
movq (%r14,%rdx,8), %r15
addss (%r15,%r10,4), %xmm2
movss %xmm2, (%r15,%r10,4)
addq $0x4, %rbx
cmpq %rbx, %rcx
jne 0x5733
movss (%r9,%r10,4), %xmm2
ucomiss %xmm0, %xmm2
jne 0x5777
jp 0x5777
movl $0x358637bd, (%r9,%r10,4) # imm = 0x358637BD
incl %esi
incq %r10
cmpq %rax, %r10
jne 0x5724
xorps %xmm2, %xmm2
cvtsi2ss %esi, %xmm2
cvtss2sd %xmm2, %xmm2
mulsd %xmm1, %xmm2
cmpl $0x0, 0x10(%rsp)
jle 0x57d8
movq 0x10(%rsp), %rdi
subl %esi, %edi
xorps %xmm3, %xmm3
cvtsi2ss %edi, %xmm3
cvtss2sd %xmm3, %xmm3
divsd %xmm3, %xmm2
cvtsd2ss %xmm2, %xmm2
movq (%r14,%rdx,8), %rsi
xorl %edi, %edi
movss (%rsi,%rdi,4), %xmm3
xorps %xmm4, %xmm4
cvtss2sd %xmm3, %xmm4
ucomisd %xmm1, %xmm4
jbe 0x57d0
subss %xmm2, %xmm3
movss %xmm3, (%rsi,%rdi,4)
incq %rdi
cmpq %rdi, %rax
jne 0x57b5
incq %rdx
cmpq 0x18(%rsp), %rdx
jne 0x56fe
cmpl $0x0, 0x18(%rsp)
jle 0x5abe
xorps %xmm0, %xmm0
cvtsi2ss %r13d, %xmm0
movss %xmm0, 0x70(%rsp)
movq 0xa0(%rsp), %rax
addq $0x8, %rax
movq %rax, 0xc8(%rsp)
movq 0x10(%rsp), %r15
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
movq $0x0, 0x30(%rsp)
leaq 0xc(%rsp), %rbx
movabsq $0x280000200001, %rbp   # imm = 0x280000200001
movq %r15, 0xd0(%rsp)
cmpl $0x0, 0x10(%rsp)
jle 0x5a04
xorps %xmm0, %xmm0
xorl %r13d, %r13d
xorpd %xmm1, %xmm1
movss %xmm1, 0x28(%rsp)
movq 0xa8(%rsp), %rax
movzbl (%rax,%r13), %eax
movb %al, 0xc(%rsp)
addl $-0x2d, %eax
cmpl $0x2d, %eax
ja 0x5886
btq %rax, %rbp
jae 0x5886
incq %r13
cmpq %r13, %r15
jne 0x585a
jmp 0x59db
movss %xmm0, 0x7c(%rsp)
movq %rbp, %r15
movq 0x30(%rsp), %rax
movq (%r14,%rax,8), %r12
movss (%r12,%r13,4), %xmm0
movss %xmm0, 0x20(%rsp)
leaq 0x38(%rsp), %rbx
movq %rbx, %rdi
leaq 0xc(%rsp), %rbp
movq %rbp, %rsi
callq 0x5c36
movss 0x20(%rsp), %xmm0
xorps %xmm2, %xmm2
cvtss2sd %xmm0, %xmm2
mulss 0xa78a(%rip), %xmm0     # 0x10058
cvtss2sd %xmm0, %xmm0
xorps %xmm1, %xmm1
cvtss2sd (%rax), %xmm1
mulsd 0xa787(%rip), %xmm1     # 0x10068
addsd %xmm0, %xmm1
movsd %xmm2, 0x20(%rsp)
movaps %xmm2, %xmm0
divsd %xmm1, %xmm0
callq 0x41d0
movsd %xmm0, 0xe0(%rsp)
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x5c36
xorps %xmm0, %xmm0
cvtss2sd (%rax), %xmm0
movsd %xmm0, 0xd8(%rsp)
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x5c36
movss (%rax), %xmm0
movss %xmm0, 0x78(%rsp)
movss (%r12,%r13,4), %xmm0
movss %xmm0, 0x74(%rsp)
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x5c36
xorps %xmm0, %xmm0
cvtss2sd 0x28(%rsp), %xmm0
movsd 0x20(%rsp), %xmm1
mulsd 0xe0(%rsp), %xmm1
addsd %xmm0, %xmm1
xorps %xmm0, %xmm0
cvtsd2ss %xmm1, %xmm0
movss %xmm0, 0x28(%rsp)
movss 0x74(%rsp), %xmm0
mulss 0xa6da(%rip), %xmm0     # 0x10058
xorps %xmm1, %xmm1
cvtss2sd %xmm0, %xmm1
xorps %xmm2, %xmm2
cvtss2sd (%rax), %xmm2
xorps %xmm0, %xmm0
cvtss2sd 0x78(%rsp), %xmm0
mulsd 0xa6cb(%rip), %xmm2     # 0x10068
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
callq 0x41d0
xorps %xmm1, %xmm1
cvtss2sd 0x7c(%rsp), %xmm1
movsd 0xd8(%rsp), %xmm2
mulsd %xmm0, %xmm2
addsd %xmm1, %xmm2
xorps %xmm0, %xmm0
cvtsd2ss %xmm2, %xmm0
movq %r15, %rbp
movq 0xd0(%rsp), %r15
jmp 0x5879
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x20(%rsp)
movss 0x28(%rsp), %xmm0
mulss 0xa665(%rip), %xmm0     # 0x10058
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x28(%rsp)
leaq 0xc(%rsp), %rbx
jmp 0x5a13
xorps %xmm0, %xmm0
movsd %xmm0, 0x28(%rsp)
movsd %xmm0, 0x20(%rsp)
movq 0x68(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0xbeb4
movq 0x18(%rsp), %r12
movq 0xa0(%rsp), %rcx
movsd 0x20(%rsp), %xmm2
mulsd 0xa62b(%rip), %xmm2     # 0x10068
addsd 0x28(%rsp), %xmm2
movsd 0xa625(%rip), %xmm0     # 0x10070
xorps %xmm1, %xmm1
cvtsi2ss %eax, %xmm1
subsd %xmm2, %xmm0
divss 0x70(%rsp), %xmm1
movss 0xa5f0(%rip), %xmm2     # 0x10054
subss %xmm1, %xmm2
xorps %xmm1, %xmm1
cvtss2sd %xmm2, %xmm1
mulsd %xmm0, %xmm1
xorps %xmm0, %xmm0
cvtsd2ss %xmm1, %xmm0
movss %xmm0, 0xc(%rsp)
movq 0x10(%rcx), %rsi
cmpq 0x18(%rcx), %rsi
je 0x5a98
movss %xmm0, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x10(%rcx)
jmp 0x5aa8
movq 0xc8(%rsp), %rdi
movq %rbx, %rdx
callq 0x51ca
movq 0x30(%rsp), %rcx
incq %rcx
movq %rcx, 0x30(%rsp)
cmpq %r12, %rcx
jne 0x583f
movq 0x18(%rsp), %r15
testl %r15d, %r15d
jle 0x5adb
xorl %ebx, %ebx
movq (%r14,%rbx,8), %rdi
callq 0x42d0
incq %rbx
cmpq %rbx, %r15
jne 0x5aca
movq %r14, %rdi
callq 0x42d0
leaq 0x38(%rsp), %rdi
callq 0x5d5c
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
leaq 0xb8(%rsp), %rbx
je 0x5b12
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x4250
movq 0xa8(%rsp), %rdi
cmpq %rbx, %rdi
je 0x5b2f
movq 0xb8(%rsp), %rsi
incq %rsi
callq 0x4250
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x4566
callq 0x458a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
jmp 0x5b7a
movq %rax, %rbx
jmp 0x5b8f
jmp 0x5b7a
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x5d5c
leaq 0xb8(%rsp), %r15
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x5bac
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x4250
movq 0xa8(%rsp), %rdi
cmpq %r15, %rdi
je 0x5bc9
movq 0xb8(%rsp), %rsi
incq %rsi
callq 0x4250
movq %rbx, %rdi
callq 0x4440
nop