// File: /workspace/github_cpp_makefile_star2_O2/ashlall[P]StreamStats/Test/./../SourceCode/ChiSquare/ChiSquareCategorical.cpp
// Function: ChiSquareCategorical::calculate_statistic(ChiSquareCategorical const&, int)
double ChiSquareCategorical::calculate_statistic(const ChiSquareCategorical& second_distribution, int seed)
{      	//Getting the size of both streams
	int stream_size_1=stream_size;
	int stream_size_2=second_distribution.stream_size;
	srand(seed);
	
	double constant_1 = sqrt((double)stream_size_2/stream_size_1);
	double constant_2 = sqrt((double)stream_size_1/stream_size_2);
	double estimateSum = 0.0;
	int count = 0;
	for ( auto it = map.begin(); it != map.end(); ++it )
	{
		 // Getting the frequencies if the i'th bin from the two streams.
		 int frequency_1= it->second;
		 int frequency_2 = 0;
		 if (second_distribution.map.find(it->first) != second_distribution.map.end())
		   frequency_2= second_distribution.map.at(it->first);
	 	
		 //Calculating the Chi-Squared Statistic
		
		 // Naive sampling:
		 double value = frequency_1 * constant_1 - frequency_2 * constant_2;
		 chi_squared += (100.0/percent) * (value * value) / (frequency_1 + frequency_2);
	}

	// loop through second stream to find bins where 1st stream is 0
	for (auto i = second_distribution.map.begin(); i != second_distribution.map.end(); ++i)
        {
	  if (map.find(i->first) == map.end())
	  {
	    int frequency_1 = 0;
	    int frequency_2 = i->second;
	    double value = frequency_1 * constant_1 - frequency_2 * constant_2;
	    chi_squared += (100.0/percent) * (value * value) / (frequency_1 + frequency_2);
	  }
	}
		 
		 
		 /*
		 // AMS-sampling from https://people.cs.umass.edu/~mcgregor/papers/07-unsketchables.pdf
		 int r, s;
		 double X;
		 if (rand() % 2 == 0) // randomly pick between stream 1 and stream 2
		 {
		     r = (1 + rand() % stream_size_2) + (rand() % frequency_1) * stream_size_2;
		     s = frequency_2 * stream_size_1;
		     X = 2.0 * ((double)(r * s) / (r + s) - ((double)(r - 1)*s)/(r + s - 1));  
		 }
		 else
		 {
		     r = 0;
		     s = (1 + rand() % stream_size_1) + (rand() % frequency_2) * stream_size_1;
		     X = 2.0 * ((double)(r * s) / (r + s) - ((double)r*(s - 1))/(r + s - 1));
		 }
		 
		 estimateSum += X;
		 count++;
		 */
	
	
	return chi_squared;
	//return (stream_size_1 + stream_size_2 - 4 * stream_size_1 * estimateSum / count);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rsi, %r14
cvtsi2sdl 0x20(%rsi), %xmm0
movsd %xmm0, -0x40(%rbp)
movq %rdi, -0x38(%rbp)
cvtsi2sdl 0x20(%rdi), %xmm0
movsd %xmm0, -0x50(%rbp)
movl %edx, %edi
callq 0x10f0
movsd -0x40(%rbp), %xmm0
divsd -0x50(%rbp), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x145b
sqrtsd %xmm0, %xmm0
jmp 0x1464
callq 0x10b0
xorpd %xmm1, %xmm1
movsd %xmm0, -0x30(%rbp)
movsd -0x50(%rbp), %xmm0
divsd -0x40(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x147f
sqrtsd %xmm0, %xmm0
jmp 0x1484
callq 0x10b0
movq -0x38(%rbp), %rax
leaq 0x40(%rax), %r13
leaq 0x30(%r14), %rbx
xorpd 0x1cc8(%rip), %xmm0     # 0x3160
movapd %xmm0, -0x50(%rbp)
movq %rbx, -0x40(%rbp)
movq (%r13), %r13
testq %r13, %r13
je 0x151c
leaq 0x8(%r13), %r12
movl 0x10(%r13), %r15d
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2452
testq %rax, %rax
je 0x14d1
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2870
movl (%rax), %eax
jmp 0x14d3
xorl %eax, %eax
cvtsi2sd %r15d, %xmm0
cvtsi2sd %eax, %xmm1
mulsd -0x50(%rbp), %xmm1
mulsd -0x30(%rbp), %xmm0
addsd %xmm1, %xmm0
movsd 0x1b16(%rip), %xmm1     # 0x3008
movq -0x38(%rbp), %rcx
divsd 0x10(%rcx), %xmm1
mulsd %xmm0, %xmm0
mulsd %xmm1, %xmm0
addl %r15d, %eax
cvtsi2sd %eax, %xmm1
divsd %xmm1, %xmm0
addsd (%rcx), %xmm0
movsd %xmm0, (%rcx)
movq -0x40(%rbp), %rbx
jmp 0x14a1
movq -0x38(%rbp), %rax
leaq 0x30(%rax), %r15
addq $0x40, %r14
xorpd %xmm0, %xmm0
movsd -0x30(%rbp), %xmm1
mulsd %xmm0, %xmm1
movsd %xmm1, -0x30(%rbp)
movq (%r14), %r14
testq %r14, %r14
je 0x158e
leaq 0x8(%r14), %rsi
movq %r15, %rdi
callq 0x284e
testq %rax, %rax
jne 0x153a
cvtsi2sdl 0x10(%r14), %xmm0
movapd -0x50(%rbp), %xmm1
mulsd %xmm0, %xmm1
addsd -0x30(%rbp), %xmm1
movsd 0x1a99(%rip), %xmm2     # 0x3008
movq -0x38(%rbp), %rax
divsd 0x10(%rax), %xmm2
mulsd %xmm1, %xmm1
mulsd %xmm2, %xmm1
divsd %xmm0, %xmm1
addsd (%rax), %xmm1
movsd %xmm1, (%rax)
jmp 0x153a
movq -0x38(%rbp), %rax
movsd (%rax), %xmm0
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq