// File: /workspace/github_c_makefile_star2_O1/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 $0x1258, %rsp           # imm = 0x1258
movq %r9, 0xc8(%rsp)
movq %r8, %r15
movsd %xmm0, 0x30(%rsp)
movl %ecx, %r12d
movq %rdx, 0xf8(%rsp)
movq %rsi, 0x70(%rsp)
movq %rdi, %r13
movq %rsp, %rbp
movq 0x12a8(%rsp), %r14
movaps 0xd3be6(%rip), %xmm0    # 0xf4120
movaps %xmm0, 0x130(%rsp)
movaps 0xd3be7(%rip), %xmm0    # 0xf4130
movaps %xmm0, 0x120(%rsp)
movaps 0xd3be8(%rip), %xmm0    # 0xf4140
movaps %xmm0, 0x110(%rsp)
movapd 0xd3be8(%rip), %xmm0    # 0xf4150
movapd %xmm0, 0x100(%rsp)
movslq %ecx, %rbx
shlq $0x3, %rbx
movq %rbx, %rdi
callq 0x8460
movq %rax, 0xa8(%rsp)
testq %rax, %rax
je 0x20604
movq %rbx, %rdi
callq 0x8460
movq %rax, 0xa0(%rsp)
testq %rax, %rax
je 0x20644
movq 0x1290(%rsp), %rsi
testq %r15, %r15
sete %al
movq 0xc8(%rsp), %rdx
cmpl $0x2, %edx
setl %cl
movq $0x0, 0x78(%rsp)
orb %al, %cl
movl %r12d, 0x24(%rsp)
jne 0x20684
movsd (%r15), %xmm0
movsd %xmm0, 0x28(%rsp)
movl %edx, %eax
movsd -0x10(%r15,%rax,8), %xmm0
movsd %xmm0, 0x18(%rsp)
movsd -0x8(%r15,%rax,8), %xmm0
movsd %xmm0, 0x48(%rsp)
jmp 0x2069d
leaq 0xd09f9(%rip), %rsi     # 0xf1004
leaq 0xf5bb8(%rip), %rdx     # 0x1161ca
movq %r14, %r15
leaq 0x250(%rsp), %r14
movq %r14, %rdi
movl %ebx, %ecx
xorl %eax, %eax
callq 0x30c2c
leaq 0xd0a04(%rip), %rsi     # 0xf1034
leaq 0xd3bde(%rip), %rdx     # 0xf4215
movq %r15, %rdi
movl $0x6c, %ecx
jmp 0x21348
leaq 0xd09b9(%rip), %rsi     # 0xf1004
leaq 0xeacc9(%rip), %rdx     # 0x10b31b
movq %r14, %r15
leaq 0x250(%rsp), %r14
movq %r14, %rdi
movl %ebx, %ecx
xorl %eax, %eax
callq 0x30c2c
leaq 0xd09c4(%rip), %rsi     # 0xf1034
leaq 0xd3b9e(%rip), %rdx     # 0xf4215
movq %r15, %rdi
movl $0x6d, %ecx
jmp 0x21348
xorpd %xmm0, %xmm0
movsd %xmm0, 0x28(%rsp)
movsd %xmm0, 0x48(%rsp)
movsd %xmm0, 0x18(%rsp)
xorl %r15d, %r15d
movsd 0xd1693(%rip), %xmm0    # 0xf1d38
mulsd 0x30(%rsp), %xmm0
movq %r14, (%rsp)
leaq 0x140(%rsp), %rbx
movsd 0xd0ba1(%rip), %xmm2    # 0xf1260
xorpd %xmm1, %xmm1
movq %rbx, %rdi
movq 0x1298(%rsp), %rdx
movq 0x12a0(%rsp), %rcx
movl $0x1, %r8d
movl $0x1, %r9d
callq 0x2136c
movq (%rbx), %r12
movq %r12, %rdi
callq 0x215d0
movq %r12, %rdi
movl $0x1, %esi
callq 0x21607
movsd %xmm0, 0x68(%rsp)
xorpd %xmm1, %xmm1
addsd %xmm0, %xmm1
movl 0x20(%r12), %ebx
movl $0xffffffff, 0x9c(%rsp) # imm = 0xFFFFFFFF
testl %ebx, %ebx
setg %r14b
movq %r12, 0x80(%rsp)
movsd %xmm1, 0x88(%rsp)
jle 0x20774
movq %r12, %rdi
movl %ebx, %esi
callq 0x21607
movsd 0x68(%rsp), %xmm1
subsd %xmm0, %xmm1
divsd 0x88(%rsp), %xmm1
andpd 0xd0ae5(%rip), %xmm1    # 0xf1240
movsd 0x30(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x2078f
movl 0x24(%rsp), %r12d
movsd 0x28(%rsp), %xmm1
jmp 0x207e5
movl 0x24(%rsp), %r12d
movl %r12d, 0x54(%rsp)
movsd 0x30(%rsp), %xmm0
movsd 0x28(%rsp), %xmm1
jmp 0x20847
movl 0x24(%rsp), %r12d
movsd 0x28(%rsp), %xmm1
cmpl $0x2, %ebx
setge %r14b
jl 0x20842
decl %ebx
movq 0x80(%rsp), %rdi
movl %ebx, %esi
callq 0x21607
movsd 0x68(%rsp), %xmm1
subsd %xmm0, %xmm1
movsd 0x30(%rsp), %xmm0
divsd 0x88(%rsp), %xmm1
andpd 0xd0a67(%rip), %xmm1    # 0xf1240
ucomisd %xmm1, %xmm0
movsd 0x28(%rsp), %xmm1
jbe 0x2079a
movl %r12d, 0x54(%rsp)
testb %r14b, %r14b
je 0x20847
movq 0x80(%rsp), %r14
movq %r14, %rdi
movl %ebx, %esi
callq 0x21642
movq %r14, %rdi
callq 0x215d0
movsd 0x28(%rsp), %xmm1
movsd 0x30(%rsp), %xmm0
movl 0x20(%r14), %eax
leal (%rax,%rax,4), %eax
leal (%rax,%rax,2), %edx
xorl %ecx, %ecx
cmpl %r12d, %edx
setle %cl
movq %rcx, 0x78(%rsp)
cmovgel %r12d, %edx
movl %edx, 0x54(%rsp)
leal (%rax,%rax,2), %eax
decl %eax
movl %eax, 0x9c(%rsp)
jmp 0x20847
movl %r12d, 0x54(%rsp)
testq %r15, %r15
movq %r13, 0x90(%rsp)
movq %rbp, 0xd0(%rsp)
movq %r15, 0xc0(%rsp)
je 0x20c63
leaq 0x58(%rsp), %rsi
movq 0x12a0(%rsp), %r14
movq %r14, %rdi
movapd %xmm1, %xmm0
movsd %xmm1, 0x28(%rsp)
callq *0x1298(%rsp)
movsd 0xd143f(%rip), %xmm0    # 0xf1cd0
mulsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
movl $0x0, 0x14(%rsp)
xorl %eax, %eax
xorpd %xmm1, %xmm1
leaq 0x60(%rsp), %rbx
movq 0x1290(%rsp), %r12
movsd %xmm1, 0x40(%rsp)
cltq
movsd 0x120(%rsp,%rax,8), %xmm0
addsd 0xd098f(%rip), %xmm0    # 0xf1260
mulsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x120(%rsp,%rax,8)
movsd 0x100(%rsp,%rax,8), %xmm1
mulsd 0xd13df(%rip), %xmm1    # 0xf1cd0
mulsd 0x28(%rsp), %xmm1
mulsd 0x58(%rsp), %xmm1
movsd %xmm1, 0x100(%rsp,%rax,8)
movq %r14, %rdi
movq %rbx, %rsi
callq *%r12
movsd 0x40(%rsp), %xmm1
movslq 0x14(%rsp), %rcx
movsd 0x100(%rsp,%rcx,8), %xmm0
mulsd 0x60(%rsp), %xmm0
leal 0x1(%rcx), %eax
addsd %xmm0, %xmm1
movl %eax, 0x14(%rsp)
cmpq $0x3, %rcx
jl 0x208b8
movsd %xmm1, 0x40(%rsp)
leaq 0x148(%rsp), %rbx
movq %r14, %rdi
movsd 0x18(%rsp), %xmm0
movq %rbx, %rsi
movq 0x1298(%rsp), %r15
callq *%r15
leaq 0x58(%rsp), %r14
movq 0x12a0(%rsp), %rdi
movsd 0x48(%rsp), %xmm0
movq %r14, %rsi
callq *%r15
movsd (%rbx), %xmm0
movsd (%r14), %xmm1
movsd %xmm1, 0x38(%rsp)
movq 0x12a0(%rsp), %r14
divsd %xmm1, %xmm0
addsd 0xd0e49(%rip), %xmm0    # 0xf17e8
movsd 0x48(%rsp), %xmm2
movapd %xmm2, %xmm1
subsd 0x18(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd 0xd35ed(%rip), %xmm1    # 0xf3fa8
maxsd %xmm0, %xmm1
movapd %xmm1, 0xb0(%rsp)
movapd %xmm2, %xmm0
mulsd %xmm1, %xmm0
callq 0x8670
mulsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
leaq 0x1d0(%rsp), %rdi
leaq 0x150(%rsp), %rsi
xorpd %xmm0, %xmm0
movsd %xmm0, 0x38(%rsp)
movl $0x10, %edx
movq 0xa8(%rsp), %rcx
movq 0xa0(%rsp), %r8
movl $0x1, %r9d
callq 0x2016f
movapd 0xb0(%rsp), %xmm1
movsd 0x18(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
movapd 0xd07f4(%rip), %xmm0    # 0xf1230
xorpd %xmm1, %xmm0
mulsd 0x48(%rsp), %xmm0
movapd %xmm0, 0xe0(%rsp)
movl $0x0, 0x14(%rsp)
xorl %eax, %eax
leaq 0x60(%rsp), %rbx
cltq
movsd 0x1d0(%rsp,%rax,8), %xmm0
xorpd 0xd07bf(%rip), %xmm0    # 0xf1230
callq 0x8670
movslq 0x14(%rsp), %rax
mulsd 0x150(%rsp,%rax,8), %xmm0
movsd %xmm0, 0x150(%rsp,%rax,8)
movsd 0x1d0(%rsp,%rax,8), %xmm0
divsd 0xb0(%rsp), %xmm0
addsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x1d0(%rsp,%rax,8)
movapd 0xe0(%rsp), %xmm0
callq 0x8670
mulsd 0x18(%rsp), %xmm0
movslq 0x14(%rsp), %rax
mulsd 0x150(%rsp,%rax,8), %xmm0
movsd %xmm0, 0x150(%rsp,%rax,8)
movsd 0x1d0(%rsp,%rax,8), %xmm0
movq %r14, %rdi
movq %rbx, %rsi
callq *%r12
movslq 0x14(%rsp), %rcx
movsd 0x150(%rsp,%rcx,8), %xmm0
mulsd 0x60(%rsp), %xmm0
leal 0x1(%rcx), %eax
movsd 0x38(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x38(%rsp)
movl %eax, 0x14(%rsp)
cmpq $0xf, %rcx
jl 0x20a5e
movsd 0xd3488(%rip), %xmm0    # 0xf3fb0
mulsd 0x30(%rsp), %xmm0
movq 0x12a8(%rsp), %rax
movq %rax, (%rsp)
leaq 0xd8(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
movq %r15, %rdx
movq %r14, %rcx
movl $0x1, %r8d
movsd 0x28(%rsp), %xmm1
movsd 0x48(%rsp), %xmm2
xorl %r9d, %r9d
callq 0x2136c
movq (%rbx), %rbx
movq %rbx, %rdi
callq 0x215d0
movl 0x20(%rbx), %r14d
testl %r14d, %r14d
setg %r15b
jle 0x20c75
movsd 0x40(%rsp), %xmm0
addsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x40(%rsp)
movq %rbx, %rdi
movl %r14d, %esi
callq 0x21607
movsd 0x40(%rsp), %xmm2
addsd %xmm2, %xmm0
movsd 0x68(%rsp), %xmm1
subsd %xmm0, %xmm1
divsd 0x88(%rsp), %xmm1
andpd 0xd067a(%rip), %xmm1    # 0xf1240
movsd 0x30(%rsp), %xmm0
ucomisd %xmm1, %xmm0
movl 0x24(%rsp), %r12d
ja 0x20c24
cmpl $0x2, %r14d
setge %r15b
jl 0x20c87
decl %r14d
movq %rbx, %rdi
movl %r14d, %esi
callq 0x21607
movsd 0x40(%rsp), %xmm2
addsd %xmm2, %xmm0
movsd 0x68(%rsp), %xmm1
subsd %xmm0, %xmm1
divsd 0x88(%rsp), %xmm1
andpd 0xd0628(%rip), %xmm1    # 0xf1240
movsd 0x30(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x20bd7
movq $0x0, 0x18(%rsp)
movl $0x0, %eax
testb %r15b, %r15b
je 0x20c92
movq %rbx, %rdi
movl %r14d, %esi
callq 0x21642
movq %rbx, %rdi
callq 0x215d0
movl 0x20(%rbx), %eax
leal (%rax,%rax,4), %eax
leal (%rax,%rax,2), %eax
addl $0x14, %eax
movq %rax, 0x18(%rsp)
cmpl %r12d, %eax
setle %al
jmp 0x20c92
xorl %ecx, %ecx
xorl %edx, %edx
movq $0x0, 0x48(%rsp)
jmp 0x20dc3
movq $0x0, 0x18(%rsp)
xorl %eax, %eax
movl 0x24(%rsp), %r12d
jmp 0x20c92
movq $0x0, 0x18(%rsp)
xorl %eax, %eax
movl %eax, 0xb0(%rsp)
movq 0xc8(%rsp), %r15
movslq %r15d, %r14
leaq (,%r14,8), %rbx
movq %rbx, %rdi
callq 0x8460
movq %rax, 0x48(%rsp)
testq %rax, %rax
je 0x20f1d
movl $0x0, 0x14(%rsp)
testl %r15d, %r15d
jle 0x20db1
decl %r15d
movq 0xc0(%rsp), %r13
leaq -0x8(,%r14,8), %r12
addq %r13, %r12
leaq -0x10(,%r14,8), %rbx
addq %r13, %rbx
leaq 0x8(%r13), %r14
xorl %eax, %eax
movslq %eax, %rcx
movq %r13, %rdx
movq %r14, %rsi
testl %eax, %eax
je 0x20d28
movq %rbx, %rdx
movq %r12, %rsi
cmpl %r15d, %eax
je 0x20d28
leaq 0x8(,%rcx,8), %rsi
addq %r13, %rsi
leaq -0x8(,%rcx,8), %rdx
addq %r13, %rdx
movsd (%rsi), %xmm0
subsd (%rdx), %xmm0
movsd %xmm0, 0x40(%rsp)
movsd (%r13,%rcx,8), %xmm0
movq 0x12a0(%rsp), %rbp
movq %rbp, %rdi
leaq 0x58(%rsp), %rsi
callq *0x1298(%rsp)
movsd 0x58(%rsp), %xmm0
mulsd 0xd0f6e(%rip), %xmm0    # 0xf1cd0
mulsd 0x40(%rsp), %xmm0
movslq 0x14(%rsp), %rax
movq 0x48(%rsp), %rcx
movsd %xmm0, (%rcx,%rax,8)
movsd (%r13,%rax,8), %xmm0
movq %rbp, %rdi
leaq 0x60(%rsp), %rsi
callq *0x1290(%rsp)
movl 0x14(%rsp), %eax
incl %eax
movl %eax, 0x14(%rsp)
cmpl 0xc8(%rsp), %eax
jl 0x20cfa
movq 0x90(%rsp), %r13
movl 0x24(%rsp), %r12d
movsd 0x30(%rsp), %xmm0
movq 0x18(%rsp), %rcx
movl 0xb0(%rsp), %edx
cmpl $0x50, %r12d
movl $0x50, %eax
cmovll %r12d, %eax
cmpl $0x2, %r12d
movq %rcx, 0x18(%rsp)
movl %edx, 0xb0(%rsp)
jge 0x20df4
movl $0x2, %r12d
xorl %eax, %eax
movl $0x2, %ecx
jmp 0x20f71
movl %eax, 0x28(%rsp)
movl $0x2, %eax
movl $0x2, %ecx
movq %rcx, 0x38(%rsp)
movl %eax, %r12d
xorpd %xmm0, %xmm0
movq %r13, %rdi
movq %r13, %rbp
movq 0x70(%rsp), %r13
movq %r13, %rsi
movl %eax, %edx
movq 0xa8(%rsp), %rcx
movq 0xa0(%rsp), %r8
movl $0x1, %r9d
callq 0x2016f
xorpd %xmm2, %xmm2
movl $0x0, 0x14(%rsp)
testl %r12d, %r12d
movq 0x12a0(%rsp), %r15
movq 0x1290(%rsp), %rcx
leaq 0x60(%rsp), %r14
jle 0x20ecb
xorl %eax, %eax
movsd %xmm2, 0x40(%rsp)
cltq
movsd (%rbp,%rax,8), %xmm0
movq %r15, %rdi
movq %r14, %rsi
movq %rcx, %rbx
callq *%rcx
movslq 0x14(%rsp), %rax
movsd (%rbp,%rax,8), %xmm0
movq %r15, %rdi
leaq 0x58(%rsp), %rsi
callq *0x1298(%rsp)
movq %rbx, %rcx
movsd 0x40(%rsp), %xmm2
movsd 0x58(%rsp), %xmm0
movslq 0x14(%rsp), %rax
mulsd (%r13,%rax,8), %xmm0
movsd %xmm0, (%r13,%rax,8)
mulsd 0x60(%rsp), %xmm0
addsd %xmm0, %xmm2
incl %eax
movl %eax, 0x14(%rsp)
cmpl %r12d, %eax
jl 0x20e61
movsd 0x68(%rsp), %xmm1
movapd %xmm1, %xmm0
subsd %xmm2, %xmm0
divsd %xmm1, %xmm0
andpd 0xd035b(%rip), %xmm0    # 0xf1240
movsd 0x30(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movapd %xmm1, %xmm0
seta %al
ja 0x20f5f
movl 0x28(%rsp), %ecx
cmpl %ecx, %r12d
movq 0x90(%rsp), %r13
je 0x20f6e
leal 0xa(%r12), %eax
cmpl %eax, %ecx
cmovll %ecx, %eax
movq %r12, 0x38(%rsp)
jmp 0x20e07
leaq 0xd00e0(%rip), %rsi     # 0xf1004
leaq 0xd32f8(%rip), %rdx     # 0xf4223
leaq 0x250(%rsp), %r14
movq %r14, %rdi
movl %ebx, %ecx
xorl %eax, %eax
callq 0x30c2c
leaq 0xd00ee(%rip), %rsi     # 0xf1034
leaq 0xd32c8(%rip), %rdx     # 0xf4215
movq 0x12a8(%rsp), %rdi
movl $0xd0, %ecx
jmp 0x21348
movq 0x90(%rsp), %r13
movq 0x38(%rsp), %rcx
jmp 0x20f71
movl %r12d, %ecx
movl %eax, 0xe0(%rsp)
testb %al, %al
je 0x210b9
movl %r12d, %eax
subl %ecx, %eax
cmpl $0x2, %eax
jl 0x210b9
movq 0x70(%rsp), %rbp
movq 0x90(%rsp), %rbx
movq %r12, 0x28(%rsp)
movq %rcx, 0x38(%rsp)
leal (%rcx,%r12), %r13d
movl %r13d, %r14d
shrl %r14d
xorpd %xmm0, %xmm0
movq 0x90(%rsp), %rdi
movq %rbp, %rsi
movl %r14d, %edx
movq 0xa8(%rsp), %rcx
movq 0xa0(%rsp), %r8
movl $0x1, %r9d
callq 0x2016f
xorpd %xmm1, %xmm1
movl $0x0, 0x14(%rsp)
cmpl $0x2, %r13d
movq 0x12a0(%rsp), %r13
movq 0x1290(%rsp), %rcx
leaq 0x60(%rsp), %r12
jb 0x2106b
xorl %eax, %eax
movsd %xmm1, 0x40(%rsp)
cltq
movsd (%rbx,%rax,8), %xmm0
movq %r13, %rdi
movq %r12, %rsi
movq %rcx, %r15
callq *%rcx
movslq 0x14(%rsp), %rax
movsd (%rbx,%rax,8), %xmm0
movq %r13, %rdi
leaq 0x58(%rsp), %rsi
callq *0x1298(%rsp)
movq %r15, %rcx
movsd 0x40(%rsp), %xmm1
movsd 0x58(%rsp), %xmm0
movslq 0x14(%rsp), %rax
mulsd (%rbp,%rax,8), %xmm0
movsd %xmm0, (%rbp,%rax,8)
mulsd 0x60(%rsp), %xmm0
addsd %xmm0, %xmm1
incl %eax
movl %eax, 0x14(%rsp)
cmpl %r14d, %eax
jl 0x21005
movq %rbx, %r13
movsd 0x68(%rsp), %xmm0
subsd %xmm1, %xmm0
divsd 0x88(%rsp), %xmm0
andpd 0xd01b7(%rip), %xmm0    # 0xf1240
movsd 0x30(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movapd %xmm1, %xmm0
movq 0x28(%rsp), %r12
cmoval %r14d, %r12d
movq 0x38(%rsp), %rcx
cmovbel %r14d, %ecx
movl %r12d, %eax
subl %ecx, %eax
cmpl $0x1, %eax
jg 0x20f9b
jmp 0x210bc
movl %r12d, %r14d
movl 0x54(%rsp), %edx
movq 0x18(%rsp), %rsi
cmpl %edx, %esi
setle %cl
xorl %eax, %eax
movl 0xb0(%rsp), %edi
andb %cl, %dil
cmovnel %esi, %edx
movq 0xf8(%rsp), %r12
movl %edx, (%r12)
movq 0x78(%rsp), %rcx
cmovnel %eax, %ecx
movq %rcx, 0x78(%rsp)
cmpb $0x0, 0xe0(%rsp)
je 0x2112f
xorl %eax, %eax
cmpl (%r12), %r14d
movq 0xd0(%rsp), %rbp
movq 0xc0(%rsp), %r15
movq 0x80(%rsp), %rbx
jg 0x21147
movl %r14d, (%r12)
movb $0x1, %al
xorl %edi, %edi
movq $0x0, 0x78(%rsp)
jmp 0x21147
movq 0xd0(%rsp), %rbp
movq 0xc0(%rsp), %r15
movq 0x80(%rsp), %rbx
cmpl $0x0, 0x78(%rsp)
je 0x21177
leaq 0x14(%rsp), %rsi
movl 0x9c(%rsp), %eax
movl %eax, (%rsi)
movq %rbx, %rdi
movq %r13, %rdx
movq 0x70(%rsp), %rcx
movl $0x1, %r8d
callq 0x216a4
jmp 0x21227
testb %al, %al
jne 0x21227
testb %dil, %dil
je 0x212f4
xorl %eax, %eax
movq 0x70(%rsp), %r14
movsd 0x120(%rsp,%rax,8), %xmm0
movsd %xmm0, (%r13,%rax,8)
movsd 0x100(%rsp,%rax,8), %xmm0
movsd %xmm0, (%r14,%rax,8)
incq %rax
cmpq $0x4, %rax
jne 0x2118f
leaq 0x14(%rsp), %rsi
movl $0x4, (%rsi)
movq 0xd8(%rsp), %rdi
xorl %ebx, %ebx
movq %r13, %rdx
movq %r14, %rcx
xorl %r8d, %r8d
callq 0x216a4
movslq 0x18(%rsp), %rcx
leaq -0x80(,%rcx,8), %rax
addq %r13, %rax
leaq (%r14,%rcx,8), %rcx
addq $-0x80, %rcx
movsd 0x1d0(%rsp,%rbx,8), %xmm0
movsd %xmm0, (%rax,%rbx,8)
movsd 0x150(%rsp,%rbx,8), %xmm0
movsd %xmm0, (%rcx,%rbx,8)
incq %rbx
cmpq $0x10, %rbx
jne 0x211f2
movl $0x10, 0x14(%rsp)
movq 0x80(%rsp), %rbx
movl (%r12), %ecx
xorl %eax, %eax
testl %ecx, %ecx
jle 0x212ae
xorpd %xmm0, %xmm0
movq 0x70(%rsp), %rdx
xorl %esi, %esi
xorl %edi, %edi
movslq %ecx, %r8
cmpq %r8, %rax
jge 0x21278
movslq %edi, %r9
leal (%rcx,%r9), %r8d
addl %esi, %r8d
leaq (%rdx,%r9,8), %r9
movsd (%r9), %xmm1
ucomisd %xmm0, %xmm1
jne 0x21278
jp 0x21278
decl %ecx
movl %ecx, (%r12)
movslq %ecx, %r10
incl %edi
addq $0x8, %r9
cmpq %r10, %rax
jl 0x21254
movl %r8d, %edi
movslq %edi, %r8
addq %rax, %r8
movsd (%r13,%r8,8), %xmm1
movsd %xmm1, (%r13,%rax,8)
movq 0x70(%rsp), %r9
movsd (%r9,%r8,8), %xmm1
movsd %xmm1, (%r9,%rax,8)
incq %rax
movslq %ecx, %r8
decl %esi
addq $0x8, %rdx
cmpq %r8, %rax
jl 0x2123e
movl %eax, 0x14(%rsp)
movq %rbx, %rdi
callq 0x21769
testq %r15, %r15
je 0x212d6
movq 0xd8(%rsp), %rdi
callq 0x21769
movq 0x48(%rsp), %rdi
callq 0x8410
movq 0xa8(%rsp), %rdi
callq 0x8410
movq 0xa0(%rsp), %rdi
callq 0x8410
xorl %eax, %eax
jmp 0x21357
leaq 0xd2f2f(%rip), %rsi     # 0xf422a
leaq 0x250(%rsp), %rbx
movq %rbx, %rdi
movl 0x24(%rsp), %edx
movb $0x1, %al
callq 0x30c2c
leaq 0xd026d(%rip), %rsi     # 0xf1585
leaq 0xa50(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x30c2c
leaq 0xcfd00(%rip), %rsi     # 0xf1034
leaq 0xd2eda(%rip), %rdx     # 0xf4215
movq 0x12a8(%rsp), %rdi
movl $0x14e, %ecx            # imm = 0x14E
movq %r14, %r8
xorl %eax, %eax
callq 0x30c2c
movl $0x1, %eax
movq %rbp, %rsp
addq $0x1258, %rsp           # imm = 0x1258
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq