// File: ghulette[P]neural-net-openmp/main.cpp
// Function: main
int main(int argc, char * const argv[]) {
	using namespace std;
	
	srand((unsigned)time(0));
	cout.precision(2);
	cout.setf(ios::fixed | ios::showpoint);
	
	DataSet *train = new DataSet(IDX_DIR + TRAINING_IMAGES, IDX_DIR + TRAINING_LABELS, OUTPUT_ENC);
	DataSet *test = new DataSet(IDX_DIR + TESTING_IMAGES, IDX_DIR + TESTING_LABELS, OUTPUT_ENC);
	NeuralNet *nn = new NeuralNet(train->image_vector_length(), NUM_HIDDEN_NODES, train->label_vector_length());
	
	int train_len = train->length();
	cout << "Training on " << train_len << " examples" << endl;
	ticks train_start = getticks();
	for(int i=0; i < train_len; i++) {
		nn->train(train->image_vector(i), train->label_vector(i), ETA);
	}
	ticks train_end = getticks();
	
	int test_len = test->length();
	cout << "Testing on " << test_len << " examples" << endl;
	ticks test_start = getticks();
	int correct = 0;
	for(int i=0; i < test_len; i++) {
		int guess = test->label_for_vector(nn->run(test->image_vector(i)));
		int answer = test->label(i);
		if(guess == answer) {
			correct ++;
		}
	}
	ticks test_end = getticks();
	
	cout << "Correct: " << correct << "/" << test_len << " (" << 100 * double(correct)/test_len << "%)" << endl;
	cout << "Training: " << elapsed(train_end, train_start) << endl;
	cout << "Testing: " << elapsed(test_end, test_start) << endl;
	
	delete nn;
	delete train;
	delete test;

    return 0;
}

