I tried to create a 'more natural' AABB tree node using TypeDeclaration
. This ended up giving a 2x slowdown during construction -- not sure if I used TypeDeclaration
properly.
Basically it makes more sense to tag the data in the node, e.g.
<|"splitloc" -> "Real64", "splitdim" -> "MachineInteger", "min" -> "Real64",
"max" -> "Real64", "indices" -> "PackedArray"::["MachineInteger", 1]|>
The return value is also invalid (I think):
tree = AABBTree[bboxes]; // AbsoluteTiming
(* {0.237855, Null} *)
tree // FullForm
(* DataStructure["BinaryTree`AABBNode",$Failed] *)
Code
nodedec = TypeDeclaration["Product", "AABBNode", <|"splitloc" -> "Real64", "splitdim" -> "MachineInteger", "min" -> "Real64", "max" -> "Real64", "indices" -> "PackedArray"::["MachineInteger", 1]|>];
$btype = "BinaryTree"::["AABBNode"];
With[{$btype = $btype, $max = $MaxMachineNumber, $min = -$MaxMachineNumber},
decl2 = FunctionDeclaration[
centerNode3D,
Typed[{"MachineInteger", "PackedArray"::["Real64", 3], "PackedArray"::["MachineInteger", 1], "Real64"} -> $btype] @ Function[{d, bboxes, inds, x},
Module[{min, max, data},
min = If[Length[inds] > 0, Min[bboxes[[inds, d, 1]]], $max];
max = If[Length[inds] > 0, Max[bboxes[[inds, d, 2]]], $min];
data = CreateTypeInstance["AABBNode", <|"splitloc" -> x, "splitdim" -> d, "min" -> min, "max" -> max, "indices" -> inds|>];
CreateDataStructure["BinaryTree", data]
]
]
]];
With[{$btype = $btype, $intvec = "PackedArray"::["MachineInteger", 1]},
pureAABBTree = Function[{Typed[bboxes, "PackedArray"::["Real64", 3]]},
Module[{iAABBTree, inds},
iAABBTree = Function[{Typed[d, "MachineInteger"], Typed[inds, $intvec]},
Module[{len, n, x, loc, r=0, l=0, c=0, j, Sleft, Scent, Sright, node},
len = Length[inds];
n = Ordering[bboxes[[inds, d, 1]]][[Quotient[len+1, 2]]];
x = bboxes[[inds[[n]], d, 1]];
If[len <= 100, Return[TypeHint[centerNode3D[d, bboxes, inds, x], $btype]]];
loc = ConstantArray[0, len];
Do[
j = inds[[i]];
If[bboxes[[j, d, 1]] < x,
l++;
loc[[i]] = 1,
If[bboxes[[j, d, 2]] > x,
r++;,
c++;
loc[[i]] = 2
]
],
{i, len}
];
Sleft = ConstantArray[0, l];
Scent = ConstantArray[0, c];
Sright = ConstantArray[0, r];
r = l = c = 1;
Do[
j = inds[[i]];
If[loc[[i]] === 0,
Sright[[r++]] = j;,
If[loc[[i]] === 1,
Sleft[[l++]] = j,
Scent[[c++]] = j;
]
],
{i, len}
];
node = TypeHint[centerNode3D[d, bboxes, Scent, x], $btype];
If[l > 1, BinaryTree`SetLeft[node, iAABBTree[Mod[d+1, 3, 1], Sleft]]];
If[r > 1, BinaryTree`SetRight[node, iAABBTree[Mod[d+1, 3, 1], Sright]]];
TypeHint[node, $btype]
]
];
inds = Typed[KernelFunction[InversePermutation], {$intvec} -> $intvec][Ordering[bboxes[[All, 1, 1]]]];
TypeHint[iAABBTree[1, inds], $btype]
]
]];
AABBTree =
FunctionCompile[{nodedec, decl2}, pureAABBTree,
CompilerOptions -> {"AbortHandling" -> False,
"LLVMOptimization" -> "ClangOptimization"[3],
"OptimizationLevel" -> 3}];