// File: /workspace/github_cpp_makefile_star2_O3/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 0x40(%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 0x1b44(%rip), %rsi      # 0x409e
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 0x4f08(%rip), %r15      # 0x74b8
leaq 0x58c9(%rip), %r12      # 0x7e80
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 0x2d5a
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 0x2f5c
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 0x2ffb
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, 0x38(%rsp)
xorl %ebx, %ebx
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x2d5a
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 0x3066
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)
xorpd %xmm0, %xmm0
xorl %eax, %eax
movdqa 0x11cd90(%rsp,%rax,8), %xmm1
movdqa 0x50(%rsp,%rax,8), %xmm2
movdqa %xmm2, %xmm3
psrlq $0x20, %xmm3
pmuludq %xmm1, %xmm3
movdqa %xmm1, %xmm4
psrlq $0x20, %xmm4
pmuludq %xmm2, %xmm4
paddq %xmm3, %xmm4
psllq $0x20, %xmm4
pmuludq %xmm1, %xmm2
paddq %xmm2, %xmm0
paddq %xmm4, %xmm0
addq $0x2, %rax
cmpq $0x239a8, %rax          # imm = 0x239A8
jne 0x2720
pshufd $0xee, %xmm0, %xmm1     # xmm1 = xmm0[2,3,2,3]
paddq %xmm0, %xmm1
movq %xmm1, %r14
callq 0x2060
movq %rax, %rbp
leaq 0x239ad0(%rsp), %rdi
leaq 0x35a440(%rsp), %rsi
callq 0x31ae
movq %rax, %rbx
callq 0x2060
subq %rbp, %rax
movabsq $0x20c49ba5e353f7cf, %rcx # imm = 0x20C49BA5E353F7CF
imulq %rcx
movq %rdx, %rbp
cmpq %rbx, %r14
je 0x28b7
movq 0x3810(%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 0x37d7(%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 0x1873(%rip), %rsi      # 0x40b0
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 0x1828(%rip), %rsi      # 0x40b3
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 0x1749(%rip), %xmm1     # 0x4008
movsd 0x18(%rsp), %xmm0
addsd 0x38(%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
leaq 0x40(%rsp), %r14
movabsq $0x431bde82d7b634db, %rbp # imm = 0x431BDE82D7B634DB
jne 0x25d6
movq 0x36a4(%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 0x1771(%rip), %rsi      # 0x40cc
movl $0x25, %edx
movq %r12, %rdi
callq 0x2150
movsd 0x10(%rsp), %xmm0
divsd 0x1692(%rip), %xmm0     # 0x4008
movq %r12, %rdi
callq 0x21a0
movq %rax, %rbx
leaq 0x176a(%rip), %r14      # 0x40f2
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 0x1730(%rip), %rsi      # 0x40f6
movl $0x1c, %edx
movq %r12, %rdi
callq 0x2150
movsd 0x18(%rsp), %xmm0
divsd 0x1627(%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 0x2a69
leaq 0x16df(%rip), %rsi      # 0x4113
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 0x3560(%rip), %rbx      # 0x5fd0
leaq 0x16ae(%rip), %rsi      # 0x4125
movl $0x1f, %edx
movq %rbx, %rdi
callq 0x2150
movsd 0x20(%rsp), %xmm0
movsd 0x1576(%rip), %xmm1     # 0x4008
divsd %xmm1, %xmm0
movq %rbx, %rdi
callq 0x21a0
movq %rax, %r14
leaq 0x164a(%rip), %rsi      # 0x40f2
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 0x1662(%rip), %rsi      # 0x4145
movl $0x21, %edx
movq %rbx, %rdi
callq 0x2150
movsd 0x28(%rsp), %xmm0
divsd 0x150a(%rip), %xmm0     # 0x4008
movq %rbx, %rdi
callq 0x21a0
movq %rax, %r14
leaq 0x1657(%rip), %rsi      # 0x4167
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 0x1620(%rip), %rsi      # 0x416b
movl $0xe, %edx
movq %rbx, %rdi
callq 0x2150
xorps %xmm0, %xmm0
cvtsi2sd %r15, %xmm0
movsd 0x14a0(%rip), %xmm1     # 0x4008
mulsd %xmm1, %xmm0
divsd %xmm1, %xmm0
movq %rbx, %rdi
callq 0x21a0
movq %rax, %r14
leaq 0x15f8(%rip), %rsi      # 0x417a
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 0x40(%rsp), %rdi
testq %rdi, %rdi
je 0x2bc5
callq 0x2170
movq 0x48(%rsp), %rdi
testq %rdi, %rdi
je 0x2bd4
callq 0x2170
leaq 0x15a1(%rip), %rsi      # 0x417c
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 0x33ca(%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
nop