// File: /workspace/github_c_makefile_star2_O3/PoulinV[P]AxiCLASS/build/../tools/quadrature.c
// Function: get_qsampling
int get_qsampling(double *x,
		  double *w,
		  int *N,
		  int N_max,
		  double rtol,
		  double *qvec,
		  int qsiz,
		  int (*test)(void * params_for_function, double q, double *psi),
		  int (*function)(void * params_for_function, double q, double *f0),
		  void * params_for_function,
		  ErrorMsg errmsg) {

  /* This routine returns the fewest possible number of abscissas and weights under
     the requirement that a test function folded with the neutrino distribution function
     can be integrated to an accuracy of rtol. If the distribution function is Fermi-Dirac
     or close, a Laguerre quadrature formula is often the best choice.

     This function combines two completely different strategies: Adaptive Gauss-Kronrod
     quadrature and Laguerres quadrature formula. */

  int i, NL=2,NR,level,Nadapt=0,NLag,NLag_max,Nold=NL;
  int adapt_converging=_FALSE_,Laguerre_converging=_FALSE_,combined_converging=_FALSE_;
  double y,y1,y2,I,Igk,err,ILag,*b,*c;
  qss_node *root,*root_comb;
  double I_comb,I_atzero,I_atinf,I_comb2;
  int N_comb=0,N_comb_lag=16,N_comb_leg=4;
  double a_comb,b_comb;
  double q_leg[4],w_leg[4];
  double q_lag[N_comb_lag],w_lag[N_comb_lag];
  char method_chosen[40];
  double qmin=0., qmax=0., qmaxm1=0.;
  double *wcomb2=NULL,delq;
  double Itot=0.0;
  int zeroskip=0;

  /* Set roots and weights for Gauss-Legendre 4 point rule: */
  q_leg[3] = sqrt((3.0+2.0*sqrt(6.0/5.0))/7.0);
  q_leg[2] = sqrt((3.0-2.0*sqrt(6.0/5.0))/7.0);
  q_leg[1] = -q_leg[2];
  q_leg[0] = -q_leg[3];
  w_leg[3] = (18.0-sqrt(30.0))/36.0;
  w_leg[2] = (18.0+sqrt(30.0))/36.0;
  w_leg[1] = w_leg[2];
  w_leg[0] = w_leg[3];

  /* Allocate storage for Laguerre coefficients: */
  class_alloc(b,N_max*sizeof(double),errmsg);
  class_alloc(c,N_max*sizeof(double),errmsg);
  /* If a vector of q values has been passed, use it: */
  if ((qvec!=NULL)&&(qsiz>1)){
    qmin = qvec[0];
    qmax = qvec[qsiz-1];
    qmaxm1 = qvec[qsiz-2];
  }
  else{
    qvec = NULL;
  }

  /* First do the adaptive quadrature - this will also give the value of the integral: */
  gk_adapt(&root,(*test),(*function), params_for_function,
	   rtol*1e-4, 1, 0.0, 1.0, _TRUE_, errmsg);
  /* Do a leaf count: */
  leaf_count(root);
  /* I can get the integral now: */
  I = get_integral(root, 1);
  //printf("I = %le |%le, used points: %d\n",I,I-1.0,15*root->leaf_childs);
  Itot += I;

  /* Starting from the top, move down in levels until tolerance is met: */
  for(level=root->leaf_childs; level>=1; level--){
    Igk = get_integral(root,level);
    err = I-Igk;
    if (fabs(err/Itot)<rtol) break;
  }
  if (level>0){
    /* Reduce tree to the found level:*/
    reduce_tree(root,level);
    /* Count the new leafs: */
    leaf_count(root);
    /* I know know how many function evaluations is
       required by the adaptively sampled grid:*/
    Nadapt = 15*root->leaf_childs;
    /* The adaptive routine could not recieve required precision
       using less than the required maximal number of points.*/
    if (Nadapt <= N_max) adapt_converging = _TRUE_;
  }


  /* Combined adaptive quadrature and Laguerre rescaled quadrature: */
  if(qvec!=NULL){
    /* Evaluate [0;qmin] using 4 point Gauss-Legendre rule: */
    (*function)(params_for_function,qmin,&y2);
    for(i=0,I_atzero=0.0; i<N_comb_leg; i++){
      q_leg[i] = 0.5*qmin*(1.0+q_leg[i]);
      w_leg[i] = w_leg[i]*0.5*qmin*y2;
      (*test)(params_for_function,q_leg[i],&y);
      I_atzero +=w_leg[i]*y;
    }

    /* Find asymptotic extrapolation:*/
    (*function)(params_for_function,qmaxm1,&y1);
    (*function)(params_for_function,qmax,&y2);

    b_comb = (y1/y2-1.0)/(qmax-qmaxm1);
    b_comb = MAX(b_comb,1e-100);
    //c_comb = -b_comb*qmax;
    a_comb = y2*exp(b_comb*qmax);
    // printf("f(q) = %g*exp(-%g*q) \n",a_comb,b_comb);
    //(*function)(params_for_function,100,&y2);
    //printf("f(100) = %e ?= %e\n",y2,a_comb*exp(-b_comb*100));

    /* Evaluate tail using 6 point Laguerre: */
    compute_Laguerre(q_lag,w_lag,N_comb_lag,0.0,b,c,_TRUE_);
    for (i=0,I_atinf=0.0; i<N_comb_lag; i++){
      w_lag[i] *= exp(-q_lag[i]);
      q_lag[i] = qmax + q_lag[i]/b_comb;
      w_lag[i] = a_comb/b_comb*exp(-b_comb*qmax)*w_lag[i];
      (*test)(params_for_function,q_lag[i],&y);
      I_atinf +=w_lag[i]*y;
    }

    /* Do the adaptive quadrature - this will also give the main part of the integral: */
    gk_adapt(&root_comb,(*test),(*function), params_for_function,
	     rtol*1e-2, 1, qmin, qmax, _FALSE_, errmsg);
    /* Do a leaf count: */
    leaf_count(root_comb);
    /* Starting from the top, move down in levels until tolerance is met: */
    for(level=root_comb->leaf_childs; level>=1; level--){
      I_comb = get_integral(root_comb,level);
      //printf("%le + %le + %le = %le | %le\n",
      //     I_atzero,I_atinf,I_comb,I_comb+I_atinf+I_atzero,I_comb+I_atinf+I_atzero-1.0);
      I_comb +=(I_atinf+I_atzero);
      err = I-I_comb;
      if (fabs(err/Itot)<rtol) break;
    }
    /* Reduce tree to the found level:*/
    if (level>0){
      reduce_tree(root_comb,level);
      /* Count the new leafs: */
      leaf_count(root_comb);
      N_comb = 15*root_comb->leaf_childs+N_comb_lag+N_comb_leg;
      if (N_comb <= N_max) combined_converging = _TRUE_;
    }

    /* Do the second combined quadrature: Same as above, but with trapezoidal rule
       using the given q grid:  */
    class_alloc(wcomb2,qsiz*sizeof(double),errmsg);
    I_comb2 = 0.0;
    for(i=0; i<qsiz; i++){
      if(i==0){
	delq = qvec[1]-qvec[0];
      }
      else if(i==qsiz-1){
	delq = qvec[qsiz-1]-qvec[qsiz-2];
      }
      else{
	delq = qvec[i+1]-qvec[i-1];
      }
      (*function)(params_for_function,qvec[i],&y2);
      wcomb2[i] = 0.5*y2*delq;
      (*test)(params_for_function,qvec[i],&y);
      I_comb2 +=wcomb2[i]*y;
    }
    I_comb2 +=(I_atzero+I_atinf);
    err = I - I_comb2;
    //    if(fabs(err/Itot)<rtol) combined2_converging= _TRUE_;
    //printf("I_comb2 = %e, rerr = %e\n",I_comb2,fabs(err/I));
  }


  /* Search for the minimal Laguerre quadrature rule: */
  NLag_max = MIN(N_max,80);
  for (NLag=NL; NLag<=NLag_max; NLag = MIN(NLag_max,NLag+10)){
    /* Evaluate integral: */
    compute_Laguerre(x,w,NLag,0.0,b,c,_TRUE_);
    ILag = 0.0;
    for (i=0; i<NLag; i++){
      (*test)(params_for_function,x[i],&y);
      (*function)(params_for_function,x[i],&y2);
      w[i] *= y2;
      ILag += y*w[i];
    }
    err = I-ILag;
    //fprintf(stderr,"\n Computing Laguerre, N=%d, I=%g and err=%g.\n",NLag,ILag,err);
    if (fabs(err/I)<rtol){
      Laguerre_converging = _TRUE_;
      break;
    }
    Nold = NLag;
    if (Nold == NLag_max) break;
  }

  if (Laguerre_converging == _TRUE_){
    /* We must refine NLag: */
    NL = Nold;
    NR = NLag;
    while ((NR-NL)>1) {
      NLag = (NL+NR)/2;
      /* Evaluate integral: */
      compute_Laguerre(x,w,NLag,0.0,b,c,_TRUE_);
      ILag = 0.0;
      for (i=0; i<NLag; i++){
	(*test)(params_for_function,x[i],&y);
	(*function)(params_for_function,x[i],&y2);
	w[i] *= y2;
	ILag += y*w[i];
      }
      err = I-ILag;
      //fprintf(stderr,"\n NLag=%d, rerr=%g.\n",NLag,fabs(err/I));
      if (fabs(err/Itot)<rtol){
	NR = NLag;
      }
      else{
	NL = NLag;
      }
    }
  }

  /* Choose best method if both works: */
  *N = N_max;
  //Laguerre_converging = _FALSE_;
  if (adapt_converging == _TRUE_) {
    *N = Nadapt;
  }
  if (combined_converging == _TRUE_){
    if(N_comb <= *N){
      *N = N_comb;
      adapt_converging = _FALSE_;
    }
    else{
      combined_converging = _FALSE_;
    }
  }
  if (Laguerre_converging == _TRUE_){
    if (NLag <= *N){
      *N = NLag;
      combined_converging = _FALSE_;
      adapt_converging = _FALSE_;
    }
    else{
      Laguerre_converging = _FALSE_;
    }
  }
  //printf("N_adapt=%d, N_combined=%d at level=%d, Nlag=%d\n",Nadapt,N_comb,level,NLag);
  if (adapt_converging==_TRUE_){
    class_sprintf(method_chosen,"Adaptive Gauss-Kronrod Quadrature");
    /* Gather weights and xvalues from tree: */
    i = Nadapt-1;
    get_leaf_x_and_w(root,&i,x,w,_TRUE_);
  }
  else if (Laguerre_converging==_TRUE_){
    class_sprintf(method_chosen,"Gauss-Laguerre Quadrature");
    /* x and w is already populated in this case. */
  }
  else if (combined_converging == _TRUE_){
    class_sprintf(method_chosen,"Combined Quadrature");
    for(i=0; i<N_comb_leg; i++){
      x[i] = q_leg[i];
      w[i] = w_leg[i];
    }
    i = N_comb_leg;
    get_leaf_x_and_w(root_comb,&i,x,w,_FALSE_);
    //printf("from %d to %d\n",N_comb_leg,i);

    for(i=0; i<N_comb_lag; i++){
      x[N_comb-N_comb_lag+i] = q_lag[i];
      w[N_comb-N_comb_lag+i] = w_lag[i];
    }
  }
  else{
    /* Failed to converge! */
    class_stop(errmsg,
		"get_qsampling fails to obtain a relative tolerance of %g as required using atmost %d points. If the PSD is interpolated from a file, try increasing the resolution and the q-interval (qmin;qmax) if possible, or decrease tol_ncdm/tol_ncdm_bg. As a last resort, increase _QUADRATURE_MAX_/_QUADRATURE_MAX_BG_.",rtol,N_max);
  }
  /* Trim weights to avoid zero weights: */
  for(i=0,zeroskip=0; i<*N; i++){
    for( ;(i<*N)&&(w[i+zeroskip]==0.0); zeroskip++,(*N)--);
    x[i] = x[i+zeroskip];
    w[i] = w[i+zeroskip];
  }


  //printf("Chosen sampling: %s, with %d points.\n",method_chosen,*N);
  //for(i=0; i<*N; i++) printf("(q,w) = (%g,%g)\n",x[i],w[i]);
  /* Deallocate tree: */
  burn_tree(root);
  if(qvec!=NULL){
    burn_tree(root_comb);
    free(wcomb2);
  }

  free(b);
  free(c);

  return _SUCCESS_;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1268, %rsp           # imm = 0x1268
movq %r9, 0xf0(%rsp)
movq %r8, 0x28(%rsp)
movsd %xmm0, 0x68(%rsp)
movq %rdx, 0x90(%rsp)
movq %rsi, %r15
movq %rdi, %r12
movq %rsp, %rbp
movq 0x12b8(%rsp), %r14
movaps 0xd0b35(%rip), %xmm0    # 0xf1130
movaps %xmm0, 0x130(%rsp)
movaps 0xd0b36(%rip), %xmm0    # 0xf1140
movaps %xmm0, 0x120(%rsp)
movaps 0xd0b37(%rip), %xmm0    # 0xf1150
movaps %xmm0, 0x110(%rsp)
movapd 0xd0b37(%rip), %xmm0    # 0xf1160
movapd %xmm0, 0x100(%rsp)
movl %ecx, 0x24(%rsp)
movslq %ecx, %rbx
shlq $0x3, %rbx
movq %rbx, %rdi
callq 0x8460
movq %rax, 0xc0(%rsp)
testq %rax, %rax
je 0x206ca
movq %rbx, %rdi
callq 0x8460
movq %rax, 0xb0(%rsp)
testq %rax, %rax
je 0x20707
movq 0x12a8(%rsp), %rdx
movq 0x28(%rsp), %rsi
testq %rsi, %rsi
sete %al
movq 0xf0(%rsp), %rdi
cmpl $0x2, %edi
setl %cl
xorpd %xmm0, %xmm0
movsd %xmm0, 0x88(%rsp)
orb %al, %cl
jne 0x20756
movsd (%rsi), %xmm0
movsd %xmm0, 0x40(%rsp)
movl %edi, %eax
movsd -0x10(%rsi,%rax,8), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd -0x8(%rsi,%rax,8), %xmm0
movsd %xmm0, 0x30(%rsp)
jmp 0x20771
leaq 0xcd933(%rip), %rsi     # 0xee004
leaq 0xf2b32(%rip), %rdx     # 0x11320a
movq %r14, %r15
leaq 0x260(%rsp), %r14
movq %r14, %rdi
movl %ebx, %ecx
xorl %eax, %eax
callq 0x30af0
leaq 0xcd93e(%rip), %rsi     # 0xee034
leaq 0xd0b28(%rip), %rdx     # 0xf1225
movq %r15, %rdi
movl $0x6c, %ecx
jmp 0x20742
leaq 0xcd8f6(%rip), %rsi     # 0xee004
leaq 0xe7c2e(%rip), %rdx     # 0x108343
movq %r14, %r15
leaq 0x260(%rsp), %r14
movq %r14, %rdi
movl %ebx, %ecx
xorl %eax, %eax
callq 0x30af0
leaq 0xcd901(%rip), %rsi     # 0xee034
leaq 0xd0aeb(%rip), %rdx     # 0xf1225
movq %r15, %rdi
movl $0x6d, %ecx
movq %r14, %r8
xorl %eax, %eax
callq 0x30af0
movl $0x1, %eax
jmp 0x2131c
movq $0x0, 0x28(%rsp)
movsd %xmm0, 0x40(%rsp)
movsd %xmm0, 0x30(%rsp)
movsd %xmm0, 0x10(%rsp)
movsd 0xce5bf(%rip), %xmm0    # 0xeed38
mulsd 0x68(%rsp), %xmm0
movq %r14, (%rsp)
leaq 0x150(%rsp), %rbx
movsd 0xcdacd(%rip), %xmm2    # 0xee260
xorps %xmm1, %xmm1
movq %rbx, %rdi
movq 0x12a0(%rsp), %rsi
movq 0x12b0(%rsp), %rcx
movl $0x1, %r8d
movl $0x1, %r9d
callq 0x2137e
movq (%rbx), %rbx
movq %rbx, %rdi
callq 0x215fb
movq %rbx, %rdi
movl $0x1, %esi
callq 0x21632
movapd %xmm0, %xmm1
movsd 0x88(%rsp), %xmm0
movsd %xmm1, 0xc8(%rsp)
addsd %xmm1, %xmm0
movsd %xmm0, 0x88(%rsp)
movq %rbx, 0xb8(%rsp)
movl 0x20(%rbx), %ebx
movl $0xffffffff, 0x98(%rsp) # imm = 0xFFFFFFFF
movb $0x1, %r14b
testl %ebx, %ebx
movq %rbp, 0xe8(%rsp)
jle 0x2085d
movq 0xb8(%rsp), %rdi
movl %ebx, %esi
callq 0x21632
movsd 0xc8(%rsp), %xmm1
subsd %xmm0, %xmm1
divsd 0x88(%rsp), %xmm1
andpd 0xcd9f9(%rip), %xmm1    # 0xee240
movsd 0x68(%rsp), %xmm0
ucomisd %xmm1, %xmm0
ja 0x20867
leal -0x1(%rbx), %eax
cmpl $0x1, %ebx
movl %eax, %ebx
jg 0x2081a
movl 0x24(%rsp), %eax
movl %eax, 0x4c(%rsp)
jmp 0x208a8
movq 0xb8(%rsp), %r14
movq %r14, %rdi
movl %ebx, %esi
callq 0x2166d
movq %r14, %rdi
callq 0x215fb
movl 0x20(%r14), %eax
leal (%rax,%rax,4), %eax
leal (%rax,%rax,2), %edx
movl 0x24(%rsp), %ecx
cmpl %ecx, %edx
setg %r14b
cmovgel %ecx, %edx
movl %edx, 0x4c(%rsp)
leal (%rax,%rax,2), %eax
decl %eax
movl %eax, 0x98(%rsp)
movq 0x28(%rsp), %r10
testq %r10, %r10
movq 0x12b0(%rsp), %rbp
movsd 0x40(%rsp), %xmm0
movb %r14b, 0xf(%rsp)
je 0x20c4f
movq %r12, 0xf8(%rsp)
leaq 0x58(%rsp), %rsi
movq %rbp, %rdi
movsd %xmm0, 0x40(%rsp)
callq *0x12a8(%rsp)
movsd 0xce3e2(%rip), %xmm0    # 0xeecd0
mulsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
xorpd %xmm1, %xmm1
xorl %r14d, %r14d
leaq 0x60(%rsp), %rbx
movq 0x12a0(%rsp), %r12
movsd %xmm1, 0x38(%rsp)
movsd 0x120(%rsp,%r14,8), %xmm0
addsd 0xcd93a(%rip), %xmm0    # 0xee260
mulsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x120(%rsp,%r14,8)
movsd 0x100(%rsp,%r14,8), %xmm1
mulsd 0xce388(%rip), %xmm1    # 0xeecd0
mulsd 0x40(%rsp), %xmm1
mulsd 0x58(%rsp), %xmm1
movsd %xmm1, 0x70(%rsp)
movsd %xmm1, 0x100(%rsp,%r14,8)
movq %rbp, %rdi
movq %rbx, %rsi
callq *%r12
movsd 0x38(%rsp), %xmm1
movsd 0x70(%rsp), %xmm0
mulsd 0x60(%rsp), %xmm0
addsd %xmm0, %xmm1
incq %r14
cmpq $0x4, %r14
jne 0x2090e
movsd %xmm1, 0x38(%rsp)
leaq 0x158(%rsp), %rbx
movq %rbp, %rdi
movsd 0x10(%rsp), %xmm0
movq %rbx, %rsi
movq 0x12a8(%rsp), %r12
callq *%r12
leaq 0x58(%rsp), %r14
movq %rbp, %rdi
movsd 0x30(%rsp), %xmm0
movq %r14, %rsi
callq *%r12
movq 0x12a0(%rsp), %r12
movsd (%rbx), %xmm0
movsd (%r14), %xmm1
movsd %xmm1, 0x70(%rsp)
divsd %xmm1, %xmm0
addsd 0xcde00(%rip), %xmm0    # 0xee7e8
movsd 0x30(%rsp), %xmm2
movapd %xmm2, %xmm1
subsd 0x10(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd 0xd05b4(%rip), %xmm1    # 0xf0fb8
maxsd %xmm0, %xmm1
movapd %xmm1, 0xa0(%rsp)
movapd %xmm2, %xmm0
mulsd %xmm1, %xmm0
callq 0x8670
mulsd 0x70(%rsp), %xmm0
movsd %xmm0, 0x50(%rsp)
leaq 0x1e0(%rsp), %rdi
leaq 0x160(%rsp), %rsi
xorpd %xmm0, %xmm0
movsd %xmm0, 0x18(%rsp)
movl $0x10, %edx
movq 0xc0(%rsp), %rcx
movq 0xb0(%rsp), %r8
movl $0x1, %r9d
callq 0x2021c
movapd 0xa0(%rsp), %xmm1
movsd 0x50(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0x50(%rsp)
movapd 0xcd7ab(%rip), %xmm0    # 0xee230
xorpd %xmm1, %xmm0
mulsd 0x30(%rsp), %xmm0
movapd %xmm0, 0xd0(%rsp)
xorl %r14d, %r14d
leaq 0x60(%rsp), %rbx
movsd 0x1e0(%rsp,%r14,8), %xmm0
movapd %xmm0, 0x70(%rsp)
xorpd 0xcd778(%rip), %xmm0    # 0xee230
callq 0x8670
mulsd 0x160(%rsp,%r14,8), %xmm0
movsd %xmm0, 0x10(%rsp)
movapd 0x70(%rsp), %xmm0
divsd 0xa0(%rsp), %xmm0
addsd 0x30(%rsp), %xmm0
movapd %xmm0, 0x70(%rsp)
movsd %xmm0, 0x1e0(%rsp,%r14,8)
movapd 0xd0(%rsp), %xmm0
callq 0x8670
mulsd 0x50(%rsp), %xmm0
mulsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd %xmm0, 0x160(%rsp,%r14,8)
movq %rbp, %rdi
movaps 0x70(%rsp), %xmm0
movq %rbx, %rsi
callq *%r12
movsd 0x10(%rsp), %xmm1
mulsd 0x60(%rsp), %xmm1
movsd 0x18(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
incq %r14
cmpq $0x10, %r14
jne 0x20aa0
movl $0x10, 0x9c(%rsp)
movsd 0xd045a(%rip), %xmm0    # 0xf0fc0
mulsd 0x68(%rsp), %xmm0
movq 0x12b8(%rsp), %rax
movq %rax, (%rsp)
leaq 0x148(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
movq 0x12a8(%rsp), %rdx
movq %rbp, %rcx
movl $0x1, %r8d
movsd 0x40(%rsp), %xmm1
movsd 0x30(%rsp), %xmm2
xorl %r9d, %r9d
callq 0x2137e
movq (%rbx), %rbx
movq %rbx, %rdi
callq 0x215fb
movq %rbx, 0x50(%rsp)
movl 0x20(%rbx), %ebx
testl %ebx, %ebx
movq 0xf8(%rsp), %r12
jle 0x20c75
movsd 0x38(%rsp), %xmm2
addsd 0x18(%rsp), %xmm2
movq 0xf0(%rsp), %rbp
movsd %xmm2, 0x38(%rsp)
movq 0x50(%rsp), %rdi
movl %ebx, %esi
callq 0x21632
movsd 0x38(%rsp), %xmm2
addsd %xmm2, %xmm0
movsd 0xc8(%rsp), %xmm1
subsd %xmm0, %xmm1
divsd 0x88(%rsp), %xmm1
andpd 0xcd624(%rip), %xmm1    # 0xee240
movsd 0x68(%rsp), %xmm0
ucomisd %xmm1, %xmm0
ja 0x20c97
leal -0x1(%rbx), %eax
cmpl $0x1, %ebx
movl %eax, %ebx
jg 0x20be8
movq $0x0, 0xa0(%rsp)
movq $0x0, 0xd0(%rsp)
jmp 0x20cd2
movq $0x0, 0xa0(%rsp)
movq $0x0, 0xd0(%rsp)
movq $0x0, 0x40(%rsp)
jmp 0x20e19
movq $0x0, 0xa0(%rsp)
movq $0x0, 0xd0(%rsp)
movq 0xf0(%rsp), %rbp
jmp 0x20cd2
movq 0x50(%rsp), %r14
movq %r14, %rdi
movl %ebx, %esi
callq 0x2166d
movq %r14, %rdi
callq 0x215fb
movl 0x20(%r14), %eax
leal (%rax,%rax,4), %eax
leal (%rax,%rax,2), %eax
addl $0x14, %eax
movq %rax, 0xa0(%rsp)
cmpl 0x24(%rsp), %eax
setle %al
movq %rax, 0xd0(%rsp)
movslq %ebp, %r14
leaq (,%r14,8), %rbx
movq %rbx, %rdi
callq 0x8460
movq %rax, 0x40(%rsp)
testq %rax, %rax
je 0x20dd2
testl %ebp, %ebp
jle 0x20e14
movq %r15, 0x10(%rsp)
leal -0x1(%rbp), %r13d
movq 0x28(%rsp), %r10
leaq (%r10,%r13,8), %rax
movq %rax, 0x38(%rsp)
leaq -0x10(%r10,%r14,8), %rax
movq %rax, 0x18(%rsp)
leaq 0x8(%r10), %rbx
movl %ebp, %r14d
shlq $0x3, %r13
shlq $0x3, %r14
xorl %ebp, %ebp
movq %r10, %rax
movq %rbx, %rcx
testq %rbp, %rbp
je 0x20d57
movq 0x18(%rsp), %rax
movq 0x38(%rsp), %rcx
cmpq %rbp, %r13
je 0x20d57
leaq (%r10,%rbp), %rcx
addq $0x8, %rcx
leaq (%r10,%rbp), %rax
addq $-0x8, %rax
movsd (%rcx), %xmm0
subsd (%rax), %xmm0
movsd %xmm0, 0x70(%rsp)
movsd (%r10,%rbp), %xmm0
movq 0x12b0(%rsp), %r15
movq %r15, %rdi
leaq 0x58(%rsp), %rsi
callq *0x12a8(%rsp)
movsd 0x58(%rsp), %xmm0
mulsd 0xcdf40(%rip), %xmm0    # 0xeecd0
mulsd 0x70(%rsp), %xmm0
movq 0x40(%rsp), %rax
movsd %xmm0, (%rax,%rbp)
movq 0x28(%rsp), %rax
movsd (%rax,%rbp), %xmm0
movq %r15, %rdi
leaq 0x60(%rsp), %rsi
callq *0x12a0(%rsp)
movq 0x28(%rsp), %r10
addq $0x8, %rbp
cmpq %rbp, %r14
jne 0x20d2d
movq 0x10(%rsp), %r15
jmp 0x20e19
leaq 0xcd22b(%rip), %rsi     # 0xee004
leaq 0xd0453(%rip), %rdx     # 0xf1233
leaq 0x260(%rsp), %r14
movq %r14, %rdi
movl %ebx, %ecx
xorl %eax, %eax
callq 0x30af0
leaq 0xcd239(%rip), %rsi     # 0xee034
leaq 0xd0423(%rip), %rdx     # 0xf1225
movq 0x12b8(%rsp), %rdi
movl $0xd0, %ecx
jmp 0x21305
movq 0x28(%rsp), %r10
movl 0x24(%rsp), %eax
cmpl $0x50, %eax
movl $0x50, %ecx
cmovll %eax, %ecx
cmpl $0x2, %eax
movq %r10, 0x28(%rsp)
jge 0x20f08
movl 0x4c(%rsp), %ecx
movq 0xa0(%rsp), %rdx
cmpl %ecx, %edx
setle %al
movq 0xd0(%rsp), %rsi
andb %al, %sil
cmovnel %edx, %ecx
movq 0x90(%rsp), %rax
movl %ecx, (%rax)
movb 0xf(%rsp), %al
orb %sil, %al
testb $0x1, %al
je 0x2102e
testb %sil, %sil
je 0x212ab
movq %r10, %r14
xorl %eax, %eax
movsd 0x120(%rsp,%rax,8), %xmm0
movsd %xmm0, (%r12,%rax,8)
movsd 0x100(%rsp,%rax,8), %xmm0
movsd %xmm0, (%r15,%rax,8)
incq %rax
cmpq $0x4, %rax
jne 0x20e7c
leaq 0x9c(%rsp), %rsi
movl $0x4, (%rsi)
xorl %ebx, %ebx
movq 0x50(%rsp), %rdi
movq %r12, %rdx
movq %r15, %rcx
xorl %r8d, %r8d
callq 0x216b8
movslq 0xa0(%rsp), %rcx
leaq (%r12,%rcx,8), %rax
addq $-0x80, %rax
leaq (%r15,%rcx,8), %rcx
addq $-0x80, %rcx
movsd 0x1e0(%rsp,%rbx,8), %xmm0
movsd %xmm0, (%rax,%rbx,8)
movsd 0x160(%rsp,%rbx,8), %xmm0
movsd %xmm0, (%rcx,%rbx,8)
incq %rbx
cmpq $0x10, %rbx
jne 0x20ede
jmp 0x2105b
movl %ecx, 0x30(%rsp)
movl $0x2, %eax
movl $0x2, %ecx
movq %rcx, 0x10(%rsp)
movl %eax, %ebx
xorpd %xmm0, %xmm0
movq %r12, %rdi
movq %r15, %rsi
movl %eax, %edx
movq 0xc0(%rsp), %rcx
movq 0xb0(%rsp), %r8
movl $0x1, %r9d
callq 0x2021c
xorpd %xmm2, %xmm2
movq %rbx, 0x18(%rsp)
testl %ebx, %ebx
movq %r12, %rbx
movq %r15, %r12
movq 0x12b0(%rsp), %r13
movq 0x12a0(%rsp), %rax
leaq 0x60(%rsp), %r15
jle 0x20fd3
movl 0x18(%rsp), %ecx
movq %rcx, 0x38(%rsp)
xorl %r14d, %r14d
movsd %xmm2, 0x70(%rsp)
movsd (%rbx,%r14,8), %xmm0
movq %r13, %rdi
movq %r15, %rsi
movq %rax, %rbp
callq *%rax
movsd (%rbx,%r14,8), %xmm0
movq %r13, %rdi
leaq 0x58(%rsp), %rsi
callq *0x12a8(%rsp)
movq %rbp, %rax
movsd 0x70(%rsp), %xmm2
movsd 0x58(%rsp), %xmm0
mulsd (%r12,%r14,8), %xmm0
movsd %xmm0, (%r12,%r14,8)
mulsd 0x60(%rsp), %xmm0
addsd %xmm0, %xmm2
incq %r14
cmpq %r14, 0x38(%rsp)
jne 0x20f78
movsd 0xc8(%rsp), %xmm1
movapd %xmm1, %xmm0
subsd %xmm2, %xmm0
divsd %xmm1, %xmm0
andpd 0xcd250(%rip), %xmm0    # 0xee240
movsd 0x68(%rsp), %xmm1
ucomisd %xmm0, %xmm1
ja 0x21166
movq 0x18(%rsp), %rdx
movl 0x30(%rsp), %esi
cmpl %esi, %edx
movq 0x28(%rsp), %r10
movq %r12, %r15
movq %rbx, %r12
je 0x20e36
leal 0xa(%rdx), %eax
cmpl %eax, %esi
cmovll %esi, %eax
movq %rdx, 0x10(%rsp)
jmp 0x20f1b
movq %r10, %r14
leaq 0x9c(%rsp), %rsi
movl 0x98(%rsp), %eax
movl %eax, (%rsi)
movq 0xb8(%rsp), %rdi
movq %r12, %rdx
movq %r15, %rcx
movl $0x1, %r8d
callq 0x216b8
movq 0x90(%rsp), %rax
movl (%rax), %ebx
movq %r14, %r10
testl %ebx, %ebx
jle 0x2111c
xorl %eax, %eax
xorpd %xmm0, %xmm0
movq %r15, %rcx
xorl %edx, %edx
xorl %esi, %esi
movq 0x90(%rsp), %rbp
movslq %ebx, %r8
cmpq %r8, %rax
jge 0x210d0
movslq %esi, %r9
leal (%rbx,%r9), %edi
addl %edx, %edi
leaq (%rcx,%r9,8), %r11
movl %ebx, %r14d
movq $-0x1, %r13
xorl %r10d, %r10d
movsd (%r11,%r10,8), %xmm1
ucomisd %xmm0, %xmm1
jne 0x210d7
jp 0x210d7
leaq (%r14,%r13), %r9
movl %r9d, (%rbp)
movslq %r9d, %r9
incq %r10
decq %r13
cmpq %r9, %rax
jl 0x210a7
subl %r10d, %ebx
jmp 0x210e5
movq %r8, %r9
movl %esi, %edi
jmp 0x210ea
addl %r10d, %esi
subq %r10, %r8
subl %r10d, %ebx
movq %r8, %r9
movl %esi, %edi
movq 0x28(%rsp), %r10
movslq %edi, %rsi
addq %rax, %rsi
movsd (%r12,%rsi,8), %xmm1
movsd %xmm1, (%r12,%rax,8)
movsd (%r15,%rsi,8), %xmm1
movsd %xmm1, (%r15,%rax,8)
incq %rax
decl %edx
addq $0x8, %rcx
movl %edi, %esi
cmpq %r9, %rax
jl 0x21085
movq 0xb8(%rsp), %rdi
movq %r10, %rbx
callq 0x21757
testq %rbx, %rbx
je 0x21145
movq 0x50(%rsp), %rdi
callq 0x21757
movq 0x40(%rsp), %rdi
callq 0x8410
movq 0xc0(%rsp), %rdi
callq 0x8410
movq 0xb0(%rsp), %rdi
callq 0x8410
xorl %eax, %eax
jmp 0x21314
movq 0x18(%rsp), %rdx
movl %edx, %eax
movq 0x10(%rsp), %rsi
subl %esi, %eax
cmpl $0x2, %eax
movq %r12, %r15
jl 0x21331
movq %rbx, %r12
movq %rdx, 0x18(%rsp)
movq %rsi, 0x10(%rsp)
leal (%rsi,%rdx), %ebp
movl %ebp, %edx
shrl %edx
xorpd %xmm0, %xmm0
movq %r12, %rdi
movq %r15, %rsi
movq %rdx, 0x30(%rsp)
movq 0xc0(%rsp), %rcx
movq 0xb0(%rsp), %r8
movl $0x1, %r9d
callq 0x2021c
xorpd %xmm1, %xmm1
cmpl $0x2, %ebp
movq 0x12b0(%rsp), %rcx
movq %r15, %rbx
movq %r12, %r15
movq 0x12a0(%rsp), %rax
leaq 0x60(%rsp), %r13
jb 0x21256
movq 0x30(%rsp), %rbp
cmpl $0x1, %ebp
adcl $0x0, %ebp
movq %rbp, 0x38(%rsp)
xorl %r14d, %r14d
movsd %xmm1, 0x70(%rsp)
movsd (%r15,%r14,8), %xmm0
movq %rcx, %rbp
movq %rcx, %rdi
movq %r13, %rsi
movq %rax, %r12
callq *%rax
movsd (%r15,%r14,8), %xmm0
movq %rbp, %rdi
leaq 0x58(%rsp), %rsi
callq *0x12a8(%rsp)
movq %rbp, %rcx
movq %r12, %rax
movsd 0x70(%rsp), %xmm1
movsd 0x58(%rsp), %xmm0
mulsd (%rbx,%r14,8), %xmm0
movsd %xmm0, (%rbx,%r14,8)
mulsd 0x60(%rsp), %xmm0
addsd %xmm0, %xmm1
incq %r14
cmpq %r14, 0x38(%rsp)
jne 0x211f5
movsd 0xc8(%rsp), %xmm0
subsd %xmm1, %xmm0
divsd 0x88(%rsp), %xmm0
andpd 0xccfcc(%rip), %xmm0    # 0xee240
movsd 0x68(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movq 0x30(%rsp), %rdi
movq 0x18(%rsp), %rdx
cmoval %edi, %edx
movq 0x10(%rsp), %rsi
cmovbel %edi, %esi
movl %edx, %eax
subl %esi, %eax
cmpl $0x1, %eax
movq %r15, %r12
movq %rbx, %r15
jg 0x21183
jmp 0x21336
leaq 0xcff88(%rip), %rsi     # 0xf123a
leaq 0x260(%rsp), %rbx
movq %rbx, %rdi
movsd 0x68(%rsp), %xmm0
movl 0x24(%rsp), %edx
movb $0x1, %al
callq 0x30af0
leaq 0xcd2b0(%rip), %rsi     # 0xee585
leaq 0xa60(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x30af0
leaq 0xccd43(%rip), %rsi     # 0xee034
leaq 0xcff2d(%rip), %rdx     # 0xf1225
movq 0x12b8(%rsp), %rdi
movl $0x14e, %ecx            # imm = 0x14E
movq %r14, %r8
xorl %eax, %eax
callq 0x30af0
movl $0x1, %eax
movq 0xe8(%rsp), %rbp
movq %rbp, %rsp
addq $0x1268, %rsp           # imm = 0x1268
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %edx, %edi
movq %rbx, %r12
movl 0x4c(%rsp), %ecx
movq 0xa0(%rsp), %rdx
cmpl %ecx, %edx
setle %al
movq 0xd0(%rsp), %rsi
andb %al, %sil
cmovnel %edx, %ecx
movq 0x90(%rsp), %rax
movl %ecx, (%rax)
cmpl %ecx, %edi
movq 0x28(%rsp), %r10
jg 0x20e5f
movq %rdi, %rbx
movq 0x90(%rsp), %rax
movl %ebx, (%rax)
jmp 0x21068