// File: /workspace/github_c_makefile_star2_O3/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, 0x60(%rsp)
movss %xmm1, 0x2c(%rsp)
movss %xmm0, 0x28(%rsp)
movl %edx, %r13d
movq %rsi, 0x70(%rsp)
movq %rdi, 0x68(%rsp)
xorps %xmm0, %xmm0
cvtsi2ss %edx, %xmm0
movss %xmm2, 0x30(%rsp)
mulss %xmm2, %xmm0
movss %xmm0, 0x20(%rsp)
movss (%r8), %xmm1
subss (%rcx), %xmm1
movq %r8, 0x90(%rsp)
movsd 0x4(%r8), %xmm0
movq %rcx, 0x88(%rsp)
movsd 0x4(%rcx), %xmm2
subps %xmm2, %xmm0
movaps %xmm0, %xmm2
shufps $0x55, %xmm0, %xmm2     # xmm2 = xmm2[1,1],xmm0[1,1]
movaps %xmm1, %xmm3
movaps %xmm2, %xmm4
cmpltps %xmm1, %xmm4
movaps %xmm0, %xmm5
cmpltps %xmm1, %xmm5
mulss %xmm2, %xmm1
mulss %xmm0, %xmm3
xorl %ebp, %ebp
ucomiss %xmm2, %xmm0
addss %xmm1, %xmm3
mulss %xmm2, %xmm0
addss %xmm3, %xmm0
addss %xmm0, %xmm0
movss 0xd1e12(%rip), %xmm1    # 0x4d7920
divss %xmm0, %xmm1
movss %xmm1, 0x24(%rsp)
andps %xmm4, %xmm5
movd %xmm5, %eax
setbe %bpl
incl %ebp
xorl %ecx, %ecx
testb $0x1, %al
cmovnel %ecx, %ebp
movslq %edx, %rax
leaq (,%rax,8), %rcx
leal (%rax,%rax), %edx
movl %edx, 0x4(%rsp)
movslq %edx, %rdx
cmpl $0x2, %edx
movl $0x1, %esi
movq %rdx, 0x38(%rsp)
cmovgel %edx, %esi
movq %rsi, 0x80(%rsp)
leaq (%rcx,%rcx,2), %rcx
movq %rcx, 0x78(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rsp)
movq $0x0, 0x50(%rsp)
movl %eax, %eax
shlq $0x3, %rax
leaq (%rax,%rax,2), %r12
movss 0xd1d9f(%rip), %xmm0    # 0x4d7924
movss %xmm0, 0xc(%rsp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rax, 0x18(%rsp)
movl $0x0, 0x14(%rsp)
movl %r13d, 0x10(%rsp)
movq 0x78(%rsp), %rdi
callq 0x4458c0
movq %rax, %rbx
movl %ebp, (%rsp)
movl %ebp, %eax
movq %rbx, 0x40(%rsp,%rax,8)
testl %r13d, %r13d
jle 0x405ce3
xorl %ecx, %ecx
movq 0x70(%rsp), %rdx
movq 0x68(%rsp), %r8
movslq (%rdx), %rsi
movl $0x0, (%rbx,%rcx)
leaq (%rsi,%rsi,2), %rdi
leaq (%r8,%rdi,8), %rdi
movss (%rdi,%rax,4), %xmm0
movss %xmm0, 0x4(%rbx,%rcx)
movl %esi, 0x8(%rbx,%rcx)
movl $0x1, 0xc(%rbx,%rcx)
movss 0xc(%rdi,%rax,4), %xmm0
movss %xmm0, 0x10(%rbx,%rcx)
movl %esi, 0x14(%rbx,%rcx)
addq $0x4, %rdx
addq $0x18, %rcx
cmpq %rcx, %r12
jne 0x405bce
movl $0xc, %edx
movq %rbx, %rdi
movq 0x38(%rsp), %rsi
leaq -0x388(%rip), %rcx      # 0x4058a0
callq 0x426db0
testl %r13d, %r13d
jle 0x405cfc
addq $0x4, %rbx
xorl %ebp, %ebp
movl $0xffffffff, 0x8(%rsp)  # imm = 0xFFFFFFFF
xorl %r15d, %r15d
movl (%rsp), %edi
movl -0x4(%rbx), %r14d
xorl %eax, %eax
cmpl $0x1, %r14d
sete %al
subl %eax, %r13d
movss (%rbx), %xmm0
movl %r13d, %esi
movl %r15d, %edx
movss 0x24(%rsp), %xmm1
movq 0x88(%rsp), %rcx
movq 0x90(%rsp), %r8
movss 0x28(%rsp), %xmm2
movss 0x2c(%rsp), %xmm3
movss 0x30(%rsp), %xmm4
leaq 0x34(%rsp), %r9
callq 0x40593f
testb %al, %al
je 0x405cc1
movss 0x34(%rsp), %xmm0
movss 0xc(%rsp), %xmm1
ucomiss %xmm0, %xmm1
movl (%rsp), %edi
jbe 0x405cc4
movss %xmm0, 0xc(%rsp)
movl %ebp, %eax
movq %rax, 0x18(%rsp)
movl %edi, 0x8(%rsp)
jmp 0x405cc4
movl (%rsp), %edi
cmpl $0x1, %r14d
adcl $0x0, %r15d
incq %rbp
addq $0xc, %rbx
cmpq %rbp, 0x80(%rsp)
jne 0x405c4a
jmp 0x405d07
movl $0xc, %edx
movq %rbx, %rdi
movq 0x38(%rsp), %rsi
leaq -0x457(%rip), %rcx      # 0x4058a0
callq 0x426db0
movl $0xffffffff, 0x8(%rsp)  # imm = 0xFFFFFFFF
movl (%rsp), %edi
movl 0x14(%rsp), %ecx
cmpl $0x2, %ecx
movl 0x8(%rsp), %r8d
je 0x405d3a
cmpl $-0x1, %r8d
jne 0x405d3a
incl %edi
cmpl $0x3, %edi
movl $0x0, %eax
cmovel %eax, %edi
incl %ecx
movl %ecx, 0x14(%rsp)
movl 0x10(%rsp), %r13d
movl %edi, %ebp
jmp 0x405ba2
movss 0x20(%rsp), %xmm0
movss 0xc(%rsp), %xmm1
ucomiss %xmm0, %xmm1
movq 0x18(%rsp), %r9
movl 0x10(%rsp), %edx
jbe 0x405d5b
movq 0x60(%rsp), %rax
incl (%rax)
cmpl $-0x1, %r8d
sete %al
mulss 0xd1bbe(%rip), %xmm0    # 0x4d7928
movss 0xc(%rsp), %xmm1
ucomiss %xmm0, %xmm1
seta %cl
cmpl $0x10, %edx
setl %bl
andb %cl, %bl
orb %al, %bl
movq 0xf0(%rsp), %r12
movq 0xf8(%rsp), %rdx
movq 0xe0(%rsp), %r10
movq 0xe8(%rsp), %rsi
jne 0x405eed
movq 0xd0(%rsp), %rax
movl %r8d, (%rax)
movslq %r8d, %rax
movq 0x40(%rsp,%rax,8), %r14
movslq %r9d, %rax
leaq (%rax,%rax,2), %rcx
movss 0x4(%r14,%rcx,4), %xmm0
movq 0xd8(%rsp), %rcx
movss %xmm0, (%rcx)
xorl %ecx, %ecx
movq %rcx, (%r10)
movq %rcx, (%r12)
movl %ecx, (%rsi)
movl %ecx, (%rdx)
movl %r9d, %r15d
testl %eax, %eax
jle 0x405e07
leaq (,%r15,4), %rax
leaq (%rax,%rax,2), %rax
xorl %ecx, %ecx
cmpl $0x0, (%r14,%rcx)
jne 0x405dfe
incl (%rsi)
addq $0xc, %rcx
cmpq %rcx, %rax
jne 0x405df5
leal 0x1(%r9), %ebp
cmpl 0x4(%rsp), %ebp
jge 0x405e34
movslq %ebp, %rax
leaq (%rax,%rax,2), %rax
leaq (%r14,%rax,4), %rax
movl %r9d, %ecx
subl 0x4(%rsp), %ecx
incl %ecx
cmpl $0x1, (%rax)
jne 0x405e2c
incl (%rdx)
addq $0xc, %rax
incl %ecx
jne 0x405e25
movslq (%rsi), %rdi
testq %rdi, %rdi
je 0x405e5d
shlq $0x2, %rdi
callq 0x4458c0
movq 0xe0(%rsp), %r10
movq 0x18(%rsp), %r9
movq 0xf8(%rsp), %rdx
movq %rax, (%r10)
movslq (%rdx), %rdi
testq %rdi, %rdi
je 0x405e7f
shlq $0x2, %rdi
callq 0x4458c0
movq 0xe0(%rsp), %r10
movq 0x18(%rsp), %r9
movq %rax, (%r12)
testl %r9d, %r9d
jle 0x405eb1
shlq $0x2, %r15
leaq (%r15,%r15,2), %rax
xorl %ecx, %ecx
xorl %edx, %edx
cmpl $0x0, (%r14,%rcx)
jne 0x405ea8
movl 0x8(%r14,%rcx), %esi
movq (%r10), %rdi
movslq %edx, %r8
incl %edx
movl %esi, (%rdi,%r8,4)
addq $0xc, %rcx
cmpq %rcx, %rax
jne 0x405e90
cmpl 0x4(%rsp), %ebp
jge 0x405eed
movslq %ebp, %rax
leaq (%rax,%rax,2), %rax
leaq (%r14,%rax,4), %rax
addq $0x8, %rax
subl 0x4(%rsp), %r9d
incl %r9d
xorl %ecx, %ecx
cmpl $0x1, -0x8(%rax)
jne 0x405ee4
movl (%rax), %edx
movq (%r12), %rsi
movslq %ecx, %rdi
incl %ecx
movl %edx, (%rsi,%rdi,4)
addq $0xc, %rax
incl %r9d
jne 0x405ed0
movq 0x40(%rsp), %rdi
callq 0x445c00
movq 0x48(%rsp), %rdi
callq 0x445c00
movq 0x50(%rsp), %rdi
callq 0x445c00
xorb $0x1, %bl
movl %ebx, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq