2020#include < limits>
2121#include < stdexcept>
2222#include < iostream>
23+ #include < vector>
24+
2325
2426namespace grk
2527{
2628
27- /* *
28- Tag node
29- */
30- template <typename T>
31- struct TagTreeNode
32- {
33- TagTreeNode () : parent(nullptr ), value(0 ), low(0 ), known(false ) {}
34-
35- TagTreeNode* parent;
36- T value;
37- T low;
38- bool known;
39- };
40-
41- /* *
42- Tag tree
43- */
4429template <typename T>
4530class TagTree
4631{
4732public:
48- /* *
49- * @brief TagTree constructor
50- *
51- * @param leavesWidth Width of the array of leaves of the tree
52- * @param leavesHeight Height of the array of leaves of the tree
53- *
54- * @return a new tag tree if successful, otherwise nullptr
55- */
5633 TagTree (uint16_t leavesWidth, uint16_t leavesHeight)
57- : leavesWidth_(leavesWidth), leavesHeight_(leavesHeight), nodeCount( 0 ), nodes( nullptr )
34+ : leavesWidth_(leavesWidth), leavesHeight_(leavesHeight)
5835 {
59- uint16_t resLeavesWidth[16 ];
60- uint16_t resLeavesHeight[16 ];
61- int8_t numLevels = 0 ;
62- resLeavesWidth[0 ] = leavesWidth_;
63- resLeavesHeight[0 ] = leavesHeight_;
64- nodeCount = 0 ;
65- uint32_t nodesPerLevel;
66-
67- do
68- {
69- if (numLevels == 16 )
70- {
71- grklog.error (" TagTree constructor: num level overflow" );
72- throw std::runtime_error (" TagTree constructor: num level overflow" );
73- }
74- nodesPerLevel = static_cast <uint32_t >(resLeavesWidth[numLevels]) * resLeavesHeight[numLevels];
75- resLeavesWidth[numLevels + 1 ] = (uint16_t )((resLeavesWidth[numLevels] + 1 ) >> 1 );
76- resLeavesHeight[numLevels + 1 ] = (uint16_t )((resLeavesHeight[numLevels] + 1 ) >> 1 );
77- nodeCount += nodesPerLevel;
78- ++numLevels;
79- } while (nodesPerLevel > 1 );
80-
81- if (nodeCount == 0 )
82- {
83- grklog.warn (" tgt_create numnodes == 0, no tree created." );
84- throw std::runtime_error (" tgt_create numnodes == 0, no tree created" );
85- }
86-
87- nodes = new TagTreeNode<T>[nodeCount];
88- auto currentNode = nodes;
89- auto parentNode = nodes + static_cast <uint32_t >(leavesWidth_) * leavesHeight_;
90- auto parentNodeNext = parentNode;
91-
92- for (int8_t i = 0 ; i < numLevels - 1 ; ++i)
93- {
94- for (uint16_t j = 0U ; j < resLeavesHeight[i]; ++j)
95- {
96- int64_t k = resLeavesWidth[i];
97- while (--k >= 0 )
98- {
99- currentNode->parent = parentNode;
100- ++currentNode;
101- if (--k >= 0 )
102- {
103- currentNode->parent = parentNode;
104- ++currentNode;
105- }
106- ++parentNode;
107- }
108- if ((j & 1 ) || j == resLeavesHeight[i] - 1 )
109- {
110- parentNodeNext = parentNode;
111- }
112- else
113- {
114- parentNode = parentNodeNext;
115- parentNodeNext += resLeavesWidth[i];
116- }
117- }
118- }
119- currentNode->parent = nullptr ;
36+ buildTree ();
12037 reset ();
12138 }
12239
123- ~TagTree ()
124- {
125- delete[] nodes;
126- }
40+ ~TagTree () = default ;
12741
128- constexpr T getUninitializedValue (void )
42+ constexpr T getUninitializedValue () const noexcept
12943 {
13044 return (std::numeric_limits<T>::max)();
13145 }
@@ -135,13 +49,14 @@ class TagTree
13549 */
13650 void reset ()
13751 {
138- for (auto i = 0U ; i < nodeCount; ++i )
52+ for (auto & n : nodes_ )
13953 {
140- auto current_node = nodes + i;
141- current_node->value = getUninitializedValue ();
142- current_node->low = 0 ;
143- current_node->known = false ;
54+ n.value = getUninitializedValue ();
55+ n.low = 0 ;
56+ n.known = false ;
14457 }
58+ for (auto & v : leafCache_)
59+ v = getUninitializedValue ();
14560 }
14661
14762 /* *
@@ -151,11 +66,11 @@ class TagTree
15166 */
15267 void set (uint64_t leafno, T value)
15368 {
154- auto node = nodes + leafno;
155- while (node && node-> value > value)
69+ uint32_t node = static_cast < uint32_t >( leafno) ;
70+ while (node != UINT32_MAX && nodes_[ node]. value > value)
15671 {
157- node-> value = value;
158- node = node-> parent ;
72+ nodes_[ node]. value = value;
73+ node = parents_[ node] ;
15974 }
16075 }
16176
@@ -168,42 +83,44 @@ class TagTree
16883 */
16984 bool encode (t1_t2::BitIO* bio, uint64_t leafno, T threshold)
17085 {
171- TagTreeNode<T>* nodeStack[15 ];
172- auto nodeStackPtr = nodeStack;
173- auto node = nodes + leafno;
174- while (node->parent )
86+ // exact original encode logic, using flat indices
87+ uint32_t nodeStack[16 ];
88+ int stackPtr = 0 ;
89+ uint32_t node = static_cast <uint32_t >(leafno);
90+ while (parents_[node] != UINT32_MAX)
17591 {
176- *nodeStackPtr++ = node;
177- node = node-> parent ;
92+ nodeStack[stackPtr++] = node;
93+ node = parents_[ node] ;
17894 }
17995 T low = 0 ;
18096 while (true )
18197 {
182- if (node->low < low)
183- node->low = low;
98+ auto & n = nodes_[node];
99+ if (n.low < low)
100+ n.low = low;
184101 else
185- low = node-> low ;
102+ low = n. low ;
186103
187104 while (low < threshold)
188105 {
189- if (low >= node-> value )
106+ if (low >= n. value )
190107 {
191- if (!node-> known )
108+ if (!n. known )
192109 {
193110 if (!bio->write (1 ))
194111 return false ;
195- node-> known = true ;
112+ n. known = true ;
196113 }
197114 break ;
198115 }
199116 if (!bio->write (0 ))
200117 return false ;
201118 ++low;
202119 }
203- node-> low = low;
204- if (nodeStackPtr == nodeStack )
120+ n. low = low;
121+ if (stackPtr == 0 )
205122 break ;
206- node = *--nodeStackPtr ;
123+ node = nodeStack[--stackPtr] ;
207124 }
208125 return true ;
209126 }
@@ -217,49 +134,116 @@ class TagTree
217134 */
218135 void decode (t1_t2::BitIO* bio, uint64_t leafno, T threshold, T* value)
219136 {
220- TagTreeNode<T>* nodeStack[15 ];
137+ if (leafCache_[leafno] < threshold) [[likely]]
138+ {
139+ *value = leafCache_[leafno];
140+ return ;
141+ }
142+
221143 *value = getUninitializedValue ();
222- auto nodeStackPtr = nodeStack;
223- auto node = nodes + leafno;
224- // climb to top of tree
225- while (node->parent )
144+
145+ uint32_t nodeStack[16 ];
146+ int stackPtr = 0 ;
147+ uint32_t node = static_cast <uint32_t >(leafno);
148+
149+ // climb to root (exact same path as encode)
150+ while (parents_[node] != UINT32_MAX)
226151 {
227- *nodeStackPtr++ = node;
228- node = node-> parent ;
152+ nodeStack[stackPtr++] = node;
153+ node = parents_[ node] ;
229154 }
230- // descend to bottom of tree
155+
231156 T low = 0 ;
232157 while (true )
233158 {
234- if (node->low < low)
235- node->low = low;
159+ auto & n = nodes_[node];
160+
161+ if (n.low < low)
162+ n.low = low;
236163 else
237- low = node->low ;
238- while (low < threshold && low < node->value )
164+ low = n.low ;
165+
166+ while (low < threshold && low < n.value ) [[likely]]
239167 {
240168 if (bio->read ())
241169 {
242- node-> value = low;
170+ n. value = low;
243171 break ;
244172 }
245- low++ ;
173+ ++low ;
246174 }
247- node->low = low;
248- if (nodeStackPtr == nodeStack)
175+ n.low = low;
176+
177+ if (stackPtr == 0 ) [[unlikely]]
249178 break ;
250- node = *--nodeStackPtr;
179+
180+ node = nodeStack[--stackPtr]; // descend to child
251181 }
252- *value = node->value ;
182+
183+ *value = nodes_[node].value ; // now guaranteed to be the leaf node
184+ if (*value < threshold)
185+ leafCache_[leafno] = *value;
253186 }
254187
255188private:
189+ struct Node
190+ {
191+ T value;
192+ T low;
193+ bool known;
194+ };
195+
196+ void buildTree ()
197+ {
198+ // same level calculation as original
199+ uint16_t resW[16 ]{}, resH[16 ]{};
200+ int8_t levels = 0 ;
201+ resW[0 ] = leavesWidth_;
202+ resH[0 ] = leavesHeight_;
203+ uint64_t totalNodes = 0 ;
204+ uint32_t nodesPerLevel;
205+
206+ do
207+ {
208+ nodesPerLevel = static_cast <uint32_t >(resW[levels]) * resH[levels];
209+ resW[levels + 1 ] = (uint16_t )((resW[levels] + 1 ) >> 1 );
210+ resH[levels + 1 ] = (uint16_t )((resH[levels] + 1 ) >> 1 );
211+ totalNodes += nodesPerLevel;
212+ ++levels;
213+ } while (nodesPerLevel > 1 );
214+
215+ nodes_.resize (totalNodes);
216+ parents_.resize (totalNodes, UINT32_MAX);
217+ leafCache_.resize (static_cast <uint64_t >(leavesWidth_) * leavesHeight_);
218+
219+ // build parents (exact same linking logic as original, but with indices)
220+ uint64_t parentBase = static_cast <uint64_t >(leavesWidth_) * leavesHeight_;
221+ uint64_t cur = 0 ;
222+
223+ for (int8_t lvl = 0 ; lvl < levels - 1 ; ++lvl)
224+ {
225+ uint32_t w = resW[lvl];
226+ uint32_t h = resH[lvl];
227+ for (uint32_t j = 0 ; j < h; ++j)
228+ {
229+ for (uint32_t k = 0 ; k < w; ++k)
230+ {
231+ parents_[cur] = static_cast <uint32_t >(parentBase + (j >> 1 ) * resW[lvl + 1 ] + (k >> 1 ));
232+ ++cur;
233+ }
234+ }
235+ parentBase += static_cast <uint64_t >(resW[lvl + 1 ]) * resH[lvl + 1 ];
236+ }
237+ }
238+
256239 uint16_t leavesWidth_;
257240 uint16_t leavesHeight_;
258- uint64_t nodeCount;
259- TagTreeNode<T>* nodes;
241+ std::vector<Node> nodes_;
242+ std::vector<uint32_t > parents_; // UINT32_MAX = root
243+ std::vector<T> leafCache_;
260244};
261245
262246using TagTreeU8 = TagTree<uint8_t >;
263247using TagTreeU16 = TagTree<uint16_t >;
264248
265- } // namespace grk
249+ } // namespace grk
0 commit comments