@@ -3626,7 +3626,6 @@ tsk_tree_get_time(const tsk_tree_t *self, tsk_id_t u, double *t)
3626
3626
if (u == self -> virtual_root ) {
3627
3627
* t = INFINITY ;
3628
3628
} else {
3629
-
3630
3629
ret = tsk_treeseq_get_node (self -> tree_sequence , u , & node );
3631
3630
if (ret != 0 ) {
3632
3631
goto out ;
@@ -4259,16 +4258,48 @@ tsk_tree_clear(tsk_tree_t *self)
4259
4258
return ret ;
4260
4259
}
4261
4260
4261
+ tsk_size_t
4262
+ tsk_tree_get_size_bound (const tsk_tree_t * self )
4263
+ {
4264
+ tsk_size_t bound = 0 ;
4265
+
4266
+ if (self -> tree_sequence != NULL ) {
4267
+ /* This is a safe upper bound which can be computed cheaply.
4268
+ * We have at most n roots and each edge adds at most one new
4269
+ * node to the tree. We also allow space for the virtual root,
4270
+ * to simplify client code.
4271
+ *
4272
+ * In the common case of a binary tree with a single root, we have
4273
+ * 2n - 1 nodes in total, and 2n - 2 edges. Therefore, we return
4274
+ * 3n - 1, which is an over-estimate of 1/2 and we allocate
4275
+ * 1.5 times as much memory as we need.
4276
+ *
4277
+ * Since tracking the exact number of nodes in the tree would require
4278
+ * storing the number of nodes beneath every node and complicate
4279
+ * the tree transition method, this seems like a good compromise
4280
+ * and will result in less memory usage overall in nearly all cases.
4281
+ */
4282
+ bound = 1 + self -> tree_sequence -> num_samples + self -> num_edges ;
4283
+ }
4284
+ return bound ;
4285
+ }
4286
+
4262
4287
/* Traversal orders */
4263
4288
4289
+ static tsk_id_t *
4290
+ tsk_tree_alloc_node_stack (const tsk_tree_t * self )
4291
+ {
4292
+ return tsk_malloc (tsk_tree_get_size_bound (self ) * sizeof (tsk_id_t ));
4293
+ }
4294
+
4264
4295
int
4265
4296
tsk_tree_preorder (
4266
4297
const tsk_tree_t * self , tsk_id_t root , tsk_id_t * nodes , tsk_size_t * num_nodes_ret )
4267
4298
{
4268
4299
int ret = 0 ;
4269
4300
const tsk_id_t * restrict right_child = self -> right_child ;
4270
4301
const tsk_id_t * restrict left_sib = self -> left_sib ;
4271
- tsk_id_t * restrict stack = tsk_malloc (( self -> num_nodes + 1 ) * sizeof ( * stack ) );
4302
+ tsk_id_t * restrict stack = tsk_tree_alloc_node_stack ( self );
4272
4303
tsk_size_t num_nodes = 0 ;
4273
4304
tsk_id_t u , v ;
4274
4305
int stack_top ;
@@ -4320,7 +4351,7 @@ tsk_tree_postorder(
4320
4351
const tsk_id_t * restrict right_child = self -> right_child ;
4321
4352
const tsk_id_t * restrict left_sib = self -> left_sib ;
4322
4353
const tsk_id_t * restrict parent = self -> parent ;
4323
- tsk_id_t * restrict stack = tsk_malloc (( self -> num_nodes + 1 ) * sizeof ( * stack ) );
4354
+ tsk_id_t * restrict stack = tsk_tree_alloc_node_stack ( self );
4324
4355
tsk_size_t num_nodes = 0 ;
4325
4356
tsk_id_t u , v , postorder_parent ;
4326
4357
int stack_top ;
0 commit comments