// File: arinaschwartz[P]KNN-MNIST/mnist-knn.cpp
// Function: main
int main(int argc, char** argv)
{
	// For parsing command-line options
	int opt;
	// Should we be verbose?
	bool verbose = false;
	// Directory containing MNIST files
	string directory = "";
	// Distance strategy
	string type = "full";
	// K
	int k = 1;
	// Process only these many images in the testing set (0 = process all)
	int max = 0;
	// Number of images labelled correctly
	uint32 correct;

	// Parse command-line options
	while ((opt = getopt(argc, argv, "d:t:n:k:vh")) != -1)
		switch (opt)
		{
			case 'd':
				directory = optarg;
				break;
			case 't':
				type = optarg;
				break;
			case 'v':
				verbose = true;
				break;
			case 'k':
				k = atoi(optarg);
				break;
			case 'n':
				max = atoi(optarg);
				break;
			default:
				cerr << "Usage: " << argv[0] << " " << USAGE << endl;
				cerr << "ERROR: Unknown option -" << char(opt) << endl;
				exit(-1);
		}

	if(directory == "")
	{
		cerr << "Usage: " << argv[0] << " " << USAGE << endl;
		cerr << "ERROR: Must specify a directory with -d" << endl;
		exit(-1);
	}

	// Load files
	ifstream trainImageFile((directory + "/train-images-idx3-ubyte").c_str(), ios::in|ios::binary);
	ifstream trainLabelFile((directory + "/train-labels-idx1-ubyte").c_str(), ios::in|ios::binary);
	ifstream testImageFile((directory + "/t10k-images-idx3-ubyte").c_str(), ios::in|ios::binary);
	ifstream testLabelFile((directory + "/t10k-labels-idx1-ubyte").c_str(), ios::in|ios::binary);

	MNISTDataset *trainSet, *testSet;

	try
	{
		trainSet = new MNISTDataset(trainImageFile, trainLabelFile, type);
		testSet = new MNISTDataset(testImageFile, testLabelFile, type);
	} catch (MNISTFileException &e)
	{
		cerr << e.what() << endl;
		exit(-2);
	}

	if(max==0)
		max = testSet->getNumImages();

	// Run KNN
	correct = KNN(*trainSet, *testSet, k, max, verbose);

	// Print summary
	cout << type << " " << k << " " << max << " " << correct << " " << (max - correct) << " " << (float(max-correct)*100.0/max) << endl;

	// Clean up
	delete testSet;
	delete trainSet;

	trainImageFile.close();
	trainLabelFile.close();
	testImageFile.close();
	testLabelFile.close();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xad0, %rsp            # imm = 0xAD0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movb $0x0, -0x15(%rbp)
leaq -0x39(%rbp), %rdi
movq %rdi, -0x990(%rbp)
callq 0x3320
movq -0x990(%rbp), %rdx
leaq 0x124d(%rip), %rsi      # 0x7228
leaq -0x38(%rbp), %rdi
callq 0x6a40
jmp 0x5fe6
leaq -0x39(%rbp), %rdi
callq 0x3200
leaq -0x71(%rbp), %rdi
movq %rdi, -0x998(%rbp)
callq 0x3320
movq -0x998(%rbp), %rdx
leaq 0x1079(%rip), %rsi      # 0x7086
leaq -0x70(%rbp), %rdi
callq 0x6a40
jmp 0x6018
leaq -0x71(%rbp), %rdi
callq 0x3200
movl $0x1, -0x78(%rbp)
movl $0x0, -0x7c(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x11d9(%rip), %rdx      # 0x7216
callq 0x3060
movl %eax, -0x14(%rbp)
cmpl $-0x1, %eax
je 0x620b
movl -0x14(%rbp), %eax
addl $-0x64, %eax
movl %eax, %ecx
movq %rcx, -0x9a0(%rbp)
subl $0x12, %eax
ja 0x612d
movq -0x9a0(%rbp), %rax
leaq 0x112c(%rip), %rcx      # 0x71a0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x39(%rbp), %rdi
callq 0x3200
jmp 0x6a2c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x71(%rbp), %rdi
callq 0x3200
jmp 0x6a23
movq 0x4ef8(%rip), %rax      # 0xafb0
movq (%rax), %rsi
leaq -0x38(%rbp), %rdi
callq 0x32a0
jmp 0x60c6
jmp 0x6206
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x6a1a
movq 0x4ecd(%rip), %rax      # 0xafb0
movq (%rax), %rsi
leaq -0x70(%rbp), %rdi
callq 0x32a0
jmp 0x60f1
jmp 0x6206
movb $0x1, -0x15(%rbp)
jmp 0x6206
movq 0x4eaa(%rip), %rax      # 0xafb0
movq (%rax), %rdi
callq 0x32d0
movl %eax, -0x78(%rbp)
jmp 0x6206
movq 0x4e93(%rip), %rax      # 0xafb0
movq (%rax), %rdi
callq 0x32d0
movl %eax, -0x7c(%rbp)
jmp 0x6206
movq 0x4ebc(%rip), %rdi      # 0xaff0
leaq 0x10e6(%rip), %rsi      # 0x7221
callq 0x31b0
movq %rax, -0x9a8(%rbp)
jmp 0x6149
movq -0x9a8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
callq 0x31b0
movq %rax, -0x9b0(%rbp)
jmp 0x6165
movq -0x9b0(%rbp), %rdi
leaq 0x10b4(%rip), %rsi      # 0x7227
callq 0x31b0
movq %rax, -0x9b8(%rbp)
jmp 0x6181
movq -0x9b8(%rbp), %rdi
leaq 0x5069(%rip), %rsi      # 0xb1f8
callq 0x31a0
movq %rax, -0x9c0(%rbp)
jmp 0x619d
movq -0x9c0(%rbp), %rdi
movq 0x4dfd(%rip), %rsi      # 0xafa8
callq 0x31e0
jmp 0x61b2
movq 0x4e37(%rip), %rdi      # 0xaff0
leaq 0x1069(%rip), %rsi      # 0x7229
callq 0x31b0
movq %rax, -0x9c8(%rbp)
jmp 0x61ce
movq -0x9c8(%rbp), %rdi
movsbl -0x14(%rbp), %esi
callq 0x3240
movq %rax, -0x9d0(%rbp)
jmp 0x61e7
movq -0x9d0(%rbp), %rdi
movq 0x4db3(%rip), %rsi      # 0xafa8
callq 0x31e0
jmp 0x61fc
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3250
jmp 0x602f
leaq 0x1016(%rip), %rsi      # 0x7228
leaq -0x38(%rbp), %rdi
callq 0x3f30
movb %al, -0x9d1(%rbp)
jmp 0x6223
movb -0x9d1(%rbp), %al
testb $0x1, %al
jne 0x6232
jmp 0x62f2
movq 0x4db7(%rip), %rdi      # 0xaff0
leaq 0xfe1(%rip), %rsi       # 0x7221
callq 0x31b0
movq %rax, -0x9e0(%rbp)
jmp 0x624e
movq -0x9e0(%rbp), %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
callq 0x31b0
movq %rax, -0x9e8(%rbp)
jmp 0x626a
movq -0x9e8(%rbp), %rdi
leaq 0xfaf(%rip), %rsi       # 0x7227
callq 0x31b0
movq %rax, -0x9f0(%rbp)
jmp 0x6286
movq -0x9f0(%rbp), %rdi
leaq 0x4f64(%rip), %rsi      # 0xb1f8
callq 0x31a0
movq %rax, -0x9f8(%rbp)
jmp 0x62a2
movq -0x9f8(%rbp), %rdi
movq 0x4cf8(%rip), %rsi      # 0xafa8
callq 0x31e0
jmp 0x62b7
movq 0x4d32(%rip), %rdi      # 0xaff0
leaq 0xf7c(%rip), %rsi       # 0x7241
callq 0x31b0
movq %rax, -0xa00(%rbp)
jmp 0x62d3
movq -0xa00(%rbp), %rdi
movq 0x4cc7(%rip), %rsi      # 0xafa8
callq 0x31e0
jmp 0x62e8
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3250
leaq 0xf70(%rip), %rdx       # 0x7269
leaq -0x2a8(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x6af0
jmp 0x630b
leaq -0x2a8(%rbp), %rdi
callq 0x30d0
movq %rax, -0xa10(%rbp)
movl $0x8, %edi
movl $0x4, %esi
callq 0x6b70
movl %eax, -0xa04(%rbp)
jmp 0x6335
movl -0xa04(%rbp), %edx
movq -0xa10(%rbp), %rsi
leaq -0x288(%rbp), %rdi
callq 0x3340
jmp 0x6350
leaq -0x2a8(%rbp), %rdi
callq 0x3398
leaq 0xf1f(%rip), %rdx       # 0x7282
leaq -0x4d0(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x6af0
jmp 0x6375
leaq -0x4d0(%rbp), %rdi
callq 0x30d0
movq %rax, -0xa20(%rbp)
movl $0x8, %edi
movl $0x4, %esi
callq 0x6b70
movl %eax, -0xa14(%rbp)
jmp 0x639f
movl -0xa14(%rbp), %edx
movq -0xa20(%rbp), %rsi
leaq -0x4b0(%rbp), %rdi
callq 0x3340
jmp 0x63ba
leaq -0x4d0(%rbp), %rdi
callq 0x3398
leaq 0xece(%rip), %rdx       # 0x729b
leaq -0x6f8(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x6af0
jmp 0x63df
leaq -0x6f8(%rbp), %rdi
callq 0x30d0
movq %rax, -0xa30(%rbp)
movl $0x8, %edi
movl $0x4, %esi
callq 0x6b70
movl %eax, -0xa24(%rbp)
jmp 0x6409
movl -0xa24(%rbp), %edx
movq -0xa30(%rbp), %rsi
leaq -0x6d8(%rbp), %rdi
callq 0x3340
jmp 0x6424
leaq -0x6f8(%rbp), %rdi
callq 0x3398
leaq 0xe7c(%rip), %rdx       # 0x72b3
leaq -0x920(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x6af0
jmp 0x6449
leaq -0x920(%rbp), %rdi
callq 0x30d0
movq %rax, -0xa40(%rbp)
movl $0x8, %edi
movl $0x4, %esi
callq 0x6b70
movl %eax, -0xa34(%rbp)
jmp 0x6473
movl -0xa34(%rbp), %edx
movq -0xa40(%rbp), %rsi
leaq -0x900(%rbp), %rdi
callq 0x3340
jmp 0x648e
leaq -0x920(%rbp), %rdi
callq 0x3398
movl $0x18, %edi
callq 0x31c0
movq %rax, -0xa48(%rbp)
jmp 0x64ad
movb $0x1, -0x951(%rbp)
leaq -0x950(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x30e0
jmp 0x64c6
movq -0xa48(%rbp), %rdi
leaq -0x288(%rbp), %rsi
leaq -0x4b0(%rbp), %rdx
leaq -0x950(%rbp), %rcx
callq 0x3670
jmp 0x64e9
movq -0xa48(%rbp), %rax
movb $0x0, -0x951(%rbp)
movq %rax, -0x928(%rbp)
leaq -0x950(%rbp), %rdi
callq 0x3398
movl $0x18, %edi
callq 0x31c0
movq %rax, -0xa50(%rbp)
jmp 0x651d
movb $0x1, -0x979(%rbp)
leaq -0x978(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x30e0
jmp 0x6536
movq -0xa50(%rbp), %rdi
leaq -0x6d8(%rbp), %rsi
leaq -0x900(%rbp), %rdx
leaq -0x978(%rbp), %rcx
callq 0x3670
jmp 0x6559
movq -0xa50(%rbp), %rax
movb $0x0, -0x979(%rbp)
movq %rax, -0x930(%rbp)
leaq -0x978(%rbp), %rdi
callq 0x3398
jmp 0x673e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x2a8(%rbp), %rdi
callq 0x3398
jmp 0x6a1a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x6a0e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x4d0(%rbp), %rdi
callq 0x3398
jmp 0x6a0e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x6a02
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x6f8(%rbp), %rdi
callq 0x3398
jmp 0x6a02
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x69f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x920(%rbp), %rdi
callq 0x3398
jmp 0x69f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x66bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x665d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x950(%rbp), %rdi
callq 0x3398
testb $0x1, -0x951(%rbp)
jne 0x6668
jmp 0x6679
movq -0xa48(%rbp), %rdi
movl $0x18, %esi
callq 0x31d0
jmp 0x66bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x66a1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x978(%rbp), %rdi
callq 0x3398
testb $0x1, -0x979(%rbp)
jne 0x66ac
jmp 0x66bd
movq -0xa50(%rbp), %rdi
movl $0x18, %esi
callq 0x31d0
jmp 0x66bf
movl -0x4c(%rbp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0x69ea
movq -0x48(%rbp), %rdi
callq 0x30c0
movq %rax, -0x988(%rbp)
movq -0x988(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq %rax, %rsi
movq 0x48f7(%rip), %rdi      # 0xaff0
callq 0x31b0
movq %rax, -0xa58(%rbp)
jmp 0x6707
movq -0xa58(%rbp), %rdi
movq 0x4893(%rip), %rsi      # 0xafa8
callq 0x31e0
jmp 0x671c
movl $0xfffffffe, %edi       # imm = 0xFFFFFFFE
callq 0x3250
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
callq 0x32e0
jmp 0x6739
jmp 0x69ea
cmpl $0x0, -0x7c(%rbp)
jne 0x6774
movq -0x930(%rbp), %rdi
callq 0x3eb0
movl %eax, -0xa5c(%rbp)
jmp 0x6758
movl -0xa5c(%rbp), %eax
movl %eax, -0x7c(%rbp)
jmp 0x6774
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x69ea
movq -0x928(%rbp), %rdi
movq -0x930(%rbp), %rsi
movl -0x78(%rbp), %edx
movl -0x7c(%rbp), %ecx
movzbl -0x15(%rbp), %r8d
andl $0x1, %r8d
callq 0x47e0
movl %eax, -0xa60(%rbp)
jmp 0x679e
movl -0xa60(%rbp), %eax
movl %eax, -0x80(%rbp)
movq 0x4822(%rip), %rdi      # 0xafd0
leaq -0x70(%rbp), %rsi
callq 0x31a0
movq %rax, -0xa68(%rbp)
jmp 0x67c0
movq -0xa68(%rbp), %rdi
leaq 0xa59(%rip), %rsi       # 0x7227
callq 0x31b0
movq %rax, -0xa70(%rbp)
jmp 0x67dc
movq -0xa70(%rbp), %rdi
movl -0x78(%rbp), %esi
callq 0x3300
movq %rax, -0xa78(%rbp)
jmp 0x67f4
movq -0xa78(%rbp), %rdi
leaq 0xa25(%rip), %rsi       # 0x7227
callq 0x31b0
movq %rax, -0xa80(%rbp)
jmp 0x6810
movq -0xa80(%rbp), %rdi
movl -0x7c(%rbp), %esi
callq 0x3300
movq %rax, -0xa88(%rbp)
jmp 0x6828
movq -0xa88(%rbp), %rdi
leaq 0x9f1(%rip), %rsi       # 0x7227
callq 0x31b0
movq %rax, -0xa90(%rbp)
jmp 0x6844
movq -0xa90(%rbp), %rdi
movl -0x80(%rbp), %esi
callq 0x3290
movq %rax, -0xa98(%rbp)
jmp 0x685c
movq -0xa98(%rbp), %rdi
leaq 0x9bd(%rip), %rsi       # 0x7227
callq 0x31b0
movq %rax, -0xaa0(%rbp)
jmp 0x6878
movq -0xaa0(%rbp), %rdi
movl -0x7c(%rbp), %esi
movl -0x80(%rbp), %eax
subl %eax, %esi
callq 0x3290
movq %rax, -0xaa8(%rbp)
jmp 0x6895
movq -0xaa8(%rbp), %rdi
leaq 0x984(%rip), %rsi       # 0x7227
callq 0x31b0
movq %rax, -0xab0(%rbp)
jmp 0x68b1
movq -0xab0(%rbp), %rdi
movl -0x7c(%rbp), %eax
movl -0x80(%rbp), %edx
movl %eax, %ecx
subl %edx, %ecx
cvtsi2ss %rcx, %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x835(%rip), %xmm1      # 0x7108
mulsd %xmm1, %xmm0
cvtsi2sd %eax, %xmm1
divsd %xmm1, %xmm0
callq 0x3360
movq %rax, -0xab8(%rbp)
jmp 0x68ed
movq -0xab8(%rbp), %rdi
movq 0x46ad(%rip), %rsi      # 0xafa8
callq 0x31e0
jmp 0x6902
movq -0x930(%rbp), %rax
movq %rax, -0xac0(%rbp)
cmpq $0x0, %rax
je 0x6933
movq -0xac0(%rbp), %rdi
callq 0x3e80
movq -0xac0(%rbp), %rdi
movl $0x18, %esi
callq 0x31d0
movq -0x928(%rbp), %rax
movq %rax, -0xac8(%rbp)
cmpq $0x0, %rax
je 0x6964
movq -0xac8(%rbp), %rdi
callq 0x3e80
movq -0xac8(%rbp), %rdi
movl $0x18, %esi
callq 0x31d0
leaq -0x288(%rbp), %rdi
callq 0x3050
jmp 0x6972
leaq -0x4b0(%rbp), %rdi
callq 0x3050
jmp 0x6980
leaq -0x6d8(%rbp), %rdi
callq 0x3050
jmp 0x698e
leaq -0x900(%rbp), %rdi
callq 0x3050
jmp 0x699c
leaq -0x900(%rbp), %rdi
callq 0x3070
leaq -0x6d8(%rbp), %rdi
callq 0x3070
leaq -0x4b0(%rbp), %rdi
callq 0x3070
leaq -0x288(%rbp), %rdi
callq 0x3070
leaq -0x70(%rbp), %rdi
callq 0x3398
leaq -0x38(%rbp), %rdi
callq 0x3398
movl -0x4(%rbp), %eax
addq $0xad0, %rsp            # imm = 0xAD0
popq %rbp
retq
leaq -0x900(%rbp), %rdi
callq 0x3070
leaq -0x6d8(%rbp), %rdi
callq 0x3070
leaq -0x4b0(%rbp), %rdi
callq 0x3070
leaq -0x288(%rbp), %rdi
callq 0x3070
leaq -0x70(%rbp), %rdi
callq 0x3398
leaq -0x38(%rbp), %rdi
callq 0x3398
movq -0x48(%rbp), %rdi
callq 0x3310
movq %rax, %rdi
callq 0x4ca0
nopl (%rax)