// File: 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
movq %rsp, %rbp
subq $0xa10, %rsp            # imm = 0xA10
movl $0x0, -0x4(%rbp)
leaq -0x29(%rbp), %rdi
movq %rdi, -0x9c0(%rbp)
callq 0x3560
movq -0x9c0(%rbp), %rdx
leaq 0x11960(%rip), %rsi     # 0x150e0
leaq -0x28(%rbp), %rdi
callq 0x4620
jmp 0x378b
leaq -0x29(%rbp), %rdi
callq 0x3350
leaq -0x61(%rbp), %rdi
movq %rdi, -0x9c8(%rbp)
callq 0x3560
movq -0x9c8(%rbp), %rdx
leaq 0x1193c(%rip), %rsi     # 0x150ee
leaq -0x60(%rbp), %rdi
callq 0x4620
jmp 0x37bd
leaq -0x61(%rbp), %rdi
callq 0x3350
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
leaq 0x11921(%rip), %rdi     # 0x150fa
xorl %eax, %eax
callq 0x3050
jmp 0x37e2
leaq -0x2a0(%rbp), %rdi
callq 0x46d0
jmp 0x37f0
leaq -0x2c0(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x3140
jmp 0x3802
leaq -0x2a0(%rbp), %rdi
leaq -0x2c0(%rbp), %rsi
callq 0x4930
jmp 0x3817
leaq -0x2c0(%rbp), %rdi
callq 0x31e0
leaq -0x2a0(%rbp), %rdi
callq 0x49a0
movsd %xmm0, -0x9d0(%rbp)
jmp 0x3839
movsd -0x9d0(%rbp), %xmm0
movsd %xmm0, -0x2c8(%rbp)
movsd 0x117b7(%rip), %xmm0    # 0x15008
mulsd -0x2c8(%rbp), %xmm0
movsd %xmm0, -0x2d0(%rbp)
movl $0x7b, -0x2d4(%rbp)
movsd -0x2d0(%rbp), %xmm0
cvtsi2sdl -0x2d4(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x2e0(%rbp)
movl $0x0, -0x2e4(%rbp)
movl -0x2e4(%rbp), %eax
cmpl -0x2d4(%rbp), %eax
jg 0x3a2c
cvtsi2sdl -0x2e4(%rbp), %xmm0
movsd -0x2e0(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -0x2f0(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
movsd -0x2f0(%rbp), %xmm0
leaq 0x11853(%rip), %rdi     # 0x1512d
movb $0x1, %al
callq 0x3050
jmp 0x38e3
movsd -0x2f0(%rbp), %xmm0
leaq -0x2a0(%rbp), %rdi
callq 0x49c0
movb %al, -0x9d1(%rbp)
jmp 0x38ff
movb -0x9d1(%rbp), %al
andb $0x1, %al
movb %al, -0x2f1(%rbp)
testb $0x1, -0x2f1(%rbp)
je 0x3a16
movaps 0x1295f(%rip), %xmm0    # 0x16280
movaps %xmm0, -0x310(%rbp)
movabsq $0x3fd3333333333333, %rax # imm = 0x3FD3333333333333
movq %rax, -0x300(%rbp)
leaq -0x2a0(%rbp), %rdi
leaq -0x310(%rbp), %rsi
leaq -0x330(%rbp), %rdx
callq 0x4a20
jmp 0x3955
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
movsd -0x310(%rbp), %xmm0
movsd -0x308(%rbp), %xmm1
movsd -0x300(%rbp), %xmm2
movsd -0x330(%rbp), %xmm3
movsd -0x328(%rbp), %xmm4
movsd -0x320(%rbp), %xmm5
leaq 0x117a2(%rip), %rdi     # 0x1513a
movb $0x6, %al
callq 0x3050
jmp 0x39a1
jmp 0x3a16
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x29(%rbp), %rdi
callq 0x3350
jmp 0x4608
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x61(%rbp), %rdi
callq 0x3350
jmp 0x45ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x45f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x3bc1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x2c0(%rbp), %rdi
callq 0x31e0
jmp 0x3bc1
jmp 0x3a18
movl -0x2e4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2e4(%rbp)
jmp 0x3891
leaq -0x2a0(%rbp), %rdi
callq 0x5a70
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
leaq 0x11733(%rip), %rdi     # 0x1517e
xorl %eax, %eax
callq 0x3050
jmp 0x3a54
leaq -0x568(%rbp), %rdi
callq 0x46d0
jmp 0x3a62
leaq -0x588(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x3140
jmp 0x3a74
leaq -0x568(%rbp), %rdi
leaq -0x588(%rbp), %rsi
callq 0x4930
jmp 0x3a89
leaq -0x588(%rbp), %rdi
callq 0x31e0
leaq -0x568(%rbp), %rdi
callq 0x49a0
movsd %xmm0, -0x9e0(%rbp)
jmp 0x3aab
movsd -0x9e0(%rbp), %xmm0
movsd 0x1154d(%rip), %xmm1    # 0x15008
mulsd %xmm1, %xmm0
leaq -0x568(%rbp), %rdi
callq 0x49c0
jmp 0x3acd
movq 0x127cc(%rip), %rax     # 0x162a0
movq %rax, -0x5a0(%rbp)
movq 0x127c6(%rip), %rax     # 0x162a8
movq %rax, -0x598(%rbp)
movq 0x127c0(%rip), %rax     # 0x162b0
movq %rax, -0x590(%rbp)
movq 0x127c2(%rip), %rax     # 0x162c0
movq %rax, -0x5c0(%rbp)
movq 0x127bc(%rip), %rax     # 0x162c8
movq %rax, -0x5b8(%rbp)
movq 0x127b6(%rip), %rax     # 0x162d0
movq %rax, -0x5b0(%rbp)
movq 0x127b0(%rip), %rax     # 0x162d8
movq %rax, -0x5cc(%rbp)
movl 0x127ab(%rip), %eax     # 0x162e0
movl %eax, -0x5c4(%rbp)
movl -0x5cc(%rbp), %eax
imull -0x5c8(%rbp), %eax
imull -0x5c4(%rbp), %eax
cltq
movq %rax, -0x5d8(%rbp)
movl $0x0, -0x5f4(%rbp)
cmpl $0x3, -0x5f4(%rbp)
jge 0x3c00
movq -0x5d8(%rbp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x3030
movq %rax, -0x9e8(%rbp)
jmp 0x3b9a
movq -0x9e8(%rbp), %rcx
movslq -0x5f4(%rbp), %rax
movq %rcx, -0x5f0(%rbp,%rax,8)
movl -0x5f4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5f4(%rbp)
jmp 0x3b62
leaq -0x2a0(%rbp), %rdi
callq 0x5a70
jmp 0x45f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x3f0d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x588(%rbp), %rdi
callq 0x31e0
jmp 0x3f0d
leaq -0x568(%rbp), %rdi
leaq -0x5a0(%rbp), %rsi
leaq -0x5c0(%rbp), %rdx
leaq -0x5cc(%rbp), %rcx
leaq -0x5f0(%rbp), %r8
callq 0x5bd0
jmp 0x3c2a
movl $0x3, -0x5f8(%rbp)
movl $0x0, -0x5fc(%rbp)
movl $0xa, -0x600(%rbp)
movl -0x600(%rbp), %eax
movl -0x5cc(%rbp), %edx
movl -0x5c8(%rbp), %ecx
imull %ecx, %eax
imull %edx, %eax
movl -0x5fc(%rbp), %ecx
imull %edx, %ecx
addl %ecx, %eax
movl -0x5f8(%rbp), %ecx
addl %ecx, %eax
cltq
movq %rax, -0x608(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
movl -0x5f8(%rbp), %edx
movl -0x5fc(%rbp), %ecx
movl -0x600(%rbp), %r8d
movq -0x5f0(%rbp), %rax
movq -0x608(%rbp), %rdi
movss (%rax,%rdi,4), %xmm0
cvtss2sd %xmm0, %xmm0
leaq 0x11530(%rip), %rdi     # 0x151e9
movb $0x1, %al
callq 0x3050
jmp 0x3cc2
movl $0x9, -0x5f8(%rbp)
movl $0x1, -0x5fc(%rbp)
movl $0x4, -0x600(%rbp)
movl -0x600(%rbp), %eax
movl -0x5cc(%rbp), %edx
movl -0x5c8(%rbp), %ecx
imull %ecx, %eax
imull %edx, %eax
movl -0x5fc(%rbp), %ecx
imull %edx, %ecx
addl %ecx, %eax
movl -0x5f8(%rbp), %ecx
addl %ecx, %eax
cltq
movq %rax, -0x608(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
movl -0x5f8(%rbp), %edx
movl -0x5fc(%rbp), %ecx
movl -0x600(%rbp), %r8d
movq -0x5e0(%rbp), %rax
movq -0x608(%rbp), %rdi
movss (%rax,%rdi,4), %xmm0
cvtss2sd %xmm0, %xmm0
leaq 0x114e9(%rip), %rdi     # 0x1523a
movb $0x1, %al
callq 0x3050
jmp 0x3d5a
movl $0x0, -0x60c(%rbp)
cmpl $0x3, -0x60c(%rbp)
jge 0x3dcd
movslq -0x60c(%rbp), %rax
cmpq $0x0, -0x5f0(%rbp,%rax,8)
je 0x3da9
movslq -0x60c(%rbp), %rax
movq -0x5f0(%rbp,%rax,8), %rax
movq %rax, -0x9f0(%rbp)
cmpq $0x0, %rax
je 0x3da7
movq -0x9f0(%rbp), %rdi
callq 0x3440
jmp 0x3da9
movslq -0x60c(%rbp), %rax
movq $0x0, -0x5f0(%rbp,%rax,8)
movl -0x60c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60c(%rbp)
jmp 0x3d64
leaq -0x568(%rbp), %rdi
callq 0x5a70
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
leaq 0x1149f(%rip), %rdi     # 0x1528b
xorl %eax, %eax
callq 0x3050
jmp 0x3df5
leaq -0x848(%rbp), %rdi
callq 0x46d0
jmp 0x3e03
movl $0x3, -0x84c(%rbp)
movq 0x124dc(%rip), %rax     # 0x162f0
movq %rax, -0x870(%rbp)
movq 0x124d6(%rip), %rax     # 0x162f8
movq %rax, -0x868(%rbp)
movq 0x124d0(%rip), %rax     # 0x16300
movq %rax, -0x860(%rbp)
movsd 0x111f1(%rip), %xmm0    # 0x15030
movsd %xmm0, -0x878(%rbp)
movsd 0x111d9(%rip), %xmm0    # 0x15028
movsd %xmm0, -0x880(%rbp)
movl $0x2, -0x884(%rbp)
movsd 0x111b7(%rip), %xmm0    # 0x15020
movsd %xmm0, -0x890(%rbp)
movsd 0x1119f(%rip), %xmm0    # 0x15018
movsd %xmm0, -0x898(%rbp)
movsd 0x11187(%rip), %xmm0    # 0x15010
movsd %xmm0, -0x8a0(%rbp)
movl $0x223f9, -0x8a4(%rbp)  # imm = 0x223F9
movq 0x12466(%rip), %rax     # 0x16308
movq %rax, -0x8b0(%rbp)
movl 0x12461(%rip), %eax     # 0x16310
movl %eax, -0x8a8(%rbp)
movl $0x0, -0x8d4(%rbp)
cmpl $0x3, -0x8d4(%rbp)
jge 0x3f1e
movslq -0x8d4(%rbp), %rax
movsd -0x870(%rbp,%rax,8), %xmm0
movslq -0x8d4(%rbp), %rax
cvtsi2sdl -0x8b0(%rbp,%rax,4), %xmm1
divsd %xmm1, %xmm0
movslq -0x8d4(%rbp), %rax
movsd %xmm0, -0x8d0(%rbp,%rax,8)
movl -0x8d4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8d4(%rbp)
jmp 0x3ebf
leaq -0x568(%rbp), %rdi
callq 0x5a70
jmp 0x45f6
movsd -0x8d0(%rbp), %xmm1
movsd 0x11102(%rip), %xmm0    # 0x15030
divsd %xmm0, %xmm1
movsd 0x110fe(%rip), %xmm0    # 0x15038
addsd %xmm1, %xmm0
movsd %xmm0, -0x8f0(%rbp)
movsd -0x8c8(%rbp), %xmm1
movsd 0x110da(%rip), %xmm0    # 0x15030
divsd %xmm0, %xmm1
movsd 0x110d6(%rip), %xmm0    # 0x15038
addsd %xmm1, %xmm0
movsd %xmm0, -0x8e8(%rbp)
movsd -0x8c0(%rbp), %xmm1
movsd 0x110b2(%rip), %xmm0    # 0x15030
divsd %xmm0, %xmm1
movsd 0x110ae(%rip), %xmm0    # 0x15038
addsd %xmm1, %xmm0
movsd %xmm0, -0x8e0(%rbp)
movsd -0x8d0(%rbp), %xmm1
movsd 0x1108a(%rip), %xmm0    # 0x15030
divsd %xmm0, %xmm1
movsd 0x1105e(%rip), %xmm0    # 0x15010
subsd %xmm1, %xmm0
movsd %xmm0, -0x910(%rbp)
movsd -0x8c8(%rbp), %xmm1
movsd 0x11062(%rip), %xmm0    # 0x15030
divsd %xmm0, %xmm1
movsd 0x11036(%rip), %xmm0    # 0x15010
subsd %xmm1, %xmm0
movsd %xmm0, -0x908(%rbp)
movsd -0x8c0(%rbp), %xmm1
movsd 0x1103a(%rip), %xmm0    # 0x15030
divsd %xmm0, %xmm1
movsd 0x1100e(%rip), %xmm0    # 0x15010
subsd %xmm1, %xmm0
movsd %xmm0, -0x900(%rbp)
movl -0x8b0(%rbp), %eax
imull -0x8ac(%rbp), %eax
imull -0x8a8(%rbp), %eax
cltq
movq %rax, -0x918(%rbp)
movl $0x0, -0x934(%rbp)
cmpl $0x3, -0x934(%rbp)
jge 0x40ad
movq -0x918(%rbp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x3030
movq %rax, -0x9f8(%rbp)
jmp 0x4069
movq -0x9f8(%rbp), %rcx
movslq -0x934(%rbp), %rax
movq %rcx, -0x930(%rbp,%rax,8)
movl -0x934(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x934(%rbp)
jmp 0x4035
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x848(%rbp), %rdi
callq 0x5a70
jmp 0x45f6
cvtsi2sdl -0x84c(%rbp), %xmm0
movsd -0x878(%rbp), %xmm1
movsd -0x880(%rbp), %xmm2
movl -0x884(%rbp), %edx
movsd -0x890(%rbp), %xmm3
movsd -0x898(%rbp), %xmm4
movsd -0x8a0(%rbp), %xmm5
movl -0x8a4(%rbp), %ecx
leaq -0x848(%rbp), %rdi
leaq -0x870(%rbp), %rsi
callq 0x7560
jmp 0x40fe
leaq -0x848(%rbp), %rdi
leaq -0x8f0(%rbp), %rsi
leaq -0x910(%rbp), %rdx
leaq -0x8b0(%rbp), %rcx
leaq -0x930(%rbp), %r8
callq 0x5bd0
jmp 0x4128
movl $0x3, -0x938(%rbp)
movl $0x0, -0x93c(%rbp)
movl $0xa, -0x940(%rbp)
movl -0x940(%rbp), %eax
movl -0x8b0(%rbp), %edx
movl -0x8ac(%rbp), %ecx
imull %ecx, %eax
imull %edx, %eax
movl -0x93c(%rbp), %ecx
imull %edx, %ecx
addl %ecx, %eax
movl -0x938(%rbp), %ecx
addl %ecx, %eax
cltq
movq %rax, -0x948(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
movl -0x938(%rbp), %edx
movl -0x93c(%rbp), %ecx
movl -0x940(%rbp), %r8d
movq -0x930(%rbp), %rax
movq -0x948(%rbp), %rdi
movss (%rax,%rdi,4), %xmm0
cvtss2sd %xmm0, %xmm0
leaq 0x11032(%rip), %rdi     # 0x151e9
movb $0x1, %al
callq 0x3050
jmp 0x41c0
movl $0x9, -0x938(%rbp)
movl $0x1, -0x93c(%rbp)
movl $0x4, -0x940(%rbp)
movl -0x940(%rbp), %eax
movl -0x8b0(%rbp), %edx
movl -0x8ac(%rbp), %ecx
imull %ecx, %eax
imull %edx, %eax
movl -0x93c(%rbp), %ecx
imull %edx, %ecx
addl %ecx, %eax
movl -0x938(%rbp), %ecx
addl %ecx, %eax
cltq
movq %rax, -0x948(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
movl -0x938(%rbp), %edx
movl -0x93c(%rbp), %ecx
movl -0x940(%rbp), %r8d
movq -0x920(%rbp), %rax
movq -0x948(%rbp), %rdi
movss (%rax,%rdi,4), %xmm0
cvtss2sd %xmm0, %xmm0
leaq 0x10feb(%rip), %rdi     # 0x1523a
movb $0x1, %al
callq 0x3050
jmp 0x4258
leaq -0x960(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x31b0
leaq -0x980(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x31b0
leaq -0x9a0(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x31b0
movl $0x0, -0x9a4(%rbp)
cmpl $0x3, -0x9a4(%rbp)
jge 0x443b
movq $0x0, -0x9b0(%rbp)
movq -0x9b0(%rbp), %rax
cmpq -0x918(%rbp), %rax
jge 0x435b
movslq -0x9a4(%rbp), %rax
movq -0x930(%rbp,%rax,8), %rax
movq -0x9b0(%rbp), %rcx
movss (%rax,%rcx,4), %xmm0
cvtss2sd %xmm0, %xmm0
movslq -0x9a4(%rbp), %rax
addsd -0x960(%rbp,%rax,8), %xmm0
movsd %xmm0, -0x960(%rbp,%rax,8)
movslq -0x9a4(%rbp), %rax
movq -0x930(%rbp,%rax,8), %rax
movq -0x9b0(%rbp), %rcx
movss (%rax,%rcx,4), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x10d0a(%rip), %xmm1    # 0x15030
callq 0x3540
movslq -0x9a4(%rbp), %rax
addsd -0x980(%rbp,%rax,8), %xmm0
movsd %xmm0, -0x980(%rbp,%rax,8)
movq -0x9b0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x9b0(%rbp)
jmp 0x42b3
cvtsi2sdq -0x918(%rbp), %xmm1
movslq -0x9a4(%rbp), %rax
movsd -0x960(%rbp,%rax,8), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, -0x960(%rbp,%rax,8)
movslq -0x9a4(%rbp), %rax
movsd -0x980(%rbp,%rax,8), %xmm0
cvtsi2sdq -0x918(%rbp), %xmm1
divsd %xmm1, %xmm0
callq 0x3250
movslq -0x9a4(%rbp), %rax
movsd %xmm0, -0x980(%rbp,%rax,8)
movslq -0x9a4(%rbp), %rax
movsd -0x980(%rbp,%rax,8), %xmm0
movslq -0x9a4(%rbp), %rax
movsd -0x980(%rbp,%rax,8), %xmm2
movslq -0x9a4(%rbp), %rax
movsd -0x960(%rbp,%rax,8), %xmm1
movslq -0x9a4(%rbp), %rax
mulsd -0x960(%rbp,%rax,8), %xmm1
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
callq 0x3250
movslq -0x9a4(%rbp), %rax
movsd %xmm0, -0x9a0(%rbp,%rax,8)
movl -0x9a4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9a4(%rbp)
jmp 0x429b
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
movsd -0x960(%rbp), %xmm0
movsd -0x958(%rbp), %xmm1
movsd -0x950(%rbp), %xmm2
leaq 0x10e58(%rip), %rdi     # 0x152be
movb $0x3, %al
callq 0x3050
jmp 0x446f
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
movsd -0x980(%rbp), %xmm0
movsd -0x978(%rbp), %xmm1
movsd -0x970(%rbp), %xmm2
leaq 0x10e58(%rip), %rdi     # 0x152f2
movb $0x3, %al
callq 0x3050
jmp 0x44a3
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
movsd -0x9a0(%rbp), %xmm0
movsd -0x998(%rbp), %xmm1
movsd -0x990(%rbp), %xmm2
leaq 0x10e58(%rip), %rdi     # 0x15326
movb $0x3, %al
callq 0x3050
jmp 0x44d7
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, -0xa00(%rbp)
movsd -0x9a0(%rbp), %xmm1
movsd -0x998(%rbp), %xmm0
mulsd %xmm0, %xmm0
mulsd %xmm1, %xmm1
addsd %xmm0, %xmm1
movsd -0x990(%rbp), %xmm0
mulsd %xmm0, %xmm0
addsd %xmm1, %xmm0
callq 0x3250
movq -0xa00(%rbp), %rsi
leaq 0x10e34(%rip), %rdi     # 0x1535a
movb $0x1, %al
callq 0x3050
jmp 0x452f
leaq -0x28(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
leaq 0x10e44(%rip), %rdi     # 0x15386
leaq 0x10eb2(%rip), %rdx     # 0x153fb
xorl %eax, %eax
callq 0x3050
jmp 0x4552
movl $0x0, -0x9b4(%rbp)
cmpl $0x3, -0x9b4(%rbp)
jge 0x45c5
movslq -0x9b4(%rbp), %rax
cmpq $0x0, -0x930(%rbp,%rax,8)
je 0x45a1
movslq -0x9b4(%rbp), %rax
movq -0x930(%rbp,%rax,8), %rax
movq %rax, -0xa08(%rbp)
cmpq $0x0, %rax
je 0x459f
movq -0xa08(%rbp), %rdi
callq 0x3440
jmp 0x45a1
movslq -0x9b4(%rbp), %rax
movq $0x0, -0x930(%rbp,%rax,8)
movl -0x9b4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9b4(%rbp)
jmp 0x455c
leaq -0x848(%rbp), %rdi
callq 0x5a70
movl $0x0, -0x4(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x31e0
leaq -0x28(%rbp), %rdi
callq 0x31e0
movl -0x4(%rbp), %eax
addq $0xa10, %rsp            # imm = 0xA10
popq %rbp
retq
leaq -0x60(%rbp), %rdi
callq 0x31e0
leaq -0x28(%rbp), %rdi
callq 0x31e0
movq -0x38(%rbp), %rdi
callq 0x3550
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)