// File: /workspace/github_cpp_makefile_star2_O3/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 $0x14c8, %rsp           # imm = 0x14C8
movq %r8, 0x68(%rsp)
movq %rcx, 0x78(%rsp)
movl %edx, %ebp
movq %rsi, %r14
movq %rdi, %rbx
addq $0xf8, %rsi
leaq 0x80(%rsp), %rdi
callq 0x4f48
leaq 0xc8(%r14), %rsi
leaq 0xe0(%rsp), %rdi
callq 0x640a
movq %rbx, (%rsp)
leaq 0x208(%rbx), %rsi
movq (%r14), %xmm0
movdqa %xmm0, 0x10(%rsp)
leaq 0x110(%rsp), %rbx
movl $0x1388, %edx           # imm = 0x1388
movq %rbx, %rdi
movq %rsi, 0x98(%rsp)
callq 0x21e0
movb $0x0, 0x1398(%rbx)
movq %r14, 0x60(%rsp)
movq 0x110(%r14), %rax
movq %rax, 0x139c(%rbx)
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(%rbx)
movl %ebp, 0x54(%rsp)
testl %ebp, %ebp
jle 0x3a5a
movq (%rsp), %rcx
leaq 0x8(%rcx), %rax
movq %rax, 0x48(%rsp)
leaq 0x190(%rcx), %rax
movq %rax, 0x40(%rsp)
leaq 0x1a8(%rcx), %rax
movq %rax, 0x38(%rsp)
leaq 0x1c0(%rcx), %rax
movq %rax, 0x30(%rsp)
leaq 0x1d8(%rcx), %rax
movq %rax, 0x28(%rsp)
leaq 0x30(%rcx), %rbp
leaq 0x48(%rcx), %r13
leaq 0x60(%rcx), %rbx
movq 0x78(%rsp), %rax
incl %eax
movl %eax, 0x5c(%rsp)
movl $0x1, %eax
movq %rax, 0x8(%rsp)
pxor %xmm0, %xmm0
movq %xmm0, 0x70(%rsp)
movq 0x80(%rsp), %rdi
movq 0x88(%rsp), %rsi
movq 0x98(%rsp), %rdx
callq 0x4fd5
movl $0x6, %edx
movq 0x6a15(%rip), %rdi      # 0x9ff0
leaq 0x3b43(%rip), %rsi      # 0x7125
callq 0x22a0
movq 0x6a02(%rip), %rdi      # 0x9ff0
movq 0x8(%rsp), %rsi
callq 0x23a0
movq %rax, %r14
movl $0x1, %edx
movq %rax, %rdi
leaq 0x3b22(%rip), %rsi      # 0x712c
callq 0x22a0
movq (%r14), %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
movq 0x80(%rsp), %r14
movq 0x88(%rsp), %rax
movq %rax, 0xa0(%rsp)
pxor %xmm0, %xmm0
cmpq %rax, %r14
je 0x3957
movq %xmm0, 0x10(%rsp)
movl $0x1, %esi
imull $0x26e978d5, %esi, %eax # imm = 0x26E978D5
rorl $0x3, %eax
cmpl $0x418937, %eax         # imm = 0x418937
movl %esi, 0x58(%rsp)
ja 0x36d5
movq 0x696f(%rip), %rdi      # 0x9ff0
callq 0x23a0
movl $0x1, %edx
movq %rax, %rdi
leaq 0x3abc(%rip), %rsi      # 0x7151
callq 0x22a0
movsd 0x3976(%rip), %xmm2     # 0x7018
movsd 0x70(%rsp), %xmm3
addsd %xmm2, %xmm3
movq (%rsp), %rax
movsd 0x8(%rax), %xmm0
movsd 0x18(%rax), %xmm1
mulsd %xmm0, %xmm1
movsd %xmm3, 0x70(%rsp)
mulsd %xmm3, %xmm1
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rax)
cmpl $0x0, 0x78(%rsp)
js 0x3831
xorl %r15d, %r15d
testl %r15d, %r15d
je 0x37d2
leaq 0xb0(%rsp), %r12
movq %r12, %rdi
leaq 0x110(%rsp), %rsi
movq %r14, %rdx
leaq 0xe0(%rsp), %rcx
callq 0x56d0
movq (%rsp), %rdi
movq %r12, %rsi
movsd 0x3902(%rip), %xmm0     # 0x7020
callq 0x521c
movsd %xmm0, 0xa8(%rsp)
subq $0x8, %rsp
movq 0x50(%rsp), %rdi
movq %r12, %rsi
movq 0x48(%rsp), %rdx
movq 0x40(%rsp), %rcx
movq 0x38(%rsp), %r8
movq 0x30(%rsp), %r9
pushq %rbx
pushq %r13
pushq %rbp
callq 0x54c2
addq $0x20, %rsp
leaq 0xcc(%rsp), %rdi
leaq 0x110(%rsp), %rsi
movq %r14, %rdx
leaq 0xe0(%rsp), %rcx
callq 0x57b0
movb 0xdc(%rsp), %al
movb %al, 0xc0(%rsp)
movups 0xcc(%rsp), %xmm0
movaps %xmm0, 0xb0(%rsp)
movq (%rsp), %rdi
movq %r12, %rsi
movsd 0x387a(%rip), %xmm0     # 0x7020
callq 0x521c
movsd 0x10(%rsp), %xmm1
addsd 0xa8(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rsp)
subq $0x8, %rsp
movq 0x50(%rsp), %rdi
movq %r12, %rsi
jmp 0x3802
movq (%rsp), %rdi
movq %r14, %rsi
movsd 0x3837(%rip), %xmm0     # 0x7018
callq 0x521c
movsd 0x10(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rsp)
subq $0x8, %rsp
movq 0x50(%rsp), %rdi
movq %r14, %rsi
movq 0x48(%rsp), %rdx
movq 0x40(%rsp), %rcx
movq 0x38(%rsp), %r8
movq 0x30(%rsp), %r9
pushq %rbx
pushq %r13
pushq %rbp
callq 0x54c2
addq $0x20, %rsp
incl %r15d
cmpl %r15d, 0x5c(%rsp)
jne 0x36e3
xorpd %xmm0, %xmm0
movq (%rsp), %rax
ucomisd 0x10(%rax), %xmm0
jb 0x393d
movq 0x67a5(%rip), %rcx      # 0x9ff0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2230
movsbl %al, %esi
movq 0x6787(%rip), %rdi      # 0x9ff0
callq 0x2030
movq %rax, %rdi
callq 0x2170
movl $0x17, %edx
movq 0x676e(%rip), %rdi      # 0x9ff0
leaq 0x38a5(%rip), %rsi      # 0x712e
callq 0x22a0
movq 0x675b(%rip), %rcx      # 0x9ff0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2230
movsbl %al, %esi
movq 0x673d(%rip), %rdi      # 0x9ff0
callq 0x2030
movq %rax, %rdi
callq 0x2170
movl $0xc, %edx
movq 0x6724(%rip), %rdi      # 0x9ff0
leaq 0x3873(%rip), %rsi      # 0x7146
callq 0x22a0
movq 0x6711(%rip), %rdi      # 0x9ff0
movq 0x10(%rsp), %xmm0
callq 0x2360
movq %rax, %r15
movq (%rax), %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
subq $0x8, %rsp
movq 0x70(%rsp), %rdi
movq %rbp, %rsi
movq %r13, %rdx
movq %rbx, %rcx
movq 0x8(%rsp), %r8
movq 0x68(%rsp), %r9
pushq 0x10(%rsp)
callq 0x588e
addq $0x10, %rsp
movl 0x58(%rsp), %esi
incl %esi
addq $0x14, %r14
cmpq 0xa0(%rsp), %r14
jne 0x3666
jmp 0x395d
movq %xmm0, 0x10(%rsp)
movq 0x668c(%rip), %rcx      # 0x9ff0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2230
movsbl %al, %esi
movq 0x666e(%rip), %rdi      # 0x9ff0
callq 0x2030
movq %rax, %rdi
callq 0x2170
movq 0x665a(%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 0x377e(%rip), %rsi      # 0x7146
callq 0x22a0
movq 0x661c(%rip), %rdi      # 0x9ff0
movq 0x10(%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, 0x8(%rsp), %eax # imm = 0xCCCCCCCD
rorl %eax
cmpl $0x19999999, %eax       # imm = 0x19999999
ja 0x3a43
subq $0x8, %rsp
movq 0x70(%rsp), %rdi
movq %rbp, %rsi
movq %r13, %rdx
movq %rbx, %rcx
movq 0x8(%rsp), %r8
movq 0x68(%rsp), %r9
pushq 0x10(%rsp)
callq 0x588e
addq $0x10, %rsp
movq 0x8(%rsp), %rcx
leal 0x1(%rcx), %eax
cmpl 0x54(%rsp), %ecx
movq %rax, 0x8(%rsp)
jne 0x35b2
leaq 0xe0(%rsp), %rdi
callq 0x3c20
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x3a84
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
addq $0x14c8, %rsp           # imm = 0x14C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
jmp 0x3ab3
jmp 0x3aa3
jmp 0x3aa3
jmp 0x3aa3
jmp 0x3aa3
movq %rax, %rbx
leaq 0xe0(%rsp), %rdi
callq 0x3c20
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x3ad0
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
movq %rbx, %rdi
callq 0x23b0