// File: /workspace/github_c_makefile_star2_O1/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 $0xa8, %rsp
movq %r9, 0x68(%rsp)
movaps %xmm2, %xmm3
movss %xmm1, 0x34(%rsp)
movss %xmm0, 0x30(%rsp)
movl %edx, %r15d
movq %rsi, %r14
movq %rdi, %r13
cvtsi2ss %edx, %xmm6
movss (%r8), %xmm2
movss 0x4(%r8), %xmm0
subss (%rcx), %xmm2
subss 0x4(%rcx), %xmm0
movss %xmm3, 0x38(%rsp)
mulss %xmm3, %xmm6
movq %r8, 0xa0(%rsp)
movss 0x8(%r8), %xmm1
movq %rcx, 0x98(%rsp)
subss 0x8(%rcx), %xmm1
movaps %xmm2, %xmm3
movaps %xmm1, %xmm4
cmpltps %xmm2, %xmm4
movaps %xmm0, %xmm5
cmpltps %xmm2, %xmm5
mulss %xmm1, %xmm2
mulss %xmm0, %xmm3
addss %xmm2, %xmm3
xorl %ebx, %ebx
ucomiss %xmm1, %xmm0
mulss %xmm1, %xmm0
addss %xmm3, %xmm0
addss %xmm0, %xmm0
movss 0xcfa21(%rip), %xmm1    # 0x4d5490
divss %xmm0, %xmm1
movss %xmm1, 0x2c(%rsp)
andps %xmm4, %xmm5
movd %xmm5, %eax
setbe %bl
incl %ebx
xorl %ebp, %ebp
testb $0x1, %al
cmovnel %ebp, %ebx
movslq %edx, %rax
leaq (,%rax,8), %rcx
leaq (%rcx,%rcx,2), %rcx
movq %rcx, 0x80(%rsp)
leal (%rax,%rax), %ecx
movl %ecx, 0x10(%rsp)
movslq %ecx, %rcx
movss 0xd0e8b(%rip), %xmm0    # 0x4d6940
movss %xmm6, 0x28(%rsp)
mulss %xmm6, %xmm0
movss %xmm0, 0x24(%rsp)
cmpl $0x2, %ecx
movl $0x1, %edx
movq %rcx, 0x78(%rsp)
cmovgel %ecx, %edx
movq %rdx, 0x90(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rsp)
movq $0x0, 0x50(%rsp)
movl %eax, %edx
movss 0xd0e4c(%rip), %xmm0    # 0x4d6944
movss %xmm0, 0xc(%rsp)
movl $0xffffffff, 0x8(%rsp)  # imm = 0xFFFFFFFF
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
movl %r15d, 0x14(%rsp)
movq %rsi, 0x60(%rsp)
movq %rdi, 0x58(%rsp)
movq %rdx, 0x70(%rsp)
movq %rbp, 0x88(%rsp)
movq 0x80(%rsp), %rdi
callq 0x4449d0
movq 0x70(%rsp), %r8
movq %rax, %rbp
movl %ebx, %eax
movq %rbp, 0x40(%rsp,%rax,8)
testl %r15d, %r15d
jle 0x405b96
leaq 0x14(%rbp), %rcx
xorl %edx, %edx
movslq (%r14,%rdx,4), %rsi
movl $0x0, -0x14(%rcx)
leaq (%rsi,%rsi,2), %rdi
leaq (,%rdi,8), %rdi
addq %r13, %rdi
movss (%rdi,%rax,4), %xmm0
movss %xmm0, -0x10(%rcx)
movl %esi, -0xc(%rcx)
movl $0x1, -0x8(%rcx)
movss 0xc(%rdi,%rax,4), %xmm0
movss %xmm0, -0x4(%rcx)
movl %esi, (%rcx)
incq %rdx
addq $0x18, %rcx
cmpq %rdx, %r8
jne 0x405b4f
movq %r12, 0x18(%rsp)
movl $0xc, %edx
movq %rbp, %rdi
movq 0x78(%rsp), %rsi
leaq -0x3af(%rip), %rcx      # 0x405800
callq 0x425ec0
testl %r15d, %r15d
jle 0x405c5d
addq $0x4, %rbp
xorl %r14d, %r14d
movl %r15d, %r12d
xorl %r13d, %r13d
movl -0x4(%rbp), %r15d
xorl %eax, %eax
cmpl $0x1, %r15d
sete %al
subl %eax, %r12d
movss (%rbp), %xmm0
movl %ebx, %edi
movl %r12d, %esi
movl %r13d, %edx
movss 0x2c(%rsp), %xmm1
movq 0x98(%rsp), %rcx
movq 0xa0(%rsp), %r8
movss 0x30(%rsp), %xmm2
movss 0x34(%rsp), %xmm3
movss 0x38(%rsp), %xmm4
leaq 0x3c(%rsp), %r9
callq 0x40589f
testb %al, %al
je 0x405c40
movss 0x3c(%rsp), %xmm0
movss 0xc(%rsp), %xmm1
ucomiss %xmm0, %xmm1
jbe 0x405c40
movss %xmm0, 0xc(%rsp)
movl %r14d, %eax
movq %rax, 0x18(%rsp)
movl %ebx, 0x8(%rsp)
cmpl $0x1, %r15d
adcl $0x0, %r13d
incq %r14
addq $0xc, %rbp
cmpq %r14, 0x90(%rsp)
jne 0x405bca
movq 0x88(%rsp), %rbp
cmpl $0x2, %ebp
je 0x405ca3
cmpl $-0x1, 0x8(%rsp)
jne 0x405ca3
incl %ebx
movq %rbx, %rax
movl $0xaaaaaaab, %ecx       # imm = 0xAAAAAAAB
imulq %rcx, %rax
shrq $0x21, %rax
leal (%rax,%rax,2), %eax
subl %eax, %ebx
movl $0x4, %eax
movq 0x18(%rsp), %r12
movl 0x14(%rsp), %r15d
movq 0x60(%rsp), %r14
movq 0x58(%rsp), %r13
jmp 0x405d13
movss 0xc(%rsp), %xmm0
ucomiss 0x28(%rsp), %xmm0
jbe 0x405cb7
movq 0x68(%rsp), %rax
incl (%rax)
movl 0x14(%rsp), %r15d
cmpl $0x10, %r15d
setl %al
movss 0xc(%rsp), %xmm0
ucomiss 0x24(%rsp), %xmm0
seta %cl
testb %cl, %al
movq 0x18(%rsp), %r12
movq 0x60(%rsp), %r14
movq 0x58(%rsp), %r13
jne 0x405cf0
movl $0x2, %eax
cmpl $-0x1, 0x8(%rsp)
jne 0x405d13
movq 0x40(%rsp), %rdi
callq 0x444d10
movq 0x48(%rsp), %rdi
callq 0x444d10
movq 0x50(%rsp), %rdi
callq 0x444d10
movl $0x1, %eax
cmpl $0x4, %eax
jne 0x405d25
incl %ebp
cmpl $0x3, %ebp
jne 0x405b20
jmp 0x405d2e
cmpl $0x2, %eax
jne 0x405ec1
movq 0xe0(%rsp), %rax
movl 0x8(%rsp), %ecx
movl %ecx, (%rax)
movslq %ecx, %rax
movq 0x40(%rsp,%rax,8), %rbx
movslq %r12d, %rax
leaq (%rax,%rax,2), %rcx
movss 0x4(%rbx,%rcx,4), %xmm0
movq 0xe8(%rsp), %rcx
movss %xmm0, (%rcx)
xorl %ecx, %ecx
movq 0xf0(%rsp), %rdx
movq %rcx, (%rdx)
movq 0x100(%rsp), %rdx
movq %rcx, (%rdx)
movq 0xf8(%rsp), %rsi
movl %ecx, (%rsi)
movq 0x108(%rsp), %rdx
movl %ecx, (%rdx)
movl %r12d, %r15d
testl %eax, %eax
jle 0x405daf
leaq (,%r15,4), %rax
leaq (%rax,%rax,2), %rax
xorl %ecx, %ecx
cmpl $0x0, (%rbx,%rcx)
jne 0x405da6
incl (%rsi)
addq $0xc, %rcx
cmpq %rcx, %rax
jne 0x405d9e
leal 0x1(%r12), %ebp
movslq %ebp, %r14
cmpl 0x10(%rsp), %ebp
jge 0x405de5
leaq (%r14,%r14,2), %rax
leaq (%rbx,%rax,4), %rax
movl %r12d, %ecx
subl 0x10(%rsp), %ecx
incl %ecx
cmpl $0x1, (%rax)
jne 0x405ddd
movq 0x108(%rsp), %rdx
incl (%rdx)
addq $0xc, %rax
incl %ecx
jne 0x405dce
movslq (%rsi), %rdi
testq %rdi, %rdi
je 0x405e01
shlq $0x2, %rdi
callq 0x4449d0
movq 0xf0(%rsp), %rcx
movq %rax, (%rcx)
movq 0x108(%rsp), %rax
movslq (%rax), %rdi
testq %rdi, %rdi
je 0x405e25
shlq $0x2, %rdi
callq 0x4449d0
movq 0x100(%rsp), %rcx
movq %rax, (%rcx)
testl %r12d, %r12d
jle 0x405e5d
shlq $0x2, %r15
leaq (%r15,%r15,2), %rax
xorl %ecx, %ecx
xorl %edx, %edx
cmpl $0x0, (%rbx,%rcx)
jne 0x405e54
movl 0x8(%rbx,%rcx), %esi
movq 0xf0(%rsp), %rdi
movq (%rdi), %rdi
movslq %edx, %r8
incl %edx
movl %esi, (%rdi,%r8,4)
addq $0xc, %rcx
cmpq %rcx, %rax
jne 0x405e36
movl 0x10(%rsp), %eax
cmpl %eax, %ebp
jge 0x405e9f
movl %eax, %ecx
leaq (%r14,%r14,2), %rax
leaq (%rbx,%rax,4), %rax
addq $0x8, %rax
subl %ecx, %r12d
incl %r12d
xorl %ecx, %ecx
cmpl $0x1, -0x8(%rax)
jne 0x405e96
movl (%rax), %edx
movq 0x100(%rsp), %rsi
movq (%rsi), %rsi
movslq %ecx, %rdi
incl %ecx
movl %edx, (%rsi,%rdi,4)
addq $0xc, %rax
incl %r12d
jne 0x405e7b
movq 0x40(%rsp), %rdi
callq 0x444d10
movq 0x48(%rsp), %rdi
callq 0x444d10
movq 0x50(%rsp), %rdi
callq 0x444d10
movb $0x1, %al
jmp 0x405ec3
xorl %eax, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq