// File: /workspace/github_cpp_makefile_star2_O1/chfeder[P]turbulence_generator/TurbGenDemo.cpp
// Function: main
int main(void)
{
  std::string funcsig = "TurbGenDemo: ";
  std::string parameter_file = "TurbGen.par";

  // 1st example case (turbulence driving)
  if (true) {
    printf("\n%s === 1st example case (turbulence driving) ===\n", funcsig.c_str());

    // create TurbGen class object
    TurbGen tg = TurbGen();

    // First, initialise the turbulence generator with input parameters from parameter_file
    // If MPI is present, we pass the MPI rank to TurbGen.init_driving(...);
    // note that the MPI rank is simply to control printf to stdout, i.e., only rank 0 will print.
    // This function should only be called once, i.e., to initialise the turbulence generator.
    tg.init_driving(parameter_file);

    // as an example, let's loop through a few time steps (e.g., of a hydro code)
    // to demonstrate how the turbulence generator is updated and how the physical turbulent
    // acceleration field is returned by TurbGen.h

    // get the turbulent turnover time
    double t_turb = tg.get_turnover_time();
    // let's go through 5 turnover times based on the inputs in parameter_file above
    double t_end = 5.0 * t_turb;

    // set some number of time steps that the hydro code would go through
    int nsteps = 123;
    // time step (this will normally be set by the hydro code;
    // ultimately, one simply feeds in the 'time' at which one wants the respective
    // physical turbulent acceleration field -- see below in call to TurbGen.check_for_update(...)
    double dt = t_end / nsteps;

    // loop through time steps
    for (int step = 0; step <= nsteps; step++) {

      double time = step * dt;
      printf("%stime = %f\n", funcsig.c_str(), time);

      // Function to update the turbulence driving mode coefficients.
      // Based on input 'time', it checks if the pattern needs to be updated.
      // If it was updated, return true in 'have_updated_pattern', else return false.
      // Note that this call to TurbGen_update(time) is very cheap and returns right away if current input
      // time means that no update of the turbulence driving pattern is necessary; therefore, we can safely
      // call this in every hydro timestep without wasting compute time.
      bool have_updated_pattern = tg.check_for_update(time);

      if (have_updated_pattern) {
        // say we want the turbulent vector field value at some physical position pos[3]
        double pos[3] = {0.1, -0.5, 0.3};
        double v[3]; // return vector
        tg.get_turb_vector(pos, v); // get the vector
        printf("%sturbulent vector at position (%f %f %f) is vx, vy, vz = %f %f %f\n",
               funcsig.c_str(), pos[0], pos[1], pos[2], v[0], v[1], v[2]);
      }

    } // end of loop over timesteps

  } // end of 1st example


  // 2nd example case (return turbulent vector field on uniform grid)
  if (true) {
    printf("\n%s === 2nd example case (fast forward to 5 t_turb and return turbulent vector field on uniform grid) ===\n",
           funcsig.c_str());

    // create TurbGen class object
    TurbGen tg = TurbGen();

    // The above example returns the turbulent vector field at only a single position.
    // Here we want the turbulent vector field at all positions on a 3D uniform grid of size nx, nz, nz.
    // In grid codes, this would be function to call, because it is faster than calling TurbGen_get_turb_vector
    // at every requested position; here, it is done for an entire block (uniform grid) of data.

    // first init as in example 1
    tg.init_driving(parameter_file);

    // now fast forward to target time (e.g., after 5 turbulent turnover times)
    tg.check_for_update(5*tg.get_turnover_time());

    // random example of physical coordinates of a target output grid (pos_beg must be < pos_end):
    double pos_beg[3] = {0.1, -0.5, 0.3}; // first cell coordinate in uniform grid (x,y,z)
    double pos_end[3] = {0.4, -0.3, 0.5}; // last  cell coordinate in uniform grid (x,y,z)
    int n[3] = {10, 20, 13}; // some random number of cells that define the output grid size
    long ntot = n[0]*n[1]*n[2]; // total number of grid cells
    float * grid_out[3]; // output grid (3 cartesian components: vx, vy, vz), receiving the turbulent acceleration field

    // allocate
    for (int dim = 0; dim < 3; dim++) grid_out[dim] = new float[ntot];

    // call to return 3 uniform grids with the 3 components of the turbulent acceleration field at requested positions
    tg.get_turb_vector_unigrid(pos_beg, pos_end, n, grid_out);

    // indices in x,y,z, i.e., i,j,k, and 1D index
    int i, j, k; long index;
    i = 3; j = 0; k = 10;
    index = k*n[1]*n[0] + j*n[0] + i;
    printf("%se.g., x-component of turbulent vector field at index i,j,k = (%i %i %i) is %f\n",
           funcsig.c_str(), i, j, k, grid_out[0][index]);
    i = 9; j = 1; k = 4;
    index = k*n[1]*n[0] + j*n[0] + i;
    printf("%se.g., z-component of turbulent vector field at index i,j,k = (%i %i %i) is %f\n",
           funcsig.c_str(), i, j, k, grid_out[2][index]);

    // clean up
    for (int dim = 0; dim < 3; dim++) {
      if (grid_out[dim]) delete [] grid_out[dim]; grid_out[dim] = NULL;
    }

  } // end of 2nd example


  // 3rd example case (single realisation)
  if (true) {
    printf("\n%s === 3rd example case (single realisation) ===\n", funcsig.c_str());

    // create TurbGen class object
    TurbGen tg = TurbGen();

    // Example of how to generate a single realisation of a turbulent vector field.
    // One can use this for example to generate an intial turbulent velocity or magnetic field
    // with the spectral properties specified in the call to TurbGen_get_turb_vector_unigrid_single_realisation.

    int ndim = 3; // dimensionality
    double L[3] = {1.0, 1.0, 1.0}; // size of box in x, y, z
    double k_min = 2.0; // minimum wavenumber for turbulent field (in units of 2pi / L[X])
    double k_max = 20.0; // minimum wavenumber for turbulent field (in units of 2pi / L[X])
    int spect_form = 2; // 0: band/rectangle/constant, 1: paraboloid, 2: power law
    double power_law_exp = -2.0; // if spect_form == 2: power-law exponent (e.g., -2 would be Burgers,
                                 // or -5/3 would be Kolmogorov, or 1.5 would Kazantsev)
    double angles_exp = 1.0; // if spect_form == 2: spectral sampling of angles;
                             // number of modes (angles) in k-shell surface increases as k^angles_exp.
                             // For full sampling, angles_exp = 2.0; for healpix-type sampling, angles_exp = 0.0.
    double sol_weight = 0.5; // solenoidal weight: 1.0: solenoidal driving, 0.0: compressive driving, 0.5: natural mixture
    int random_seed = 140281; // random seed for this turbulent realisation

    // random example of physical coordinates of a target output grid (pos_beg must be < pos_end):
    int n[3] = {64, 64, 64}; // some random number of cells that define the output grid size
    double d[3]; for (int dim = 0; dim < 3; dim++) d[dim] = L[dim] / n[dim]; // define cell size of uniform grid
    double pos_beg[3] = {-0.5+d[0]/2, -0.5+d[1]/2, -0.5+d[2]/2}; // first cell coordinate in uniform grid (x,y,z); cell-centered example
    double pos_end[3] = {+0.5-d[0]/2, +0.5-d[1]/2, +0.5-d[2]/2}; // last  cell coordinate in uniform grid (x,y,z); cell-centered example
    long ntot = n[0]*n[1]*n[2]; // total number of grid cells
    float * grid_out[3]; // output grid (three cartesian components: vx, vy, vz), which receives the turbulent acceleration field

    // allocate
    for (int dim = 0; dim < 3; dim++) grid_out[dim] = new float[ntot];

    // initialise generator to return a single turbulent realisation based on input parameters
    tg.init_single_realisation(ndim, L, k_min, k_max, spect_form, power_law_exp, angles_exp, sol_weight, random_seed);

    // call to return 3 uniform grids with the 3 components of the turbulent acceleration field at requested positions
    tg.get_turb_vector_unigrid(pos_beg, pos_end, n, grid_out);

    // indices in x,y,z, i.e., i,j,k, and 1D index
    int i, j, k; long index;
    i = 3; j = 0; k = 10;
    index = k*n[1]*n[0] + j*n[0] + i;
    printf("%se.g., x-component of turbulent vector field at index i,j,k = (%i %i %i) is %f\n",
           funcsig.c_str(), i, j, k, grid_out[0][index]);
    i = 9; j = 1; k = 4;
    index = k*n[1]*n[0] + j*n[0] + i;
    printf("%se.g., z-component of turbulent vector field at index i,j,k = (%i %i %i) is %f\n",
           funcsig.c_str(), i, j, k, grid_out[2][index]);

    // compute mean and RMS of vector field
    double mean[3] = {0.0, 0.0, 0.0};
    double rms[3] = {0.0, 0.0, 0.0};
    double std[3] = {0.0, 0.0, 0.0};
    for (int dim = 0; dim < 3; dim++) {
      for (long ni = 0; ni < ntot; ni++) {
        mean[dim] += grid_out[dim][ni];
        rms [dim] += pow(grid_out[dim][ni],2.0);
      }
      mean[dim] /= ntot; // mean
      rms[dim] = sqrt(rms[dim] / ntot); // root mean squared
      std[dim] = sqrt(rms[dim]*rms[dim] - mean[dim]*mean[dim]); // standard deviation
    }
    printf("%sTurbulent vector field mean (x,y,z) = (%e %e %e)\n", funcsig.c_str(), mean[0], mean[1], mean[2]);
    printf("%sTurbulent vector field  rms (x,y,z) = (%e %e %e)\n", funcsig.c_str(),  rms[0],  rms[1],  rms[2]);
    printf("%sTurbulent vector field  std (x,y,z) = (%e %e %e)\n", funcsig.c_str(),  std[0],  std[1],  std[2]);
    printf("%sTurbulent vector field total 3D std = %e\n", funcsig.c_str(), sqrt(std[0]*std[0]+std[1]*std[1]+std[2]*std[2]));
    printf("%sNote that the standard deviations will usually need to be normalised to the target std for single realisations.\n%s",
           funcsig.c_str(), "             See TurbGen for a full program that does this.\n");

    // clean up
    for (int dim = 0; dim < 3; dim++) {
      if (grid_out[dim]) delete [] grid_out[dim]; grid_out[dim] = NULL;
    }

  } // end of 3rd example

  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x3d8, %rsp            # imm = 0x3D8
leaq 0x30(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0xaa83(%rip), %rsi      # 0xe110
leaq 0xaa89(%rip), %rdx      # 0xe11d
leaq 0x20(%rsp), %rdi
callq 0xbba2
leaq 0x110(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0xaa6d(%rip), %rsi      # 0xe11e
leaq 0xaa71(%rip), %rdx      # 0xe129
leaq 0x100(%rsp), %rdi
callq 0xbba2
movq 0x20(%rsp), %rsi
leaq 0xaa59(%rip), %rdi      # 0xe12a
xorl %eax, %eax
callq 0x3050
leaq 0x1a0(%rsp), %rdi
callq 0x406e
leaq 0x190(%rsp), %r14
movq %r14, -0x10(%r14)
movq 0x100(%rsp), %rsi
movq 0x108(%rsp), %rdx
addq %rsi, %rdx
leaq 0x180(%rsp), %rdi
callq 0xdf02
leaq 0x1a0(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0x4242
movq 0x180(%rsp), %rdi
cmpq %r14, %rdi
je 0x3743
movq 0x190(%rsp), %rsi
incq %rsi
callq 0x32a0
leaq 0x1a0(%rsp), %rbx
movsd 0x198(%rbx), %xmm0
mulsd 0xa8ad(%rip), %xmm0     # 0xe008
divsd 0xa8ad(%rip), %xmm0     # 0xe010
movsd %xmm0, 0x10(%rsp)
xorl %r12d, %r12d
leaq 0xa9ea(%rip), %r14      # 0xe15d
movabsq $-0x4010000000000000, %rbp # imm = 0xBFF0000000000000
leaq 0x40(%rsp), %r15
leaq 0xa9e1(%rip), %r13      # 0xe16a
xorps %xmm0, %xmm0
cvtsi2sd %r12d, %xmm0
mulsd 0x10(%rsp), %xmm0
movq 0x20(%rsp), %rsi
movq %r14, %rdi
movsd %xmm0, 0x18(%rsp)
movb $0x1, %al
callq 0x3050
xorl %eax, %eax
movq %rbp, 0x40(%rsp,%rax,8)
incq %rax
cmpq $0x3, %rax
jne 0x37ae
movq %rbx, %rdi
movsd 0x18(%rsp), %xmm0
movq %r15, %rsi
callq 0xc4fc
testb %al, %al
je 0x383b
movaps 0xbad8(%rip), %xmm0     # 0xf2b0
movaps %xmm0, 0x40(%rsp)
movabsq $0x3fd3333333333333, %rax # imm = 0x3FD3333333333333
movq %rax, 0x50(%rsp)
movq %rbx, %rdi
movq %r15, %rsi
leaq 0x80(%rsp), %rdx
callq 0x42c2
movq 0x20(%rsp), %rsi
movsd 0x40(%rsp), %xmm0
movsd 0x48(%rsp), %xmm1
movsd 0x50(%rsp), %xmm2
movsd 0x80(%rsp), %xmm3
movsd 0x88(%rsp), %xmm4
movsd 0x90(%rsp), %xmm5
movq %r13, %rdi
movb $0x6, %al
callq 0x3050
incl %r12d
cmpl $0x7c, %r12d
jne 0x3789
leaq 0x1a0(%rsp), %rdi
callq 0x4b40
movq 0x20(%rsp), %rsi
leaq 0xa94d(%rip), %rdi      # 0xe1ae
xorl %eax, %eax
callq 0x3050
leaq 0x1a0(%rsp), %rdi
callq 0x406e
leaq 0x170(%rsp), %r14
movq %r14, -0x10(%r14)
movq 0x100(%rsp), %rsi
movq 0x108(%rsp), %rdx
addq %rsi, %rdx
leaq 0x160(%rsp), %rdi
callq 0xdf02
leaq 0x1a0(%rsp), %rdi
leaq 0x160(%rsp), %rsi
callq 0x4242
movq 0x160(%rsp), %rdi
cmpq %r14, %rdi
je 0x38d3
movq 0x170(%rsp), %rsi
incq %rsi
callq 0x32a0
movsd 0x338(%rsp), %xmm0
xorl %eax, %eax
movq %rbp, 0x40(%rsp,%rax,8)
incq %rax
cmpq $0x3, %rax
jne 0x38de
mulsd 0xa714(%rip), %xmm0     # 0xe008
leaq 0x1a0(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0xc4fc
movaps 0xb9a3(%rip), %xmm0     # 0xf2b0
movaps %xmm0, 0x40(%rsp)
movabsq $0x3fd3333333333333, %rax # imm = 0x3FD3333333333333
movq %rax, 0x50(%rsp)
movapd 0xb9a7(%rip), %xmm0     # 0xf2d0
movapd %xmm0, 0x80(%rsp)
movabsq $0x3fe0000000000000, %rax # imm = 0x3FE0000000000000
movq %rax, 0x90(%rsp)
movabsq $0x140000000a, %rax     # imm = 0x140000000A
movq %rax, 0x60(%rsp)
movl $0xd, 0x68(%rsp)
movslq 0x64(%rsp), %rax
movq %rax, %rcx
shlq $0x7, %rcx
leaq (%rcx,%rax,2), %rax
movq %rax, %rcx
shlq $0x2, %rcx
testl %eax, %eax
movq $-0x1, %rbx
cmovnsq %rcx, %rbx
xorl %r14d, %r14d
movq %rbx, %rdi
callq 0x3030
movq %rax, 0xa0(%rsp,%r14,8)
incq %r14
cmpq $0x3, %r14
jne 0x3982
leaq 0x1a0(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x80(%rsp), %rdx
leaq 0x60(%rsp), %rcx
leaq 0xa0(%rsp), %r8
callq 0x4cb4
movslq 0x64(%rsp), %rax
movslq 0x60(%rsp), %rcx
imulq %rax, %rcx
movq 0x20(%rsp), %rsi
movq 0xa0(%rsp), %rax
leaq (%rcx,%rcx,4), %rcx
xorps %xmm0, %xmm0
cvtss2sd 0xc(%rax,%rcx,8), %xmm0
leaq 0xa828(%rip), %rdi      # 0xe219
xorl %ebx, %ebx
movl $0x3, %edx
xorl %ecx, %ecx
movl $0xa, %r8d
movb $0x1, %al
callq 0x3050
movl 0x64(%rsp), %eax
leal 0x1(,%rax,4), %eax
imull 0x60(%rsp), %eax
movq 0x20(%rsp), %rsi
movq 0xb0(%rsp), %rcx
cltq
xorps %xmm0, %xmm0
cvtss2sd 0x24(%rcx,%rax,4), %xmm0
leaq 0xa834(%rip), %rdi      # 0xe26a
movl $0x9, %edx
movl $0x1, %ecx
movl $0x4, %r8d
movb $0x1, %al
callq 0x3050
movq 0xa0(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x3a5f
callq 0x3350
movq $0x0, 0xa0(%rsp,%rbx,8)
incq %rbx
cmpq $0x3, %rbx
jne 0x3a4d
leaq 0x1a0(%rsp), %rdi
callq 0x4b40
movq 0x20(%rsp), %rsi
leaq 0xa82e(%rip), %rdi      # 0xe2bb
xorl %eax, %eax
callq 0x3050
leaq 0x1a0(%rsp), %rdi
callq 0x406e
movapd 0xb857(%rip), %xmm0     # 0xf300
movapd %xmm0, 0x40(%rsp)
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, 0x50(%rsp)
movabsq $0x4000000040, %rax     # imm = 0x4000000040
movq %rax, (%rsp)
movl $0x40, 0x8(%rsp)
xorl %eax, %eax
movsd 0x40(%rsp,%rax,8), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdl (%rsp,%rax,4), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp,%rax,8)
incq %rax
cmpq $0x3, %rax
jne 0x3ad6
movsd 0xa516(%rip), %xmm0     # 0xe018
movsd 0x80(%rsp), %xmm1
mulsd %xmm0, %xmm1
movsd 0xa509(%rip), %xmm2     # 0xe020
movapd %xmm0, %xmm3
subsd %xmm1, %xmm3
addsd %xmm2, %xmm1
movsd %xmm1, 0xa0(%rsp)
movsd 0x88(%rsp), %xmm1
mulsd %xmm0, %xmm1
movapd %xmm0, %xmm4
subsd %xmm1, %xmm4
addsd %xmm2, %xmm1
movsd %xmm1, 0xa8(%rsp)
movsd 0x90(%rsp), %xmm1
mulsd %xmm0, %xmm1
addsd %xmm1, %xmm2
movsd %xmm2, 0xb0(%rsp)
movsd %xmm3, 0x60(%rsp)
movsd %xmm4, 0x68(%rsp)
subsd %xmm1, %xmm0
movsd %xmm0, 0x70(%rsp)
movslq (%rsp), %rax
movslq 0x4(%rsp), %rcx
imulq %rax, %rcx
movslq 0x8(%rsp), %r14
imulq %rcx, %r14
leaq (,%r14,4), %rax
testl %r14d, %r14d
movq $-0x1, %rbx
cmovnsq %rax, %rbx
xorl %r15d, %r15d
movq %rbx, %rdi
callq 0x3030
movq %rax, 0x120(%rsp,%r15,8)
incq %r15
cmpq $0x3, %r15
jne 0x3bad
leaq 0x1a0(%rsp), %rdi
movsd 0xa452(%rip), %xmm0     # 0xe028
leaq 0x40(%rsp), %rsi
movsd 0xa44d(%rip), %xmm1     # 0xe030
movsd 0xa44d(%rip), %xmm2     # 0xe038
movsd 0xa44d(%rip), %xmm4     # 0xe040
movsd 0xa44d(%rip), %xmm6     # 0xe048
movsd 0xa415(%rip), %xmm7     # 0xe018
movapd %xmm2, %xmm3
movl $0x2, %edx
movapd %xmm4, %xmm5
movl $0x223f9, %ecx          # imm = 0x223F9
callq 0xd8a2
leaq 0x1a0(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
leaq 0x60(%rsp), %rdx
movq %rsp, %rcx
leaq 0x120(%rsp), %r8
callq 0x4cb4
movslq 0x4(%rsp), %rax
movslq (%rsp), %rcx
imulq %rax, %rcx
movq 0x20(%rsp), %rsi
movq 0x120(%rsp), %rax
leaq (%rcx,%rcx,4), %rcx
xorps %xmm0, %xmm0
cvtss2sd 0xc(%rax,%rcx,8), %xmm0
leaq 0xa5ac(%rip), %rdi      # 0xe219
xorl %ebx, %ebx
movl $0x3, %edx
xorl %ecx, %ecx
movl $0xa, %r8d
movb $0x1, %al
callq 0x3050
movl 0x4(%rsp), %eax
leal 0x1(,%rax,4), %eax
imull (%rsp), %eax
movq 0x20(%rsp), %rsi
movq 0x130(%rsp), %rcx
cltq
xorps %xmm0, %xmm0
cvtss2sd 0x24(%rcx,%rax,4), %xmm0
leaq 0xa5b9(%rip), %rdi      # 0xe26a
movl $0x9, %edx
movl $0x1, %ecx
movl $0x4, %r8d
movb $0x1, %al
callq 0x3050
movq %rbx, 0xf0(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0xe0(%rsp)
movq %rbx, 0xd0(%rsp)
movaps %xmm0, 0xc0(%rsp)
movq %rbx, 0x150(%rsp)
movaps %xmm0, 0x140(%rsp)
xorps %xmm0, %xmm0
cvtsi2sd %r14d, %xmm0
movsd %xmm0, 0x18(%rsp)
xorpd %xmm3, %xmm3
testl %r14d, %r14d
jle 0x3d5c
movq 0x120(%rsp,%rbx,8), %rax
movsd 0xe0(%rsp,%rbx,8), %xmm1
movsd 0xc0(%rsp,%rbx,8), %xmm0
xorl %ecx, %ecx
xorps %xmm2, %xmm2
cvtss2sd (%rax,%rcx,4), %xmm2
addsd %xmm2, %xmm1
mulsd %xmm2, %xmm2
addsd %xmm2, %xmm0
incq %rcx
cmpq %rcx, %r14
jne 0x3d2e
movsd %xmm1, 0xe0(%rsp,%rbx,8)
movsd %xmm0, 0xc0(%rsp,%rbx,8)
movsd 0xe0(%rsp,%rbx,8), %xmm2
movsd 0x18(%rsp), %xmm1
divsd %xmm1, %xmm2
movsd %xmm2, 0xe0(%rsp,%rbx,8)
movsd 0xc0(%rsp,%rbx,8), %xmm0
divsd %xmm1, %xmm0
ucomisd %xmm3, %xmm0
jb 0x3d91
sqrtsd %xmm0, %xmm0
jmp 0x3da6
movsd %xmm2, 0x10(%rsp)
callq 0x3210
movsd 0x10(%rsp), %xmm2
xorpd %xmm3, %xmm3
movsd %xmm0, 0xc0(%rsp,%rbx,8)
mulsd %xmm2, %xmm2
mulsd %xmm0, %xmm0
subsd %xmm2, %xmm0
ucomisd %xmm3, %xmm0
jb 0x3dc7
sqrtsd %xmm0, %xmm0
jmp 0x3dd0
callq 0x3210
xorpd %xmm3, %xmm3
movsd %xmm0, 0x140(%rsp,%rbx,8)
incq %rbx
cmpq $0x3, %rbx
jne 0x3d0d
movq 0x20(%rsp), %rsi
movsd 0xe0(%rsp), %xmm0
movsd 0xe8(%rsp), %xmm1
movsd 0xf0(%rsp), %xmm2
leaq 0xa4e1(%rip), %rdi      # 0xe2ee
movb $0x3, %al
callq 0x3050
movq 0x20(%rsp), %rsi
movsd 0xc0(%rsp), %xmm0
movsd 0xc8(%rsp), %xmm1
movsd 0xd0(%rsp), %xmm2
leaq 0xa4e7(%rip), %rdi      # 0xe322
movb $0x3, %al
callq 0x3050
movq 0x20(%rsp), %rsi
movsd 0x140(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x148(%rsp), %xmm1
movsd %xmm1, 0x10(%rsp)
movsd 0x150(%rsp), %xmm2
movsd %xmm2, 0x158(%rsp)
leaq 0xa4d8(%rip), %rdi      # 0xe356
movb $0x3, %al
callq 0x3050
movsd 0x158(%rsp), %xmm0
movq 0x20(%rsp), %rbx
movsd 0x10(%rsp), %xmm2
mulsd %xmm2, %xmm2
movsd 0x18(%rsp), %xmm1
mulsd %xmm1, %xmm1
addsd %xmm2, %xmm1
mulsd %xmm0, %xmm0
addsd %xmm1, %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x3ec3
sqrtsd %xmm0, %xmm0
jmp 0x3ec8
callq 0x3210
leaq 0x30(%rsp), %r14
leaq 0xa4b6(%rip), %rdi      # 0xe38a
movq %rbx, %rsi
movb $0x1, %al
callq 0x3050
movq 0x20(%rsp), %rsi
leaq 0xa4cc(%rip), %rdi      # 0xe3b6
leaq 0xa53a(%rip), %rdx      # 0xe42b
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x3050
movq 0x120(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x3f0c
callq 0x3350
movq $0x0, 0x120(%rsp,%rbx,8)
incq %rbx
cmpq $0x3, %rbx
jne 0x3efa
leaq 0x1a0(%rsp), %rdi
callq 0x4b40
movq 0x100(%rsp), %rdi
leaq 0x110(%rsp), %rax
cmpq %rax, %rdi
je 0x3f53
movq 0x110(%rsp), %rsi
incq %rsi
callq 0x32a0
movq 0x20(%rsp), %rdi
cmpq %r14, %rdi
je 0x3f6a
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x32a0
xorl %eax, %eax
addq $0x3d8, %rsp            # imm = 0x3D8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3fc2
jmp 0x3fd6
movq %rax, %rbx
movq 0x160(%rsp), %rdi
cmpq %r14, %rdi
je 0x3fd9
movq 0x170(%rsp), %rsi
jmp 0x3fb6
jmp 0x3fc2
movq %rax, %rbx
movq 0x180(%rsp), %rdi
cmpq %r14, %rdi
je 0x3fd9
movq 0x190(%rsp), %rsi
incq %rsi
callq 0x32a0
jmp 0x3fd9
jmp 0x3fd6
movq %rax, %rbx
jmp 0x3fe6
movq %rax, %rbx
jmp 0x400b
jmp 0x3fd6
jmp 0x3fd6
jmp 0x3fd6
jmp 0x3fd6
jmp 0x3fd6
movq %rax, %rbx
leaq 0x1a0(%rsp), %rdi
callq 0x4b40
movq 0x100(%rsp), %rdi
leaq 0x110(%rsp), %rax
cmpq %rax, %rdi
je 0x400b
movq 0x110(%rsp), %rsi
incq %rsi
callq 0x32a0
movq 0x20(%rsp), %rdi
leaq 0x30(%rsp), %rax
cmpq %rax, %rdi
je 0x4027
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x32a0
movq %rbx, %rdi
callq 0x3480
nop