// File: /workspace/github_cpp_makefile_star2_O2/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)
movl %ecx, 0x4c(%rsp)
movl %edx, %ebp
movq %rsi, %rbx
movq %rdi, %r15
addq $0xf8, %rsi
leaq 0x70(%rsp), %rdi
callq 0x4b0c
leaq 0xc8(%rbx), %rsi
leaq 0xd0(%rsp), %rdi
callq 0x5790
leaq 0x208(%r15), %rsi
movq (%rbx), %xmm0
movdqa %xmm0, 0x10(%rsp)
leaq 0x100(%rsp), %r14
movl $0x1388, %edx           # imm = 0x1388
movq %r14, %rdi
movq %rsi, 0x88(%rsp)
callq 0x21c0
movb $0x0, 0x1398(%r14)
movq %rbx, 0x50(%rsp)
movq 0x110(%rbx), %rax
movq %rax, 0x139c(%r14)
pcmpeqd %xmm0, %xmm0
paddd 0x10(%rsp), %xmm0
pxor %xmm1, %xmm1
punpckldq %xmm0, %xmm1    # xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
movdqu %xmm1, 0x13a4(%r14)
leaq 0x8(%r15), %rax
movq %rax, 0x40(%rsp)
leaq 0x190(%r15), %rax
movq %rax, 0x38(%rsp)
leaq 0x1a8(%r15), %rax
movq %rax, 0x30(%rsp)
leaq 0x1c0(%r15), %rax
movq %rax, 0x28(%rsp)
leaq 0x1d8(%r15), %rax
movq %rax, 0x20(%rsp)
leaq 0x30(%r15), %rax
movq %rax, (%rsp)
leaq 0x48(%r15), %r14
xorl %eax, %eax
testl %ebp, %ebp
cmovlel %eax, %ebp
movq %r15, %r12
leaq 0x60(%r15), %rbx
incl %ebp
pushq $0x1
popq %rax
pxor %xmm0, %xmm0
movq %xmm0, 0x68(%rsp)
leaq 0xa0(%rsp), %r15
movl %eax, %r13d
movl %ebp, 0x48(%rsp)
cmpl %ebp, %r13d
je 0x3429
movq 0x70(%rsp), %rdi
movq 0x78(%rsp), %rsi
movq 0x88(%rsp), %rdx
callq 0x4b69
movq %r12, %rbp
movq 0x6f10(%rip), %rdi      # 0x9ff0
leaq 0x2ffe(%rip), %rsi      # 0x60e5
callq 0x2200
movq %rax, %rdi
movl %r13d, %esi
callq 0x2340
movq %rax, %rdi
leaq 0x2feb(%rip), %rsi      # 0x60ec
callq 0x2200
movq %rax, %rdi
callq 0x2100
movq %r13, 0x60(%rsp)
movq 0x70(%rsp), %r13
movq 0x78(%rsp), %rax
movq %rax, 0x90(%rsp)
pxor %xmm0, %xmm0
movq %xmm0, 0x10(%rsp)
pushq $0x1
popq %rax
movl %eax, 0xc(%rsp)
cmpq 0x90(%rsp), %r13
je 0x338a
movl 0xc(%rsp), %esi
movl %esi, %eax
xorl %edx, %edx
movl $0x3e8, %ecx            # imm = 0x3E8
divl %ecx
testl %edx, %edx
jne 0x31a9
movq 0x6e92(%rip), %rdi      # 0x9ff0
callq 0x2340
movq %rax, %rdi
leaq 0x2fa4(%rip), %rsi      # 0x6111
callq 0x2200
movsd 0x2e9e(%rip), %xmm2     # 0x6018
movsd 0x68(%rsp), %xmm3
addsd %xmm2, %xmm3
movsd 0x8(%rbp), %xmm0
movsd 0x18(%rbp), %xmm1
mulsd %xmm0, %xmm1
movsd %xmm3, 0x68(%rsp)
mulsd %xmm3, %xmm1
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rbp)
incl 0xc(%rsp)
xorl %ebp, %ebp
cmpl 0x4c(%rsp), %ebp
jg 0x32fa
testl %ebp, %ebp
je 0x32a0
movq %r15, %rdi
leaq 0x100(%rsp), %rsi
movq %r13, %rdx
leaq 0xd0(%rsp), %rcx
callq 0x50a6
movq %r12, %rdi
movq %r15, %rsi
movsd 0x2e36(%rip), %xmm0     # 0x6020
callq 0x4d4a
movsd %xmm0, 0x98(%rsp)
subq $0x8, %rsp
movq 0x48(%rsp), %rdi
movq %r15, %rsi
movq 0x40(%rsp), %rdx
movq 0x38(%rsp), %rcx
movq 0x30(%rsp), %r8
movq 0x28(%rsp), %r9
pushq %rbx
pushq %r14
pushq 0x18(%rsp)
callq 0x4ed6
addq $0x20, %rsp
leaq 0xbc(%rsp), %rdi
leaq 0x100(%rsp), %rsi
movq %r13, %rdx
leaq 0xd0(%rsp), %rcx
callq 0x5156
movb 0xcc(%rsp), %al
movb %al, 0xb0(%rsp)
movups 0xbc(%rsp), %xmm0
movaps %xmm0, 0xa0(%rsp)
movq %r12, %rdi
movq %r15, %rsi
movsd 0x2dac(%rip), %xmm0     # 0x6020
callq 0x4d4a
movsd 0x10(%rsp), %xmm1
addsd 0x98(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rsp)
subq $0x8, %rsp
movq 0x48(%rsp), %rdi
movq %r15, %rsi
jmp 0x32cf
movq %r12, %rdi
movq %r13, %rsi
movsd 0x2d6a(%rip), %xmm0     # 0x6018
callq 0x4d4a
movsd 0x10(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rsp)
subq $0x8, %rsp
movq 0x48(%rsp), %rdi
movq %r13, %rsi
movq 0x40(%rsp), %rdx
movq 0x38(%rsp), %rcx
movq 0x30(%rsp), %r8
movq 0x28(%rsp), %r9
pushq %rbx
pushq %r14
pushq 0x18(%rsp)
callq 0x4ed6
addq $0x20, %rsp
incl %ebp
jmp 0x31af
movq %r12, %rbp
xorpd %xmm0, %xmm0
ucomisd 0x10(%r12), %xmm0
jb 0x3381
movq 0x6cdf(%rip), %rdi      # 0x9ff0
callq 0x2100
movq 0x6cd3(%rip), %rdi      # 0x9ff0
leaq 0x2dca(%rip), %rsi      # 0x60ee
callq 0x2200
movq %rax, %rdi
callq 0x2100
movq 0x6cb8(%rip), %rdi      # 0x9ff0
leaq 0x2dc7(%rip), %rsi      # 0x6106
callq 0x2200
movq %rax, %rdi
movq 0x10(%rsp), %xmm0
callq 0x2300
movq %rax, %rdi
callq 0x2100
subq $0x8, %rsp
movq 0x60(%rsp), %rdi
movq 0x8(%rsp), %rsi
movq %r14, %rdx
movq %rbx, %rcx
movq %rbp, %r8
movq 0x58(%rsp), %r9
pushq 0x68(%rsp)
callq 0x521a
popq %rax
popq %rcx
addq $0x14, %r13
jmp 0x3136
movq 0x6c5f(%rip), %rdi      # 0x9ff0
callq 0x2100
movq 0x60(%rsp), %r13
movq 0x6c4e(%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)
leaq 0x2d37(%rip), %rsi      # 0x6106
callq 0x2200
movq %rax, %rdi
movq 0x10(%rsp), %xmm0
callq 0x2300
movq %rax, %rdi
callq 0x2100
movl %r13d, %eax
xorl %edx, %edx
pushq $0xa
popq %rcx
divl %ecx
testl %edx, %edx
jne 0x341d
subq $0x8, %rsp
movq 0x60(%rsp), %rdi
movq 0x8(%rsp), %rsi
movq %r14, %rdx
movq %rbx, %rcx
movq %rbp, %r8
movq 0x58(%rsp), %r9
pushq %r13
callq 0x521a
popq %rax
popq %rcx
incl %r13d
movl 0x48(%rsp), %ebp
jmp 0x30b6
leaq 0xd0(%rsp), %rdi
callq 0x3622
leaq 0x70(%rsp), %rdi
callq 0x35e6
addq $0x14b8, %rsp           # imm = 0x14B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
jmp 0x346f
jmp 0x345f
jmp 0x345f
jmp 0x345f
jmp 0x345f
movq %rax, %rbx
leaq 0xd0(%rsp), %rdi
callq 0x3622
leaq 0x70(%rsp), %rdi
callq 0x35e6
movq %rbx, %rdi
callq 0x2350
nop