// File: jc-kim[P]swaptions/HJM.cpp
// Function: HJM_Drifts(double*, double*, int, int, double, double*)
int HJM_Drifts(FTYPE *pdTotalDrift,	//Output vector that stores the total drift correction for each maturity
    FTYPE *ppdDrifts,		//Output matrix that stores drift correction for each factor for each maturity
    int iN, 
    int iFactors,
    FTYPE dYears,
    FTYPE *ppdFactors)		//Input factor volatilities
{
  //This function computes drift corrections required for each factor for each maturity based on given factor volatilities

  int i, j, l;
  FTYPE ddelt = (FTYPE)(dYears/iN);
  FTYPE dSumVol;

  //computation of factor drifts for shortest maturity
  for (i = 0; i < iFactors; i++)
    ppdDrifts[i * (iN - 1)] = 0.5 * ddelt * (ppdFactors[i * (iN - 1)]) * (ppdFactors[i * (iN - 1)]);

  //computation of factor drifts for other maturities
  for (i = 0; i < iFactors;i++)
    for (j = 1; j < iN - 1; j++)
    {
      ppdDrifts[i * (iN - 1) + j] = 0;
      for(l = 0; l < j; l++) ppdDrifts[i * (iN - 1) + j] -= ppdDrifts[i * (iN - 1) + l];

      dSumVol=0;
      for(l = 0; l <= j; l++) dSumVol += ppdFactors[i * (iN - 1) + l];

      ppdDrifts[i * (iN - 1) + j] += 0.5 * ddelt * dSumVol * dSumVol;
    }

  //computation of total drifts for all maturities
  for(i = 0; i < iN - 1; i++)
  {
    pdTotalDrift[i]=0;
    for(j = 0; j < iFactors; j++) pdTotalDrift[i] += ppdDrifts[j * (iN - 1) + i];
  }

  return 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movl %ecx, -0x18(%rbp)
movsd %xmm0, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movsd -0x20(%rbp), %xmm0
cvtsi2sdl -0x14(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x40(%rbp)
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x18(%rbp), %eax
jge 0x31ad
movsd 0x1ebb(%rip), %xmm0     # 0x5010
mulsd -0x40(%rbp), %xmm0
movq -0x28(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl -0x14(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
movslq %ecx, %rcx
mulsd (%rax,%rcx,8), %xmm0
movq -0x28(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl -0x14(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
movslq %ecx, %rcx
mulsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl -0x14(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x3145
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x18(%rbp), %eax
jge 0x32f3
movl $0x1, -0x30(%rbp)
movl -0x30(%rbp), %eax
movl -0x14(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x32e3
movq -0x10(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl -0x14(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
addl -0x30(%rbp), %ecx
movslq %ecx, %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0x324f
movq -0x10(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl -0x14(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
addl -0x34(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm1
movq -0x10(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl -0x14(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
addl -0x30(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x31fd
xorps %xmm0, %xmm0
movsd %xmm0, -0x48(%rbp)
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x30(%rbp), %eax
jg 0x3296
movq -0x28(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl -0x14(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
addl -0x34(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
addsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x325e
movsd 0x1d72(%rip), %xmm0     # 0x5010
mulsd -0x40(%rbp), %xmm0
mulsd -0x48(%rbp), %xmm0
movsd -0x48(%rbp), %xmm2
movq -0x10(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl -0x14(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
addl -0x30(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x31c7
jmp 0x32e5
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x31b4
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movl -0x14(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x336b
movq -0x8(%rbp), %rax
movslq -0x2c(%rbp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl $0x0, -0x30(%rbp)
movl -0x30(%rbp), %eax
cmpl -0x18(%rbp), %eax
jge 0x335e
movq -0x10(%rbp), %rax
movl -0x30(%rbp), %ecx
movl -0x14(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
addl -0x2c(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x8(%rbp), %rax
movslq -0x2c(%rbp), %rcx
addsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x331e
jmp 0x3360
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x32fa
movl $0x1, %eax
popq %rbp
retq
nopw %cs:(%rax,%rax)