// File: szmer[P]brill/./src/rules_applier.cpp
// Function: RulesApplier::transform(Corpus*)
Corpus RulesApplier::transform(Corpus * corp) {

	Corpus next_corp = * corp;

	// Tag with loaded initial (unigram) tagger. 
	next_corp = next_corp.tag_with_table(& tag_lookup);
	baseline_score = Corpus::compare_corpora( gold_corp, & next_corp);

	// Apply each rule on the list consecutively.
	for(unsigned int i = 0; i < rules.size(); i++) {

		// Figure out what rule this is.
		int rule_type = -1;
		string cue1, cue2, alter_tag, target;

		if(rules[i] >= EXT_RULE_RANGE) {
			long long rule_ind = rules[i]; // temporary variable that will be stripped

			rule_type = rule_ind / EXT_RULE_RANGE; // nice that int will strip the remainder
			rule_ind -= rule_type * EXT_RULE_RANGE;

			int tag_id = rule_ind / pow(tag_index.size(), 3);
			cue1 = tag_index[ tag_id ];
			rule_ind -= tag_id * pow(tag_index.size(), 3);

			tag_id = rule_ind / pow(tag_index.size(), 2);
			cue2 = tag_index[ tag_id ];
			rule_ind -= tag_id * pow(tag_index.size(), 2);

			tag_id = rule_ind / tag_index.size();
			alter_tag = tag_index[ tag_id ];
			rule_ind -= tag_id * tag_index.size();

			target = tag_index[ rule_ind ];
		}

		else {
			long long rule_ind = rules[i]; // temporary variable that will be stripped

			rule_type = rule_ind / RULE_RANGE;
			rule_ind -= rule_type * RULE_RANGE;

			int tag_id = rule_ind / pow(tag_index.size(), 2);
			cue1 = tag_index[ tag_id ];
			rule_ind -= tag_id * pow(tag_index.size(), 2);

			tag_id = rule_ind / tag_index.size();
			alter_tag = tag_index[ tag_id ];
			rule_ind -= tag_id * tag_index.size();

			target = tag_index[ rule_ind ];
		}

		// Create this rule and apply it.
		Rule rl;
		rl.cue1 = cue1;
		rl.cue2 = cue2;
		rl.alter_tag = alter_tag;
		rl.target = target;
		rl.id = rules[i];

		next_corp = rl.transform_corp(& next_corp);
	}

	final_score = Corpus::compare_corpora( gold_corp, & next_corp);

	return next_corp;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2b0, %rsp            # imm = 0x2B0
movq %rdi, -0x1f8(%rbp)
movq %rdi, %rax
movq %rax, -0x208(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x200(%rbp)
movb $0x0, -0x19(%rbp)
movq -0x18(%rbp), %rsi
callq 0x9440
movq -0x200(%rbp), %rdx
movq -0x1f8(%rbp), %rsi
addq $0x30, %rdx
leaq -0x68(%rbp), %rdi
callq 0x48d0
jmp 0x741d
movq -0x1f8(%rbp), %rdi
leaq -0x68(%rbp), %rsi
movq %rsi, -0x218(%rbp)
callq 0x94a0
movq -0x218(%rbp), %rdi
callq 0x8300
movq -0x200(%rbp), %rax
movq -0x1f8(%rbp), %rsi
movq 0x60(%rax), %rdi
callq 0x35f0
movsd %xmm0, -0x210(%rbp)
jmp 0x7461
movq -0x200(%rbp), %rax
movsd -0x210(%rbp), %xmm0
movsd %xmm0, 0x68(%rax)
movl $0x0, -0x78(%rbp)
movq -0x200(%rbp), %rdi
movl -0x78(%rbp), %eax
movq %rax, -0x220(%rbp)
addq $0x18, %rdi
callq 0x94e0
movq %rax, %rcx
movq -0x220(%rbp), %rax
cmpq %rcx, %rax
jae 0x7b35
movl $0xffffffff, -0x7c(%rbp) # imm = 0xFFFFFFFF
leaq -0xa0(%rbp), %rdi
callq 0x3320
leaq -0xc0(%rbp), %rdi
callq 0x3320
leaq -0xe0(%rbp), %rdi
callq 0x3320
leaq -0x100(%rbp), %rdi
callq 0x3320
movq -0x200(%rbp), %rdi
addq $0x18, %rdi
movl -0x78(%rbp), %eax
movl %eax, %esi
callq 0x9500
movabsq $0xe6f93c791, %rcx      # imm = 0xE6F93C791
cmpq %rcx, (%rax)
jl 0x77f7
movq -0x200(%rbp), %rdi
addq $0x18, %rdi
movl -0x78(%rbp), %eax
movl %eax, %esi
callq 0x9500
movq -0x200(%rbp), %rdi
movq (%rax), %rax
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rcx
movabsq $-0x72218692302eefe9, %rdx # imm = 0x8DDE796DCFD11017
movq %rcx, %rax
imulq %rdx
movq %rdx, %rax
addq %rcx, %rax
movq %rax, %rcx
shrq $0x3f, %rcx
sarq $0x23, %rax
addl %ecx, %eax
movl %eax, -0x7c(%rbp)
movslq -0x7c(%rbp), %rcx
movabsq $0xe6f93c791, %rax      # imm = 0xE6F93C791
imulq %rax, %rcx
movq -0x108(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x108(%rbp)
cvtsi2sdq -0x108(%rbp), %xmm0
movsd %xmm0, -0x230(%rbp)
callq 0x9570
movq %rax, %rdi
movl $0x3, %esi
callq 0x9520
movsd %xmm0, -0x228(%rbp)
jmp 0x75ab
movq -0x200(%rbp), %rdi
movsd -0x228(%rbp), %xmm1
movsd -0x230(%rbp), %xmm0
divsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x10c(%rbp)
movslq -0x10c(%rbp), %rsi
callq 0x9590
movq %rax, %rsi
leaq -0xa0(%rbp), %rdi
callq 0x3040
jmp 0x75ed
movq -0x200(%rbp), %rdi
cvtsi2sdl -0x10c(%rbp), %xmm0
movsd %xmm0, -0x240(%rbp)
callq 0x9570
movq %rax, %rdi
movl $0x3, %esi
callq 0x9520
movsd %xmm0, -0x238(%rbp)
jmp 0x7620
movq -0x200(%rbp), %rdi
movsd -0x238(%rbp), %xmm2
movsd -0x240(%rbp), %xmm1
cvtsi2sdq -0x108(%rbp), %xmm0
mulsd %xmm2, %xmm1
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x108(%rbp)
cvtsi2sdq -0x108(%rbp), %xmm0
movsd %xmm0, -0x250(%rbp)
callq 0x9570
movq %rax, %rdi
movl $0x2, %esi
callq 0x9520
movsd %xmm0, -0x248(%rbp)
jmp 0x7681
movq -0x200(%rbp), %rdi
movsd -0x248(%rbp), %xmm1
movsd -0x250(%rbp), %xmm0
divsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x10c(%rbp)
movslq -0x10c(%rbp), %rsi
callq 0x9590
movq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0x3040
jmp 0x76c3
movq -0x200(%rbp), %rdi
cvtsi2sdl -0x10c(%rbp), %xmm0
movsd %xmm0, -0x260(%rbp)
callq 0x9570
movq %rax, %rdi
movl $0x2, %esi
callq 0x9520
movsd %xmm0, -0x258(%rbp)
jmp 0x76f6
movq -0x200(%rbp), %rdi
movsd -0x258(%rbp), %xmm2
movsd -0x260(%rbp), %xmm1
cvtsi2sdq -0x108(%rbp), %xmm0
mulsd %xmm2, %xmm1
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rax
movq %rax, -0x268(%rbp)
callq 0x9570
movq -0x200(%rbp), %rdi
movq %rax, %rcx
movq -0x268(%rbp), %rax
xorl %edx, %edx
divq %rcx
movl %eax, -0x10c(%rbp)
movslq -0x10c(%rbp), %rsi
callq 0x9590
movq %rax, %rsi
leaq -0xe0(%rbp), %rdi
callq 0x3040
jmp 0x7776
movq -0x200(%rbp), %rdi
movslq -0x10c(%rbp), %rax
movq %rax, -0x270(%rbp)
callq 0x9570
movq -0x270(%rbp), %rcx
movq -0x200(%rbp), %rdi
imulq %rax, %rcx
movq -0x108(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rsi
callq 0x9590
movq %rax, %rsi
leaq -0x100(%rbp), %rdi
callq 0x3040
jmp 0x77d0
jmp 0x79e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x7b90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x7b03
movq -0x200(%rbp), %rdi
addq $0x18, %rdi
movl -0x78(%rbp), %eax
movl %eax, %esi
callq 0x9500
movq -0x200(%rbp), %rdi
movq (%rax), %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rax
movabsq $0x452229ac43052097, %rcx # imm = 0x452229AC43052097
imulq %rcx
movq %rdx, %rax
shrq $0x3f, %rax
movl %eax, %ecx
shrq $0x19, %rdx
movl %edx, %eax
addl %ecx, %eax
movl %eax, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
imull $0x767ed6b, %eax, %eax  # imm = 0x767ED6B
movslq %eax, %rcx
movq -0x118(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x118(%rbp)
cvtsi2sdq -0x118(%rbp), %xmm0
movsd %xmm0, -0x280(%rbp)
callq 0x9570
movq %rax, %rdi
movl $0x2, %esi
callq 0x9520
movsd %xmm0, -0x278(%rbp)
jmp 0x788f
movq -0x200(%rbp), %rdi
movsd -0x278(%rbp), %xmm1
movsd -0x280(%rbp), %xmm0
divsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x11c(%rbp)
movslq -0x11c(%rbp), %rsi
callq 0x9590
movq %rax, %rsi
leaq -0xa0(%rbp), %rdi
callq 0x3040
jmp 0x78d1
movq -0x200(%rbp), %rdi
cvtsi2sdl -0x11c(%rbp), %xmm0
movsd %xmm0, -0x290(%rbp)
callq 0x9570
movq %rax, %rdi
movl $0x2, %esi
callq 0x9520
movsd %xmm0, -0x288(%rbp)
jmp 0x7904
movq -0x200(%rbp), %rdi
movsd -0x288(%rbp), %xmm2
movsd -0x290(%rbp), %xmm1
cvtsi2sdq -0x118(%rbp), %xmm0
mulsd %xmm2, %xmm1
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rax
movq %rax, -0x298(%rbp)
callq 0x9570
movq -0x200(%rbp), %rdi
movq %rax, %rcx
movq -0x298(%rbp), %rax
xorl %edx, %edx
divq %rcx
movl %eax, -0x11c(%rbp)
movslq -0x11c(%rbp), %rsi
callq 0x9590
movq %rax, %rsi
leaq -0xe0(%rbp), %rdi
callq 0x3040
jmp 0x7984
movq -0x200(%rbp), %rdi
movslq -0x11c(%rbp), %rax
movq %rax, -0x2a0(%rbp)
callq 0x9570
movq -0x2a0(%rbp), %rcx
movq -0x200(%rbp), %rdi
imulq %rax, %rcx
movq -0x118(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rsi
callq 0x9590
movq %rax, %rsi
leaq -0x100(%rbp), %rdi
callq 0x3040
jmp 0x79de
jmp 0x79e0
leaq -0x1a8(%rbp), %rdi
movq %rdi, -0x2a8(%rbp)
callq 0x95b0
movq -0x2a8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x3040
jmp 0x7a08
leaq -0x188(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x3040
jmp 0x7a1d
leaq -0x168(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x3040
jmp 0x7a32
leaq -0x148(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0x3040
jmp 0x7a47
movq -0x200(%rbp), %rdi
addq $0x18, %rdi
movl -0x78(%rbp), %eax
movl %eax, %esi
callq 0x9500
movq -0x1f8(%rbp), %rdx
movq (%rax), %rax
movq %rax, -0x128(%rbp)
leaq -0x1f0(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x5590
jmp 0x7a82
movq -0x1f8(%rbp), %rdi
leaq -0x1f0(%rbp), %rsi
callq 0x94a0
leaq -0x1f0(%rbp), %rdi
callq 0x8300
leaq -0x1a8(%rbp), %rdi
callq 0x9600
leaq -0x100(%rbp), %rdi
callq 0x34b8
leaq -0xe0(%rbp), %rdi
callq 0x34b8
leaq -0xc0(%rbp), %rdi
callq 0x34b8
leaq -0xa0(%rbp), %rdi
callq 0x34b8
movl -0x78(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x78(%rbp)
jmp 0x747c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x1a8(%rbp), %rdi
callq 0x9600
leaq -0x100(%rbp), %rdi
callq 0x34b8
leaq -0xe0(%rbp), %rdi
callq 0x34b8
leaq -0xc0(%rbp), %rdi
callq 0x34b8
leaq -0xa0(%rbp), %rdi
callq 0x34b8
jmp 0x7b90
movq -0x1f8(%rbp), %rsi
movq -0x200(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x35f0
movsd %xmm0, -0x2b0(%rbp)
jmp 0x7b56
movq -0x200(%rbp), %rax
movsd -0x2b0(%rbp), %xmm0
movsd %xmm0, 0x70(%rax)
movb $0x1, -0x19(%rbp)
testb $0x1, -0x19(%rbp)
jne 0x7b80
movq -0x1f8(%rbp), %rdi
callq 0x8300
movq -0x208(%rbp), %rax
addq $0x2b0, %rsp            # imm = 0x2B0
popq %rbp
retq
movq -0x1f8(%rbp), %rdi
callq 0x8300
movq -0x70(%rbp), %rdi
callq 0x3400
nopw %cs:(%rax,%rax)