// File: /workspace/github_cpp_makefile_star2_O1/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 $0x38, %rsp
movq %rdi, %rbx
movq %rsi, -0x40(%rbp)
cvtsi2sdl 0x20(%rsi), %xmm0
movsd %xmm0, -0x60(%rbp)
xorps %xmm0, %xmm0
cvtsi2sdl 0x20(%rdi), %xmm0
movsd %xmm0, -0x30(%rbp)
movl %edx, %edi
callq 0x1100
movsd -0x60(%rbp), %xmm2
movsd -0x30(%rbp), %xmm1
movapd %xmm2, %xmm0
divsd %xmm1, %xmm0
xorpd %xmm3, %xmm3
ucomisd %xmm3, %xmm0
jb 0x14ca
sqrtsd %xmm0, %xmm0
jmp 0x14dd
callq 0x10c0
xorpd %xmm3, %xmm3
movsd -0x60(%rbp), %xmm2
movsd -0x30(%rbp), %xmm1
movsd %xmm0, -0x38(%rbp)
divsd %xmm2, %xmm1
ucomisd %xmm3, %xmm1
jb 0x14f5
xorps %xmm0, %xmm0
sqrtsd %xmm1, %xmm0
jmp 0x14fe
movapd %xmm1, %xmm0
callq 0x10c0
movapd %xmm0, -0x50(%rbp)
movq 0x40(%rbx), %r13
testq %r13, %r13
je 0x15ca
movq -0x40(%rbp), %rax
addq $0x30, %rax
movq %rax, -0x30(%rbp)
movapd 0x1c3c(%rip), %xmm0     # 0x3160
xorpd -0x50(%rbp), %xmm0
movapd %xmm0, -0x60(%rbp)
leaq 0x8(%r13), %r12
movl 0x10(%r13), %r14d
movq 0x8(%r13), %rcx
xorl %r15d, %r15d
movq %rcx, %rax
xorl %edx, %edx
movq -0x40(%rbp), %rsi
divq 0x38(%rsi)
movq -0x30(%rbp), %rdi
movq %rdx, %rsi
movq %r12, %rdx
callq 0x26c8
testq %rax, %rax
je 0x1573
cmpq $0x0, (%rax)
je 0x1573
movq -0x30(%rbp), %rdi
movq %r12, %rsi
callq 0x2a2a
movl (%rax), %r15d
xorps %xmm0, %xmm0
cvtsi2sd %r14d, %xmm0
xorps %xmm1, %xmm1
cvtsi2sd %r15d, %xmm1
mulsd -0x60(%rbp), %xmm1
mulsd -0x38(%rbp), %xmm0
addsd %xmm1, %xmm0
movsd 0x1a6f(%rip), %xmm1     # 0x3008
divsd 0x10(%rbx), %xmm1
mulsd %xmm0, %xmm0
addl %r14d, %r15d
xorps %xmm2, %xmm2
cvtsi2sd %r15d, %xmm2
mulsd %xmm1, %xmm0
divsd %xmm2, %xmm0
addsd (%rbx), %xmm0
movsd %xmm0, (%rbx)
movq (%r13), %r13
testq %r13, %r13
jne 0x152e
movq -0x40(%rbp), %rax
movq 0x40(%rax), %r15
testq %r15, %r15
je 0x1670
movapd -0x50(%rbp), %xmm0
xorpd 0x1b78(%rip), %xmm0     # 0x3160
movapd %xmm0, -0x50(%rbp)
leaq 0x30(%rbx), %r14
xorpd %xmm0, %xmm0
movsd -0x38(%rbp), %xmm1
mulsd %xmm0, %xmm1
movsd %xmm1, -0x38(%rbp)
leaq 0x8(%r15), %rcx
movq 0x8(%r15), %r8
movq %r8, %rax
xorl %edx, %edx
divq 0x38(%rbx)
movq %r14, %rdi
movq %rdx, %rsi
movq %rcx, %rdx
movq %r8, %rcx
callq 0x26c8
testq %rax, %rax
je 0x1630
cmpq $0x0, (%rax)
jne 0x1668
xorps %xmm0, %xmm0
cvtsi2sdl 0x10(%r15), %xmm0
movapd -0x50(%rbp), %xmm1
mulsd %xmm0, %xmm1
addsd -0x38(%rbp), %xmm1
movsd 0x19b9(%rip), %xmm2     # 0x3008
divsd 0x10(%rbx), %xmm2
mulsd %xmm1, %xmm1
mulsd %xmm2, %xmm1
divsd %xmm0, %xmm1
addsd (%rbx), %xmm1
movsd %xmm1, (%rbx)
movq (%r15), %r15
testq %r15, %r15
jne 0x1603
movsd (%rbx), %xmm0
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq