// File: /workspace/github_cpp_makefile_star2_O1/Luthaf[P]zeopp/area_and_volume.cc
// Function: NEWcalcAV(MATERIAL*, double, int, double, double)
double NEWcalcAV(MATERIAL *Mat, double r_probe, int numSamples, double low_dist_cutoff, double high_dist_cutoff){

  // Inital checks
  if(!(Mat->accessAnalysis.alreadySegmentedFlag))
      {
      cerr << "Cannot run calcAV without prior accessibility analysis.\nExiting with return 0\n";
      return 0;
      }

  // Setting parameters
  Mat->AVprobeRadius = r_probe;

  // Cleaning structures in case of previous runs
  Mat->AVcount = 0; 
  Mat->AVcount_inaxs = 0; 
  Mat->AVcount_within_range = 0; 
  Mat->AVcount_outside_range = 0;
  Mat->AVaxsPoints.clear(); 
  Mat->AVaxsPointsChannelIDs.clear(); 
  Mat->AVinaxsPoints.clear(); 
  Mat->AVinaxsPointsPocketIDs.clear(); 
  Mat->AVcount_inChannel.clear();
  Mat->AVcount_inPocket.clear();


  //determine whether we are only sampling volume within a specific distance range of the surface
  bool within_range = false;
  if(!(low_dist_cutoff<0 || high_dist_cutoff<0)) {
    if(high_dist_cutoff<low_dist_cutoff) { //swap them
      double temp = low_dist_cutoff;
      low_dist_cutoff = high_dist_cutoff;
      high_dist_cutoff = temp;
    }
    within_range = true;
  }

  Mat->AVwithin_rangeFlag = within_range;

  // setting up MC sampling
  srand(randSeed);

  numSamples = int(numSamples * calcDeterminant(Mat->atmnet.ucVectors));
  Mat->AVnumSamples = numSamples;

  cout << "Number of samples in volume calc: " << numSamples << endl;

  bool excludePockets = true; // this is default (in old version, without voro-stuff it was used)

  int count = 0;
  int count_inaxs = 0;
  int count_within_range = 0;
  int count_outside_range = 0;

  // MC statistics can be collected w.r.t to identified channels and inaccessible pockets
  Mat->AVcount_inChannel.resize(Mat->accessAnalysis.n_channels,0);
  Mat->AVcount_inPocket.resize(Mat->accessAnalysis.n_pockets,0);

  for(int i = 0; i < numSamples; i++){
    bool overlaps = false;
    bool inside = false;

    // Randomly sample point across the unit cell
    double aPoint = (rand()*1.0)/RAND_MAX;
    double bPoint = (rand()*1.0)/RAND_MAX;
    double cPoint = (rand()*1.0)/RAND_MAX;

    // Convert coords relative to the unit cell vectors into (x,y,z) coords
    Point samplingPoint = Mat->atmnet.abc_to_xyz(aPoint, bPoint, cPoint);

    // Calling accessibility object to determine accessibility of the point (this replaced a big chunk of code by Thomas)
    pair<bool,bool> answer = (Mat->accessAnalysis.isVPointInsideAtomAndNotAccessible(samplingPoint));
    inside = answer.first; overlaps = answer.second;
    if(Mat->accessAnalysis.needToResample() == true) i--; // the sampled point could not be analyzed in isVPointInsideAtomAndNotAccessible() function, resampling needed

    if(inside == false && excludePockets == false) overlaps = false; // if ignore inacceible pockets, treat the point as accessible (unless inside atom)
      
    // Store sampled points that did not overlap with an atom but were inaccessible for later visualization
    if(Mat->accessAnalysis.needToResample() == false && !inside && overlaps){
      count_inaxs++;
      pair <int,int> CoP = Mat->accessAnalysis.lastChannelOrPocket();
      if(CoP.first!=-1) 
        {
        cout << "Error: CoP.first!=-1 in pocket, consult source code provider\n";
        } else {
        Mat->AVcount_inPocket[CoP.second]++;
        };
      if(!within_range) {
        //Point abcCoords = Point(aPoint, bPoint, cPoint); // to be removed as now we store fractional coordinates
        //Point coords = Mat->atmnet.abc_to_xyz(abcCoords);
        Point coords = Point(aPoint, bPoint, cPoint);
        Mat->AVinaxsPoints.push_back(coords);
        Mat->AVinaxsPointsPocketIDs.push_back(CoP.second);
      };
    };

    // Store accessible points for later visualization
    if(Mat->accessAnalysis.needToResample() == false && !overlaps) {
      count++;     
      pair <int,int> CoP = Mat->accessAnalysis.lastChannelOrPocket();
      if(CoP.second!=-1) 
        {
        cout << "Error: CoP.second!=-1 in channel, consult source code provider\n";
        } else {
        Mat->AVcount_inChannel[CoP.first]++;
        };
      //Point abcCoords = Point(aPoint, bPoint, cPoint);  // to be removed as now we store fractional coordinates
      //Point coords = Mat->atmnet.abc_to_xyz(abcCoords);
      Point coords = Point(aPoint, bPoint, cPoint);
      if(within_range) {
        if(Mat->accessAnalysis.lastMinDist() >= low_dist_cutoff && Mat->accessAnalysis.lastMinDist() <= high_dist_cutoff) { //NOTE: minDist is the distance between centroids, it is NOT the distance to the surface - here we are comparing this distance to the tolerance range
                                                                               // RECHECK IF STILL TRUE FOR NON INFLATED ATOMS
          count_within_range++;
          Mat->AVaxsPoints.push_back(coords);
        } else {
          count_outside_range++;
          Mat->AVinaxsPoints.push_back(coords);
        }
      } else 
      {
      Mat->AVaxsPoints.push_back(coords); 
      Mat->AVaxsPointsChannelIDs.push_back(CoP.first);
      };
    }
  }; // ends a for loop over all sampled points

  // Warn user if points were resampled
  int resampleCount =  Mat->accessAnalysis.getResampleCount();
  if(resampleCount != 0){
    cerr << "\n" << "\n"
         << "Warning: Resampled " << resampleCount << " points out of " << numSamples
         << " when analyzing " << Mat->atmnet.name << "\n"
         << "\n" << "\n";
  };

  Mat->AVcount = count;
  Mat->AVcount_inaxs = count_inaxs;
  Mat->AVcount_within_range = count_within_range;
  Mat->AVcount_outside_range = count_outside_range;


  return count/numSamples;

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
cmpb $0x0, 0xb1d(%rdi)
je 0x414e3
movl %esi, %ebp
movq %rdi, %rbx
movsd %xmm0, 0xc70(%rdi)
xorpd %xmm0, %xmm0
movupd %xmm0, 0xc7c(%rdi)
movq 0xc90(%rdi), %rax
cmpq %rax, 0xc98(%rdi)
je 0x41412
movq %rax, 0xc98(%rbx)
movq 0xca8(%rbx), %rax
cmpq %rax, 0xcb0(%rbx)
je 0x41429
movq %rax, 0xcb0(%rbx)
movq 0xcc0(%rbx), %rax
cmpq %rax, 0xcc8(%rbx)
je 0x41440
movq %rax, 0xcc8(%rbx)
movq 0xcd8(%rbx), %rax
cmpq %rax, 0xce0(%rbx)
je 0x41457
movq %rax, 0xce0(%rbx)
movq 0xcf0(%rbx), %rax
cmpq %rax, 0xcf8(%rbx)
je 0x4146e
movq %rax, 0xcf8(%rbx)
movq 0xd08(%rbx), %rax
cmpq %rax, 0xd10(%rbx)
je 0x41485
movq %rax, 0xd10(%rbx)
leaq 0xcf0(%rbx), %rax
movq %rax, 0x70(%rsp)
leaq 0xd08(%rbx), %rax
movq %rax, 0x68(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm2, %xmm4
cmpnltpd %xmm0, %xmm4
movapd %xmm1, %xmm3
cmpnltpd %xmm0, %xmm3
andpd %xmm4, %xmm3
movd %xmm3, %eax
movl %eax, 0x3c(%rsp)
testb $0x1, %al
je 0x41504
movapd %xmm2, %xmm0
minsd %xmm1, %xmm0
maxsd %xmm2, %xmm1
movapd %xmm1, 0xd0(%rsp)
movapd %xmm0, 0xc0(%rsp)
jmp 0x41516
movq 0x155b06(%rip), %rdi    # 0x196ff0
leaq 0x1124d7(%rip), %rsi    # 0x1539c8
movl $0x4e, %edx
callq 0x44e0
xorpd %xmm0, %xmm0
jmp 0x41af4
movapd %xmm1, 0xc0(%rsp)
movapd %xmm2, 0xd0(%rsp)
movl 0x3c(%rsp), %eax
andb $0x1, %al
movb %al, 0xc8c(%rbx)
movl $0x3b4ca6f5, %edi       # imm = 0x3B4CA6F5
callq 0x4410
xorps %xmm0, %xmm0
cvtsi2sd %ebp, %xmm0
movsd %xmm0, 0x40(%rsp)
leaq 0x80(%rbx), %rdi
callq 0x84ffd
mulsd 0x40(%rsp), %xmm0
cvttsd2si %xmm0, %r15d
movl %r15d, 0xc78(%rbx)
movq 0x155a62(%rip), %r14    # 0x196fc0
leaq 0x1124b2(%rip), %rsi    # 0x153a17
movl $0x22, %edx
movq %r14, %rdi
callq 0x44e0
movq %r14, %rdi
movl %r15d, %esi
callq 0x4750
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x4420
movsbl %al, %esi
movq %r14, %rdi
callq 0x4040
movq %rax, %rdi
callq 0x42c0
movslq 0xa68(%rbx), %rsi
xorl %ebp, %ebp
leaq 0xa8(%rsp), %r14
movl %ebp, (%r14)
movq 0x70(%rsp), %rdi
movq %r14, %rdx
callq 0x49326
movslq 0xa6c(%rbx), %rsi
movl $0x0, 0x38(%rsp)
movl %ebp, (%r14)
leaq 0xa8(%rsp), %rdx
movq 0x68(%rsp), %rdi
callq 0x49326
movl $0x0, 0x2c(%rsp)
movl $0x0, 0x30(%rsp)
movl $0x0, 0x34(%rsp)
movl %r15d, 0x4c(%rsp)
testl %r15d, %r15d
jle 0x419db
leaq 0x990(%rbx), %r13
leaq 0xc90(%rbx), %rax
movq %rax, 0x60(%rsp)
leaq 0xca8(%rbx), %rax
movq %rax, 0xa0(%rsp)
leaq 0xcc0(%rbx), %rax
movq %rax, 0x58(%rsp)
leaq 0xcd8(%rbx), %rax
movq %rax, 0x98(%rsp)
movl $0x0, 0x34(%rsp)
leaq 0x80(%rsp), %r14
movq 0x15595a(%rip), %rbp    # 0x196fc0
xorl %r12d, %r12d
movl $0x0, 0x30(%rsp)
movl $0x0, 0x2c(%rsp)
movl $0x0, 0x38(%rsp)
callq 0x4150
xorps %xmm1, %xmm1
cvtsi2sd %eax, %xmm1
movsd 0x111ecb(%rip), %xmm0   # 0x153560
divsd %xmm0, %xmm1
movsd %xmm1, 0x40(%rsp)
callq 0x4150
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
divsd 0x111ead(%rip), %xmm0   # 0x153560
movsd %xmm0, 0x50(%rsp)
callq 0x4150
xorps %xmm2, %xmm2
cvtsi2sd %eax, %xmm2
divsd 0x111e93(%rip), %xmm2   # 0x153560
leaq 0xa8(%rsp), %rdi
movq %rbx, %rsi
movsd 0x40(%rsp), %xmm0
movsd 0x50(%rsp), %xmm1
movsd %xmm2, 0x78(%rsp)
callq 0x53092
movq 0xb8(%rsp), %rax
movq %rax, 0x10(%rsp)
movupd 0xa8(%rsp), %xmm0
movupd %xmm0, (%rsp)
movq %r13, %rdi
callq 0x970b0
movl %eax, %r15d
movq %r13, %rdi
callq 0x4935a
movb %al, 0x1f(%rsp)
movq %r13, %rdi
callq 0x4935a
testb %al, %al
jne 0x41829
testb $0x1, %r15b
jne 0x41829
movl %r15d, %eax
andl $0x100, %eax            # imm = 0x100
je 0x41829
movq %r13, %rdi
callq 0x493cc
movq %rax, 0x20(%rsp)
cmpl $-0x1, %eax
je 0x41771
movl $0x3d, %edx
movq %rbp, %rdi
leaq 0x111f36(%rip), %rsi    # 0x1536a0
callq 0x44e0
jmp 0x41781
movslq 0x24(%rsp), %rax
movq 0x68(%rsp), %rcx
movq (%rcx), %rcx
incl (%rcx,%rax,4)
testb $0x1, 0x3c(%rsp)
jne 0x41825
movq %r14, %rbp
movq %r14, %rdi
movsd 0x40(%rsp), %xmm0
movsd 0x50(%rsp), %xmm1
movsd 0x78(%rsp), %xmm2
callq 0x85436
movq 0xcc8(%rbx), %rsi
cmpq 0xcd0(%rbx), %rsi
je 0x417dc
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsi)
movupd 0x80(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0xcc8(%rbx)
jmp 0x417e9
movq 0x58(%rsp), %rdi
movq %rbp, %rdx
callq 0x3012c
movq 0xce0(%rbx), %rsi
cmpq 0xce8(%rbx), %rsi
movq 0x1557c2(%rip), %rbp    # 0x196fc0
je 0x41813
movl 0x24(%rsp), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0xce0(%rbx)
jmp 0x41825
movq 0x98(%rsp), %rdi
leaq 0x24(%rsp), %rdx
callq 0xf7b4
incl 0x38(%rsp)
shrl $0x8, %r15d
andl $0x1, %r15d
movq %r13, %rdi
callq 0x4935a
orb %r15b, %al
jne 0x419c3
movq %r13, %rdi
callq 0x493cc
movq %rax, 0x20(%rsp)
cmpl $-0x1, 0x24(%rsp)
je 0x4186c
movl $0x3f, %edx
movq %rbp, %rdi
leaq 0x111e79(%rip), %rsi    # 0x1536de
callq 0x44e0
jmp 0x4187c
movslq 0x20(%rsp), %rax
movq 0x70(%rsp), %rcx
movq (%rcx), %rcx
incl (%rcx,%rax,4)
movq %r14, %rdi
movsd 0x40(%rsp), %xmm0
movsd 0x50(%rsp), %xmm1
movsd 0x78(%rsp), %xmm2
callq 0x85436
testb $0x1, 0x3c(%rsp)
je 0x418fd
movsd 0xad8(%rbx), %xmm0
ucomisd 0xc0(%rsp), %xmm0
movapd 0xd0(%rsp), %xmm1
jb 0x41930
ucomisd %xmm0, %xmm1
jb 0x41930
incl 0x2c(%rsp)
movq 0xc98(%rbx), %rsi
cmpq 0xca0(%rbx), %rsi
je 0x419b2
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsi)
movupd 0x80(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0xc98(%rbx)
jmp 0x419bf
movq 0xc98(%rbx), %rsi
cmpq 0xca0(%rbx), %rsi
je 0x41967
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsi)
movupd 0x80(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0xc98(%rbx)
jmp 0x41974
incl 0x30(%rsp)
movq 0xcc8(%rbx), %rsi
cmpq 0xcd0(%rbx), %rsi
je 0x419ab
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsi)
movupd 0x80(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0xcc8(%rbx)
jmp 0x419bf
movq 0x60(%rsp), %rdi
movq %r14, %rdx
callq 0x3012c
movq 0xcb0(%rbx), %rsi
cmpq 0xcb8(%rbx), %rsi
je 0x41997
movl 0x20(%rsp), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0xcb0(%rbx)
jmp 0x419bf
movq 0xa0(%rsp), %rdi
leaq 0x20(%rsp), %rdx
callq 0xf7b4
jmp 0x419bf
movq 0x58(%rsp), %rdi
jmp 0x419b7
movq 0x60(%rsp), %rdi
movq %r14, %rdx
callq 0x3012c
incl 0x34(%rsp)
movzbl 0x1f(%rsp), %eax
negl %eax
addl %eax, %r12d
incl %r12d
cmpl 0x4c(%rsp), %r12d
jl 0x41681
movl 0xb18(%rbx), %r15d
testl %r15d, %r15d
movl 0x4c(%rsp), %r12d
je 0x41abf
movq 0x1555f9(%rip), %r13    # 0x196ff0
leaq 0x113b30(%rip), %r14    # 0x15552e
movl $0x1, %edx
movq %r13, %rdi
movq %r14, %rsi
callq 0x44e0
movl $0x1, %edx
movq %r13, %rdi
movq %r14, %rsi
callq 0x44e0
leaq 0x111cf9(%rip), %rsi    # 0x15371e
movl $0x13, %edx
movq %r13, %rdi
callq 0x44e0
movq %r13, %rdi
movl %r15d, %esi
callq 0x4750
movq %rax, %r15
leaq 0x111ceb(%rip), %rsi    # 0x153732
movl $0xf, %edx
movq %rax, %rdi
callq 0x44e0
movq %r15, %rdi
movl %r12d, %esi
callq 0x4750
movq %rax, %r15
leaq 0x11da80(%rip), %rsi    # 0x15f4e9
movl $0x10, %edx
movq %rax, %rdi
callq 0x44e0
movq 0x320(%rbx), %rsi
movq 0x328(%rbx), %rdx
movq %r15, %rdi
callq 0x44e0
movq %rax, %r15
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x44e0
movl $0x1, %edx
movq %r15, %rdi
movq %r14, %rsi
callq 0x44e0
movl $0x1, %edx
movq %r15, %rdi
movq %r14, %rsi
callq 0x44e0
movl 0x34(%rsp), %ecx
movl %ecx, 0xc7c(%rbx)
movl 0x38(%rsp), %eax
movl %eax, 0xc80(%rbx)
movl 0x2c(%rsp), %eax
movl %eax, 0xc84(%rbx)
movl 0x30(%rsp), %eax
movl %eax, 0xc88(%rbx)
movl %ecx, %eax
cltd
idivl %r12d
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq