// File: /workspace/github_c_makefile_star2_O2/PoulinV[P]AxiCLASS/build/../source/thermodynamics.c
// Function: thermodynamics_reionization_function
int thermodynamics_reionization_function(
                                         double z,
                                         struct thermodynamics * pth,
                                         struct thermo_reionization_parameters * preio,
                                         double * x
                                         ) {

  /** Summary: */

  /** - define local variables */
  double argument;
  int i;
  double z_jump;

  int jump;
  double center,before, after,width,one_jump;
  double z_min, z_max;

  switch (pth->reio_parametrization) {

    /** - no reionization means nothing to be added to xe_before */
  case reio_none:
    *x = preio->reionization_parameters[preio->index_re_xe_before];
    break;

    /** - implementation of ionization function similar to the one in CAMB */
  case reio_camb:

    /** - --> case z > z_reio_start */
    if (z > preio->reionization_parameters[preio->index_re_reio_start]) {
      *x = preio->reionization_parameters[preio->index_re_xe_before];
    }
    else {
      /** - --> case z < z_reio_start: hydrogen contribution (tanh of complicated argument) */
      argument = (pow((1.+preio->reionization_parameters[preio->index_re_reio_redshift]),
                      preio->reionization_parameters[preio->index_re_reio_exponent])
                  -pow((1.+z),preio->reionization_parameters[preio->index_re_reio_exponent]))
        /(preio->reionization_parameters[preio->index_re_reio_exponent]
          *pow((1.+preio->reionization_parameters[preio->index_re_reio_redshift]),
               (preio->reionization_parameters[preio->index_re_reio_exponent]-1.)))
        /preio->reionization_parameters[preio->index_re_reio_width];

      *x = (preio->reionization_parameters[preio->index_re_xe_after]
            -preio->reionization_parameters[preio->index_re_xe_before])
        *(tanh(argument)+1.)/2.
        +preio->reionization_parameters[preio->index_re_xe_before];

      /** - --> case z < z_reio_start: helium contribution (tanh of simpler argument) */
      argument = (preio->reionization_parameters[preio->index_re_helium_fullreio_redshift] - z)
        /preio->reionization_parameters[preio->index_re_helium_fullreio_width];

      *x += preio->reionization_parameters[preio->index_re_helium_fullreio_fraction]
        *(tanh(argument)+1.)/2.;
    }
    break;

    /** - implementation of half-tangent like in 1209.0247 */
  case reio_half_tanh:

    /** - --> case z > z_reio_start */
    if (z > preio->reionization_parameters[preio->index_re_reio_start]) {
      *x = preio->reionization_parameters[preio->index_re_xe_before];
    }
    else {
      /** - --> case z < z_reio_start: hydrogen contribution (tanh of complicated argument) */
      argument = (pow((1.+preio->reionization_parameters[preio->index_re_reio_redshift]),
                      preio->reionization_parameters[preio->index_re_reio_exponent])
                  -pow((1.+z),preio->reionization_parameters[preio->index_re_reio_exponent]))
        /(preio->reionization_parameters[preio->index_re_reio_exponent]
          *pow((1.+preio->reionization_parameters[preio->index_re_reio_redshift]),
               (preio->reionization_parameters[preio->index_re_reio_exponent]-1.)))
        /preio->reionization_parameters[preio->index_re_reio_width];

      /* argument goes from 0 to infty, not from -infty to infty like
         in reio_camb case. Thus tanh(argument) goes from 0 to 1, not
         from -1 to 1.  */

      *x = (preio->reionization_parameters[preio->index_re_xe_after]
            -preio->reionization_parameters[preio->index_re_xe_before])
        *tanh(argument)
        +preio->reionization_parameters[preio->index_re_xe_before];
    }
    break;

    /** - implementation of binned ionization function similar to astro-ph/0606552 */
  case reio_bins_tanh:

    /** - --> case z > z_reio_start */
    if (z > preio->reionization_parameters[preio->index_re_first_z+preio->re_z_size-1]) {
      *x = preio->reionization_parameters[preio->index_re_xe_before];
    }
    else if (z < preio->reionization_parameters[preio->index_re_first_z]) {
      *x = preio->reionization_parameters[preio->index_re_first_xe];
    }
    else {
      i = 0;
      while (preio->reionization_parameters[preio->index_re_first_z+i+1]<z) i++;

      /* fix the final xe to xe_before*/
      preio->reionization_parameters[preio->index_re_first_xe+preio->re_z_size-1] = preio->reionization_parameters[preio->index_re_xe_before];

      /* This is the expression of the tanh-like jumps of the reio_bins_tanh scheme until the 10.06.2015. It appeared to be
         not robust enough. It could lead to a kink in xe(z) near the maximum value of z at which reionisation is sampled. It has
         been replaced by the simpler and more robust expression below.

         *xe = preio->reionization_parameters[preio->index_re_first_xe+i]
         +0.5*(tanh((2.*(z-preio->reionization_parameters[preio->index_re_first_z+i])
         /(preio->reionization_parameters[preio->index_re_first_z+i+1]
         -preio->reionization_parameters[preio->index_re_first_z+i])-1.)
         /preio->reionization_parameters[preio->index_re_step_sharpness])
         /tanh(1./preio->reionization_parameters[preio->index_re_step_sharpness])+1.)
         *(preio->reionization_parameters[preio->index_re_first_xe+i+1]
         -preio->reionization_parameters[preio->index_re_first_xe+i]);
      */

      /* compute the central redshift value of the tanh jump */
      if (i == preio->re_z_size-2) {
        z_jump = preio->reionization_parameters[preio->index_re_first_z+i]
          + 0.5*(preio->reionization_parameters[preio->index_re_first_z+i]
                 -preio->reionization_parameters[preio->index_re_first_z+i-1]);
      }
      else{
        z_jump =  0.5*(preio->reionization_parameters[preio->index_re_first_z+i+1]
                       + preio->reionization_parameters[preio->index_re_first_z+i]);
      }

      /* implementation of the tanh jump */
      *x = preio->reionization_parameters[preio->index_re_first_xe+i]
        +0.5*(tanh((z-z_jump)
                   /preio->reionization_parameters[preio->index_re_step_sharpness])+1.)
        *(preio->reionization_parameters[preio->index_re_first_xe+i+1]
          -preio->reionization_parameters[preio->index_re_first_xe+i]);
    }
    break;

    /** - implementation of many tanh jumps */
  case reio_many_tanh:

    /** - --> case z > z_reio_start */
    if (z > preio->reionization_parameters[preio->index_re_first_z+preio->re_z_size-1]) {
      *x = preio->reionization_parameters[preio->index_re_xe_before];
    }
    else if (z > preio->reionization_parameters[preio->index_re_first_z]) {

      *x = preio->reionization_parameters[preio->index_re_xe_before];

      /* fix the final xe to xe_before*/
      preio->reionization_parameters[preio->index_re_first_xe+preio->re_z_size-1] = preio->reionization_parameters[preio->index_re_xe_before];

      for (jump=1; jump<preio->re_z_size-1; jump++) {

        center = preio->reionization_parameters[preio->index_re_first_z+preio->re_z_size-1-jump];

        /* before and after are meant with respect to growing z, not growing time */
        before = preio->reionization_parameters[preio->index_re_first_xe+preio->re_z_size-1-jump]
          -preio->reionization_parameters[preio->index_re_first_xe+preio->re_z_size-jump];
        after = 0.;
        width = preio->reionization_parameters[preio->index_re_step_sharpness];

        one_jump = before + (after-before)*(tanh((z-center)/width)+1.)/2.;

        *x += one_jump;
      }

    }
    else{
      *x = preio->reionization_parameters[preio->index_re_first_xe];
    }
    break;

    /** - implementation of reio_inter */
  case reio_inter:

    /** - --> case z > z_reio_start */
    if (z > preio->reionization_parameters[preio->index_re_first_z+preio->re_z_size-1]) {
      *x = preio->reionization_parameters[preio->index_re_xe_before];
    }
    else{
      i=0;
      while (preio->reionization_parameters[preio->index_re_first_z+i+1] < z) i++;

      z_min = preio->reionization_parameters[preio->index_re_first_z+i];
      z_max = preio->reionization_parameters[preio->index_re_first_z+i+1];

      /* fix the final xe to xe_before*/
      preio->reionization_parameters[preio->index_re_first_xe+preio->re_z_size-1] = preio->reionization_parameters[preio->index_re_xe_before];

      class_test(z<z_min,
                 pth->error_message,
                 "z out of range for reionization interpolation");

      class_test(z>z_max,
                 pth->error_message,
                 "z out of range for reionization interpolation");

      argument =(z-preio->reionization_parameters[preio->index_re_first_z+i])
        /(preio->reionization_parameters[preio->index_re_first_z+i+1]
          -preio->reionization_parameters[preio->index_re_first_z+i]);

      *x = preio->reionization_parameters[preio->index_re_first_xe+i]
        + argument*(preio->reionization_parameters[preio->index_re_first_xe+i+1]
                    -preio->reionization_parameters[preio->index_re_first_xe+i]);

      class_test(*x<0.,
                 pth->error_message,
                 "Interpolation gives negative ionization fraction\n",
                 argument,
                 preio->reionization_parameters[preio->index_re_first_xe+i],
                 preio->reionization_parameters[preio->index_re_first_xe+i+1]);
    }
    break;

  default:
    class_stop(pth->error_message,
               "value of reio_parametrization=%d unclear",pth->reio_parametrization);
    break;
  }
  return _SUCCESS_;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x1020, %rsp           # imm = 0x1020
movq %rdx, %rbx
movq %rdi, %r15
movl 0x18(%rdi), %edx
cmpq $0x5, %rdx
ja 0x6c745
movq %rsi, %r14
movapd %xmm0, %xmm3
leaq 0x982a1(%rip), %rax     # 0x1046f8
movslq (%rax,%rdx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x38(%r14), %rax
jmp 0x6c726
movq 0x38(%r14), %rcx
movslq 0x24(%r14), %rsi
movl 0x20(%r14), %eax
movslq %eax, %rdx
leaq (%rdx,%rsi), %rdi
ucomisd -0x8(%rcx,%rdi,8), %xmm3
jbe 0x6c7a3
movslq 0xc(%r14), %rax
jmp 0x6c910
movq 0x38(%r14), %rax
movslq 0x24(%r14), %rcx
movslq 0x20(%r14), %rdx
leaq (%rdx,%rcx), %rsi
ucomisd -0x8(%rax,%rsi,8), %xmm3
ja 0x6c726
movsd (%rax,%rcx,8), %xmm0
ucomisd %xmm3, %xmm0
jbe 0x6c91a
movslq 0x28(%r14), %rcx
jmp 0x6c72a
movq 0x38(%r14), %rax
movslq 0x30(%r14), %rcx
ucomisd (%rax,%rcx,8), %xmm3
ja 0x6c726
movslq (%r14), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x78d78(%rip), %xmm0    # 0xe5260
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
movsd %xmm3, 0x10(%rsp)
callq 0x8650
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
addsd 0x78d50(%rip), %xmm0    # 0xe5260
movq 0x38(%r14), %rax
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
callq 0x8650
movsd 0x8(%rsp), %xmm1
subsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movq 0x38(%r14), %rax
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm2
movsd %xmm2, 0x18(%rsp)
movslq (%r14), %rcx
movsd 0x78d10(%rip), %xmm0    # 0xe5260
addsd (%rax,%rcx,8), %xmm0
movsd 0x7928b(%rip), %xmm1    # 0xe57e8
addsd %xmm2, %xmm1
callq 0x8650
mulsd 0x18(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
divsd %xmm0, %xmm1
movq 0x38(%r14), %rax
movslq 0x8(%r14), %rcx
divsd (%rax,%rcx,8), %xmm1
movapd %xmm1, %xmm0
movslq 0x10(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
movslq 0xc(%r14), %rcx
subsd (%rax,%rcx,8), %xmm1
movsd %xmm1, 0x8(%rsp)
callq 0x80d0
movq 0x38(%r14), %rax
movslq 0xc(%r14), %rcx
mulsd 0x8(%rsp), %xmm0
addsd (%rax,%rcx,8), %xmm0
jmp 0x6c72f
movq 0x38(%r14), %rax
movslq 0x30(%r14), %rcx
ucomisd (%rax,%rcx,8), %xmm3
ja 0x6c726
movslq (%r14), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x78c81(%rip), %xmm0    # 0xe5260
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
movsd %xmm3, 0x10(%rsp)
callq 0x8650
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
addsd 0x78c59(%rip), %xmm0    # 0xe5260
movq 0x38(%r14), %rax
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
callq 0x8650
movsd 0x8(%rsp), %xmm1
subsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movq 0x38(%r14), %rax
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm2
movsd %xmm2, 0x18(%rsp)
movslq (%r14), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x78c14(%rip), %xmm0    # 0xe5260
movsd 0x79194(%rip), %xmm1    # 0xe57e8
addsd %xmm2, %xmm1
callq 0x8650
mulsd 0x18(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
divsd %xmm0, %xmm1
movq 0x38(%r14), %rax
movslq 0x8(%r14), %rcx
divsd (%rax,%rcx,8), %xmm1
movapd %xmm1, %xmm0
movslq 0x10(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
movslq 0xc(%r14), %rcx
subsd (%rax,%rcx,8), %xmm1
movsd %xmm1, 0x8(%rsp)
callq 0x80d0
addsd 0x78bbd(%rip), %xmm0    # 0xe5260
mulsd 0x8(%rsp), %xmm0
mulsd 0x795ff(%rip), %xmm0    # 0xe5cb0
movq 0x38(%r14), %rax
movslq 0xc(%r14), %rcx
addsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rbx)
movslq 0x18(%r14), %rcx
movsd (%rax,%rcx,8), %xmm0
subsd 0x10(%rsp), %xmm0
movslq 0x1c(%r14), %rcx
divsd (%rax,%rcx,8), %xmm0
movslq 0x14(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
movsd %xmm1, 0x8(%rsp)
callq 0x80d0
addsd 0x78b6a(%rip), %xmm0    # 0xe5260
mulsd 0x8(%rsp), %xmm0
mulsd 0x795ac(%rip), %xmm0    # 0xe5cb0
addsd (%rbx), %xmm0
jmp 0x6c72f
movq 0x38(%r14), %rax
movslq 0x24(%r14), %rcx
movslq 0x20(%r14), %rsi
leaq (%rsi,%rcx), %rdx
ucomisd -0x8(%rax,%rdx,8), %xmm3
jbe 0x6c879
movslq 0xc(%r14), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rbx)
xorl %eax, %eax
addq $0x1020, %rsp           # imm = 0x1020
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x98f4f(%rip), %rsi     # 0x10569b
leaq 0x820(%rsp), %rbx
movq %rbx, %rdi
xorl %eax, %eax
callq 0x2e014
leaq 0x78e20(%rip), %rsi     # 0xe5585
leaq 0x20(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x2e014
addq $0x1064, %r15           # imm = 0x1064
leaq 0x788af(%rip), %rsi     # 0xe5034
leaq 0x9c466(%rip), %rdx     # 0x108bf2
movq %r15, %rdi
movl $0x10fb, %ecx           # imm = 0x10FB
movq %r14, %r8
xorl %eax, %eax
callq 0x2e014
pushq $0x1
popq %rax
jmp 0x6c735
ucomisd (%rcx,%rsi,8), %xmm3
jbe 0x6c90c
movslq 0xc(%r14), %rsi
movsd (%rcx,%rsi,8), %xmm0
movsd %xmm0, (%rbx)
movslq 0x28(%r14), %rsi
addq %rdx, %rsi
movsd %xmm0, -0x8(%rcx,%rsi,8)
pushq $0x1
popq %rbp
pushq $-0x2
popq %r15
pushq $-0x1
popq %r12
movsd %xmm3, 0x10(%rsp)
leal -0x1(%rax), %ecx
cmpl %ecx, %ebp
jge 0x6c733
movq 0x38(%r14), %rcx
movl 0x24(%r14), %edx
addl %eax, %edx
addl %r15d, %edx
movslq %edx, %rdx
movslq 0x28(%r14), %rsi
leal (%r15,%rax), %edi
addl %esi, %edi
movslq %edi, %rdi
movsd (%rcx,%rdi,8), %xmm0
cltq
addq %r12, %rax
addq %rsi, %rax
subsd (%rcx,%rax,8), %xmm0
movsd %xmm0, 0x8(%rsp)
movslq 0x2c(%r14), %rax
xorpd %xmm1, %xmm1
subsd %xmm0, %xmm1
movsd %xmm1, 0x18(%rsp)
movapd %xmm3, %xmm0
subsd (%rcx,%rdx,8), %xmm0
divsd (%rcx,%rax,8), %xmm0
callq 0x80d0
movsd 0x10(%rsp), %xmm3
addsd 0x78a14(%rip), %xmm0    # 0xe5260
mulsd 0x18(%rsp), %xmm0
mulsd 0x79456(%rip), %xmm0    # 0xe5cb0
addsd 0x8(%rsp), %xmm0
addsd (%rbx), %xmm0
movsd %xmm0, (%rbx)
incl %ebp
movl 0x20(%r14), %eax
decl %r15d
decq %r12
jmp 0x6c7d9
leaq (%rax,%rcx,8), %rdx
pushq $-0x1
popq %rcx
ucomisd 0x10(%rdx,%rcx,8), %xmm3
leaq 0x1(%rcx), %rcx
ja 0x6c880
movsd (%rdx,%rcx,8), %xmm0
movslq 0xc(%r14), %rdi
movsd (%rax,%rdi,8), %xmm1
movslq 0x28(%r14), %rdi
addq %rdi, %rsi
movsd %xmm1, -0x8(%rax,%rsi,8)
ucomisd %xmm3, %xmm0
jbe 0x6c981
leaq 0x9c304(%rip), %rsi     # 0x108bbc
leaq 0x820(%rsp), %rbx
movq %rbx, %rdi
xorl %eax, %eax
callq 0x2e014
leaq 0x787b1(%rip), %rsi     # 0xe5082
leaq 0x9c312(%rip), %rdx     # 0x108bea
leaq 0x20(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2e014
addq $0x1064, %r15           # imm = 0x1064
leaq 0x7873c(%rip), %rsi     # 0xe5034
leaq 0x9c2f3(%rip), %rdx     # 0x108bf2
movq %r15, %rdi
movl $0x10e2, %ecx           # imm = 0x10E2
jmp 0x6c794
movslq 0x28(%r14), %rax
movsd (%rcx,%rax,8), %xmm0
jmp 0x6c72f
movl %edx, %r8d
leaq (%rax,%rcx,8), %rdx
addq $-0x10, %rdx
pushq $0x1
popq %rbp
pushq $0x1
popq %rsi
decl %ebp
ucomisd 0x10(%rdx,%rsi,8), %xmm3
leaq 0x1(%rsi), %rsi
ja 0x6c92b
movslq 0xc(%r14), %rdi
movsd (%rax,%rdi,8), %xmm0
movl 0x28(%r14), %edi
leal (%rdi,%r8), %r9d
movslq %r9d, %r9
movsd %xmm0, -0x8(%rax,%r9,8)
cmpl %esi, %r8d
jne 0x6ca32
movsd (%rdx,%rsi,8), %xmm1
leaq (%rax,%rcx,8), %rcx
movapd %xmm1, %xmm0
subsd -0x18(%rcx,%rsi,8), %xmm0
mulsd 0x79338(%rip), %xmm0    # 0xe5cb0
addsd %xmm1, %xmm0
jmp 0x6ca49
movl %edi, %esi
movsd (%rdx,%rcx,8), %xmm0
movsd 0x8(%rdx,%rcx,8), %xmm1
subsd %xmm0, %xmm3
subsd %xmm0, %xmm1
divsd %xmm1, %xmm3
addl %ecx, %esi
movslq %esi, %rcx
movsd (%rax,%rcx,8), %xmm0
movsd 0x8(%rax,%rcx,8), %xmm1
subsd %xmm0, %xmm1
mulsd %xmm3, %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, (%rbx)
xorpd %xmm0, %xmm0
ucomisd %xmm1, %xmm0
jbe 0x6c733
movsd (%rax,%rcx,8), %xmm1
movsd 0x8(%rax,%rcx,8), %xmm2
leaq 0x9c23d(%rip), %rsi     # 0x108c17
leaq 0x820(%rsp), %rbx
movq %rbx, %rdi
movapd %xmm3, %xmm0
movb $0x3, %al
callq 0x2e014
leaq 0x7868b(%rip), %rsi     # 0xe5082
leaq 0x9c24b(%rip), %rdx     # 0x108c49
leaq 0x20(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2e014
addq $0x1064, %r15           # imm = 0x1064
leaq 0x78616(%rip), %rsi     # 0xe5034
leaq 0x9c1cd(%rip), %rdx     # 0x108bf2
movq %r15, %rdi
movl $0x10f5, %ecx           # imm = 0x10F5
jmp 0x6c794
leaq (%rax,%rcx,8), %rcx
movsd -0x8(%rcx,%rsi,8), %xmm0
addsd (%rdx,%rsi,8), %xmm0
mulsd 0x79267(%rip), %xmm0    # 0xe5cb0
subl %ebp, %edi
movslq %edi, %rcx
movsd (%rax,%rcx,8), %xmm1
movsd %xmm1, 0x8(%rsp)
subsd %xmm0, %xmm3
movslq 0x2c(%r14), %rcx
divsd (%rax,%rcx,8), %xmm3
movapd %xmm3, %xmm0
callq 0x80d0
addsd 0x787e9(%rip), %xmm0    # 0xe5260
mulsd 0x79231(%rip), %xmm0    # 0xe5cb0
movq 0x38(%r14), %rax
movl 0x28(%r14), %ecx
subl %ebp, %ecx
movslq %ecx, %rcx
movsd 0x8(%rax,%rcx,8), %xmm1
subsd (%rax,%rcx,8), %xmm1
mulsd %xmm0, %xmm1
addsd 0x8(%rsp), %xmm1
movsd %xmm1, (%rbx)
jmp 0x6c733