// File: /workspace/github_cpp_makefile_star2_O3/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 0x40f9c
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 0x40ecb
movq %rax, 0xc98(%rbx)
movq 0xca8(%rbx), %rax
cmpq %rax, 0xcb0(%rbx)
je 0x40ee2
movq %rax, 0xcb0(%rbx)
movq 0xcc0(%rbx), %rax
cmpq %rax, 0xcc8(%rbx)
je 0x40ef9
movq %rax, 0xcc8(%rbx)
movq 0xcd8(%rbx), %rax
cmpq %rax, 0xce0(%rbx)
je 0x40f10
movq %rax, 0xce0(%rbx)
movq 0xcf0(%rbx), %rax
cmpq %rax, 0xcf8(%rbx)
je 0x40f27
movq %rax, 0xcf8(%rbx)
movq 0xd08(%rbx), %rax
cmpq %rax, 0xd10(%rbx)
je 0x40f3e
movq %rax, 0xd10(%rbx)
leaq 0xcf0(%rbx), %rax
movq %rax, 0x68(%rsp)
leaq 0xd08(%rbx), %rax
movq %rax, 0x70(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm2, %xmm4
cmpnltpd %xmm0, %xmm4
movapd %xmm1, %xmm3
cmpnltpd %xmm0, %xmm3
andpd %xmm4, %xmm3
movd %xmm3, %eax
movl %eax, 0x34(%rsp)
testb $0x1, %al
je 0x40fbd
movapd %xmm2, %xmm0
minsd %xmm1, %xmm0
maxsd %xmm2, %xmm1
movapd %xmm1, 0xd0(%rsp)
movapd %xmm0, 0xc0(%rsp)
jmp 0x40fcf
movq 0x15404d(%rip), %rdi    # 0x194ff0
leaq 0x110ace(%rip), %rsi    # 0x151a78
movl $0x4e, %edx
callq 0x44e0
xorpd %xmm0, %xmm0
jmp 0x415b9
movapd %xmm1, 0xc0(%rsp)
movapd %xmm2, 0xd0(%rsp)
movl 0x34(%rsp), %eax
andb $0x1, %al
movb %al, 0xc8c(%rbx)
movl $0x3b4ca6f5, %edi       # imm = 0x3B4CA6F5
callq 0x4410
xorps %xmm0, %xmm0
cvtsi2sd %ebp, %xmm0
movsd %xmm0, 0x38(%rsp)
leaq 0x80(%rbx), %rdi
callq 0x83b30
mulsd 0x38(%rsp), %xmm0
cvttsd2si %xmm0, %ebp
movl %ebp, 0xc78(%rbx)
movq 0x153fab(%rip), %r14    # 0x194fc0
leaq 0x110aab(%rip), %rsi    # 0x151ac7
movl $0x22, %edx
movq %r14, %rdi
callq 0x44e0
movq %r14, %rdi
movl %ebp, %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 %r15d, %r15d
leaq 0xa8(%rsp), %r14
movl %r15d, (%r14)
movq 0x68(%rsp), %rdi
movq %r14, %rdx
callq 0x48a3e
movslq 0xa6c(%rbx), %rsi
movl $0x0, 0x30(%rsp)
movl %r15d, (%r14)
leaq 0xa8(%rsp), %rdx
movq 0x70(%rsp), %rdi
callq 0x48a3e
movl $0x0, 0x24(%rsp)
movl $0x0, 0x28(%rsp)
movl $0x0, 0x2c(%rsp)
movl %ebp, 0x4c(%rsp)
testl %ebp, %ebp
jle 0x414a3
leaq 0x990(%rbx), %r13
leaq 0xc90(%rbx), %rax
movq %rax, 0x58(%rsp)
leaq 0xca8(%rbx), %rax
movq %rax, 0x98(%rsp)
leaq 0xcc0(%rbx), %rax
movq %rax, 0x60(%rsp)
leaq 0xcd8(%rbx), %rax
movq %rax, 0xa0(%rsp)
movl $0x0, 0x2c(%rsp)
leaq 0x80(%rsp), %r12
xorl %ebp, %ebp
movl $0x0, 0x28(%rsp)
movl $0x0, 0x24(%rsp)
movl $0x0, 0x30(%rsp)
callq 0x4150
xorps %xmm1, %xmm1
cvtsi2sd %eax, %xmm1
movsd 0x1104ae(%rip), %xmm0   # 0x1515f0
divsd %xmm0, %xmm1
movsd %xmm1, 0x38(%rsp)
callq 0x4150
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
divsd 0x110490(%rip), %xmm0   # 0x1515f0
movsd %xmm0, 0x50(%rsp)
callq 0x4150
xorps %xmm2, %xmm2
cvtsi2sd %eax, %xmm2
divsd 0x110476(%rip), %xmm2   # 0x1515f0
leaq 0xa8(%rsp), %rdi
movq %rbx, %rsi
movsd 0x38(%rsp), %xmm0
movsd 0x50(%rsp), %xmm1
movsd %xmm2, 0x78(%rsp)
callq 0x52d94
movq 0xb8(%rsp), %rax
movq %rax, 0x10(%rsp)
movupd 0xa8(%rsp), %xmm0
movupd %xmm0, (%rsp)
movq %r13, %rdi
callq 0x95036
movl %eax, %r14d
movq %r13, %rdi
callq 0x48a72
movl %eax, %r15d
movq %r13, %rdi
callq 0x48a72
testb %al, %al
jne 0x4120c
testb $0x1, %r14b
jne 0x4120c
movl %r14d, %eax
andl $0x100, %eax            # imm = 0x100
je 0x4120c
movq %r13, %rdi
callq 0x48aea
movq %rax, 0x40(%rsp)
cmpl $-0x1, %eax
jne 0x41257
sarq $0x20, %rax
movq 0x70(%rsp), %rcx
movq (%rcx), %rcx
incl (%rcx,%rax,4)
jmp 0x4126f
shrl $0x8, %r14d
andl $0x1, %r14d
movq %r13, %rdi
callq 0x48a72
orb %r14b, %al
jne 0x4148f
movq %r13, %rdi
callq 0x48aea
movq %rax, 0x40(%rsp)
movabsq $-0x100000001, %rcx     # imm = 0xFFFFFFFEFFFFFFFF
cmpq %rcx, %rax
jbe 0x412ce
movq 0x68(%rsp), %rcx
movq (%rcx), %rcx
cltq
incl (%rcx,%rax,4)
jmp 0x412e6
movl $0x3d, %edx
movq 0x153d5d(%rip), %rdi    # 0x194fc0
leaq 0x1104e6(%rip), %rsi    # 0x151750
callq 0x44e0
testb $0x1, 0x34(%rsp)
jne 0x413eb
movq %r12, %rdi
movsd 0x38(%rsp), %xmm0
movsd 0x50(%rsp), %xmm1
movsd 0x78(%rsp), %xmm2
callq 0x83f68
movq 0xcc8(%rbx), %rsi
cmpq 0xcd0(%rbx), %rsi
je 0x413a9
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsi)
movupd 0x80(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0xcc8(%rbx)
jmp 0x413b6
movl $0x3f, %edx
movq 0x153ce6(%rip), %rdi    # 0x194fc0
leaq 0x1104ad(%rip), %rsi    # 0x15178e
callq 0x44e0
movq %r12, %rdi
movsd 0x38(%rsp), %xmm0
movsd 0x50(%rsp), %xmm1
movsd 0x78(%rsp), %xmm2
callq 0x83f68
testb $0x1, 0x34(%rsp)
je 0x4136f
movsd 0xad8(%rbx), %xmm0
ucomisd 0xc0(%rsp), %xmm0
movapd 0xd0(%rsp), %xmm1
jb 0x413fc
ucomisd %xmm0, %xmm1
jb 0x413fc
incl 0x24(%rsp)
movq 0xc98(%rbx), %rsi
cmpq 0xca0(%rbx), %rsi
je 0x4147e
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsi)
movupd 0x80(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0xc98(%rbx)
jmp 0x4148b
movq 0xc98(%rbx), %rsi
cmpq 0xca0(%rbx), %rsi
je 0x41433
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsi)
movupd 0x80(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0xc98(%rbx)
jmp 0x41440
movq 0x60(%rsp), %rdi
movq %r12, %rdx
callq 0x2fec4
movq 0xce0(%rbx), %rsi
cmpq 0xce8(%rbx), %rsi
je 0x413d9
movl 0x44(%rsp), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0xce0(%rbx)
jmp 0x413eb
movq 0xa0(%rsp), %rdi
leaq 0x44(%rsp), %rdx
callq 0xf864
incl 0x30(%rsp)
movq %r13, %rdi
callq 0x48a72
jmp 0x4148f
incl 0x28(%rsp)
movq 0xcc8(%rbx), %rsi
cmpq 0xcd0(%rbx), %rsi
je 0x41477
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsi)
movupd 0x80(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0xcc8(%rbx)
jmp 0x4148b
movq 0x58(%rsp), %rdi
movq %r12, %rdx
callq 0x2fec4
movq 0xcb0(%rbx), %rsi
cmpq 0xcb8(%rbx), %rsi
je 0x41463
movl 0x40(%rsp), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0xcb0(%rbx)
jmp 0x4148b
movq 0x98(%rsp), %rdi
leaq 0x40(%rsp), %rdx
callq 0xf864
jmp 0x4148b
movq 0x60(%rsp), %rdi
jmp 0x41483
movq 0x58(%rsp), %rdi
movq %r12, %rdx
callq 0x2fec4
incl 0x2c(%rsp)
movzbl %r15b, %eax
negl %eax
addl %eax, %ebp
incl %ebp
cmpl 0x4c(%rsp), %ebp
jl 0x4112e
movl 0xb18(%rbx), %r15d
testl %r15d, %r15d
movl 0x4c(%rsp), %ebp
je 0x41585
movq 0x153b32(%rip), %r13    # 0x194ff0
leaq 0x112159(%rip), %r14    # 0x15361e
movl $0x1, %edx
movq %r13, %rdi
movq %r14, %rsi
callq 0x44e0
movl $0x1, %edx
movq %r13, %rdi
movq %r14, %rsi
callq 0x44e0
leaq 0x1102e2(%rip), %rsi    # 0x1517ce
movl $0x13, %edx
movq %r13, %rdi
callq 0x44e0
movq %r13, %rdi
movl %r15d, %esi
callq 0x4750
movq %rax, %r15
leaq 0x1102d4(%rip), %rsi    # 0x1517e2
movl $0xf, %edx
movq %rax, %rdi
callq 0x44e0
movq %r15, %rdi
movl %ebp, %esi
callq 0x4750
movq %rax, %r15
leaq 0x11be37(%rip), %rsi    # 0x15d366
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 0x2c(%rsp), %ecx
movl %ecx, 0xc7c(%rbx)
movl 0x30(%rsp), %eax
movl %eax, 0xc80(%rbx)
movl 0x24(%rsp), %eax
movl %eax, 0xc84(%rbx)
movl 0x28(%rsp), %eax
movl %eax, 0xc88(%rbx)
movl %ecx, %eax
cltd
idivl %ebp
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq