// File: /workspace/github_c_makefile_star2_O3/archer1357[P]Offline-Raytracer/kdtree.c
// Function: buildKdTree
struct KdNode *buildKdTree(const struct BoundingBox *bounds,
                           int primsNum,
                           const float *minBound,
                           const float *maxBound,
                           int maxDepth) {
int curDepth;
  int i,maxPrimsNum;
  float emptyBonus,isectCost,traversalCost;

  int badRefines;
  struct KdBuildStack *buildStack;
  struct KdNode *rootNode;

  curDepth=0;

  // maxDepth=(int)(8.0+1.3*log2((double)primsNum));

  // maxDepth=24;
  // maxDepth+=6;
  // printf("md %i\n",maxDepth);

  isectCost=80.0f;
  traversalCost=1.0f;

  maxPrimsNum=1;
  badRefines=0;

  emptyBonus=0.5f;


  rootNode=(struct KdNode*)malloc(sizeof(struct KdNode));

  buildStack=(struct KdBuildStack*)malloc(sizeof(struct KdBuildStack));
  buildStack->next=0;
  buildStack->primInds=(unsigned int*)malloc(sizeof(int)*primsNum);
  buildStack->primsNum=primsNum;
  buildStack->node=rootNode;
  buildStack->depth=0;//maxDepth;

  for(i=0;i<primsNum;i++) {
     buildStack->primInds[i]=i;
  }

  //
  for(i=0;i<3;i++) {
    buildStack->minBound[i]=minBound[i];
    buildStack->maxBound[i]=maxBound[i];
  }

  //
  while(buildStack) {
    struct KdBuildStack *curBuild;

    //
    curBuild=buildStack;
    buildStack=buildStack->next;

    //

    if(curBuild->depth > curDepth) {
      curDepth=curBuild->depth;
    }
    //

    // printf("start (%g %g %g) (%g %g %g)\n",
    //        curBuild->minBound[0],curBuild->minBound[1],curBuild->minBound[2],
    //        curBuild->maxBound[0],curBuild->maxBound[1],curBuild->maxBound[2]);

    //
    if(curBuild->primsNum <=maxPrimsNum || curBuild->depth==
       maxDepth
       //0
       ) {
      //make leaf
      curBuild->node->type=3;
      curBuild->node->thing.leaf.primsNum=curBuild->primsNum;
      curBuild->node->thing.leaf.primInds=curBuild->primInds;


      // printf("make leaf (%i) @ %i \n",
      //        curBuild->node->thing.leaf.primsNum,
      //        curBuild->depth);
    } else {
      int axis;
      float split;
      unsigned int *leftInds,*rightInds;
      int leftIndsNum,rightIndsNum;
      bool splitResult;
      splitResult=findSplitPlane(bounds,
                                 curBuild->primInds,curBuild->primsNum,
                                 curBuild->minBound,curBuild->maxBound,
                                 emptyBonus,traversalCost,isectCost,
                                 &badRefines,&axis,&split,
                                 &leftInds,&leftIndsNum,
                                 &rightInds,&rightIndsNum);


      if(splitResult) {
        //make branch


        if(rightIndsNum!=0) {
          struct KdBuildStack *rightBuild;
          struct KdNode *rightNode;

          rightBuild=(struct KdBuildStack*)malloc(sizeof(struct KdBuildStack));
          rightNode=(struct KdNode*)malloc(sizeof(struct KdNode));

          rightBuild->node=rightNode;
          rightBuild->primsNum=rightIndsNum;
          rightBuild->primInds=rightInds;
          rightBuild->depth=curBuild->depth +1;//-1;


          memcpy(rightBuild->minBound,curBuild->minBound,sizeof(float)*3);
          memcpy(rightBuild->maxBound,curBuild->maxBound,sizeof(float)*3);
          rightBuild->minBound[axis]=split;

          rightBuild->next=buildStack;
          buildStack=rightBuild;



          curBuild->node->thing.branch.right=rightNode;
        } else {
          curBuild->node->thing.branch.right=0;
        }

        if(leftIndsNum!=0) {
          struct KdBuildStack *leftBuild;
          struct KdNode *leftNode;

          leftBuild=(struct KdBuildStack*)malloc(sizeof(struct KdBuildStack));
          leftNode=(struct KdNode*)malloc(sizeof(struct KdNode));

          leftBuild->node=leftNode;
          leftBuild->primsNum=leftIndsNum;
          leftBuild->primInds=leftInds;
          leftBuild->depth=curBuild->depth +1;//-1;
          memcpy(leftBuild->minBound,curBuild->minBound,sizeof(float)*3);
          memcpy(leftBuild->maxBound,curBuild->maxBound,sizeof(float)*3);
          leftBuild->maxBound[axis]=split;

          leftBuild->next=buildStack;
          buildStack=leftBuild;



          curBuild->node->thing.branch.left=leftNode;
        } else {
          curBuild->node->thing.branch.left=0;
        }

        curBuild->node->type=axis;
        curBuild->node->thing.branch.split=split;

        free(curBuild->primInds);

      } else {
        //make leaf
        curBuild->node->type=3;
        curBuild->node->thing.leaf.primsNum=curBuild->primsNum;
        curBuild->node->thing.leaf.primInds=curBuild->primInds;

      }
    }

    free(curBuild);
  }

  //


  return rootNode;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %r8d, 0x8(%rsp)
movq %rcx, 0x20(%rsp)
movq %rdx, %rbp
movl %esi, %r15d
movq %rdi, 0x30(%rsp)
xorl %ebx, %ebx
movl %ebx, 0x1c(%rsp)
movl $0x20, %edi
callq 0x4458c0
movq %rax, %r13
movl $0x40, %edi
callq 0x4458c0
movq %rax, %r12
movq $0x0, 0x10(%rax)
movslq %r15d, %r14
leaq (,%r14,4), %rdi
callq 0x4458c0
movq %rax, (%r12)
movl %r14d, 0x8(%r12)
movq %r13, 0x28(%rsp)
movq %r13, 0x18(%r12)
movl %ebx, 0x20(%r12)
testl %r14d, %r14d
jle 0x406127
movl %r15d, %ecx
incl %r15d
andl $-0x2, %r15d
decq %rcx
movq %rcx, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
movdqa 0xd1889(%rip), %xmm1    # 0x4d7940
xorl %ecx, %ecx
movdqa 0xd188f(%rip), %xmm2    # 0x4d7950
pxor %xmm2, %xmm0
pcmpeqd %xmm3, %xmm3
movdqa 0xd188f(%rip), %xmm4    # 0x4d7960
movdqa %xmm1, %xmm5
pxor %xmm2, %xmm5
movdqa %xmm5, %xmm6
pcmpgtd %xmm0, %xmm6
pcmpeqd %xmm0, %xmm5
pshufd $0xf5, %xmm5, %xmm7     # xmm7 = xmm5[1,1,3,3]
pand %xmm6, %xmm7
pshufd $0xf5, %xmm6, %xmm5     # xmm5 = xmm6[1,1,3,3]
por %xmm7, %xmm5
movd %xmm5, %edx
notl %edx
testb $0x1, %dl
je 0x406105
movl %ecx, (%rax,%rcx,4)
pxor %xmm3, %xmm5
pextrw $0x4, %xmm5, %edx
testb $0x1, %dl
je 0x40611a
leal 0x1(%rcx), %edx
movl %edx, 0x4(%rax,%rcx,4)
addq $0x2, %rcx
paddq %xmm4, %xmm1
cmpq %rcx, %r15
jne 0x4060d1
movl 0x8(%rbp), %eax
movl %eax, 0x2c(%r12)
movq (%rbp), %rax
movq %rax, 0x24(%r12)
movq 0x20(%rsp), %rcx
movq (%rcx), %rax
movq %rax, 0x30(%r12)
movl 0x8(%rcx), %eax
movl %eax, 0x38(%r12)
leaq 0xc(%rsp), %r13
movl 0x8(%rsp), %ebx
movq 0x10(%r12), %r14
movl 0x8(%r12), %edx
cmpl $0x2, %edx
jl 0x406253
cmpl %ebx, 0x20(%r12)
je 0x406253
movq (%r12), %rsi
leaq 0x24(%r12), %r15
leaq 0x30(%r12), %rbp
movq 0x30(%rsp), %rdi
movq %r15, %rcx
movq %rbp, %r8
movd 0xd02f3(%rip), %xmm0    # 0x4d6488
movd 0xd1783(%rip), %xmm1    # 0x4d7920
movd 0xd1793(%rip), %xmm2    # 0x4d7938
leaq 0x1c(%rsp), %r9
pushq %r13
leaq 0x40(%rsp), %rax
pushq %rax
leaq 0x28(%rsp), %rax
pushq %rax
leaq 0x58(%rsp), %rax
pushq %rax
leaq 0x30(%rsp), %rax
pushq %rax
leaq 0x3c(%rsp), %rax
pushq %rax
callq 0x405a64
addq $0x30, %rsp
testb %al, %al
je 0x406263
movl 0xc(%rsp), %ebx
testl %ebx, %ebx
je 0x406288
movl $0x40, %edi
callq 0x4458c0
movq %rax, %r13
movl $0x20, %edi
callq 0x4458c0
movq %rax, 0x18(%r13)
movl %ebx, 0x8(%r13)
movq 0x38(%rsp), %rcx
movq %rcx, (%r13)
movl 0x20(%r12), %ecx
incl %ecx
movl %ecx, 0x20(%r13)
movl 0x8(%r15), %ecx
movl %ecx, 0x2c(%r13)
movq (%r15), %rcx
movq %rcx, 0x24(%r13)
movq (%rbp), %rcx
movq %rcx, 0x30(%r13)
movl 0x8(%rbp), %ecx
movl %ecx, 0x38(%r13)
movd 0x10(%rsp), %xmm0
movslq 0x14(%rsp), %rcx
movd %xmm0, 0x24(%r13,%rcx,4)
movq %r14, 0x10(%r13)
movq %r13, %r14
jmp 0x40628a
movq 0x18(%r12), %rax
movl $0x3, (%rax)
movl %edx, 0x10(%rax)
jmp 0x406276
movq 0x18(%r12), %rax
movl $0x3, (%rax)
movl 0x8(%r12), %ecx
movl %ecx, 0x10(%rax)
movq (%r12), %rax
movq 0x18(%r12), %rcx
movq %rax, 0x8(%rcx)
jmp 0x406345
xorl %eax, %eax
movq 0x18(%r12), %rcx
movq %rax, 0x18(%rcx)
movl 0x18(%rsp), %ebx
testl %ebx, %ebx
je 0x406310
movl $0x40, %edi
callq 0x4458c0
movq %rax, %r13
movl $0x20, %edi
callq 0x4458c0
movq %rax, 0x18(%r13)
movl %ebx, 0x8(%r13)
movq 0x40(%rsp), %rcx
movq %rcx, (%r13)
movl 0x20(%r12), %ecx
incl %ecx
movl %ecx, 0x20(%r13)
movl 0x8(%r15), %ecx
movl %ecx, 0x2c(%r13)
movq (%r15), %rcx
movq %rcx, 0x24(%r13)
movq (%rbp), %rcx
movq %rcx, 0x30(%r13)
movl 0x8(%rbp), %ecx
movl %ecx, 0x38(%r13)
movd 0x10(%rsp), %xmm0
movslq 0x14(%rsp), %rcx
movd %xmm0, 0x30(%r13,%rcx,4)
movq %r14, 0x10(%r13)
movq 0x18(%r12), %rdx
movq %rax, 0x10(%rdx)
movq %r13, %r14
jmp 0x406327
movq 0x18(%r12), %rax
movq $0x0, 0x10(%rax)
movl 0x14(%rsp), %ecx
movd 0x10(%rsp), %xmm0
movl 0x8(%rsp), %ebx
leaq 0xc(%rsp), %r13
movq 0x18(%r12), %rax
movl %ecx, (%rax)
movd %xmm0, 0x8(%rax)
movq (%r12), %rdi
callq 0x445c00
movq %r12, %rdi
callq 0x445c00
movq %r14, %r12
testq %r14, %r14
jne 0x406156
movq 0x28(%rsp), %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq