// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x8d8, %rsp            # imm = 0x8D8
movq %rsi, %r14
movl %edi, %r15d
leaq 0xf44(%rip), %rsi       # 0x41f6
leaq 0x18(%rsp), %rdi
leaq 0x6d0(%rsp), %rdx
callq 0x38ec
leaq 0xdbb(%rip), %rsi       # 0x4086
leaq 0x38(%rsp), %r13
leaq 0x6d0(%rsp), %rdx
movq %r13, %rdi
callq 0x38ec
pushq $0x1
popq %rax
movl %eax, 0x10(%rsp)
movl $0x0, 0x14(%rsp)
leaq 0xeee(%rip), %rbx       # 0x41e4
movq 0x3cbb(%rip), %r12      # 0x6fb8
movl $0x0, 0xc(%rsp)
movl %r15d, %edi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x2050
cmpl $0x64, %eax
je 0x3342
movl %eax, %ebp
movq %r13, %rdi
cmpl $0x74, %eax
je 0x3347
cmpl $-0x1, %ebp
je 0x3370
cmpl $0x6b, %ebp
je 0x3352
cmpl $0x6e, %ebp
je 0x3361
cmpl $0x76, %ebp
jne 0x36a8
movb $0x1, %al
movl %eax, 0xc(%rsp)
jmp 0x3305
leaq 0x18(%rsp), %rdi
movq (%r12), %rsi
callq 0x22a0
jmp 0x3305
movq (%r12), %rdi
callq 0x2210
movl %eax, 0x10(%rsp)
jmp 0x3305
movq (%r12), %rdi
callq 0x2210
movl %eax, 0x14(%rsp)
jmp 0x3305
leaq 0xe7f(%rip), %rsi       # 0x41f6
leaq 0x18(%rsp), %rdi
callq 0x294c
testb %al, %al
jne 0x371a
leaq 0xea7(%rip), %rdx       # 0x4237
leaq 0x4c8(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x3927
movl 0x14(%rsp), %r12d
movl 0x10(%rsp), %ebx
movq 0x4c8(%rsp), %rsi
leaq 0x6d0(%rsp), %rdi
pushq $0xc
popq %rdx
callq 0x2280
leaq 0x4c8(%rsp), %rdi
callq 0x22b8
leaq 0xe79(%rip), %rdx       # 0x4250
leaq 0x2c0(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x3927
movq 0x2c0(%rsp), %rsi
leaq 0x4c8(%rsp), %rdi
pushq $0xc
popq %rdx
callq 0x2280
leaq 0x2c0(%rsp), %rdi
callq 0x22b8
leaq 0xe54(%rip), %rdx       # 0x4269
leaq 0xb8(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x3927
movq 0xb8(%rsp), %rsi
leaq 0x2c0(%rsp), %rdi
pushq $0xc
popq %rdx
callq 0x2280
leaq 0xb8(%rsp), %rdi
callq 0x22b8
leaq 0xe2e(%rip), %rdx       # 0x4281
leaq 0x98(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x3927
movq 0x98(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
pushq $0xc
popq %rdx
callq 0x2280
leaq 0x98(%rsp), %rdi
callq 0x22b8
pushq $0x18
popq %rdi
callq 0x2180
movq %rax, %r14
leaq 0x78(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x21f0
leaq 0x6d0(%rsp), %rsi
leaq 0x4c8(%rsp), %rdx
leaq 0x78(%rsp), %rcx
movq %r14, %rdi
callq 0x24b2
leaq 0x78(%rsp), %rdi
callq 0x22b8
pushq $0x18
popq %rdi
callq 0x2180
movq %rax, %r15
leaq 0x58(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x21f0
leaq 0x2c0(%rsp), %rsi
leaq 0xb8(%rsp), %rdx
leaq 0x58(%rsp), %rcx
movq %r15, %rdi
callq 0x24b2
leaq 0x58(%rsp), %rdi
callq 0x22b8
testl %r12d, %r12d
jne 0x351c
movq %r15, %rdi
callq 0x293e
movl %eax, %r12d
movzbl 0xc(%rsp), %r8d
andl $0x1, %r8d
movq %r14, %rdi
movq %r15, %rsi
movl %ebx, %edx
movl %r12d, %ecx
callq 0x2d48
movl %eax, %ebp
movq 0x3a89(%rip), %rdi      # 0x6fc8
leaq 0x38(%rsp), %rsi
callq 0x2160
leaq 0xca5(%rip), %rsi       # 0x41f5
movq %rax, %rdi
callq 0x2170
movq %rax, %rdi
movl %ebx, %esi
callq 0x2250
leaq 0xc8c(%rip), %rsi       # 0x41f5
movq %rax, %rdi
callq 0x2170
movq %rax, %rdi
movl %r12d, %esi
callq 0x2250
leaq 0xc72(%rip), %rsi       # 0x41f5
movq %rax, %rdi
callq 0x2170
movl %ebp, %esi
movq %rax, %rdi
callq 0x2100
leaq 0xc59(%rip), %rsi       # 0x41f5
movq %rax, %rdi
callq 0x2170
movl %r12d, %ebx
subl %ebp, %ebx
movq %rax, %rdi
movq %rbx, %rsi
callq 0x2100
leaq 0xc3a(%rip), %rsi       # 0x41f5
movq %rax, %rdi
callq 0x2170
movl %ebx, %ecx
cvtsi2ss %rcx, %xmm0
cvtss2sd %xmm0, %xmm0
mulsd 0xb32(%rip), %xmm0      # 0x4108
cvtsi2sd %r12d, %xmm1
divsd %xmm1, %xmm0
movq %rax, %rdi
callq 0x2220
movq %rax, %rdi
callq 0x20d0
movq %r15, %rdi
callq 0x2930
pushq $0x18
popq %rbx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x2190
movq %r14, %rdi
callq 0x2930
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2190
leaq 0x6d0(%rsp), %rdi
callq 0x2040
leaq 0x4c8(%rsp), %rdi
callq 0x2040
leaq 0x2c0(%rsp), %rdi
callq 0x2040
leaq 0xb8(%rsp), %rdi
callq 0x2040
leaq 0xb8(%rsp), %rdi
callq 0x2060
leaq 0x2c0(%rsp), %rdi
callq 0x2060
leaq 0x4c8(%rsp), %rdi
callq 0x2060
leaq 0x6d0(%rsp), %rdi
callq 0x2060
leaq 0x38(%rsp), %rdi
callq 0x22b8
leaq 0x18(%rsp), %rdi
callq 0x22b8
xorl %eax, %eax
addq $0x8d8, %rsp            # imm = 0x8D8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x3941(%rip), %rdi      # 0x6ff0
leaq 0xb39(%rip), %rsi       # 0x41ef
callq 0x2170
movq (%r14), %rsi
movq %rax, %rdi
callq 0x2170
leaq 0xb28(%rip), %rsi       # 0x41f5
movq %rax, %rdi
callq 0x2170
leaq 0x3aac(%rip), %rsi      # 0x7188
movq %rax, %rdi
callq 0x2160
movq %rax, %rdi
callq 0x20d0
movq 0x38fd(%rip), %rdi      # 0x6ff0
leaq 0xafd(%rip), %rsi       # 0x41f7
callq 0x2170
movsbl %bpl, %esi
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x20d0
pushq $-0x1
jmp 0x387a
movq 0x38cf(%rip), %rdi      # 0x6ff0
leaq 0xac7(%rip), %rsi       # 0x41ef
callq 0x2170
movq (%r14), %rsi
movq %rax, %rdi
callq 0x2170
leaq 0xab6(%rip), %rsi       # 0x41f5
movq %rax, %rdi
callq 0x2170
leaq 0x3a3a(%rip), %rsi      # 0x7188
movq %rax, %rdi
callq 0x2160
movq %rax, %rdi
callq 0x20d0
movq 0x388b(%rip), %rdi      # 0x6ff0
leaq 0xaa3(%rip), %rsi       # 0x420f
callq 0x2170
movq %rax, %rdi
callq 0x20d0
jmp 0x3713
movq %rdx, %r12
movq %rax, %rbx
leaq 0x58(%rsp), %rdi
callq 0x22b8
jmp 0x3793
movq %rdx, %r12
movq %rax, %rbx
pushq $0x18
popq %rsi
movq %r15, %rdi
jmp 0x37b9
movq %rdx, %r12
movq %rax, %rbx
leaq 0x78(%rsp), %rdi
callq 0x22b8
jmp 0x37b3
movq %rdx, %r12
movq %rax, %rbx
pushq $0x18
popq %rsi
movq %r14, %rdi
callq 0x2190
jmp 0x384a
movq %rax, %rbx
leaq 0x98(%rsp), %rdi
callq 0x22b8
jmp 0x38a2
movq %rax, %rbx
jmp 0x38a2
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x22b8
jmp 0x38af
movq %rax, %rbx
jmp 0x38af
movq %rax, %rbx
leaq 0x2c0(%rsp), %rdi
callq 0x22b8
jmp 0x38bc
movq %rax, %rbx
jmp 0x38bc
movq %rax, %rbx
leaq 0x4c8(%rsp), %rdi
callq 0x22b8
jmp 0x38d0
jmp 0x38cd
movq %rax, %rbx
jmp 0x38da
movq %rax, %rbx
jmp 0x38e4
movq %rdx, %r12
movq %rax, %rbx
cmpl $0x1, %r12d
jne 0x3895
movq %rbx, %rdi
callq 0x20b0
movq (%rax), %rcx
movq %rax, %rdi
callq *0x10(%rcx)
movq 0x3788(%rip), %rdi      # 0x6ff0
movq %rax, %rsi
callq 0x2170
movq %rax, %rdi
callq 0x20d0
pushq $-0x2
popq %rdi
callq 0x21c0
movq %rax, %rbx
callq 0x2230
jmp 0x3895
movq %rax, %rdi
callq 0x2f03
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x2060
leaq 0x2c0(%rsp), %rdi
callq 0x2060
leaq 0x4c8(%rsp), %rdi
callq 0x2060
leaq 0x6d0(%rsp), %rdi
callq 0x2060
jmp 0x38d0
jmp 0x38cd
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x22b8
leaq 0x18(%rsp), %rdi
callq 0x22b8
movq %rbx, %rdi
callq 0x2260