// File: /workspace/github_c_makefile_star2_O2/archer1357[P]Offline-Raytracer/kdtree.c
// Function: findSplitPlane
bool findSplitPlane(const struct BoundingBox *bounds,
                    const unsigned int *primInds,int primsNum,
                    const float *minBound,const float *maxBound,
                    float emptyBonus,float traversalCost,float isectCost,
                    int *badRefines,
                    int *axisOut,float *splitOut,
                    unsigned int **leftInds,int *leftIndsNum,
                    unsigned int **rightInds,int *rightIndsNum) {

  int bestAxis,bestOffset,axis,retries,i;
  float bestCost,oldCost,totalSa,invTotalSa;
  struct BoundingEdge *edges[3];

  bestAxis=-1;
  bestOffset=-1;
  bestCost=INFINITY;
  oldCost=isectCost*(float)primsNum;

  totalSa=calcBoundingBoxSa(minBound,maxBound);
  invTotalSa=1.0f/totalSa;
  axis=calcBoundingBoxMaximumExtent(minBound,maxBound);

  edges[0]=0;
  edges[1]=0;
  edges[2]=0;

  for(retries=0;retries<3;retries++) {
    int nBelow,nAbove;

    //
    edges[axis]=(struct BoundingEdge*)
      malloc(sizeof(struct BoundingEdge)*primsNum*2);

    //
    for(i=0;i<primsNum;i++) {
      int v;
      v=primInds[i];

      edges[axis][2*i].type=0;
      edges[axis][2*i].val=bounds[v].start[axis];
      edges[axis][2*i].primInd=v;

      edges[axis][2*i+1].type=1;
      edges[axis][2*i+1].val=bounds[v].end[axis];
      edges[axis][2*i+1].primInd=v;
    }

    qsort(edges[axis],primsNum*2,
          sizeof(struct BoundingEdge),
          boundingEdgeCompare);

    //
    nBelow=0;
    nAbove=primsNum;


    //
    for(i=0;i<2*primsNum;i++) {
      float edget,cost;

      if(edges[axis][i].type==1) {
        nAbove--;
      }

      edget=edges[axis][i].val;

      if(calcSaCost(axis,edget,nAbove,nBelow,
                    invTotalSa,minBound,maxBound,
                    emptyBonus,traversalCost,isectCost,
                    &cost)) {
        // printf("cost %g\n",(double)cost);
        //update best split if lowest score so far
        if(cost < bestCost) {
          bestCost=cost;
          bestAxis=axis;
          bestOffset=i;
        }
      }

      if(edges[axis][i].type==0) {
        nBelow++;
      }
    }

    //
    if(bestAxis == -1 && retries < 2) {
      axis = (axis+1) % 3;
      continue;
    }

    if(bestCost > oldCost) {
      ++(*badRefines);
    }
    // printf("br %i\n",*badRefines);
    if((bestCost>(4.0f*oldCost) && primsNum<16) ||
       bestAxis == -1
       // || (*badRefines) == 3
       ) {
      free(edges[0]);
      free(edges[1]);
      free(edges[2]);
      return false;
    }

    break;
  }

  *axisOut=bestAxis;
  *splitOut=edges[bestAxis][bestOffset].val;

  *leftInds=0;
  *rightInds=0;
  *leftIndsNum=0;
  *rightIndsNum=0;

  for(i=0;i<bestOffset;i++) {
    if(edges[bestAxis][i].type==0) {
      (*leftIndsNum)++;
    }
  }

  for(i=bestOffset+1;i<2*primsNum;i++) {
    if(edges[bestAxis][i].type==1) {
      (*rightIndsNum)++;
    }
  }

  if(*leftIndsNum != 0) {
    *leftInds=(unsigned int*)malloc(sizeof(int)*(*leftIndsNum));
  }

  if(*rightIndsNum != 0) {
    *rightInds=(unsigned int*)malloc(sizeof(int)*(*rightIndsNum));
  }

  int n0,n1;
  n0=0;
  n1=0;

  for(i=0;i<bestOffset;i++) {
    if(edges[bestAxis][i].type==0) {
      (*leftInds)[n0++]=edges[bestAxis][i].primInd;
    }
  }

  for(i=bestOffset+1;i<2*primsNum;i++) {
    if(edges[bestAxis][i].type==1) {
      (*rightInds)[n1++]=edges[bestAxis][i].primInd;
    }
  }

  free(edges[0]);
  free(edges[1]);
  free(edges[2]);
  return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %r9, 0x58(%rsp)
movss %xmm1, 0x34(%rsp)
movss %xmm0, 0x30(%rsp)
movq %r8, %r14
movq %rcx, %r15
movl %edx, %ebx
movq %rsi, 0x78(%rsp)
movq %rdi, %r12
cvtsi2ss %edx, %xmm0
movss %xmm2, 0x38(%rsp)
mulss %xmm2, %xmm0
movss %xmm0, 0x28(%rsp)
movq %rcx, %rdi
movq %r8, %rsi
callq 0x40540d
movss 0xcce90(%rip), %xmm1    # 0x4d2460
divss %xmm0, %xmm1
movss %xmm1, 0x2c(%rsp)
movq %r15, 0x80(%rsp)
movq %r15, %rdi
movq %r14, 0x88(%rsp)
movq %r14, %rsi
callq 0x405445
movl %eax, %r13d
movslq %ebx, %rax
imulq $0x18, %rax, %rcx
movq %rcx, 0x70(%rsp)
leal (%rax,%rax), %ecx
movslq %ecx, %rcx
testl %eax, %eax
movl $0x0, %eax
movl %ebx, 0x14(%rsp)
cmovgl %ebx, %eax
testl %ecx, %ecx
movl $0x0, %edx
movq %rcx, 0x20(%rsp)
cmovgl %ecx, %edx
movq %rdx, 0x90(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rsp)
andq $0x0, 0x50(%rsp)
imulq $0x6, %rax, %r14
pushq $-0x1
popq %rax
movss 0xce2c4(%rip), %xmm0    # 0x4d3910
movss %xmm0, 0xc(%rsp)
movl $0x0, 0x18(%rsp)
movl %eax, 0x10(%rsp)
movq %r12, 0x68(%rsp)
movq %r14, 0x60(%rsp)
movq 0x70(%rsp), %rdi
callq 0x442160
movq %rax, %rbx
movl %r13d, %eax
movq %rbx, 0x40(%rsp,%rax,8)
movq 0x78(%rsp), %rcx
xorl %edx, %edx
cmpq %rdx, %r14
je 0x4056c8
movslq (%rcx), %rsi
andl $0x0, (%rbx,%rdx,4)
imulq $0x18, %rsi, %rdi
addq %r12, %rdi
movss (%rdi,%rax,4), %xmm0
movss %xmm0, 0x4(%rbx,%rdx,4)
movl %esi, 0x8(%rbx,%rdx,4)
movl $0x1, 0xc(%rbx,%rdx,4)
movss 0xc(%rdi,%rax,4), %xmm0
movss %xmm0, 0x10(%rbx,%rdx,4)
movl %esi, 0x14(%rbx,%rdx,4)
addq $0x6, %rdx
addq $0x4, %rcx
jmp 0x405684
movq %rbx, %rdi
movq 0x20(%rsp), %rsi
pushq $0xc
popq %rdx
leaq -0x2f6(%rip), %rcx      # 0x4053e4
callq 0x423650
addq $0x4, %rbx
xorl %r12d, %r12d
xorl %ebp, %ebp
movl 0x14(%rsp), %r15d
pushq $-0x1
popq %rax
movl %eax, 0x1c(%rsp)
cmpq %r12, 0x90(%rsp)
je 0x405788
movl -0x4(%rbx), %r14d
xorl %eax, %eax
cmpl $0x1, %r14d
sete %al
subl %eax, %r15d
movss (%rbx), %xmm0
movl %r13d, %edi
movl %r15d, %esi
movl %ebp, %edx
movss 0x2c(%rsp), %xmm1
movq 0x80(%rsp), %rcx
movq 0x88(%rsp), %r8
movss 0x30(%rsp), %xmm2
movss 0x34(%rsp), %xmm3
movss 0x38(%rsp), %xmm4
leaq 0x3c(%rsp), %r9
callq 0x405483
testb %al, %al
je 0x405775
movss 0x3c(%rsp), %xmm0
movss 0xc(%rsp), %xmm1
ucomiss %xmm0, %xmm1
jbe 0x405775
movss %xmm0, 0xc(%rsp)
movl %r12d, 0x10(%rsp)
movl %r13d, 0x1c(%rsp)
cmpl $0x1, %r14d
adcl $0x0, %ebp
incq %r12
addq $0xc, %rbx
jmp 0x4056f4
movl 0x18(%rsp), %ecx
cmpl $0x2, %ecx
movl 0x1c(%rsp), %edx
je 0x4057bf
cmpl $-0x1, %edx
jne 0x4057bf
incl %r13d
cmpl $0x3, %r13d
movl $0x0, %eax
cmovel %eax, %r13d
incl %ecx
movl %ecx, 0x18(%rsp)
movq 0x68(%rsp), %r12
movq 0x60(%rsp), %r14
jmp 0x405668
movss 0x28(%rsp), %xmm0
movss 0xc(%rsp), %xmm1
ucomiss %xmm0, %xmm1
jbe 0x4057d7
movq 0x58(%rsp), %rax
incl (%rax)
cmpl $-0x1, %edx
sete %al
mulss 0xce12f(%rip), %xmm0    # 0x4d3914
movss 0xc(%rsp), %xmm1
ucomiss %xmm0, %xmm1
seta %cl
cmpl $0x10, 0x14(%rsp)
setl %bpl
andb %cl, %bpl
orb %al, %bpl
movq 0xf0(%rsp), %r13
je 0x405840
movq 0x40(%rsp), %rdi
callq 0x4424a0
movq 0x48(%rsp), %rdi
callq 0x4424a0
movq 0x50(%rsp), %rdi
callq 0x4424a0
xorb $0x1, %bpl
movl %ebp, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0xd0(%rsp), %rax
movl %edx, (%rax)
movslq %edx, %rax
movq 0x40(%rsp,%rax,8), %rbx
movl 0x10(%rsp), %esi
movslq %esi, %rcx
imulq $0xc, %rcx, %rax
movss 0x4(%rbx,%rax), %xmm0
movq 0xd8(%rsp), %rax
movss %xmm0, (%rax)
movq 0xe0(%rsp), %rax
andq $0x0, (%rax)
andq $0x0, (%r13)
movq 0xe8(%rsp), %rdx
andl $0x0, (%rdx)
movq 0xf8(%rsp), %rax
andl $0x0, (%rax)
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %ecx
cmovgl %esi, %ecx
imulq $0xc, %rcx, %r15
movq %rdx, %rcx
cmpq %rax, %r15
je 0x4058bc
cmpl $0x0, (%rbx,%rax)
jne 0x4058b6
incl (%rcx)
addq $0xc, %rax
jmp 0x4058a9
movl 0x10(%rsp), %eax
incl %eax
movslq %eax, %r14
imulq $0xc, %r14, %r12
leaq (%rbx,%r12), %rax
movq %r14, %rcx
cmpq 0x20(%rsp), %rcx
jge 0x4058ef
cmpl $0x1, (%rax)
jne 0x4058e6
movq 0xf8(%rsp), %rdx
incl (%rdx)
incq %rcx
addq $0xc, %rax
jmp 0x4058d0
movq 0xe8(%rsp), %rax
movslq (%rax), %rdi
testq %rdi, %rdi
je 0x405913
shlq $0x2, %rdi
callq 0x442160
movq 0xe0(%rsp), %rcx
movq %rax, (%rcx)
movq 0xf8(%rsp), %rax
movslq (%rax), %rdi
testq %rdi, %rdi
je 0x405930
shlq $0x2, %rdi
callq 0x442160
movq %rax, (%r13)
xorl %eax, %eax
xorl %ecx, %ecx
cmpq %rax, %r15
je 0x40595c
cmpl $0x0, (%rbx,%rax)
jne 0x405956
movl 0x8(%rbx,%rax), %edx
movq 0xe0(%rsp), %rsi
movq (%rsi), %rsi
movslq %ecx, %rdi
incl %ecx
movl %edx, (%rsi,%rdi,4)
addq $0xc, %rax
jmp 0x405934
leaq (%rbx,%r12), %rax
addq $0x8, %rax
xorl %ecx, %ecx
cmpq 0x20(%rsp), %r14
jge 0x40580a
cmpl $0x1, -0x8(%rax)
jne 0x405985
movl (%rax), %edx
movq (%r13), %rsi
movslq %ecx, %rdi
incl %ecx
movl %edx, (%rsi,%rdi,4)
incq %r14
addq $0xc, %rax
jmp 0x405966