// File: /workspace/github_cpp_makefile_star2_O1/dwkim606[P]IPPBA/main.cpp
// Function: main
int main() {
	
		long count = 0;
		
		double mskTime = 0.;
		double skTime = 0.;
		double encTime = 0.;
		double ipTime = 0.;
		
		int64_t ptxtResult;
		chrono::high_resolution_clock::time_point t1;
		chrono::high_resolution_clock::time_point t2;

		MasterSecretKey msk;
		EncryptedTemplate T;
		EncryptedBio B;

		Biometric X, Y;

		// Start Test
		cout << TEST_NUM << " iteration start!" << endl;
		for (long i = 0; i < TEST_NUM; i++) {
			printProgress((double)i / TEST_NUM);

			// Make template biometric
			for (long i = 0; i < K; i++) {
				X[i] = U(GEN) % 2;
				X[i] = 1 - 2 * X[i];
			}

			// Generate Master Secret Key
			t1 = chrono::high_resolution_clock::now();
			Scheme::mskGen(msk);
			t2 = chrono::high_resolution_clock::now();
			mskTime += chrono::duration_cast<chrono::milliseconds>(t2 - t1).count();
		
			// Generate Encryped Template corresponding to X
			t1 = chrono::high_resolution_clock::now();
			Scheme::templateGen(T, msk, X);
			t2 = chrono::high_resolution_clock::now();
			skTime += chrono::duration_cast<chrono::milliseconds>(t2 - t1).count();
					
			// Set random Y
			for (long j = 0; j < K; j++) {
				Y[j] = U(GEN) % 2;
				Y[j] = 1 - 2 * Y[j];
			}
			// Encrypt Bio information
			t1 = chrono::high_resolution_clock::now();
			Scheme::encryptBio(B, msk, Y);
			t2 = chrono::high_resolution_clock::now();
			encTime += chrono::duration_cast<chrono::milliseconds>(t2 - t1).count();
			// Compute Result in un-encrypted state for check
			ptxtResult = 0;
			for (long j = 0; j < K; j++) {
				ptxtResult += X[j] * Y[j];
			}
			// InnerProduct using encrypted template T and encrypted bio B
			t1 = chrono::high_resolution_clock::now();
			int64_t result = Scheme::innerProduct(T, B);
			t2 = chrono::high_resolution_clock::now();
			ipTime += chrono::duration_cast<chrono::microseconds>(t2 - t1).count();
			// Check the result
			if (ptxtResult != result) {
				cout << ptxtResult << endl;
				cout << result << endl;
				cout << "  " << endl;
				count++;
				cout << i << "-th running has ERROR!!!" << endl;
			}
		}

		cout << endl;
		cout << "- Master Secret Key Generation Time: " << mskTime / TEST_NUM << " ms" << endl;
		cout << "- Template Generation Time: " << skTime / TEST_NUM << " ms" << endl;

		if (count == 0) cout << "No error occured." << endl;
		cout << "- Average Time for Encryption: " << encTime / TEST_NUM << " ms" << endl;
		cout << "- Average Time for InnerProduct: " << ipTime / TEST_NUM << " us" << endl;
		cout << "- Error Rate: " << 100 * (double)count / TEST_NUM << "%" << endl;


		delete[] msk.S;
		delete[] msk.U;



	cout << "PRESS ENTER to EXIT" << endl;
	cin.ignore();
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x47adb8, %rsp         # imm = 0x47ADB8
movl $0x10bb8c48, %edi       # imm = 0x10BB8C48
callq 0x2030
leaq 0x38(%rsp), %r14
movq %rax, (%r14)
movl $0x120968, %edi         # imm = 0x120968
callq 0x2030
movq %rax, 0x8(%r14)
movq 0x3a8a(%rip), %rdi      # 0x5fd0
movl $0x64, %esi
callq 0x21c0
movq %rax, %rbx
leaq 0x1b0c(%rip), %rsi      # 0x4066
movl $0x11, %edx
movq %rax, %rdi
callq 0x2150
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
xorpd %xmm0, %xmm0
movsd %xmm0, 0x10(%rsp)
movq $0x0, 0x30(%rsp)
movsd 0x1a5f(%rip), %xmm1     # 0x4008
leaq 0x4f00(%rip), %r15      # 0x74b0
leaq 0x58c1(%rip), %r12      # 0x7e78
movabsq $0x431bde82d7b634db, %rbp # imm = 0x431BDE82D7B634DB
movsd %xmm0, 0x18(%rsp)
movsd %xmm0, 0x20(%rsp)
movsd %xmm0, 0x28(%rsp)
xorl %r13d, %r13d
xorps %xmm0, %xmm0
cvtsi2sd %r13, %xmm0
divsd %xmm1, %xmm0
callq 0x24bc
xorl %ebx, %ebx
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x2d18
addl %eax, %eax
andl $0x2, %eax
movl $0x1, %ecx
subq %rax, %rcx
movq %rcx, 0x11cd90(%rsp,%rbx,8)
incq %rbx
cmpq $0x239a8, %rbx          # imm = 0x239A8
jne 0x25e9
callq 0x2060
movq %rax, %rbx
movq %r14, %rdi
callq 0x2ef4
callq 0x2060
subq %rbx, %rax
imulq %rbp
movq %rdx, %rax
shrq $0x3f, %rax
sarq $0x12, %rdx
addq %rax, %rdx
xorps %xmm0, %xmm0
cvtsi2sd %rdx, %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x2060
movq %rax, %rbx
leaq 0x239ad0(%rsp), %rdi
movq %r14, %rsi
leaq 0x11cd90(%rsp), %rdx
callq 0x2f93
callq 0x2060
subq %rbx, %rax
imulq %rbp
movq %rdx, %rax
shrq $0x3f, %rax
sarq $0x12, %rdx
addq %rax, %rdx
xorps %xmm0, %xmm0
cvtsi2sd %rdx, %xmm0
movsd %xmm0, 0x48(%rsp)
xorl %ebx, %ebx
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x2d18
addl %eax, %eax
andl $0x2, %eax
movl $0x1, %ecx
subq %rax, %rcx
movq %rcx, 0x50(%rsp,%rbx,8)
incq %rbx
cmpq $0x239a8, %rbx          # imm = 0x239A8
jne 0x2698
movsd 0x10(%rsp), %xmm0
addsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
callq 0x2060
movq %rax, %rbx
leaq 0x35a440(%rsp), %rdi
movq %r14, %rsi
leaq 0x50(%rsp), %rdx
callq 0x3001
callq 0x2060
subq %rbx, %rax
imulq %rbp
movq %rdx, %rax
shrq $0x3f, %rax
sarq $0x12, %rdx
addq %rax, %rdx
xorps %xmm0, %xmm0
cvtsi2sd %rdx, %xmm0
movsd %xmm0, 0x8(%rsp)
xorl %eax, %eax
xorl %r14d, %r14d
movq 0x50(%rsp,%rax,8), %rcx
imulq 0x11cd90(%rsp,%rax,8), %rcx
addq %rcx, %r14
incq %rax
cmpq $0x239a8, %rax          # imm = 0x239A8
jne 0x271f
callq 0x2060
movq %rax, %rbp
leaq 0x239ad0(%rsp), %rdi
leaq 0x35a440(%rsp), %rsi
callq 0x3149
movq %rax, %rbx
callq 0x2060
subq %rbp, %rax
movabsq $0x20c49ba5e353f7cf, %rcx # imm = 0x20C49BA5E353F7CF
imulq %rcx
movq %rdx, %rbp
cmpq %rbx, %r14
je 0x287a
movq 0x384d(%rip), %rdi      # 0x5fd0
movq %r14, %rsi
callq 0x2120
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
movq 0x3814(%rip), %r14      # 0x5fd0
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2120
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
movl $0x2, %edx
movq %r14, %rdi
leaq 0x1878(%rip), %rsi      # 0x4078
callq 0x2150
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
incq 0x30(%rsp)
movq %r14, %rdi
movq %r13, %rsi
callq 0x2120
movq %rax, %rbx
movl $0x18, %edx
movq %rax, %rdi
leaq 0x182d(%rip), %rsi      # 0x407b
callq 0x2150
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
movsd 0x1786(%rip), %xmm1     # 0x4008
leaq 0x38(%rsp), %r14
movsd 0x18(%rsp), %xmm0
addsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movq %rbp, %rax
shrq $0x3f, %rax
sarq $0x7, %rbp
addq %rax, %rbp
xorps %xmm0, %xmm0
cvtsi2sd %rbp, %xmm0
movsd 0x20(%rsp), %xmm2
addsd 0x8(%rsp), %xmm2
movsd %xmm2, 0x20(%rsp)
movsd 0x28(%rsp), %xmm2
addsd %xmm0, %xmm2
movsd %xmm2, 0x28(%rsp)
incq %r13
cmpq $0x64, %r13
movabsq $0x431bde82d7b634db, %rbp # imm = 0x431BDE82D7B634DB
jne 0x25d6
movq 0x36e1(%rip), %r12      # 0x5fd0
movq (%r12), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %r12, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
leaq 0x1776(%rip), %rsi      # 0x4094
movl $0x25, %edx
movq %r12, %rdi
callq 0x2150
movsd 0x10(%rsp), %xmm0
divsd 0x16cf(%rip), %xmm0     # 0x4008
movq %r12, %rdi
callq 0x21a0
movq %rax, %rbx
leaq 0x176f(%rip), %r14      # 0x40ba
movl $0x3, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x2150
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
leaq 0x1735(%rip), %rsi      # 0x40be
movl $0x1c, %edx
movq %r12, %rdi
callq 0x2150
movsd 0x18(%rsp), %xmm0
divsd 0x1664(%rip), %xmm0     # 0x4008
movq %r12, %rdi
callq 0x21a0
movq %rax, %rbx
movl $0x3, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x2150
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
movq 0x30(%rsp), %r15
testq %r15, %r15
jne 0x2a2c
leaq 0x16e4(%rip), %rsi      # 0x40db
movl $0x11, %edx
movq %r12, %rdi
callq 0x2150
movq (%r12), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %r12, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
movq 0x359d(%rip), %rbx      # 0x5fd0
leaq 0x16b3(%rip), %rsi      # 0x40ed
movl $0x1f, %edx
movq %rbx, %rdi
callq 0x2150
movsd 0x20(%rsp), %xmm0
movsd 0x15b3(%rip), %xmm1     # 0x4008
divsd %xmm1, %xmm0
movq %rbx, %rdi
callq 0x21a0
movq %rax, %r14
leaq 0x164f(%rip), %rsi      # 0x40ba
movl $0x3, %edx
movq %rax, %rdi
callq 0x2150
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
leaq 0x1667(%rip), %rsi      # 0x410d
movl $0x21, %edx
movq %rbx, %rdi
callq 0x2150
movsd 0x28(%rsp), %xmm0
divsd 0x1547(%rip), %xmm0     # 0x4008
movq %rbx, %rdi
callq 0x21a0
movq %rax, %r14
leaq 0x165c(%rip), %rsi      # 0x412f
movl $0x3, %edx
movq %rax, %rdi
callq 0x2150
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
leaq 0x1625(%rip), %rsi      # 0x4133
movl $0xe, %edx
movq %rbx, %rdi
callq 0x2150
xorps %xmm0, %xmm0
cvtsi2sd %r15, %xmm0
movsd 0x14dd(%rip), %xmm1     # 0x4008
mulsd %xmm1, %xmm0
divsd %xmm1, %xmm0
movq %rbx, %rdi
callq 0x21a0
movq %rax, %r14
leaq 0x15fd(%rip), %rsi      # 0x4142
movl $0x1, %edx
movq %rax, %rdi
callq 0x2150
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
movq 0x38(%rsp), %rdi
testq %rdi, %rdi
je 0x2b88
callq 0x2170
movq 0x40(%rsp), %rdi
testq %rdi, %rdi
je 0x2b97
callq 0x2170
leaq 0x15a6(%rip), %rsi      # 0x4144
movl $0x13, %edx
movq %rbx, %rdi
callq 0x2150
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2130
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
movq 0x3407(%rip), %rdi      # 0x5fe0
callq 0x21f0
xorl %eax, %eax
addq $0x47adb8, %rsp         # imm = 0x47ADB8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq