// File: /workspace/github_c_makefile_star2_O2/PoulinV[P]AxiCLASS/build/../source/transfer.c
// Function: transfer_integrate
int transfer_integrate(
                       struct perturbations * ppt,
                       struct transfer * ptr,
                       struct transfer_workspace *ptw,
                       int index_q,
                       int index_md,
                       int index_tt,
                       double l,
                       int index_l,
                       double k,
                       radial_function_type radial_type,
                       double * trsf
                       ) {

  /** Summary: */

  /** - define local variables */

  double * tau0_minus_tau = ptw->tau0_minus_tau;
  double * w_trapz = ptw->w_trapz;
  double * sources = ptw->sources;

  /* minimum value of \f$ (\tau0-\tau) \f$ at which \f$ j_l(k[\tau_0-\tau]) \f$ is known, given that \f$ j_l(x) \f$ is sampled above some finite value \f$ x_{\min} \f$ (below which it can be approximated by zero) */
  double tau0_minus_tau_min_bessel;

  /* index in the source's tau list corresponding to the last point in the overlapping region between sources and bessels. Also the index of possible Bessel truncation. */
  int index_tau_max, index_tau_max_Bessel;

  double bessel, *radial_function;

  double x_turning_point;

  /** - find minimum value of (tau0-tau) at which \f$ j_l(k[\tau_0-\tau]) \f$ is known, given that \f$ j_l(x) \f$ is sampled above some finite value \f$ x_{\min} \f$ (below which it can be approximated by zero) */
  //tau0_minus_tau_min_bessel = x_min_l/k; /* segmentation fault impossible, checked before that k != 0 */
  //printf("index_l=%d\n",index_l);
  if (ptw->sgnK==0){
    tau0_minus_tau_min_bessel = ptw->pBIS->chi_at_phimin[index_l]/k; /* segmentation fault impossible, checked before that k != 0 */
  }
  else{

    if (index_q < ptr->index_q_flat_approximation) {

      tau0_minus_tau_min_bessel = ptw->HIS.chi_at_phimin[index_l]/sqrt(ptw->sgnK*ptw->K);

    }
    else {

      tau0_minus_tau_min_bessel = ptw->pBIS->chi_at_phimin[index_l]/sqrt(ptw->sgnK*ptw->K);

      if (ptw->sgnK == 1) {
        x_turning_point = asin(sqrt(l*(l+1.))/ptr->q[index_q]*sqrt(ptw->sgnK*ptw->K));
        tau0_minus_tau_min_bessel *= x_turning_point/sqrt(l*(l+1.));
      }
      else {
        x_turning_point = asinh(sqrt(l*(l+1.))/ptr->q[index_q]*sqrt(ptw->sgnK*ptw->K));
        tau0_minus_tau_min_bessel *= x_turning_point/sqrt(l*(l+1.));
      }
    }
  }
  /** - if there is no overlap between the region in which bessels and sources are non-zero, return zero */
  if (tau0_minus_tau_min_bessel >= tau0_minus_tau[0]) {
    *trsf = 0.;
    return _SUCCESS_;
  }

  /** - if there is an overlap: */

  /** - --> trivial case: the source is a Dirac function and is sampled in only one point */
  if (ptw->tau_size == 1) {

    class_call(transfer_radial_function(
                                        ptw,
                                        ppt,
                                        ptr,
                                        k,
                                        index_q,
                                        index_l,
                                        1,
                                        &bessel,
                                        radial_type
                                        ),
               ptr->error_message,
               ptr->error_message);

    *trsf = sources[0] * bessel;
    return _SUCCESS_;
  }

  /** - --> other cases */

  /** - ---> (a) find index in the source's tau list corresponding to the last point in the overlapping region. After this step, index_tau_max can be as small as zero, but not negative. */
  index_tau_max = ptw->tau_size-1;
  while (tau0_minus_tau[index_tau_max] < tau0_minus_tau_min_bessel)
    index_tau_max--;
  /* Set index so we know if the truncation of the convolution integral is due to Bessel and not
     due to the source. */
  index_tau_max_Bessel = index_tau_max;

  /** - ---> (b) the source function can vanish at large \f$ \tau \f$. Check if further points can be eliminated. After this step and if we did not return a null transfer function, index_tau_max can be as small as zero, but not negative. */
  while (sources[index_tau_max] == 0.) {
    index_tau_max--;
    if (index_tau_max < 0) {
      *trsf = 0.;
      return _SUCCESS_;
    }
  }

  if (ptw->neglect_late_source == _TRUE_) {

    while (tau0_minus_tau[index_tau_max] < ptw->tau0_minus_tau_cut) {
      index_tau_max--;
      if (index_tau_max < 0) {
        *trsf = 0.;
        return _SUCCESS_;
      }
    }
  }

  /** - Compute the radial function: */
  class_alloc(radial_function,sizeof(double)*(index_tau_max+1),ptr->error_message);

  class_call(transfer_radial_function(
                                      ptw,
                                      ppt,
                                      ptr,
                                      k,
                                      index_q,
                                      index_l,
                                      index_tau_max+1,
                                      radial_function,
                                      radial_type
                                      ),
             ptr->error_message,
             ptr->error_message);

  /** - Now we do most of the convolution integral: */
  class_call(array_trapezoidal_convolution(sources,
                                           radial_function,
                                           index_tau_max+1,
                                           w_trapz,
                                           trsf,
                                           ptr->error_message),
             ptr->error_message,
             ptr->error_message);

  /** - This integral is correct for the case where no truncation has
      occurred. If it has been truncated at some index_tau_max because
      f[index_tau_max+1]==0, it is still correct. The 'mistake' in using
      the wrong weight w_trapz[index_tau_max] is exactly compensated by the
      triangle we miss. However, for the Bessel cut off, we must subtract the
      wrong triangle and add the correct triangle. */
  if ((index_tau_max!=(ptw->tau_size-1))&&(index_tau_max==index_tau_max_Bessel)){
    //Bessel truncation
    *trsf -= 0.5*(tau0_minus_tau[index_tau_max+1]-tau0_minus_tau_min_bessel)*
      radial_function[index_tau_max]*sources[index_tau_max];
  }


  free(radial_function);
  return _SUCCESS_;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x858, %rsp            # imm = 0x858
movl %ecx, %ebx
movq %rdx, %r15
movq %rsi, %r12
movl 0x890(%rsp), %r8d
movq 0x88(%rdx), %r14
movq 0x90(%rdx), %rbp
movq 0x98(%rdx), %r13
movl 0xc0(%rdx), %ecx
movslq %r8d, %rax
testl %ecx, %ecx
je 0xa8d7d
movapd %xmm0, %xmm3
cvtsi2sd %ecx, %xmm0
cmpl %ebx, 0x938(%r12)
jle 0xa8d93
movq 0x28(%r15), %rcx
mulsd 0xb8(%r15), %xmm0
movsd (%rcx,%rax,8), %xmm2
xorpd %xmm3, %xmm3
ucomisd %xmm3, %xmm0
jb 0xa8dca
sqrtsd %xmm0, %xmm0
jmp 0xa8def
movq 0x68(%r15), %rcx
movq 0x28(%rcx), %rcx
movsd (%rcx,%rax,8), %xmm2
divsd %xmm1, %xmm2
jmp 0xa8f04
movq 0x68(%r15), %rcx
movq 0x28(%rcx), %rcx
mulsd 0xb8(%r15), %xmm0
movsd (%rcx,%rax,8), %xmm2
xorpd %xmm4, %xmm4
ucomisd %xmm4, %xmm0
movsd %xmm2, 0x18(%rsp)
movq %r13, 0x20(%rsp)
movsd %xmm1, 0x10(%rsp)
jb 0xa8df8
sqrtsd %xmm0, %xmm0
jmp 0xa8e0d
movsd %xmm2, 0x18(%rsp)
movsd %xmm1, 0x10(%rsp)
callq 0x82d0
movl 0x890(%rsp), %r8d
movsd 0x10(%rsp), %xmm1
movsd 0x18(%rsp), %xmm2
divsd %xmm0, %xmm2
jmp 0xa8f04
movsd %xmm3, 0x8(%rsp)
callq 0x82d0
xorpd %xmm4, %xmm4
movsd 0x8(%rsp), %xmm3
movsd %xmm0, 0x30(%rsp)
movl 0xc0(%r15), %r13d
movsd 0x3c43e(%rip), %xmm0    # 0xe5260
addsd %xmm3, %xmm0
mulsd %xmm3, %xmm0
ucomisd %xmm4, %xmm0
movsd %xmm0, 0x8(%rsp)
jb 0xa8e3c
sqrtsd %xmm0, %xmm2
jmp 0xa8e45
callq 0x82d0
movapd %xmm0, %xmm2
movq 0x928(%r12), %rax
movslq %ebx, %rcx
divsd (%rax,%rcx,8), %xmm2
cvtsi2sdl 0xc0(%r15), %xmm0
mulsd 0xb8(%r15), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0xa8e77
sqrtsd %xmm0, %xmm0
jmp 0xa8e88
movsd %xmm2, 0x38(%rsp)
callq 0x82d0
movsd 0x38(%rsp), %xmm2
movsd 0x18(%rsp), %xmm1
mulsd %xmm0, %xmm2
divsd 0x30(%rsp), %xmm1
movsd %xmm1, 0x18(%rsp)
movapd %xmm2, %xmm0
cmpl $0x1, %r13d
jne 0xa8eaf
callq 0x85d0
jmp 0xa8eb4
callq 0x84a0
movapd %xmm0, %xmm3
xorpd %xmm0, %xmm0
movsd 0x8(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movapd %xmm1, %xmm0
jb 0xa8ed2
sqrtsd %xmm0, %xmm0
jmp 0xa8ee3
movsd %xmm3, 0x8(%rsp)
callq 0x82d0
movsd 0x8(%rsp), %xmm3
movsd 0x10(%rsp), %xmm1
movl 0x890(%rsp), %r8d
movq 0x20(%rsp), %r13
divsd %xmm0, %xmm3
movsd 0x18(%rsp), %xmm2
mulsd %xmm3, %xmm2
movq 0x8a0(%rsp), %rdi
ucomisd (%rbp), %xmm2
jae 0xa904a
movq %r13, 0x20(%rsp)
movl 0x898(%rsp), %esi
movslq 0x74(%r15), %r13
cmpq $0x1, %r13
jne 0xa8fa5
movq %rdi, %rbp
leaq 0x48(%rsp), %rax
pushq $0x1
popq %r13
movq %r15, %rdi
movq %r12, %rdx
movapd %xmm1, %xmm0
movl %ebx, %ecx
movl %r13d, %r9d
pushq %rsi
pushq %rax
callq 0xa9261
popq %rcx
popq %rdx
testl %eax, %eax
je 0xa9123
addq $0x96a, %r12            # imm = 0x96A
leaq 0x3c489(%rip), %rsi     # 0xe53f0
leaq 0x6dc58(%rip), %rdx     # 0x116bc6
leaq 0x50(%rsp), %r14
movq %r14, %rdi
movq %r12, %rcx
xorl %eax, %eax
callq 0x2e014
leaq 0x3c0ad(%rip), %rsi     # 0xe5034
leaq 0x6dc90(%rip), %rdx     # 0x116c1e
movq %r12, %rdi
movl $0xdb3, %ecx            # imm = 0xDB3
movq %r14, %r8
xorl %eax, %eax
callq 0x2e014
jmp 0xa9051
movl %ebx, 0x30(%rsp)
movq %r12, 0x8(%rsp)
leal -0x1(%r13), %eax
movslq %eax, %rcx
leaq 0x8(,%rcx,8), %rax
addq %rbp, %rax
movq %r13, %r12
shlq $0x20, %r12
movq %rbp, 0x38(%rsp)
leaq -0x8(,%r13,8), %rdx
addq %rbp, %rdx
xorl %ebp, %ebp
movabsq $-0x100000000, %rsi     # imm = 0xFFFFFFFF00000000
addq %rsi, %r12
addq $-0x8, %rax
ucomisd (%rdx,%rbp,8), %xmm2
leaq -0x1(%rbp), %rbp
ja 0xa8fe3
leaq (%rcx,%rbp), %rbx
incq %rbx
xorpd %xmm0, %xmm0
movsd (%r14,%rbx,8), %xmm3
ucomisd %xmm0, %xmm3
jne 0xa9020
jp 0xa9020
leaq -0x1(%rbx), %rcx
addq $-0x8, %rax
testq %rbx, %rbx
movq %rcx, %rbx
jg 0xa9000
jmp 0xa904a
cmpw $0x1, 0xd0(%r15)
jne 0xa9066
movsd 0xc8(%r15), %xmm0
ucomisd (%rax), %xmm0
jbe 0xa9066
leaq -0x1(%rbx), %rcx
addq $-0x8, %rax
testq %rbx, %rbx
movq %rcx, %rbx
jg 0xa9034
andq $0x0, (%rdi)
xorl %r13d, %r13d
movl %r13d, %eax
addq $0x858, %rsp            # imm = 0x858
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movsd %xmm1, 0x10(%rsp)
movsd %xmm2, 0x18(%rsp)
movslq %ebx, %rax
movq %rax, 0x28(%rsp)
leaq 0x8(,%rax,8), %rdi
movq %rdi, 0x40(%rsp)
callq 0x8490
testq %rax, %rax
je 0xa9138
movq %rax, %rsi
movq 0x28(%rsp), %r9
incq %r9
movq %r15, %rdi
movq 0x8(%rsp), %rdx
movsd 0x10(%rsp), %xmm0
movl 0x30(%rsp), %ecx
movl 0x890(%rsp), %r8d
movq %r9, 0x28(%rsp)
movl 0x898(%rsp), %eax
pushq %rax
pushq %rsi
movq %rsi, 0x20(%rsp)
callq 0xa9261
popq %rcx
popq %rdx
testl %eax, %eax
je 0xa917b
movq 0x8(%rsp), %rbx
addq $0x96a, %rbx            # imm = 0x96A
leaq 0x3c301(%rip), %rsi     # 0xe53f0
leaq 0x6db3b(%rip), %rdx     # 0x116c31
leaq 0x50(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2e014
leaq 0x3bf25(%rip), %rsi     # 0xe5034
leaq 0x6db08(%rip), %rdx     # 0x116c1e
movq %rbx, %rdi
movl $0xde6, %ecx            # imm = 0xDE6
jmp 0xa91eb
movsd (%r14), %xmm0
mulsd 0x48(%rsp), %xmm0
movsd %xmm0, (%rbp)
jmp 0xa904e
leaq 0x3bec5(%rip), %rsi     # 0xe5004
leaq 0x6e1fc(%rip), %rdx     # 0x117342
leaq 0x50(%rsp), %r14
movq %r14, %rdi
movq 0x40(%rsp), %rcx
xorl %eax, %eax
callq 0x2e014
movq 0x8(%rsp), %rdi
addq $0x96a, %rdi            # imm = 0x96A
leaq 0x3bec7(%rip), %rsi     # 0xe5034
leaq 0x6daaa(%rip), %rdx     # 0x116c1e
movl $0xdd8, %ecx            # imm = 0xDD8
jmp 0xa91eb
movq 0x8(%rsp), %r9
addq $0x96a, %r9             # imm = 0x96A
movq %r14, %rdi
movq 0x10(%rsp), %rsi
movq 0x28(%rsp), %rdx
movq 0x20(%rsp), %rcx
movq 0x8a0(%rsp), %r8
movq %r9, 0x8(%rsp)
callq 0x192bc
cmpl $0x1, %eax
jne 0xa91fe
leaq 0x3c239(%rip), %rsi     # 0xe53f0
leaq 0x6dae1(%rip), %rdx     # 0x116c9f
leaq 0x50(%rsp), %r14
movq %r14, %rdi
movq 0x8(%rsp), %rbx
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2e014
leaq 0x3be58(%rip), %rsi     # 0xe5034
leaq 0x6da3b(%rip), %rdx     # 0x116c1e
movq %rbx, %rdi
movl $0xdf0, %ecx            # imm = 0xDF0
movq %r14, %r8
xorl %eax, %eax
callq 0x2e014
pushq $0x1
popq %r13
jmp 0xa9051
negl %r13d
movq %rbx, %rax
addq %r13, %rax
cmpl %ebp, %eax
movq 0x10(%rsp), %rdi
jne 0xa9257
movl 0x74(%r15), %eax
decl %eax
cmpl %ebx, %eax
je 0xa9257
movq 0x38(%rsp), %rax
movq 0x28(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
subsd 0x18(%rsp), %xmm0
sarq $0x1d, %r12
mulsd 0x3f1fd(%rip), %xmm0    # 0xe8438
mulsd (%rdi,%r12), %xmm0
mulsd (%r14,%r12), %xmm0
movq 0x8a0(%rsp), %rax
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
callq 0x8430
jmp 0xa904e