// File: wenleix[P]EdgePPR/src/ParamPPR.cpp
// Function: main
int main(int argc, char** argv) {
	if (argc != 7) {
		fprintf(stderr, "Usage: %s [ParamGraph.txt] [NumUseVtx] [ParameterFile] "
				"[OutputPrefix] [OutFormat: bin/txt] [NumThread]\n",
			    argv[0]);
		return 1;
	}

	FILE *gfile = fopen(argv[1], "r");
	int numUseVtx = atoi(argv[2]);	//	# Useful Vertices
	FILE *paramFile = fopen(argv[3], "r");
	char* outputPrefix = argv[4];
	char *outFormat = argv[5];
	int numThread = atoi(argv[6]);

	assert(strcmp(outFormat, "bin") == 0 || strcmp(outFormat, "txt") == 0);
	ParamGraph *g = ParamGraph::ReadTextFile(gfile);

	int paramId = 0;
	double *pref = new double[g->numVertex];
	memset(pref, 0, sizeof(double) * g->numVertex);
	for (int i = 0; i < numUseVtx; i++)
		pref[i] = 1.0 - DAMP_FACTOR;

	vector<double> params;
	//	Read all the parameters
	while (true) {
		double p;
		if (fscanf(paramFile, "%lf", &p) == EOF)
			break;
		params.push_back(p);
	}

	assert(params.size() % ParamGraph_NumEdgeTypes == 0);
	int numParam = params.size() / ParamGraph_NumEdgeTypes;
	fprintf(stdout, "INFO: # Params = %lu. \n", params.size() / ParamGraph_NumEdgeTypes);
	int *paramIdx = new int[numParam];		//	Random shuffle the parameter indices assigned to each thread, to get better workload balance.
	for (int i = 0; i < numParam; i++)
		paramIdx[i] = i;
	random_shuffle(paramIdx, paramIdx + numParam);

	ThreadConfig *conf = new ThreadConfig[numThread];
	pthread_t *threads = new pthread_t[numThread];
	for (int i = 0; i < numThread; i++) {
		conf[i].threadId = i;
		conf[i].params = &params[0];
		conf[i].start = i * numParam / numThread;
		conf[i].end = (i + 1) * numParam / numThread;
		conf[i].numUseVtx = numUseVtx;
		conf[i].outputPrefix = outputPrefix;
		conf[i].pref = pref;
		conf[i].g = g;
		conf[i].paramIdx = paramIdx;
		conf[i].outputFormat = outFormat;

		//	Start thread
		int rc = pthread_create(&threads[i], NULL /* attr */, WorkerThread, (void*)&conf[i]);
		assert(rc == 0);
	}

	for (int i = 0; i < numThread; i++)
		pthread_join(threads[i], NULL /* retval */);



	delete g;
	delete [] conf;
	delete [] threads;
	delete [] paramIdx;
	fclose(gfile);
	fclose(paramFile);

	//	Finish
	pthread_exit(NULL);

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x7, -0x8(%rbp)
je 0x26bc
movq 0x994a(%rip), %rax      # 0xbfe0
movq (%rax), %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rdx
leaq 0x59e0(%rip), %rsi      # 0x8087
movb $0x0, %al
callq 0x2280
movl $0x1, %eax
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
leaq 0x5a24(%rip), %rsi      # 0x80ef
callq 0x2220
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x22b0
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
leaq 0x59fc(%rip), %rsi      # 0x80ef
callq 0x2220
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x22b0
movl %eax, -0x3c(%rbp)
movq -0x38(%rbp), %rdi
leaq 0x59c2(%rip), %rsi      # 0x80f1
callq 0x2270
movl %eax, %ecx
movb $0x1, %al
cmpl $0x0, %ecx
movb %al, -0xbd(%rbp)
je 0x275f
movq -0x38(%rbp), %rdi
leaq 0x59a7(%rip), %rsi      # 0x80f5
callq 0x2270
cmpl $0x0, %eax
sete %al
movb %al, -0xbd(%rbp)
movb -0xbd(%rbp), %al
testb $0x1, %al
jne 0x276b
jmp 0x276d
jmp 0x278c
leaq 0x5985(%rip), %rdi      # 0x80f9
leaq 0x59bd(%rip), %rsi      # 0x8138
movl $0x48, %edx
leaq 0x59c2(%rip), %rcx      # 0x8149
callq 0x20f0
movq -0x18(%rbp), %rdi
callq 0x3a10
movq %rax, -0x48(%rbp)
movl $0x0, -0x4c(%rbp)
movq -0x48(%rbp), %rax
movslq (%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rdi
movq -0x48(%rbp), %rax
movslq (%rax), %rdx
shlq $0x3, %rdx
xorl %esi, %esi
callq 0x20d0
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x2811
movq -0x58(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movsd 0x580f(%rip), %xmm0     # 0x8010
movsd %xmm0, (%rax,%rcx,8)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x27e9
leaq -0x78(%rbp), %rdi
callq 0x2d40
jmp 0x281c
movq -0x28(%rbp), %rdi
leaq 0x5939(%rip), %rsi      # 0x8160
xorl %eax, %eax
leaq -0x80(%rbp), %rdx
callq 0x2350
movl %eax, -0xc4(%rbp)
jmp 0x283a
movl -0xc4(%rbp), %eax
cmpl $-0x1, %eax
jne 0x2867
jmp 0x2878
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x2eb0
jmp 0x2d2a
leaq -0x78(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x2d60
jmp 0x2876
jmp 0x281a
leaq -0x78(%rbp), %rdi
callq 0x2dd0
movl $0x7, %ecx
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
jne 0x2893
jmp 0x28b2
leaq 0x58ca(%rip), %rdi      # 0x8164
leaq 0x5897(%rip), %rsi      # 0x8138
movl $0x5a, %edx
leaq 0x589c(%rip), %rcx      # 0x8149
callq 0x20f0
leaq -0x78(%rbp), %rdi
movq %rdi, -0xf8(%rbp)
callq 0x2dd0
movq -0xf8(%rbp), %rdi
movq %rax, -0xf0(%rbp)
movabsq $0x2492492492492493, %rcx # imm = 0x2492492492492493
movq %rcx, -0xe8(%rbp)
mulq %rcx
movq -0xf0(%rbp), %rax
subq %rdx, %rax
shrq %rax
addq %rdx, %rax
shrq $0x2, %rax
movl %eax, -0x90(%rbp)
movq 0x96c3(%rip), %rax      # 0xbfc8
movq (%rax), %rax
movq %rax, -0xe0(%rbp)
callq 0x2dd0
movq -0xe8(%rbp), %rcx
movq -0xe0(%rbp), %rdi
movq %rax, -0xd8(%rbp)
mulq %rcx
movq %rdx, %rax
movq -0xd8(%rbp), %rdx
subq %rax, %rdx
shrq %rdx
addq %rax, %rdx
shrq $0x2, %rdx
leaq 0x5847(%rip), %rsi      # 0x8191
xorl %eax, %eax
callq 0x2280
movslq -0x90(%rbp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x2030
movq %rax, -0xd0(%rbp)
jmp 0x297c
movq -0xd0(%rbp), %rax
movq %rax, -0x98(%rbp)
movl $0x0, -0x9c(%rbp)
movl -0x9c(%rbp), %eax
cmpl -0x90(%rbp), %eax
jge 0x29ca
movl -0x9c(%rbp), %edx
movq -0x98(%rbp), %rax
movslq -0x9c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x9c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9c(%rbp)
jmp 0x2994
movq -0x98(%rbp), %rdi
movslq -0x90(%rbp), %rax
leaq (%rdi,%rax,4), %rsi
callq 0x2df0
jmp 0x29e3
movslq -0x3c(%rbp), %rax
movl $0x48, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x2030
movq %rax, -0x100(%rbp)
jmp 0x2a0b
movq -0x100(%rbp), %rax
movq %rax, -0xa8(%rbp)
movslq -0x3c(%rbp), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x2030
movq %rax, -0x108(%rbp)
jmp 0x2a41
movq -0x108(%rbp), %rax
movq %rax, -0xb0(%rbp)
movl $0x0, -0xb4(%rbp)
movl -0xb4(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jge 0x2c36
movl -0xb4(%rbp), %ecx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movl %ecx, (%rax)
leaq -0x78(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2e90
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movl -0xb4(%rbp), %eax
imull -0x90(%rbp), %eax
cltd
idivl -0x3c(%rbp)
movl %eax, %ecx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x10(%rax)
movl -0xb4(%rbp), %eax
addl $0x1, %eax
imull -0x90(%rbp), %eax
cltd
idivl -0x3c(%rbp)
movl %eax, %ecx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x14(%rax)
movl -0x1c(%rbp), %ecx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x18(%rax)
movq -0x30(%rbp), %rcx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x20(%rax)
movq -0x58(%rbp), %rcx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x28(%rax)
movq -0x48(%rbp), %rcx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x40(%rax)
movq -0x98(%rbp), %rcx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x30(%rax)
movq -0x38(%rbp), %rcx
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rdx
imulq $0x48, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x38(%rax)
movq -0xb0(%rbp), %rdi
movslq -0xb4(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0xa8(%rbp), %rcx
movslq -0xb4(%rbp), %rax
imulq $0x48, %rax, %rax
addq %rax, %rcx
xorl %eax, %eax
movl %eax, %esi
leaq -0x75b(%rip), %rdx      # 0x2490
callq 0x2340
movl %eax, -0xb8(%rbp)
cmpl $0x0, -0xb8(%rbp)
jne 0x2c01
jmp 0x2c20
leaq 0x55a1(%rip), %rdi      # 0x81a9
leaq 0x5529(%rip), %rsi      # 0x8138
movl $0x72, %edx
leaq 0x552e(%rip), %rcx      # 0x8149
callq 0x20f0
jmp 0x2c22
movl -0xb4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb4(%rbp)
jmp 0x2a59
movl $0x0, -0xbc(%rbp)
movl -0xbc(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jge 0x2c7b
movq -0xb0(%rbp), %rax
movslq -0xbc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2170
jmp 0x2c68
jmp 0x2c6a
movl -0xbc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xbc(%rbp)
jmp 0x2c40
movq -0x48(%rbp), %rax
movq %rax, -0x110(%rbp)
cmpq $0x0, %rax
je 0x2ca9
movq -0x110(%rbp), %rdi
callq 0x42b0
movq -0x110(%rbp), %rdi
movl $0x18, %esi
callq 0x21a0
movq -0xa8(%rbp), %rax
movq %rax, -0x118(%rbp)
cmpq $0x0, %rax
je 0x2cc9
movq -0x118(%rbp), %rdi
callq 0x2250
movq -0xb0(%rbp), %rax
movq %rax, -0x120(%rbp)
cmpq $0x0, %rax
je 0x2ce9
movq -0x120(%rbp), %rdi
callq 0x2250
movq -0x98(%rbp), %rax
movq %rax, -0x128(%rbp)
cmpq $0x0, %rax
je 0x2d09
movq -0x128(%rbp), %rdi
callq 0x2250
movq -0x18(%rbp), %rdi
callq 0x2180
jmp 0x2d14
movq -0x28(%rbp), %rdi
callq 0x2180
jmp 0x2d1f
xorl %eax, %eax
movl %eax, %edi
callq 0x2310
jmp 0x2d2a
movq -0x88(%rbp), %rdi
callq 0x2300
nopw %cs:(%rax,%rax)