13 #ifndef OPENVDB_TREE_NODEMANAGER_HAS_BEEN_INCLUDED    14 #define OPENVDB_TREE_NODEMANAGER_HAS_BEEN_INCLUDED    17 #include <tbb/parallel_for.h>    18 #include <tbb/parallel_reduce.h>    29 template<
typename TreeOrLeafManagerT, Index LEVELS = TreeOrLeafManagerT::RootNodeType::LEVEL>
    35 template<
typename TreeOrLeafManagerT, Index _LEVELS = TreeOrLeafManagerT::RootNodeType::LEVEL>
    46     static bool valid(
size_t) { 
return true; }
    53 template<
typename NodeT>
    59     NodeT& 
operator()(
size_t n)
 const { assert(n<mNodeCount); 
return *(mNodes[n]); }
    61     NodeT*& 
operator[](
size_t n) { assert(n<mNodeCount); 
return mNodes[n]; }
    73     template <
typename RootT>
    78         size_t nodeCount = root.childCount();
    80         if (nodeCount != mNodeCount) {
    82                 mNodePtrs.reset(
new NodeT*[nodeCount]);
    83                 mNodes = mNodePtrs.get();
    88             mNodeCount = nodeCount;
    91         if (mNodeCount == 0)    
return false;
    95         NodeT** nodePtr = mNodes;
    96         for (
auto iter = root.beginChildOn(); iter; ++iter) {
    97             *nodePtr++ = &iter.getValue();
   104     template <
typename ParentsT, 
typename NodeFilterT>
   105     bool initNodeChildren(ParentsT& parents, 
const NodeFilterT& nodeFilter = NodeFilterT(), 
bool serial = 
false)
   109         std::vector<Index32> nodeCounts;
   111             nodeCounts.reserve(parents.nodeCount());
   112             for (
size_t i = 0; i < parents.nodeCount(); i++) {
   113                 if (!nodeFilter.valid(i))   nodeCounts.push_back(0);
   114                 else                        nodeCounts.push_back(parents(i).childCount());
   117             nodeCounts.resize(parents.nodeCount());
   122                 tbb::blocked_range<Index64>(0, parents.nodeCount(), 64),
   123                 [&](tbb::blocked_range<Index64>& range)
   125                     for (
Index64 i = range.begin(); i < range.end(); i++) {
   126                         if (!nodeFilter.valid(i))   nodeCounts[i] = 0;
   127                         else                        nodeCounts[i] = parents(i).childCount();
   135         for (
size_t i = 1; i < nodeCounts.size(); i++) {
   136             nodeCounts[i] += nodeCounts[i-1];
   139         const size_t nodeCount = nodeCounts.empty() ? 0 : nodeCounts.back();
   143         if (nodeCount != mNodeCount) {
   145                 mNodePtrs.reset(
new NodeT*[nodeCount]);
   146                 mNodes = mNodePtrs.get();
   151             mNodeCount = nodeCount;
   154         if (mNodeCount == 0)    
return false;
   159             NodeT** nodePtr = mNodes;
   160             for (
size_t i = 0; i < parents.nodeCount(); i++) {
   161                 if (!nodeFilter.valid(i))   
continue;
   162                 for (
auto iter = parents(i).beginChildOn(); iter; ++iter) {
   163                     *nodePtr++ = &iter.getValue();
   168                 tbb::blocked_range<Index64>(0, parents.nodeCount()),
   169                 [&](tbb::blocked_range<Index64>& range)
   172                     NodeT** nodePtr = mNodes;
   173                     if (i > 0)  nodePtr += nodeCounts[i-1];
   174                     for ( ; i < range.end(); i++) {
   175                         if (!nodeFilter.valid(i))   
continue;
   176                         for (
auto iter = parents(i).beginChildOn(); iter; ++iter) {
   177                             *nodePtr++ = &iter.getValue();
   192             mEnd(end), mBegin(begin), mGrainSize(grainSize), mNodeList(nodeList) {}
   195             mEnd(r.mEnd), mBegin(doSplit(r)), mGrainSize(r.mGrainSize),
   196             mNodeList(r.mNodeList) {}
   198         size_t size()
 const { 
return mEnd - mBegin; }
   204         bool empty()
 const {
return !(mBegin < mEnd);}
   220             NodeT& 
operator*()
 const { 
return mRange.mNodeList(mPos); }
   224             size_t pos()
 const { 
return mPos; }
   225             bool isValid()
 const { 
return mPos>=mRange.mBegin && mPos<=mRange.mEnd; }
   227             bool test()
 const { 
return mPos < mRange.mEnd; }
   229             operator bool()
 const { 
return this->test(); }
   231             bool empty()
 const { 
return !this->test(); }
   234                 return (mPos != other.mPos) || (&mRange != &other.mRange);
   249         size_t mEnd, mBegin, mGrainSize;
   255             size_t middle = r.mBegin + (r.mEnd - r.mBegin) / 2u;
   264         return NodeRange(0, this->nodeCount(), *
this, grainsize);
   267     template<
typename NodeOp>
   268     void foreach(
const NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
   270         NodeTransformerCopy<NodeOp> transform(op); 
   271         transform.run(this->nodeRange(grainSize), threaded);
   274     template<
typename NodeOp>
   275     void reduce(NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
   277         NodeReducer<NodeOp> transform(op);
   278         transform.run(this->nodeRange(grainSize), threaded);
   283     template<
typename NodeOp>
   286         NodeTransformer<NodeOp, OpWithIndex> transform(op);
   287         transform.run(this->nodeRange(grainSize), threaded);
   291     template<
typename NodeOp>
   294         NodeReducer<NodeOp, OpWithIndex> transform(op);
   295         transform.run(this->nodeRange(grainSize), threaded);
   302     struct OpWithoutIndex
   304         template <
typename T>
   305         static void eval(T& node, 
typename NodeRange::Iterator& iter) { node(*iter); }
   312         template <
typename T>
   313         static void eval(T& node, 
typename NodeRange::Iterator& iter) { node(*iter, iter.pos()); }
   317     template<
typename NodeOp, 
typename OpT = OpWithoutIndex>
   318     struct NodeTransformerCopy
   320         NodeTransformerCopy(
const NodeOp& nodeOp) : mNodeOp(nodeOp)
   323         void run(
const NodeRange& range, 
bool threaded = 
true)
   325             threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
   327         void operator()(
const NodeRange& range)
 const   329             for (
typename NodeRange::Iterator it = range.begin(); it; ++it) {
   330                 OpT::template eval(mNodeOp, it);
   333         const NodeOp mNodeOp;
   337     template<
typename NodeOp, 
typename OpT = OpWithoutIndex>
   338     struct NodeTransformer
   340         NodeTransformer(
const NodeOp& nodeOp) : mNodeOp(nodeOp)
   343         void run(
const NodeRange& range, 
bool threaded = 
true)
   345             threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
   347         void operator()(
const NodeRange& range)
 const   349             for (
typename NodeRange::Iterator it = range.begin(); it; ++it) {
   350                 OpT::template eval(mNodeOp, it);
   353         const NodeOp& mNodeOp;
   357     template<
typename NodeOp, 
typename OpT = OpWithoutIndex>
   360         NodeReducer(NodeOp& nodeOp) : mNodeOp(&nodeOp)
   363         NodeReducer(
const NodeReducer& other, tbb::split)
   364             : mNodeOpPtr(std::make_unique<NodeOp>(*(other.mNodeOp), tbb::split()))
   365             , mNodeOp(mNodeOpPtr.get())
   368         void run(
const NodeRange& range, 
bool threaded = 
true)
   370             threaded ? tbb::parallel_reduce(range, *
this) : (*this)(range);
   372         void operator()(
const NodeRange& range)
   374             for (
typename NodeRange::Iterator it = range.begin(); it; ++it) {
   375                 OpT::template eval(*mNodeOp, it);
   378         void join(
const NodeReducer& other)
   380             mNodeOp->join(*(other.mNodeOp));
   382         std::unique_ptr<NodeOp> mNodeOpPtr;
   383         NodeOp *mNodeOp = 
nullptr;
   388     size_t mNodeCount = 0;
   390     NodeT** mNodes = 
nullptr;
   401 template<
typename NodeT, Index LEVEL>
   410     void clear() { mList.clear(); mNext.clear(); }
   412     template <
typename RootT>
   415         mList.initRootChildren(root);
   416         mNext.initNodeChildren(mList, serial);
   419     template<
typename ParentsT>
   422         mList.initNodeChildren(parents, 
NodeFilter(), serial);
   423         mNext.initNodeChildren(mList, serial);
   430         return i==NodeT::LEVEL ? mList.nodeCount() : mNext.nodeCount(i);
   433     template<
typename NodeOp>
   436         mNext.foreachBottomUp(op, threaded, grainSize);
   437         mList.foreach(op, threaded, grainSize);
   440     template<
typename NodeOp>
   443         mList.foreach(op, threaded, grainSize);
   444         mNext.foreachTopDown(op, threaded, grainSize);
   447     template<
typename NodeOp>
   450         mNext.reduceBottomUp(op, threaded, grainSize);
   451         mList.reduce(op, threaded, grainSize);
   454     template<
typename NodeOp>
   457         mList.reduce(op, threaded, grainSize);
   458         mNext.reduceTopDown(op, threaded, grainSize);
   473 template<
typename NodeT>
   480     void clear() { mList.
clear(); }
   482     template <
typename RootT>
   483     void initRootChildren(RootT& root, 
bool  = 
false) { mList.initRootChildren(root); }
   485     template<
typename ParentsT>
   486     void initNodeChildren(ParentsT& parents, 
bool serial = 
false) { mList.initNodeChildren(parents, 
NodeFilter(), serial); }
   488     Index64 nodeCount()
 const { 
return mList.nodeCount(); }
   490     Index64 nodeCount(
Index)
 const { 
return mList.nodeCount(); }
   492     template<
typename NodeOp>
   493     void foreachBottomUp(
const NodeOp& op, 
bool threaded, 
size_t grainSize)
   495         mList.foreach(op, threaded, grainSize);
   498     template<
typename NodeOp>
   499     void foreachTopDown(
const NodeOp& op, 
bool threaded, 
size_t grainSize)
   501         mList.foreach(op, threaded, grainSize);
   504     template<
typename NodeOp>
   505     void reduceBottomUp(NodeOp& op, 
bool threaded, 
size_t grainSize)
   507         mList.reduce(op, threaded, grainSize);
   510     template<
typename NodeOp>
   511     void reduceTopDown(NodeOp& op, 
bool threaded, 
size_t grainSize)
   513         mList.reduce(op, threaded, grainSize);
   529 template<
typename TreeOrLeafManagerT, Index _LEVELS>
   533     static const Index LEVELS = _LEVELS;
   534     static_assert(LEVELS > 0,
   535         "expected instantiation of template specialization"); 
   540     static_assert(RootNodeType::LEVEL >= LEVELS, 
"number of levels exceeds root node height");
   545         this->rebuild(serial);
   555     void rebuild(
bool serial = 
false) { mChain.initRootChildren(mRoot, serial); }
   623     template<
typename NodeOp>
   626         mChain.foreachBottomUp(op, threaded, grainSize);
   630     template<
typename NodeOp>
   634         mChain.foreachTopDown(op, threaded, grainSize);
   697     template<
typename NodeOp>
   700         mChain.reduceBottomUp(op, threaded, grainSize);
   704     template<
typename NodeOp>
   708         mChain.reduceTopDown(op, threaded, grainSize);
   723 template <
typename OpT>
   728         , mValidPtr(
std::make_unique<bool[]>(size))
   729         , mValid(mValidPtr.get()) { }
   733         , mValid(other.mValid) { }
   735     template<
typename NodeT>
   738         mValid[idx] = mOp(node, idx);
   741     bool valid(
size_t idx)
 const { 
return mValid[idx]; }
   743     const OpT& 
op()
 const { 
return mOp; }
   747     std::unique_ptr<bool[]> mValidPtr;
   748     bool* mValid = 
nullptr;
   754 template <
typename OpT>
   759         , mValidPtr(
std::make_unique<bool[]>(size))
   760         , mValid(mValidPtr.get()) { }
   764         , mValid(other.mValid) { }
   767         : mOpPtr(
std::make_unique<OpT>(*(other.mOp), tbb::split()))
   769         , mValid(other.mValid) { }
   771     template<
typename NodeT>
   774         mValid[idx] = (*mOp)(node, idx);
   779         mOp->join(*(other.mOp));
   787     OpT& 
op() { 
return *mOp; }
   790     std::unique_ptr<OpT> mOpPtr;
   792     std::unique_ptr<bool[]> mValidPtr;
   793     bool* mValid = 
nullptr;
   801 template<
typename NodeT, Index LEVEL>
   810     template<
typename NodeOpT, 
typename RootT>
   812         size_t leafGrainSize, 
size_t nonLeafGrainSize)
   814         if (!op(root, 0))         
return;
   815         if (!mList.initRootChildren(root))  
return;
   817         mList.foreachWithIndex(filterOp, threaded, LEVEL == 0 ? leafGrainSize : nonLeafGrainSize);
   818         mNext.foreachTopDownRecurse(filterOp, mList, threaded, leafGrainSize, nonLeafGrainSize);
   821     template<
typename FilterOpT, 
typename ParentT>
   823         size_t leafGrainSize, 
size_t nonLeafGrainSize)
   825         if (!mList.initNodeChildren(parent, filterOp, !threaded))   
return;
   826         FilterOpT childFilterOp(filterOp.op(), mList.nodeCount());
   827         mList.foreachWithIndex(childFilterOp, threaded, LEVEL == 0 ? leafGrainSize : nonLeafGrainSize);
   828         mNext.foreachTopDownRecurse(childFilterOp, mList, threaded, leafGrainSize, nonLeafGrainSize);
   831     template<
typename NodeOpT, 
typename RootT>
   833         size_t leafGrainSize, 
size_t nonLeafGrainSize)
   835         if (!op(root, 0))         
return;
   836         if (!mList.initRootChildren(root))  
return;
   838         mList.reduceWithIndex(filterOp, threaded, LEVEL == 0 ? leafGrainSize : nonLeafGrainSize);
   839         mNext.reduceTopDownRecurse(filterOp, mList, threaded, leafGrainSize, nonLeafGrainSize);
   842     template<
typename FilterOpT, 
typename ParentT>
   844         size_t leafGrainSize, 
size_t nonLeafGrainSize)
   846         if (!mList.initNodeChildren(parent, filterOp, !threaded))   
return;
   847         FilterOpT childFilterOp(filterOp.op(), mList.nodeCount());
   848         mList.reduceWithIndex(childFilterOp, threaded, LEVEL == 0 ? leafGrainSize : nonLeafGrainSize);
   849         mNext.reduceTopDownRecurse(childFilterOp, mList, threaded, leafGrainSize, nonLeafGrainSize);
   861 template<
typename NodeT>
   867     template<
typename NodeFilterOp, 
typename ParentT>
   868     void foreachTopDownRecurse(
const NodeFilterOp& nodeFilterOp, ParentT& parent, 
bool threaded,
   869         size_t leafGrainSize, 
size_t )
   871         if (!mList.initNodeChildren(parent, nodeFilterOp, !threaded))   
return;
   872         mList.foreachWithIndex(nodeFilterOp.op(), threaded, leafGrainSize);
   875     template<
typename NodeFilterOp, 
typename ParentT>
   876     void reduceTopDownRecurse(NodeFilterOp& nodeFilterOp, ParentT& parent, 
bool threaded,
   877         size_t leafGrainSize, 
size_t )
   879         if (!mList.initNodeChildren(parent, nodeFilterOp, !threaded))   
return;
   880         mList.reduceWithIndex(nodeFilterOp.op(), threaded, leafGrainSize);
   888 template<
typename TreeOrLeafManagerT, Index _LEVELS>
   892     static const Index LEVELS = _LEVELS;
   893     static_assert(LEVELS > 0,
   894         "expected instantiation of template specialization"); 
   899     static_assert(RootNodeType::LEVEL >= LEVELS, 
"number of levels exceeds root node height");
   975     template<
typename NodeOp>
   977         size_t leafGrainSize=1, 
size_t nonLeafGrainSize=1)
   979         mChain.foreachTopDown(op, mRoot, threaded, leafGrainSize, nonLeafGrainSize);
  1042     template<
typename NodeOp>
  1044         size_t leafGrainSize=1, 
size_t nonLeafGrainSize=1)
  1046         mChain.reduceTopDown(op, mRoot, threaded, leafGrainSize, nonLeafGrainSize);
  1061 template<
typename TreeOrLeafManagerT>
  1067     static const Index LEVELS = 0;
  1069     NodeManager(TreeOrLeafManagerT& tree, 
bool  = 
false) : mRoot(tree.root()) { }
  1078     void rebuild(
bool  = 
false) { }
  1084     Index64 nodeCount()
 const { 
return 0; }
  1088     template<
typename NodeOp>
  1089     void foreachBottomUp(
const NodeOp& op, 
bool, 
size_t) { op(mRoot); }
  1091     template<
typename NodeOp>
  1092     void foreachTopDown(
const NodeOp& op, 
bool, 
size_t) { op(mRoot); }
  1094     template<
typename NodeOp>
  1095     void reduceBottomUp(NodeOp& op, 
bool, 
size_t) { op(mRoot); }
  1097     template<
typename NodeOp>
  1098     void reduceTopDown(NodeOp& op, 
bool, 
size_t) { op(mRoot); }
  1110 template<
typename TreeOrLeafManagerT>
  1116     static_assert(RootNodeType::LEVEL > 0, 
"expected instantiation of template specialization");
  1117     static const Index LEVELS = 1;
  1119     NodeManager(TreeOrLeafManagerT& tree, 
bool serial = 
false)
  1120         : mRoot(tree.root())
  1122         this->rebuild(serial);
  1128     void clear() { mList0.
clear(); }
  1132     void rebuild(
bool  = 
false) { mList0.initRootChildren(mRoot); }
  1138     Index64 nodeCount()
 const { 
return mList0.nodeCount(); }
  1142     Index64 nodeCount(
Index i)
 const { 
return i==0 ? mList0.nodeCount() : 0; }
  1144     template<
typename NodeOp>
  1145     void foreachBottomUp(
const NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1147         mList0.foreach(op, threaded, grainSize);
  1151     template<
typename NodeOp>
  1152     void foreachTopDown(
const NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1155         mList0.foreach(op, threaded, grainSize);
  1158     template<
typename NodeOp>
  1159     void reduceBottomUp(NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1161         mList0.reduce(op, threaded, grainSize);
  1165     template<
typename NodeOp>
  1166     void reduceTopDown(NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1169         mList0.reduce(op, threaded, grainSize);
  1174     using NonConstNodeT0 = 
typename NodeT1::ChildNodeType;
  1188 template<
typename TreeOrLeafManagerT>
  1194     static_assert(RootNodeType::LEVEL > 1, 
"expected instantiation of template specialization");
  1195     static const Index LEVELS = 2;
  1197     NodeManager(TreeOrLeafManagerT& tree, 
bool serial = 
false) : mRoot(tree.root())
  1199         this->rebuild(serial);
  1205     void clear() { mList0.
clear(); mList1.clear(); }
  1209     void rebuild(
bool serial = 
false)
  1211         mList1.initRootChildren(mRoot);
  1212         mList0.initNodeChildren(mList1, 
NodeFilter(), serial);
  1219     Index64 nodeCount()
 const { 
return mList0.nodeCount() + mList1.nodeCount(); }
  1225         return i==0 ? mList0.nodeCount() : i==1 ? mList1.nodeCount() : 0;
  1228     template<
typename NodeOp>
  1229     void foreachBottomUp(
const NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1231         mList0.foreach(op, threaded, grainSize);
  1232         mList1.foreach(op, threaded, grainSize);
  1236     template<
typename NodeOp>
  1237     void foreachTopDown(
const NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1240         mList1.foreach(op, threaded, grainSize);
  1241         mList0.foreach(op, threaded, grainSize);
  1244     template<
typename NodeOp>
  1245     void reduceBottomUp(NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1247         mList0.reduce(op, threaded, grainSize);
  1248         mList1.reduce(op, threaded, grainSize);
  1252     template<
typename NodeOp>
  1253     void reduceTopDown(NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1256         mList1.reduce(op, threaded, grainSize);
  1257         mList0.reduce(op, threaded, grainSize);
  1262     using NonConstNodeT1 = 
typename NodeT2::ChildNodeType;
  1264     using NonConstNodeT0 = 
typename NodeT1::ChildNodeType;
  1281 template<
typename TreeOrLeafManagerT>
  1287     static_assert(RootNodeType::LEVEL > 2, 
"expected instantiation of template specialization");
  1288     static const Index LEVELS = 3;
  1290     NodeManager(TreeOrLeafManagerT& tree, 
bool serial = 
false) : mRoot(tree.root())
  1292         this->rebuild(serial);
  1298     void clear() { mList0.
clear(); mList1.clear(); mList2.clear(); }
  1302     void rebuild(
bool serial = 
false)
  1304         mList2.initRootChildren(mRoot);
  1305         mList1.initNodeChildren(mList2, 
NodeFilter(), serial);
  1306         mList0.initNodeChildren(mList1, 
NodeFilter(), serial);
  1313     Index64 nodeCount()
 const { 
return mList0.nodeCount()+mList1.nodeCount()+mList2.nodeCount(); }
  1319         return i==0 ? mList0.nodeCount() : i==1 ? mList1.nodeCount()
  1320              : i==2 ? mList2.nodeCount() : 0;
  1323     template<
typename NodeOp>
  1324     void foreachBottomUp(
const NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1326         mList0.foreach(op, threaded, grainSize);
  1327         mList1.foreach(op, threaded, grainSize);
  1328         mList2.foreach(op, threaded, grainSize);
  1332     template<
typename NodeOp>
  1333     void foreachTopDown(
const NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1336         mList2.foreach(op, threaded, grainSize);
  1337         mList1.foreach(op, threaded, grainSize);
  1338         mList0.foreach(op, threaded, grainSize);
  1341     template<
typename NodeOp>
  1342     void reduceBottomUp(NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1344         mList0.reduce(op, threaded, grainSize);
  1345         mList1.reduce(op, threaded, grainSize);
  1346         mList2.reduce(op, threaded, grainSize);
  1350     template<
typename NodeOp>
  1351     void reduceTopDown(NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1354         mList2.reduce(op, threaded, grainSize);
  1355         mList1.reduce(op, threaded, grainSize);
  1356         mList0.reduce(op, threaded, grainSize);
  1361     using NonConstNodeT2 = 
typename NodeT3::ChildNodeType;
  1363     using NonConstNodeT1 = 
typename NodeT2::ChildNodeType;
  1365     using NonConstNodeT0 = 
typename NodeT1::ChildNodeType;
  1384 template<
typename TreeOrLeafManagerT>
  1390     static_assert(RootNodeType::LEVEL > 3, 
"expected instantiation of template specialization");
  1391     static const Index LEVELS = 4;
  1393     NodeManager(TreeOrLeafManagerT& tree, 
bool serial = 
false) : mRoot(tree.root())
  1395         this->rebuild(serial);
  1401     void clear() { mList0.
clear(); mList1.clear(); mList2.clear(); mList3.clear(); }
  1405     void rebuild(
bool serial = 
false)
  1407         mList3.initRootChildren(mRoot);
  1408         mList2.initNodeChildren(mList3, 
NodeFilter(), serial);
  1409         mList1.initNodeChildren(mList2, 
NodeFilter(), serial);
  1410         mList0.initNodeChildren(mList1, 
NodeFilter(), serial);
  1419         return mList0.nodeCount() + mList1.nodeCount()
  1420              + mList2.nodeCount() + mList3.nodeCount();
  1427         return i==0 ? mList0.nodeCount() : i==1 ? mList1.nodeCount() :
  1428                i==2 ? mList2.nodeCount() : i==3 ? mList3.nodeCount() : 0;
  1431     template<
typename NodeOp>
  1432     void foreachBottomUp(
const NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1434         mList0.foreach(op, threaded, grainSize);
  1435         mList1.foreach(op, threaded, grainSize);
  1436         mList2.foreach(op, threaded, grainSize);
  1437         mList3.foreach(op, threaded, grainSize);
  1441     template<
typename NodeOp>
  1442     void foreachTopDown(
const NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1445         mList3.foreach(op, threaded, grainSize);
  1446         mList2.foreach(op, threaded, grainSize);
  1447         mList1.foreach(op, threaded, grainSize);
  1448         mList0.foreach(op, threaded, grainSize);
  1451     template<
typename NodeOp>
  1452     void reduceBottomUp(NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1454         mList0.reduce(op, threaded, grainSize);
  1455         mList1.reduce(op, threaded, grainSize);
  1456         mList2.reduce(op, threaded, grainSize);
  1457         mList3.reduce(op, threaded, grainSize);
  1461     template<
typename NodeOp>
  1462     void reduceTopDown(NodeOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
  1465         mList3.reduce(op, threaded, grainSize);
  1466         mList2.reduce(op, threaded, grainSize);
  1467         mList1.reduce(op, threaded, grainSize);
  1468         mList0.reduce(op, threaded, grainSize);
  1473     using NonConstNodeT3 = 
typename NodeT4::ChildNodeType;
  1475     using NonConstNodeT2 = 
typename NodeT3::ChildNodeType;
  1477     using NonConstNodeT1 = 
typename NodeT2::ChildNodeType;
  1479     using NonConstNodeT0 = 
typename NodeT1::ChildNodeType;
  1500 template<
typename TreeOrLeafManagerT>
  1506     static_assert(RootNodeType::LEVEL > 0, 
"expected instantiation of template specialization");
  1507     static const Index LEVELS = 0;
  1516     template<
typename NodeOp>
  1517     void foreachTopDown(
const NodeOp& op, 
bool =
true, 
size_t =1)
  1520         if (!op(mRoot, 0))                                
return;
  1523     template<
typename NodeOp>
  1524     void reduceTopDown(NodeOp& op, 
bool =
true, 
size_t =1)
  1527         if (!op(mRoot, 0))                                
return;
  1542 template<
typename TreeOrLeafManagerT>
  1548     static_assert(RootNodeType::LEVEL > 0, 
"expected instantiation of template specialization");
  1549     static const Index LEVELS = 1;
  1558     template<
typename NodeOp>
  1559     void foreachTopDown(
const NodeOp& op, 
bool threaded = 
true,
  1560         size_t leafGrainSize=1, 
size_t  =1)
  1563         if (!op(mRoot, 0))                                
return;
  1565         if (!mList0.initRootChildren(mRoot))                        
return;
  1567         mList0.foreachWithIndex(nodeOp, threaded, leafGrainSize);
  1570     template<
typename NodeOp>
  1571     void reduceTopDown(NodeOp& op, 
bool threaded = 
true,
  1572         size_t leafGrainSize=1, 
size_t  =1)
  1575         if (!op(mRoot, 0))                                
return;
  1577         if (!mList0.initRootChildren(mRoot))                        
return;
  1579         mList0.reduceWithIndex(nodeOp, threaded, leafGrainSize);
  1584     using NonConstNodeT0 = 
typename NodeT1::ChildNodeType;
  1598 template<
typename TreeOrLeafManagerT>
  1604     static_assert(RootNodeType::LEVEL > 1, 
"expected instantiation of template specialization");
  1605     static const Index LEVELS = 2;
  1614     template<
typename NodeOp>
  1615     void foreachTopDown(
const NodeOp& op, 
bool threaded = 
true,
  1616         size_t leafGrainSize=1, 
size_t nonLeafGrainSize=1)
  1619         if (!op(mRoot, 0))                                
return;
  1621         if (!mList1.initRootChildren(mRoot))                        
return;
  1623         mList1.foreachWithIndex(nodeOp, threaded, nonLeafGrainSize);
  1625         if (!mList0.initNodeChildren(mList1, nodeOp, !threaded))   
return;
  1626         mList0.foreachWithIndex(op, threaded, leafGrainSize);
  1629     template<
typename NodeOp>
  1630     void reduceTopDown(NodeOp& op, 
bool threaded = 
true,
  1631         size_t leafGrainSize=1, 
size_t nonLeafGrainSize=1)
  1634         if (!op(mRoot, 0))                                
return;
  1636         if (!mList1.initRootChildren(mRoot))                        
return;
  1638         mList1.reduceWithIndex(nodeOp, threaded, nonLeafGrainSize);
  1640         if (!mList0.initNodeChildren(mList1, nodeOp, !threaded))   
return;
  1641         mList0.reduceWithIndex(op, threaded, leafGrainSize);
  1646     using NonConstNodeT1 = 
typename NodeT2::ChildNodeType;
  1648     using NonConstNodeT0 = 
typename NodeT1::ChildNodeType;
  1665 template<
typename TreeOrLeafManagerT>
  1671     static_assert(RootNodeType::LEVEL > 2, 
"expected instantiation of template specialization");
  1672     static const Index LEVELS = 3;
  1681     template<
typename NodeOp>
  1682     void foreachTopDown(
const NodeOp& op, 
bool threaded = 
true,
  1683         size_t leafGrainSize=1, 
size_t nonLeafGrainSize=1)
  1686         if (!op(mRoot, 0))                                
return;
  1688         if (!mList2.initRootChildren(mRoot))                        
return;
  1690         mList2.foreachWithIndex(nodeOp2, threaded, nonLeafGrainSize);
  1692         if (!mList1.initNodeChildren(mList2, nodeOp2, !threaded))   
return;
  1694         mList1.foreachWithIndex(nodeOp1, threaded, nonLeafGrainSize);
  1696         if (!mList0.initNodeChildren(mList1, nodeOp1, !threaded))   
return;
  1697         mList0.foreachWithIndex(op, threaded, leafGrainSize);
  1700     template<
typename NodeOp>
  1701     void reduceTopDown(NodeOp& op, 
bool threaded = 
true,
  1702         size_t leafGrainSize=1, 
size_t nonLeafGrainSize=1)
  1705         if (!op(mRoot, 0))                                
return;
  1707         if (!mList2.initRootChildren(mRoot))                        
return;
  1709         mList2.reduceWithIndex(nodeOp2, threaded, nonLeafGrainSize);
  1711         if (!mList1.initNodeChildren(mList2, nodeOp2, !threaded))   
return;
  1713         mList1.reduceWithIndex(nodeOp1, threaded, nonLeafGrainSize);
  1715         if (!mList0.initNodeChildren(mList1, nodeOp1, !threaded))   
return;
  1716         mList0.reduceWithIndex(op, threaded, leafGrainSize);
  1721     using NonConstNodeT2 = 
typename NodeT3::ChildNodeType;
  1723     using NonConstNodeT1 = 
typename NodeT2::ChildNodeType;
  1725     using NonConstNodeT0 = 
typename NodeT1::ChildNodeType;
  1744 template<
typename TreeOrLeafManagerT>
  1750     static_assert(RootNodeType::LEVEL > 3, 
"expected instantiation of template specialization");
  1751     static const Index LEVELS = 4;
  1760     template<
typename NodeOp>
  1761     void foreachTopDown(
const NodeOp& op, 
bool threaded = 
true,
  1762         size_t leafGrainSize=1, 
size_t nonLeafGrainSize=1)
  1765         if (!op(mRoot, 0))                                
return;
  1767         if (!mList3.initRootChildren(mRoot))                        
return;
  1769         mList3.foreachWithIndex(nodeOp3, threaded, nonLeafGrainSize);
  1771         if (!mList2.initNodeChildren(mList3, nodeOp3, !threaded))   
return;
  1773         mList2.foreachWithIndex(nodeOp2, threaded, nonLeafGrainSize);
  1775         if (!mList1.initNodeChildren(mList2, nodeOp2, !threaded))   
return;
  1777         mList1.foreachWithIndex(nodeOp1, threaded, nonLeafGrainSize);
  1779         if (!mList0.initNodeChildren(mList1, nodeOp1, !threaded))   
return;
  1780         mList0.foreachWithIndex(op, threaded, leafGrainSize);
  1783     template<
typename NodeOp>
  1784     void reduceTopDown(NodeOp& op, 
bool threaded = 
true,
  1785         size_t leafGrainSize=1, 
size_t nonLeafGrainSize=1)
  1788         if (!op(mRoot, 0))                                
return;
  1790         if (!mList3.initRootChildren(mRoot))                        
return;
  1792         mList3.reduceWithIndex(nodeOp3, threaded, nonLeafGrainSize);
  1794         if (!mList2.initNodeChildren(mList3, nodeOp3, !threaded))   
return;
  1796         mList2.reduceWithIndex(nodeOp2, threaded, nonLeafGrainSize);
  1798         if (!mList1.initNodeChildren(mList2, nodeOp2, !threaded))   
return;
  1800         mList1.reduceWithIndex(nodeOp1, threaded, nonLeafGrainSize);
  1802         if (!mList0.initNodeChildren(mList1, nodeOp1, !threaded))   
return;
  1803         mList0.reduceWithIndex(op, threaded, leafGrainSize);
  1808     using NonConstNodeT3 = 
typename NodeT4::ChildNodeType;
  1810     using NonConstNodeT2 = 
typename NodeT3::ChildNodeType;
  1812     using NonConstNodeT1 = 
typename NodeT2::ChildNodeType;
  1814     using NonConstNodeT0 = 
typename NodeT1::ChildNodeType;
  1834 #endif // OPENVDB_TREE_NODEMANAGER_HAS_BEEN_INCLUDED Definition: NodeManager.h:187
OpT & op()
Definition: NodeManager.h:787
bool isValid() const 
Definition: NodeManager.h:225
void operator()(NodeT &node, size_t idx) const 
Definition: NodeManager.h:736
NodeList< NodeT > mList
Definition: NodeManager.h:462
DynamicNodeManager(TreeOrLeafManagerT &tree)
Definition: NodeManager.h:901
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix. 
Definition: Mat3.h:611
typename TreeOrLeafManagerT::RootNodeType NonConstRootNodeType
Definition: NodeManager.h:536
Iterator(const NodeRange &range, size_t pos)
Definition: NodeManager.h:211
typename CopyConstness< TreeOrLeafManagerT, NonConstChildNodeType >::Type ChildNodeType
Definition: NodeManager.h:539
NodeT & operator()(size_t n) const 
Definition: NodeManager.h:59
Iterator end() const 
Definition: NodeManager.h:246
Definition: NodeManager.h:44
void foreachWithIndex(const NodeOp &op, bool threaded=true, size_t grainSize=1)
Definition: NodeManager.h:284
NodeManagerLink< ChildNodeType, LEVEL-1 > mNext
Definition: NodeManager.h:463
This class is a link in a chain that each caches tree nodes of a specific type in a linear array...
Definition: NodeManager.h:802
void foreachTopDown(const NodeOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to all the nodes in the tree. 
Definition: NodeManager.h:631
RootNodeType & mRoot
Definition: NodeManager.h:713
void reduce(NodeOp &op, bool threaded=true, size_t grainSize=1)
Definition: NodeManager.h:275
void operator()(NodeT &node, size_t idx) const 
Definition: NodeManager.h:772
void clear()
Definition: NodeManager.h:410
Index64 nodeCount() const 
Definition: NodeManager.h:426
void foreachTopDown(const NodeOp &op, bool threaded=true, size_t leafGrainSize=1, size_t nonLeafGrainSize=1)
Threaded method that applies a user-supplied functor to all the nodes in the tree. 
Definition: NodeManager.h:976
size_t grainsize() const 
Definition: NodeManager.h:200
NodeT *& operator[](size_t n)
Definition: NodeManager.h:61
bool initRootChildren(RootT &root)
Definition: NodeManager.h:74
DynamicNodeManagerLink< ChildNodeType, LEVELS-1 > mChain
Definition: NodeManager.h:1051
void rebuild(bool serial=false)
Clear and recache all the tree nodes from the tree. This is required if tree nodes have been added or...
Definition: NodeManager.h:555
void initNodeChildren(ParentsT &parents, bool serial=false)
Definition: NodeManager.h:420
ReduceFilterOp(OpT &op, openvdb::Index64 size)
Definition: NodeManager.h:757
typename ChildNodeType::ChildNodeType NonConstChildNodeType
Definition: NodeManager.h:805
void reduceBottomUp(NodeOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that processes nodes with a user supplied functor. 
Definition: NodeManager.h:698
NodeManager(TreeOrLeafManagerT &tree, bool serial=false)
Definition: NodeManager.h:542
typename TreeOrLeafManagerT::RootNodeType NonConstRootNodeType
Definition: NodeManager.h:895
bool valid(size_t idx) const 
Definition: NodeManager.h:741
typename ChildNodeType::ChildNodeType NonConstChildNodeType
Definition: NodeManager.h:405
Index64 nodeCount(Index i) const 
Definition: NodeManager.h:428
void reduceBottomUp(NodeOp &op, bool threaded, size_t grainSize)
Definition: NodeManager.h:448
void join(const ReduceFilterOp &other)
Definition: NodeManager.h:777
Iterator begin() const 
Definition: NodeManager.h:244
std::unique_ptr< NodeT *[]> mNodePtrs
Definition: NodeManager.h:389
void reduceTopDown(NodeOp &op, bool threaded=true, size_t leafGrainSize=1, size_t nonLeafGrainSize=1)
Threaded method that processes nodes with a user supplied functor. 
Definition: NodeManager.h:1043
Definition: NodeManager.h:755
const NodeList & nodeList() const 
Definition: NodeManager.h:202
typename CopyConstness< TreeOrLeafManagerT, NonConstRootNodeType >::Type RootNodeType
Definition: NodeManager.h:537
ReduceFilterOp(const ReduceFilterOp &other)
Definition: NodeManager.h:762
void clear()
Definition: NodeManager.h:65
Index64 nodeCount() const 
Return the total number of cached nodes (excluding the root node) 
Definition: NodeManager.h:561
bool empty() const 
Definition: NodeManager.h:204
void reduceTopDown(NodeOp &op, bool threaded, size_t grainSize)
Definition: NodeManager.h:455
To facilitate threading over the nodes of a tree, cache node pointers in linear arrays, one for each level of the tree. 
Definition: NodeManager.h:30
typename CopyConstness< ChildNodeType, NonConstChildNodeType >::Type ChildNodeType
Definition: NodeManager.h:406
bool test() const 
Return true if this iterator is not yet exhausted. 
Definition: NodeManager.h:227
This class is a link in a chain that each caches tree nodes of a specific type in a linear array...
Definition: NodeManager.h:402
void clear()
Clear all the cached tree nodes. 
Definition: NodeManager.h:551
const RootNodeType & root() const 
Return a reference to the root node. 
Definition: NodeManager.h:558
const OpT & op() const 
Definition: NodeManager.h:743
bool operator!=(const Iterator &other) const 
Definition: NodeManager.h:232
NodeT & operator*() const 
Return a reference to the node to which this iterator is pointing. 
Definition: NodeManager.h:220
DynamicNodeManagerLink< ChildNodeType, LEVEL-1 > mNext
Definition: NodeManager.h:854
uint64_t Index64
Definition: Types.h:53
Definition: Exceptions.h:13
Index64 nodeCount() const 
Definition: NodeManager.h:63
ForeachFilterOp(const ForeachFilterOp &other)
Definition: NodeManager.h:731
const NonConstRootNodeType & root() const 
Return a reference to the root node. 
Definition: NodeManager.h:906
void initRootChildren(RootT &root, bool serial=false)
Definition: NodeManager.h:413
NodeRange(NodeRange &r, tbb::split)
Definition: NodeManager.h:194
typename CopyConstness< TreeOrLeafManagerT, NonConstChildNodeType >::Type ChildNodeType
Definition: NodeManager.h:898
ForeachFilterOp(const OpT &op, openvdb::Index64 size)
Definition: NodeManager.h:726
NodeList< NodeT > mList
Definition: NodeManager.h:853
NodeT * operator->() const 
Return a pointer to the node to which this iterator is pointing. 
Definition: NodeManager.h:222
Index32 Index
Definition: Types.h:54
size_t size() const 
Definition: NodeManager.h:198
void reduceTopDown(NodeOpT &op, RootT &root, bool threaded, size_t leafGrainSize, size_t nonLeafGrainSize)
Definition: NodeManager.h:832
NodeRange(size_t begin, size_t end, const NodeList &nodeList, size_t grainSize=1)
Definition: NodeManager.h:191
const NodeRange & nodeRange() const 
Definition: NodeManager.h:237
void foreachTopDownRecurse(const FilterOpT &filterOp, ParentT &parent, bool threaded, size_t leafGrainSize, size_t nonLeafGrainSize)
Definition: NodeManager.h:822
Iterator & operator++()
Advance to the next node. 
Definition: NodeManager.h:218
NodeRange nodeRange(size_t grainsize=1) const 
Return a TBB-compatible NodeRange. 
Definition: NodeManager.h:262
bool isValid(GridType gridType, GridClass gridClass)
return true if the combination of GridType and GridClass is valid. 
Definition: NanoVDB.h:520
void foreachTopDown(const NodeOp &op, bool threaded, size_t grainSize)
Definition: NodeManager.h:441
void foreachBottomUp(const NodeOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to all the nodes in the tree. 
Definition: NodeManager.h:624
void foreachBottomUp(const NodeOp &op, bool threaded, size_t grainSize)
Definition: NodeManager.h:434
typename RootNodeType::ChildNodeType NonConstChildNodeType
Definition: NodeManager.h:897
bool valid(size_t idx) const 
Definition: NodeManager.h:782
bool operator==(const Iterator &other) const 
Definition: NodeManager.h:236
typename CopyConstness< TreeOrLeafManagerT, NonConstRootNodeType >::Type RootNodeType
Definition: NodeManager.h:896
void run(const char *ax, openvdb::GridBase &grid, const AttributeBindings &bindings={})
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid. 
NodeManagerLink< ChildNodeType, LEVELS-1 > mChain
Definition: NodeManager.h:714
This class caches tree nodes of a specific type in a linear array. 
Definition: NodeManager.h:54
void reduceTopDownRecurse(FilterOpT &filterOp, ParentT &parent, bool threaded, size_t leafGrainSize, size_t nonLeafGrainSize)
Definition: NodeManager.h:843
void reduceTopDown(NodeOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that processes nodes with a user supplied functor. 
Definition: NodeManager.h:705
bool empty() const 
Return true if this iterator is exhausted. 
Definition: NodeManager.h:231
typename std::remove_const< ToType >::type Type
Definition: Types.h:400
Definition: NodeManager.h:724
ReduceFilterOp(const ReduceFilterOp &other, tbb::split)
Definition: NodeManager.h:766
#define OPENVDB_VERSION_NAME
The version namespace name for this library version. 
Definition: version.h.in:116
Index64 nodeCount(Index i) const 
Return the number of cached nodes at level i, where 0 corresponds to the lowest level. 
Definition: NodeManager.h:565
bool initNodeChildren(ParentsT &parents, const NodeFilterT &nodeFilter=NodeFilterT(), bool serial=false)
Definition: NodeManager.h:105
void reduceWithIndex(NodeOp &op, bool threaded=true, size_t grainSize=1)
Definition: NodeManager.h:292
Definition: NodeManager.h:36
RootNodeType & mRoot
Definition: NodeManager.h:1050
typename CopyConstness< ChildNodeType, NonConstChildNodeType >::Type ChildNodeType
Definition: NodeManager.h:806
static bool valid(size_t)
Definition: NodeManager.h:46
typename RootNodeType::ChildNodeType NonConstChildNodeType
Definition: NodeManager.h:538
void foreachTopDown(const NodeOpT &op, RootT &root, bool threaded, size_t leafGrainSize, size_t nonLeafGrainSize)
Definition: NodeManager.h:811
bool is_divisible() const 
Definition: NodeManager.h:206
size_t pos() const 
Return the index into the list of the current node. 
Definition: NodeManager.h:224
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202
Definition: NodeManager.h:208