// File: /workspace/github_c_makefile_star2_O3/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 0x70d92
movq %rsi, %r14
movapd %xmm0, %xmm3
leaq 0x9cdb8(%rip), %rax     # 0x10d858
movslq (%rax,%rdx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x38(%r14), %rax
jmp 0x70d6f
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 0x70df3
movslq 0xc(%r14), %rax
jmp 0x70f6d
movq 0x38(%r14), %rax
movslq 0x24(%r14), %rcx
movslq 0x20(%r14), %rdx
leaq (%rdx,%rcx), %rsi
ucomisd -0x8(%rax,%rsi,8), %xmm3
ja 0x70d6f
movsd (%rax,%rcx,8), %xmm0
ucomisd %xmm3, %xmm0
jbe 0x70f77
movslq 0x28(%r14), %rcx
jmp 0x70d73
movq 0x38(%r14), %rax
movslq 0x30(%r14), %rcx
ucomisd (%rax,%rcx,8), %xmm3
ja 0x70d6f
movslq (%r14), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x7d72f(%rip), %xmm0    # 0xee260
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
movsd %xmm3, 0x10(%rsp)
callq 0x8620
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
addsd 0x7d707(%rip), %xmm0    # 0xee260
movq 0x38(%r14), %rax
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
callq 0x8620
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 0x7d6c7(%rip), %xmm0    # 0xee260
addsd (%rax,%rcx,8), %xmm0
movsd 0x7dc42(%rip), %xmm1    # 0xee7e8
addsd %xmm2, %xmm1
callq 0x8620
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 0x70d78
movq 0x38(%r14), %rax
movslq 0x30(%r14), %rcx
ucomisd (%rax,%rcx,8), %xmm3
ja 0x70d6f
movslq (%r14), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x7d638(%rip), %xmm0    # 0xee260
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
movsd %xmm3, 0x10(%rsp)
callq 0x8620
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
addsd 0x7d610(%rip), %xmm0    # 0xee260
movq 0x38(%r14), %rax
movslq 0x4(%r14), %rcx
movsd (%rax,%rcx,8), %xmm1
callq 0x8620
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 0x7d5cb(%rip), %xmm0    # 0xee260
movsd 0x7db4b(%rip), %xmm1    # 0xee7e8
addsd %xmm2, %xmm1
callq 0x8620
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 0x7d574(%rip), %xmm0    # 0xee260
mulsd 0x8(%rsp), %xmm0
mulsd 0x7dfd6(%rip), %xmm0    # 0xeecd0
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 0x7d521(%rip), %xmm0    # 0xee260
mulsd 0x8(%rsp), %xmm0
mulsd 0x7df83(%rip), %xmm0    # 0xeecd0
addsd (%rbx), %xmm0
jmp 0x70d78
movq 0x38(%r14), %rax
movslq 0x24(%r14), %rcx
movslq 0x20(%r14), %rsi
leaq (%rsi,%rcx), %rdx
ucomisd -0x8(%rax,%rdx,8), %xmm3
jbe 0x70ed2
movslq 0xc(%r14), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rbx)
xorl %r15d, %r15d
movl %r15d, %eax
addq $0x1020, %rsp           # imm = 0x1020
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x9da62(%rip), %rsi     # 0x10e7fb
leaq 0x820(%rsp), %rbx
movq %rbx, %rdi
xorl %eax, %eax
callq 0x30af0
leaq 0x7d7d3(%rip), %rsi     # 0xee585
leaq 0x20(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x30af0
addq $0x1064, %r15           # imm = 0x1064
leaq 0x7d262(%rip), %rsi     # 0xee034
leaq 0xa0f79(%rip), %rdx     # 0x111d52
movq %r15, %rdi
movl $0x10fb, %ecx           # imm = 0x10FB
movq %r14, %r8
xorl %eax, %eax
callq 0x30af0
movl $0x1, %r15d
jmp 0x70d7f
ucomisd (%rcx,%rsi,8), %xmm3
jbe 0x70f69
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)
cmpl $0x3, %edx
jl 0x70d7c
movl $0x1, %ebp
xorl %r15d, %r15d
xorl %r12d, %r12d
movsd %xmm3, 0x10(%rsp)
movq 0x38(%r14), %rcx
movslq %eax, %rdx
addl 0x24(%r14), %eax
addl %r12d, %eax
addl $-0x2, %eax
cltq
movslq 0x28(%r14), %rsi
addq %rdx, %rsi
leal (%r12,%rsi), %edx
addl $-0x2, %edx
movslq %edx, %rdx
movsd (%rcx,%rdx,8), %xmm0
addq %r12, %rsi
subsd -0x8(%rcx,%rsi,8), %xmm0
movsd %xmm0, 0x8(%rsp)
movslq 0x2c(%r14), %rdx
xorpd %xmm1, %xmm1
subsd %xmm0, %xmm1
movsd %xmm1, 0x18(%rsp)
subsd (%rcx,%rax,8), %xmm3
divsd (%rcx,%rdx,8), %xmm3
movapd %xmm3, %xmm0
callq 0x80d0
movsd 0x10(%rsp), %xmm3
addsd 0x7d3c3(%rip), %xmm0    # 0xee260
mulsd 0x18(%rsp), %xmm0
mulsd 0x7de25(%rip), %xmm0    # 0xeecd0
addsd 0x8(%rsp), %xmm0
addsd (%rbx), %xmm0
movsd %xmm0, (%rbx)
incl %ebp
movl 0x20(%r14), %eax
leal -0x1(%rax), %ecx
decq %r12
cmpl %ecx, %ebp
jl 0x70e32
jmp 0x70d7f
leaq (%rax,%rcx,8), %rdx
movq $-0x1, %rcx
ucomisd 0x10(%rdx,%rcx,8), %xmm3
leaq 0x1(%rcx), %rcx
ja 0x70edd
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 0x70fe2
leaq 0xa0e07(%rip), %rsi     # 0x111d1c
leaq 0x820(%rsp), %rbx
movq %rbx, %rdi
xorl %eax, %eax
callq 0x30af0
leaq 0x7d154(%rip), %rsi     # 0xee082
leaq 0xa0e15(%rip), %rdx     # 0x111d4a
leaq 0x20(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rcx
xorl %eax, %eax
callq 0x30af0
addq $0x1064, %r15           # imm = 0x1064
leaq 0x7d0df(%rip), %rsi     # 0xee034
leaq 0xa0df6(%rip), %rdx     # 0x111d52
movq %r15, %rdi
movl $0x10e2, %ecx           # imm = 0x10E2
jmp 0x70de1
movslq 0x28(%r14), %rax
movsd (%rcx,%rax,8), %xmm0
jmp 0x70d78
movl %edx, %r8d
leaq (%rax,%rcx,8), %rdx
addq $-0x10, %rdx
movl $0x1, %ebp
movl $0x1, %esi
decl %ebp
ucomisd 0x10(%rdx,%rsi,8), %xmm3
leaq 0x1(%rsi), %rsi
ja 0x70f8c
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 0x71093
movsd (%rdx,%rsi,8), %xmm1
leaq (%rax,%rcx,8), %rcx
movapd %xmm1, %xmm0
subsd -0x18(%rcx,%rsi,8), %xmm0
mulsd 0x7dcf7(%rip), %xmm0    # 0xeecd0
addsd %xmm1, %xmm0
jmp 0x710aa
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 0x70d7c
movsd (%rax,%rcx,8), %xmm1
movsd 0x8(%rax,%rcx,8), %xmm2
leaq 0xa0d3c(%rip), %rsi     # 0x111d77
leaq 0x820(%rsp), %rbx
movq %rbx, %rdi
movapd %xmm3, %xmm0
movb $0x3, %al
callq 0x30af0
leaq 0x7d02a(%rip), %rsi     # 0xee082
leaq 0xa0d4a(%rip), %rdx     # 0x111da9
leaq 0x20(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rcx
xorl %eax, %eax
callq 0x30af0
addq $0x1064, %r15           # imm = 0x1064
leaq 0x7cfb5(%rip), %rsi     # 0xee034
leaq 0xa0ccc(%rip), %rdx     # 0x111d52
movq %r15, %rdi
movl $0x10f5, %ecx           # imm = 0x10F5
jmp 0x70de1
leaq (%rax,%rcx,8), %rcx
movsd -0x8(%rcx,%rsi,8), %xmm0
addsd (%rdx,%rsi,8), %xmm0
mulsd 0x7dc26(%rip), %xmm0    # 0xeecd0
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 0x7d188(%rip), %xmm0    # 0xee260
mulsd 0x7dbf0(%rip), %xmm0    # 0xeecd0
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 0x70d7c