// File: /workspace/github_cpp_makefile_star2_O1/KokiKishimoto[P]cp_decomposition/cp.cpp
// Function: CP::train(Data&, int, int, ModelFileWriter&)
void train(Data& data, int maxEpoch, int negativeSize, ModelFileWriter& mfw) {
		int sampleC = 1;
		double all = 0.0;
		double loss = 0.0;
		std::vector<Triple> train_triples = data.triples;
		std::set<long long> triple_key_set = data.triple_key_set;
		RandomSampler sampler(data.key_gen, data.entity_counter, data.relation_counter, rnd);

		for (int iter = 1; iter <= maxEpoch; ++iter) {
			std::shuffle(train_triples.begin(), train_triples.end(), rnd);
			std::cerr << "Epoch " << iter << ":" << std::endl;
			for (Triple& triple : train_triples) {
				if ((sampleC % 1000) == 0) {
					std::cerr << sampleC << " ";
					++all;
					updater.decay(all);
				}
				++sampleC;
				for (int i = 0; i <= negativeSize; i++) {
					if (i == 0) {
						loss += computeGradients(triple, 1.0);
						updater.SGD(triple, outVec1, outVec2, outVec3, norms, subjVec, objVec, relationVec);
					} else {
						Triple neg_triple = sampler.negativeSamplingSbj(triple, triple_key_set);
						loss += computeGradients(neg_triple, -1.0);
						updater.SGD(neg_triple, outVec1, outVec2, outVec3, norms, subjVec, objVec, relationVec);

						neg_triple = sampler.negativeSamplingObj(triple, triple_key_set);
						loss += computeGradients(neg_triple, -1.0);
						updater.SGD(neg_triple, outVec1, outVec2, outVec3, norms, subjVec, objVec, relationVec);
					}
				}
				if (updater.learningRate <= 0.0) {
					std::cerr << std::endl;
					std::cerr << "Learning rate was zero " << std::endl;
					std::cerr << "Total loss: " << loss << std::endl;
					mfw.save(subjVec, objVec, relationVec, op, data, iter);
				}
			}
			std::cerr << std::endl;
			std::cerr << std::fixed << std::setprecision(15) << "Total loss: " << loss << std::endl;

			loss = 0.0;
			sampleC = 1;

			if (iter % 10 == 0) {
				mfw.save(subjVec, objVec, relationVec, op, data, iter);
			}
		}
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x14b8, %rsp           # imm = 0x14B8
movq %r8, 0x58(%rsp)
movq %rcx, 0x68(%rsp)
movl %edx, %ebp
movq %rsi, %r12
movq %rdi, %rbx
addq $0xf8, %rsi
leaq 0x70(%rsp), %rdi
callq 0x4efe
leaq 0xc8(%r12), %rsi
leaq 0xd0(%rsp), %rdi
callq 0x63d8
movl (%r12), %r14d
movl 0x4(%r12), %r15d
movq %rbx, (%rsp)
leaq 0x208(%rbx), %rsi
leaq 0x100(%rsp), %rbx
movl $0x1388, %edx           # imm = 0x1388
movq %rbx, %rdi
movq %rsi, 0x88(%rsp)
callq 0x21e0
movb $0x0, 0x1398(%rbx)
movq %r12, 0x50(%rsp)
movq 0x110(%r12), %rax
movq %rax, 0x139c(%rbx)
decl %r14d
shlq $0x20, %r14
movq %r14, 0x13a4(%rbx)
decl %r15d
shlq $0x20, %r15
movq %r15, 0x13ac(%rbx)
movl %ebp, 0x44(%rsp)
testl %ebp, %ebp
jle 0x3a4d
movq (%rsp), %rax
leaq 0x8(%rax), %rcx
movq %rcx, 0x38(%rsp)
leaq 0x190(%rax), %rcx
movq %rcx, 0x30(%rsp)
leaq 0x1a8(%rax), %rcx
movq %rcx, 0x28(%rsp)
leaq 0x1c0(%rax), %rcx
movq %rcx, 0x20(%rsp)
leaq 0x1d8(%rax), %rcx
movq %rcx, 0x18(%rsp)
leaq 0x30(%rax), %rbp
leaq 0x48(%rax), %r13
leaq 0x60(%rax), %rbx
movq 0x68(%rsp), %rax
incl %eax
movl %eax, 0x4c(%rsp)
movl $0x1, %eax
movq %rax, 0x10(%rsp)
xorpd %xmm0, %xmm0
movsd %xmm0, 0x60(%rsp)
leaq 0xa0(%rsp), %r12
movq 0x70(%rsp), %rdi
movq 0x78(%rsp), %rsi
movq 0x88(%rsp), %rdx
callq 0x4f8b
movl $0x6, %edx
movq 0x6a14(%rip), %rdi      # 0x9ff0
leaq 0x3b12(%rip), %rsi      # 0x70f5
callq 0x22a0
movq 0x6a01(%rip), %rdi      # 0x9ff0
movq 0x10(%rsp), %rsi
callq 0x23a0
movq %rax, %r15
movl $0x1, %edx
movq %rax, %rdi
leaq 0x3af1(%rip), %rsi      # 0x70fc
callq 0x22a0
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2230
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2170
movq 0x70(%rsp), %r15
movq 0x78(%rsp), %rax
movq %rax, 0x90(%rsp)
xorpd %xmm0, %xmm0
cmpq %rax, %r15
je 0x394a
movsd %xmm0, 0x8(%rsp)
movl $0x1, %esi
imull $0x26e978d5, %esi, %eax # imm = 0x26E978D5
rorl $0x3, %eax
cmpl $0x418937, %eax         # imm = 0x418937
movl %esi, 0x48(%rsp)
ja 0x36d0
movq 0x6974(%rip), %rdi      # 0x9ff0
callq 0x23a0
movl $0x1, %edx
movq %rax, %rdi
leaq 0x3a91(%rip), %rsi      # 0x7121
callq 0x22a0
movsd 0x397b(%rip), %xmm2     # 0x7018
movsd 0x60(%rsp), %xmm3
addsd %xmm2, %xmm3
movq (%rsp), %rax
movsd 0x8(%rax), %xmm0
movsd 0x18(%rax), %xmm1
mulsd %xmm0, %xmm1
movsd %xmm3, 0x60(%rsp)
mulsd %xmm3, %xmm1
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rax)
cmpl $0x0, 0x68(%rsp)
js 0x3824
xorl %r14d, %r14d
testl %r14d, %r14d
je 0x37c5
movq %r12, %rdi
leaq 0x100(%rsp), %rsi
movq %r15, %rdx
leaq 0xd0(%rsp), %rcx
callq 0x568a
movq (%rsp), %rdi
movq %r12, %rsi
movsd 0x390f(%rip), %xmm0     # 0x7020
callq 0x51d2
movsd %xmm0, 0x98(%rsp)
subq $0x8, %rsp
movq 0x40(%rsp), %rdi
movq %r12, %rsi
movq 0x38(%rsp), %rdx
movq 0x30(%rsp), %rcx
movq 0x28(%rsp), %r8
movq 0x20(%rsp), %r9
pushq %rbx
pushq %r13
pushq %rbp
callq 0x547c
addq $0x20, %rsp
leaq 0xbc(%rsp), %rdi
leaq 0x100(%rsp), %rsi
movq %r15, %rdx
leaq 0xd0(%rsp), %rcx
callq 0x5778
movb 0xcc(%rsp), %al
movb %al, 0xb0(%rsp)
movups 0xbc(%rsp), %xmm0
movaps %xmm0, 0xa0(%rsp)
movq (%rsp), %rdi
movq %r12, %rsi
movsd 0x3887(%rip), %xmm0     # 0x7020
callq 0x51d2
movsd 0x8(%rsp), %xmm1
addsd 0x98(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
subq $0x8, %rsp
movq 0x40(%rsp), %rdi
movq %r12, %rsi
jmp 0x37f5
movq (%rsp), %rdi
movq %r15, %rsi
movsd 0x3844(%rip), %xmm0     # 0x7018
callq 0x51d2
movsd 0x8(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
subq $0x8, %rsp
movq 0x40(%rsp), %rdi
movq %r15, %rsi
movq 0x38(%rsp), %rdx
movq 0x30(%rsp), %rcx
movq 0x28(%rsp), %r8
movq 0x20(%rsp), %r9
pushq %rbx
pushq %r13
pushq %rbp
callq 0x547c
addq $0x20, %rsp
incl %r14d
cmpl %r14d, 0x4c(%rsp)
jne 0x36de
movq (%rsp), %rax
xorpd %xmm0, %xmm0
ucomisd 0x10(%rax), %xmm0
jb 0x3930
movq 0x67b2(%rip), %rcx      # 0x9ff0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2230
movsbl %al, %esi
movq 0x6794(%rip), %rdi      # 0x9ff0
callq 0x2030
movq %rax, %rdi
callq 0x2170
movl $0x17, %edx
movq 0x677b(%rip), %rdi      # 0x9ff0
leaq 0x3882(%rip), %rsi      # 0x70fe
callq 0x22a0
movq 0x6768(%rip), %rcx      # 0x9ff0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2230
movsbl %al, %esi
movq 0x674a(%rip), %rdi      # 0x9ff0
callq 0x2030
movq %rax, %rdi
callq 0x2170
movl $0xc, %edx
movq 0x6731(%rip), %rdi      # 0x9ff0
leaq 0x3850(%rip), %rsi      # 0x7116
callq 0x22a0
movq 0x671e(%rip), %rdi      # 0x9ff0
movsd 0x8(%rsp), %xmm0
callq 0x2360
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2230
movsbl %al, %esi
movq %r14, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2170
subq $0x8, %rsp
movq 0x60(%rsp), %rdi
movq %rbp, %rsi
movq %r13, %rdx
movq %rbx, %rcx
movq 0x8(%rsp), %r8
movq 0x58(%rsp), %r9
pushq 0x18(%rsp)
callq 0x5864
addq $0x10, %rsp
movl 0x48(%rsp), %esi
incl %esi
addq $0x14, %r15
cmpq 0x90(%rsp), %r15
jne 0x3661
jmp 0x3950
movsd %xmm0, 0x8(%rsp)
movq 0x6699(%rip), %rcx      # 0x9ff0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2230
movsbl %al, %esi
movq 0x667b(%rip), %rdi      # 0x9ff0
callq 0x2030
movq %rax, %rdi
callq 0x2170
movq 0x6667(%rip), %rdi      # 0x9ff0
movq (%rdi), %rax
movq -0x18(%rax), %rcx
movl 0x18(%rdi,%rcx), %edx
movl $0xfffffefb, %esi       # imm = 0xFFFFFEFB
andl %esi, %edx
orl $0x4, %edx
movl %edx, 0x18(%rdi,%rcx)
movq -0x18(%rax), %rax
movq $0xf, 0x8(%rdi,%rax)
movl $0xc, %edx
leaq 0x375b(%rip), %rsi      # 0x7116
callq 0x22a0
movq 0x6629(%rip), %rdi      # 0x9ff0
movsd 0x8(%rsp), %xmm0
callq 0x2360
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2230
movsbl %al, %esi
movq %r14, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2170
imull $0xcccccccd, 0x10(%rsp), %eax # imm = 0xCCCCCCCD
rorl %eax
cmpl $0x19999999, %eax       # imm = 0x19999999
ja 0x3a36
subq $0x8, %rsp
movq 0x60(%rsp), %rdi
movq %rbp, %rsi
movq %r13, %rdx
movq %rbx, %rcx
movq 0x8(%rsp), %r8
movq 0x58(%rsp), %r9
pushq 0x18(%rsp)
callq 0x5864
addq $0x10, %rsp
movq 0x10(%rsp), %rcx
leal 0x1(%rcx), %eax
cmpl 0x44(%rsp), %ecx
movq %rax, 0x10(%rsp)
jne 0x35b9
leaq 0xd0(%rsp), %rdi
callq 0x3c0e
movq 0x70(%rsp), %rdi
testq %rdi, %rdi
je 0x3a74
movq 0x80(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
addq $0x14b8, %rsp           # imm = 0x14B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
jmp 0x3aa3
jmp 0x3a93
jmp 0x3a93
jmp 0x3a93
jmp 0x3a93
movq %rax, %rbx
leaq 0xd0(%rsp), %rdi
callq 0x3c0e
movq 0x70(%rsp), %rdi
testq %rdi, %rdi
je 0x3abd
movq 0x80(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
movq %rbx, %rdi
callq 0x23b0
nop