// File: ingowald[P]closestSurfacePointQueries/src/bvh.cpp
// Function: bvhlib::BVH::buildRec(unsigned long, ospcommon::box_t<float, 3, 1> const&, bvhlib::BuildPrim const*, std::vector<unsigned long, std::allocator<unsigned long>>&)
void BVH::buildRec(size_t nodeID,
                     const box3fa &centBounds,
                     const BuildPrim *const buildPrim,
                     std::vector<size_t> &primList)
  {
    if (primList.size() == 1) {
      size_t primID = primList[0];
      LockGuard(this->mutex);
      nodeList[nodeID].lower       = buildPrim[primID].lower;
      nodeList[nodeID].upper       = buildPrim[primID].upper;
      nodeList[nodeID].isLeaf      = 1;
      nodeList[nodeID].child       = primID;
      return;
    } else {
      Mutex mutex;

      std::atomic<size_t> lCount(0);
      std::atomic<size_t> rCount(0);
      std::vector<size_t> lPrim; lPrim.resize(primList.size());
      std::vector<size_t> rPrim; rPrim.resize(primList.size());
      box3fa lCentBounds = ospcommon::empty;
      box3fa rCentBounds = ospcommon::empty;

      size_t splitDim = widestDimension(centBounds);
      float  splitPos = centBounds.center()[splitDim];
      // bool   zeroVolume = (centBounds.lower == centBounds.upper);
        
      size_t blockSize = 1000;
      size_t numBlocks = (primList.size()+blockSize-1)/blockSize;
      for (size_t blockID=0;blockID<numBlocks;blockID++) {
        size_t begin   = blockID * blockSize;
        size_t end     = std::min(begin+blockSize,primList.size());
        box3fa lBounds = ospcommon::empty;
        box3fa rBounds = ospcommon::empty;
        for (size_t i=begin;i<end;i++) {
          const size_t primID = primList[i];
          const vec3f center = buildPrim[primID].center();
          if (center[splitDim] < splitPos) {
          // if ((center[splitDim] < splitPos) || (zeroVolume && (i&1))) {
            lBounds.extend(center);
            lPrim[lCount++] = primID;
          } else {
            rBounds.extend(center);
            rPrim[rCount++] = primID;
          }
        }
        LockGuard lock(mutex);
        lCentBounds.extend(lBounds);
        rCentBounds.extend(rBounds);
      }

      // sanity-check: if we got at least one empty side, simply split
      // randomly
      if (lCount == 0 || rCount == 0) {
        // std::cout << "abnormal case detected - all prims falling on same side of partitioning place (fixing right now...)" << std::endl;
        lCount = 0;
        rCount = 0;
        lCentBounds = ospcommon::empty;
        rCentBounds = ospcommon::empty;
        for (int i=0;i<primList.size();i++) {
          const size_t primID = primList[i];
          const vec3f center = buildPrim[primID].center();
          if ((i&1) == 0) {
            lCentBounds.extend(center);
            lPrim[lCount++] = primID;
          } else {
            rCentBounds.extend(center);
            rPrim[rCount++] = primID;
          }
        }
      }
      
      // OK, we've done the split ...

      // resize the lists so we don't unnecessarily waste memory
      primList.clear();
      lPrim.resize(lCount);
      rPrim.resize(rCount);

      size_t childID=0;
      { LockGuard lock(mutex);
        childID = nodeList.size();
        nodeList.push_back(Node());
        nodeList.push_back(Node());
      }

      buildRec(childID+0,lCentBounds,buildPrim,lPrim);
      buildRec(childID+1,rCentBounds,buildPrim,rPrim);
      { LockGuard lock(mutex);
        nodeList[nodeID].lower = min(nodeList[childID+0].lower,
                                     nodeList[childID+1].lower);
        nodeList[nodeID].upper = max(nodeList[childID+0].upper,
                                     nodeList[childID+1].upper);
        nodeList[nodeID].isLeaf   = 0;
        nodeList[nodeID].child    = childID;
      }
    }
  }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x490, %rsp            # imm = 0x490
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x390(%rbp)
movq -0x28(%rbp), %rdi
callq 0xdf60
cmpq $0x1, %rax
jne 0xd1fc
movq -0x28(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xdf80
movq -0x390(%rbp), %rsi
movq (%rax), %rax
movq %rax, -0x30(%rbp)
addq $0x18, %rsi
leaq -0x38(%rbp), %rdi
movq %rdi, -0x3a0(%rbp)
callq 0xdfa0
movq -0x3a0(%rbp), %rdi
callq 0xdfd0
movq -0x20(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rdi
callq 0xdff0
movq -0x390(%rbp), %rdi
movss %xmm1, -0x50(%rbp)
movlpd %xmm0, -0x58(%rbp)
movl -0x50(%rbp), %eax
movl %eax, -0x40(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x10(%rbp), %rsi
callq 0xe040
movl -0x40(%rbp), %ecx
movl %ecx, 0x8(%rax)
movq -0x48(%rbp), %rcx
movq %rcx, (%rax)
movq -0x20(%rbp), %rax
movq -0x30(%rbp), %rcx
shlq $0x5, %rcx
leaq 0x10(%rax,%rcx), %rdi
callq 0xdff0
movq -0x390(%rbp), %rdi
movss %xmm1, -0x70(%rbp)
movlpd %xmm0, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x64(%rbp)
movl -0x70(%rbp), %eax
movl %eax, -0x5c(%rbp)
movq -0x10(%rbp), %rsi
callq 0xe040
movq -0x390(%rbp), %rdi
movq -0x64(%rbp), %rcx
movq %rcx, 0x10(%rax)
movl -0x5c(%rbp), %ecx
movl %ecx, 0x18(%rax)
movq -0x10(%rbp), %rsi
callq 0xe040
movq -0x390(%rbp), %rdi
movl $0x1, 0xc(%rax)
movq -0x30(%rbp), %rax
movl %eax, -0x394(%rbp)
movq -0x10(%rbp), %rsi
callq 0xe040
movl -0x394(%rbp), %ecx
movl %ecx, 0x1c(%rax)
jmp 0xdc04
leaq -0xa0(%rbp), %rdi
callq 0x9fa0
movq $0x0, -0xa8(%rbp)
movq $0x0, -0xb0(%rbp)
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x3a8(%rbp)
callq 0xe060
movq -0x28(%rbp), %rdi
callq 0xdf60
movq -0x3a8(%rbp), %rdi
movq %rax, %rsi
callq 0xe080
jmp 0xd24b
leaq -0xf0(%rbp), %rdi
movq %rdi, -0x3b0(%rbp)
callq 0xe060
movq -0x28(%rbp), %rdi
callq 0xdf60
movq -0x3b0(%rbp), %rdi
movq %rax, %rsi
callq 0xe080
jmp 0xd278
leaq -0x110(%rbp), %rdi
callq 0xe110
jmp 0xd286
leaq -0x134(%rbp), %rdi
callq 0xe110
jmp 0xd294
movq -0x18(%rbp), %rdi
callq 0xe180
movq %rax, -0x3b8(%rbp)
jmp 0xd2a6
movq -0x3b8(%rbp), %rax
movq %rax, -0x140(%rbp)
movq -0x18(%rbp), %rsi
leaq -0x154(%rbp), %rdi
callq 0xe210
jmp 0xd2c6
movq -0x140(%rbp), %rsi
leaq -0x154(%rbp), %rdi
callq 0xe2a0
movq %rax, -0x3c0(%rbp)
jmp 0xd2e2
movq -0x3c0(%rbp), %rax
movss (%rax), %xmm0
movss %xmm0, -0x144(%rbp)
movq $0x3e8, -0x160(%rbp) # imm = 0x3E8
movq -0x28(%rbp), %rdi
callq 0xdf60
addq -0x160(%rbp), %rax
subq $0x1, %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq -0x160(%rbp)
movq %rax, -0x168(%rbp)
movq $0x0, -0x170(%rbp)
movq -0x170(%rbp), %rax
cmpq -0x168(%rbp), %rax
jae 0xd648
movq -0x170(%rbp), %rax
movq -0x160(%rbp), %rcx
imulq %rcx, %rax
movq %rax, -0x178(%rbp)
movq -0x178(%rbp), %rax
movq -0x160(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x188(%rbp)
movq -0x28(%rbp), %rdi
callq 0xdf60
movq %rax, -0x190(%rbp)
leaq -0x188(%rbp), %rdi
leaq -0x190(%rbp), %rsi
callq 0x70b0
movq %rax, -0x3c8(%rbp)
jmp 0xd3a2
movq -0x3c8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x180(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0xe110
jmp 0xd3c1
leaq -0x1d4(%rbp), %rdi
callq 0xe110
jmp 0xd3cf
movq -0x178(%rbp), %rax
movq %rax, -0x1e0(%rbp)
movq -0x1e0(%rbp), %rax
cmpq -0x180(%rbp), %rax
jae 0xd5c3
movq -0x28(%rbp), %rdi
movq -0x1e0(%rbp), %rsi
callq 0xdf80
movq (%rax), %rax
movq %rax, -0x1e8(%rbp)
movq -0x20(%rbp), %rsi
movq -0x1e8(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rsi
leaq -0x208(%rbp), %rdi
callq 0xe300
jmp 0xd42b
leaq -0x208(%rbp), %rdi
callq 0xdff0
movss %xmm1, -0x3e4(%rbp)
movaps %xmm0, -0x3e0(%rbp)
jmp 0xd448
movss -0x3e4(%rbp), %xmm0
movaps -0x3e0(%rbp), %xmm1
movlpd %xmm1, -0x218(%rbp)
movss %xmm0, -0x210(%rbp)
movl -0x210(%rbp), %eax
movl %eax, -0x1f0(%rbp)
movq -0x218(%rbp), %rax
movq %rax, -0x1f8(%rbp)
movq -0x140(%rbp), %rsi
leaq -0x1f8(%rbp), %rdi
callq 0xe390
movq %rax, -0x3f0(%rbp)
jmp 0xd49d
movq -0x3f0(%rbp), %rax
movss (%rax), %xmm1
movss -0x144(%rbp), %xmm0
ucomiss %xmm1, %xmm0
jbe 0xd54b
leaq -0x228(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
callq 0x95a0
jmp 0xd4ce
leaq -0x1b0(%rbp), %rdi
leaq -0x228(%rbp), %rsi
callq 0xe3f0
jmp 0xd4e3
movq -0x1e8(%rbp), %rax
movq %rax, -0x3f8(%rbp)
leaq -0xa8(%rbp), %rdi
xorl %esi, %esi
callq 0xe460
movq %rax, %rsi
leaq -0xc8(%rbp), %rdi
callq 0xdf80
movq -0x3f8(%rbp), %rcx
movq %rcx, (%rax)
jmp 0xd5aa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
jmp 0xdbf6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
jmp 0xdbea
leaq -0x238(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
callq 0x95a0
jmp 0xd560
leaq -0x1d4(%rbp), %rdi
leaq -0x238(%rbp), %rsi
callq 0xe3f0
jmp 0xd575
movq -0x1e8(%rbp), %rax
movq %rax, -0x400(%rbp)
leaq -0xb0(%rbp), %rdi
xorl %esi, %esi
callq 0xe460
movq %rax, %rsi
leaq -0xf0(%rbp), %rdi
callq 0xdf80
movq -0x400(%rbp), %rcx
movq %rcx, (%rax)
jmp 0xd5ac
movq -0x1e0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x1e0(%rbp)
jmp 0xd3dd
leaq -0x240(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0xdfa0
jmp 0xd5d8
leaq -0x110(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
callq 0xe520
jmp 0xd5ed
leaq -0x134(%rbp), %rdi
leaq -0x1d4(%rbp), %rsi
callq 0xe520
jmp 0xd602
leaq -0x240(%rbp), %rdi
callq 0xdfd0
movq -0x170(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x170(%rbp)
jmp 0xd331
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x240(%rbp), %rdi
callq 0xdfd0
jmp 0xdbea
leaq -0xa8(%rbp), %rdi
callq 0xe590
cmpq $0x0, %rax
je 0xd670
leaq -0xb0(%rbp), %rdi
callq 0xe590
cmpq $0x0, %rax
jne 0xd8b4
xorl %eax, %eax
movl %eax, %esi
movq %rsi, -0x408(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0xe620
movq -0x408(%rbp), %rsi
leaq -0xb0(%rbp), %rdi
callq 0xe620
leaq -0x260(%rbp), %rdi
callq 0xe110
jmp 0xd6a8
movups -0x260(%rbp), %xmm0
movups -0x250(%rbp), %xmm1
movaps %xmm1, -0x100(%rbp)
movaps %xmm0, -0x110(%rbp)
leaq -0x284(%rbp), %rdi
callq 0xe110
jmp 0xd6d2
movq -0x284(%rbp), %rax
movq %rax, -0x134(%rbp)
movq -0x27c(%rbp), %rax
movq %rax, -0x12c(%rbp)
movq -0x274(%rbp), %rax
movq %rax, -0x124(%rbp)
movq -0x26c(%rbp), %rax
movq %rax, -0x11c(%rbp)
movl $0x0, -0x28c(%rbp)
movslq -0x28c(%rbp), %rax
movq %rax, -0x410(%rbp)
movq -0x28(%rbp), %rdi
callq 0xdf60
movq %rax, %rcx
movq -0x410(%rbp), %rax
cmpq %rcx, %rax
jae 0xd8b2
movq -0x28(%rbp), %rdi
movslq -0x28c(%rbp), %rsi
callq 0xdf80
movq (%rax), %rax
movq %rax, -0x298(%rbp)
movq -0x20(%rbp), %rsi
movq -0x298(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rsi
leaq -0x2b4(%rbp), %rdi
callq 0xe300
jmp 0xd778
leaq -0x2b4(%rbp), %rdi
callq 0xdff0
movss %xmm1, -0x424(%rbp)
movaps %xmm0, -0x420(%rbp)
jmp 0xd795
movss -0x424(%rbp), %xmm0
movaps -0x420(%rbp), %xmm1
movlpd %xmm1, -0x2c8(%rbp)
movss %xmm0, -0x2c0(%rbp)
movq -0x2c8(%rbp), %rax
movq %rax, -0x2a4(%rbp)
movl -0x2c0(%rbp), %eax
movl %eax, -0x29c(%rbp)
movl -0x28c(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0xd83d
leaq -0x2d8(%rbp), %rdi
leaq -0x2a4(%rbp), %rsi
callq 0x95a0
jmp 0xd7f1
leaq -0x110(%rbp), %rdi
leaq -0x2d8(%rbp), %rsi
callq 0xe3f0
jmp 0xd806
movq -0x298(%rbp), %rax
movq %rax, -0x430(%rbp)
leaq -0xa8(%rbp), %rdi
xorl %esi, %esi
callq 0xe460
movq %rax, %rsi
leaq -0xc8(%rbp), %rdi
callq 0xdf80
movq -0x430(%rbp), %rcx
movq %rcx, (%rax)
jmp 0xd89c
leaq -0x2e8(%rbp), %rdi
leaq -0x2a4(%rbp), %rsi
callq 0x95a0
jmp 0xd852
leaq -0x134(%rbp), %rdi
leaq -0x2e8(%rbp), %rsi
callq 0xe3f0
jmp 0xd867
movq -0x298(%rbp), %rax
movq %rax, -0x438(%rbp)
leaq -0xb0(%rbp), %rdi
xorl %esi, %esi
callq 0xe460
movq %rax, %rsi
leaq -0xf0(%rbp), %rdi
callq 0xdf80
movq -0x438(%rbp), %rcx
movq %rcx, (%rax)
jmp 0xd89e
movl -0x28c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28c(%rbp)
jmp 0xd714
jmp 0xd8b4
movq -0x28(%rbp), %rdi
callq 0xe6b0
leaq -0xa8(%rbp), %rdi
callq 0xe590
movq %rax, %rsi
leaq -0xc8(%rbp), %rdi
callq 0xe080
jmp 0xd8da
leaq -0xb0(%rbp), %rdi
callq 0xe590
movq %rax, %rsi
leaq -0xf0(%rbp), %rdi
callq 0xe080
jmp 0xd8f7
movq $0x0, -0x2f0(%rbp)
leaq -0x2f8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0xdfa0
jmp 0xd917
movq -0x390(%rbp), %rdi
callq 0xe6d0
movq -0x390(%rbp), %rdi
movq %rax, -0x2f0(%rbp)
xorps %xmm0, %xmm0
movaps %xmm0, -0x310(%rbp)
movaps %xmm0, -0x320(%rbp)
leaq -0x320(%rbp), %rsi
callq 0xe6f0
jmp 0xd950
movq -0x390(%rbp), %rdi
xorps %xmm0, %xmm0
movaps %xmm0, -0x330(%rbp)
movaps %xmm0, -0x340(%rbp)
leaq -0x340(%rbp), %rsi
callq 0xe6f0
jmp 0xd976
leaq -0x2f8(%rbp), %rdi
callq 0xdfd0
movq -0x390(%rbp), %rdi
movq -0x2f0(%rbp), %rsi
movq -0x20(%rbp), %rcx
leaq -0x110(%rbp), %rdx
leaq -0xc8(%rbp), %r8
callq 0xd0b0
jmp 0xd9a9
movq -0x390(%rbp), %rdi
movq -0x2f0(%rbp), %rsi
incq %rsi
movq -0x20(%rbp), %rcx
leaq -0x134(%rbp), %rdx
leaq -0xf0(%rbp), %r8
callq 0xd0b0
jmp 0xd9d3
leaq -0x348(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0xdfa0
jmp 0xd9e8
movq -0x390(%rbp), %rdi
movq -0x2f0(%rbp), %rsi
callq 0xe040
movq -0x390(%rbp), %rdi
movq %rax, -0x460(%rbp)
movq -0x2f0(%rbp), %rsi
incq %rsi
callq 0xe040
movq -0x460(%rbp), %rdi
movq %rax, %rsi
callq 0xe720
movss %xmm1, -0x454(%rbp)
movaps %xmm0, -0x450(%rbp)
jmp 0xda38
movq -0x390(%rbp), %rdi
movss -0x454(%rbp), %xmm0
movaps -0x450(%rbp), %xmm1
movlpd %xmm1, -0x368(%rbp)
movss %xmm0, -0x360(%rbp)
movl -0x360(%rbp), %eax
movl %eax, -0x350(%rbp)
movq -0x368(%rbp), %rax
movq %rax, -0x358(%rbp)
movq -0x10(%rbp), %rsi
callq 0xe040
movq -0x390(%rbp), %rdi
movl -0x350(%rbp), %ecx
movl %ecx, 0x8(%rax)
movq -0x358(%rbp), %rcx
movq %rcx, (%rax)
movq -0x2f0(%rbp), %rsi
callq 0xe040
movq -0x390(%rbp), %rdi
addq $0x10, %rax
movq %rax, -0x480(%rbp)
movq -0x2f0(%rbp), %rsi
incq %rsi
callq 0xe040
movq -0x480(%rbp), %rdi
movq %rax, %rsi
addq $0x10, %rsi
callq 0xe840
movss %xmm1, -0x474(%rbp)
movaps %xmm0, -0x470(%rbp)
jmp 0xdaec
movq -0x390(%rbp), %rdi
movss -0x474(%rbp), %xmm0
movaps -0x470(%rbp), %xmm1
movlpd %xmm1, -0x388(%rbp)
movss %xmm0, -0x380(%rbp)
movq -0x388(%rbp), %rax
movq %rax, -0x374(%rbp)
movl -0x380(%rbp), %eax
movl %eax, -0x36c(%rbp)
movq -0x10(%rbp), %rsi
callq 0xe040
movq -0x390(%rbp), %rdi
movq -0x374(%rbp), %rcx
movq %rcx, 0x10(%rax)
movl -0x36c(%rbp), %ecx
movl %ecx, 0x18(%rax)
movq -0x10(%rbp), %rsi
callq 0xe040
movq -0x390(%rbp), %rdi
movl $0x0, 0xc(%rax)
movq -0x2f0(%rbp), %rax
movl %eax, -0x484(%rbp)
movq -0x10(%rbp), %rsi
callq 0xe040
movl -0x484(%rbp), %ecx
movl %ecx, 0x1c(%rax)
leaq -0x348(%rbp), %rdi
callq 0xdfd0
leaq -0xf0(%rbp), %rdi
callq 0xe960
leaq -0xc8(%rbp), %rdi
callq 0xe960
jmp 0xdc04
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0xdfd0
jmp 0xdbea
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x348(%rbp), %rdi
callq 0xdfd0
leaq -0xf0(%rbp), %rdi
callq 0xe960
leaq -0xc8(%rbp), %rdi
callq 0xe960
jmp 0xdc0d
addq $0x490, %rsp            # imm = 0x490
popq %rbp
retq
movq -0xd0(%rbp), %rdi
callq 0x33e0
nopl (%rax)