// Assembly:
subq $0x198, %rsp            # imm = 0x198
movl $0x0, 0x194(%rsp)
movl %edi, 0x190(%rsp)
movq %rsi, 0x188(%rsp)
xorl %eax, %eax
movl %eax, %edi
callq 0x2130
movl %eax, %edi
callq 0x2140
movq 0x4518(%rip), %rdi      # 0x7fd0
movq %rdi, 0x70(%rsp)
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
movl $0x2, %esi
callq 0x42e0
movq 0x70(%rsp), %rax
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
addq %rcx, %rax
movq %rax, 0x78(%rsp)
movl $0x4, %edi
movl $0x400, %esi            # imm = 0x400
callq 0x4340
movq 0x78(%rsp), %rdi
movl %eax, %esi
callq 0x4310
movl $0x28, %edi
callq 0x2160
movq %rax, 0x80(%rsp)
movb $0x1, 0x12f(%rsp)
leaq 0x4687(%rip), %rsi      # 0x81a8
leaq 0x46a0(%rip), %rdx      # 0x81c8
leaq 0x160(%rsp), %rdi
callq 0x4360
jmp 0x3b37
leaq 0x466a(%rip), %rsi      # 0x81a8
leaq 0x46a3(%rip), %rdx      # 0x81e8
leaq 0x130(%rsp), %rdi
callq 0x4360
jmp 0x3b54
movq 0x80(%rsp), %rdi
leaq 0x160(%rsp), %rsi
leaq 0x130(%rsp), %rdx
movl $0x2, %ecx
callq 0x2d90
jmp 0x3b78
movb $0x0, 0x12f(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x2308
leaq 0x160(%rsp), %rdi
callq 0x2308
movq 0x80(%rsp), %rax
movq %rax, 0x180(%rsp)
movl $0x28, %edi
callq 0x2160
movq %rax, 0x68(%rsp)
movb $0x1, 0xdf(%rsp)
leaq 0x45e0(%rip), %rsi      # 0x81a8
leaq 0x4639(%rip), %rdx      # 0x8208
leaq 0x100(%rsp), %rdi
callq 0x4360
jmp 0x3bde
leaq 0x45c3(%rip), %rsi      # 0x81a8
leaq 0x463c(%rip), %rdx      # 0x8228
leaq 0xe0(%rsp), %rdi
callq 0x4360
jmp 0x3bfb
movq 0x68(%rsp), %rdi
leaq 0x100(%rsp), %rsi
leaq 0xe0(%rsp), %rdx
movl $0x2, %ecx
callq 0x2d90
jmp 0x3c1c
movb $0x0, 0xdf(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x2308
leaq 0x100(%rsp), %rdi
callq 0x2308
movq 0x68(%rsp), %rax
movq %rax, 0x120(%rsp)
movl $0x50, %edi
callq 0x2160
movq %rax, 0x58(%rsp)
movq 0x180(%rsp), %rdi
callq 0x3410
movl %eax, 0x64(%rsp)
jmp 0x3c6d
movq 0x180(%rsp), %rdi
callq 0x3420
movl %eax, 0x54(%rsp)
jmp 0x3c80
movl 0x54(%rsp), %ecx
movl 0x64(%rsp), %esi
movq 0x58(%rsp), %rdi
movl $0x12c, %edx            # imm = 0x12C
callq 0x46c0
jmp 0x3c99
movq 0x58(%rsp), %rax
movq %rax, 0xd0(%rsp)
movq 0x180(%rsp), %rdi
callq 0x3400
movl %eax, 0xcc(%rsp)
movq 0x430f(%rip), %rdi      # 0x7fd0
leaq 0x24fb(%rip), %rsi      # 0x61c3
callq 0x2150
movq %rax, %rdi
movl 0xcc(%rsp), %esi
callq 0x2260
movq %rax, %rdi
leaq 0x24ea(%rip), %rsi      # 0x61d0
callq 0x2150
movq %rax, %rdi
movq 0x42c3(%rip), %rsi      # 0x7fb8
callq 0x2180
callq 0x41c0
movq %rax, 0xc0(%rsp)
movl $0x0, 0xbc(%rsp)
movl 0xbc(%rsp), %eax
cmpl 0xcc(%rsp), %eax
jge 0x3eac
movq 0xd0(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x180(%rsp), %rdi
movl 0xbc(%rsp), %esi
callq 0x3430
movq %rax, 0x48(%rsp)
movq 0x180(%rsp), %rdi
movl 0xbc(%rsp), %esi
callq 0x3450
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
movq %rax, %rdx
movsd 0x23bb(%rip), %xmm0     # 0x6130
callq 0x4c60
movl 0xbc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xbc(%rsp)
jmp 0x3d12
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x158(%rsp)
movl %eax, 0x154(%rsp)
jmp 0x3de7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x158(%rsp)
movl %eax, 0x154(%rsp)
jmp 0x3dda
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x158(%rsp)
movl %eax, 0x154(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x2308
leaq 0x160(%rsp), %rdi
callq 0x2308
testb $0x1, 0x12f(%rsp)
jne 0x3df3
jmp 0x3e05
movq 0x80(%rsp), %rdi
movl $0x28, %esi
callq 0x2170
jmp 0x41a5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x158(%rsp)
movl %eax, 0x154(%rsp)
jmp 0x3e64
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x158(%rsp)
movl %eax, 0x154(%rsp)
jmp 0x3e57
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x158(%rsp)
movl %eax, 0x154(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x2308
leaq 0x100(%rsp), %rdi
callq 0x2308
testb $0x1, 0xdf(%rsp)
jne 0x3e70
jmp 0x3e7f
movq 0x68(%rsp), %rdi
movl $0x28, %esi
callq 0x2170
jmp 0x41a5
movq 0x58(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x158(%rsp)
movl %eax, 0x154(%rsp)
movl $0x50, %esi
callq 0x2170
jmp 0x41a5
callq 0x41c0
movq %rax, 0xb0(%rsp)
movq 0x120(%rsp), %rdi
callq 0x3400
movl %eax, 0xac(%rsp)
movq 0x40fc(%rip), %rdi      # 0x7fd0
leaq 0x22ff(%rip), %rsi      # 0x61da
callq 0x2150
movq %rax, %rdi
movl 0xac(%rsp), %esi
callq 0x2260
movq %rax, %rdi
leaq 0x22d7(%rip), %rsi      # 0x61d0
callq 0x2150
movq %rax, %rdi
movq 0x40b0(%rip), %rsi      # 0x7fb8
callq 0x2180
callq 0x41c0
movq %rax, 0xa0(%rsp)
movl $0x0, 0x9c(%rsp)
movl $0x0, 0x98(%rsp)
movl 0x98(%rsp), %eax
cmpl 0xac(%rsp), %eax
jge 0x3fe7
movq 0x120(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0xd0(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x120(%rsp), %rdi
movl 0x98(%rsp), %esi
callq 0x3430
movq 0x30(%rsp), %rdi
movq %rax, %rsi
callq 0x4ac0
movq 0x38(%rsp), %rdi
movq %rax, %rsi
callq 0x3490
movl %eax, 0x94(%rsp)
movq 0x120(%rsp), %rdi
movl 0x98(%rsp), %esi
callq 0x3470
movl %eax, 0x90(%rsp)
movl 0x94(%rsp), %eax
cmpl 0x90(%rsp), %eax
jne 0x3fcf
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x3fd1
movl 0x98(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x98(%rsp)
jmp 0x3f30
callq 0x41c0
movq %rax, 0x88(%rsp)
movq 0x3fd5(%rip), %rdi      # 0x7fd0
leaq 0x21e4(%rip), %rsi      # 0x61e6
callq 0x2150
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x2260
movq %rax, %rdi
leaq 0x2143(%rip), %rsi      # 0x6163
callq 0x2150
movq %rax, %rdi
movl 0xac(%rsp), %esi
callq 0x2260
movq %rax, %rdi
leaq 0x21b2(%rip), %rsi      # 0x61f0
callq 0x2150
movq %rax, %rdi
cvtsi2sdl 0x9c(%rsp), %xmm1
movsd 0x20d1(%rip), %xmm0     # 0x6128
mulsd %xmm1, %xmm0
cvtsi2sdl 0xac(%rsp), %xmm1
divsd %xmm1, %xmm0
callq 0x22d0
movq %rax, %rdi
leaq 0x217c(%rip), %rsi      # 0x61f3
callq 0x2150
movq %rax, %rdi
movq 0x3f32(%rip), %rsi      # 0x7fb8
callq 0x2180
movq 0x3f3e(%rip), %rdi      # 0x7fd0
leaq 0x215d(%rip), %rsi      # 0x61f6
callq 0x2150
movq %rax, 0x18(%rsp)
movq 0xb0(%rsp), %rdi
movq 0xc0(%rsp), %rsi
callq 0x41e0
movq 0x18(%rsp), %rdi
callq 0x22d0
movq %rax, %rdi
movq 0x3eec(%rip), %rsi      # 0x7fb8
callq 0x2180
movq 0x3ef8(%rip), %rdi      # 0x7fd0
leaq 0x2122(%rip), %rsi      # 0x6201
callq 0x2150
movq %rax, 0x20(%rsp)
movq 0x88(%rsp), %rdi
movq 0xa0(%rsp), %rsi
callq 0x41e0
movq 0x20(%rsp), %rdi
callq 0x22d0
movq %rax, %rdi
movq 0x3ea6(%rip), %rsi      # 0x7fb8
callq 0x2180
movq 0xd0(%rsp), %rax
movq %rax, 0x28(%rsp)
cmpq $0x0, %rax
je 0x4143
movq 0x28(%rsp), %rdi
callq 0x49b0
movq 0x28(%rsp), %rdi
movl $0x50, %esi
callq 0x2170
movq 0x180(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x416f
movq 0x10(%rsp), %rdi
callq 0x3310
movq 0x10(%rsp), %rdi
movl $0x28, %esi
callq 0x2170
movq 0x120(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x419b
movq 0x8(%rsp), %rdi
callq 0x3310
movq 0x8(%rsp), %rdi
movl $0x28, %esi
callq 0x2170
xorl %eax, %eax
addq $0x198, %rsp            # imm = 0x198
retq
movq 0x158(%rsp), %rdi
callq 0x2270
nopw %cs:(%rax,%rax)