@@ -3509,34 +3509,29 @@ tsk_tree_get_num_samples_by_traversal(
3509
3509
const tsk_tree_t * self , tsk_id_t u , tsk_size_t * num_samples )
3510
3510
{
3511
3511
int ret = 0 ;
3512
- tsk_id_t * stack = NULL ;
3513
- tsk_id_t v ;
3512
+ tsk_size_t num_nodes , j ;
3514
3513
tsk_size_t count = 0 ;
3515
- int stack_top = 0 ;
3514
+ const tsk_flags_t * restrict flags = self -> tree_sequence -> tables -> nodes .flags ;
3515
+ tsk_id_t * nodes = tsk_malloc (tsk_tree_get_size_bound (self ) * sizeof (* nodes ));
3516
+ tsk_id_t v ;
3516
3517
3517
- stack = tsk_malloc (self -> num_nodes * sizeof (* stack ));
3518
- if (stack == NULL ) {
3518
+ if (nodes == NULL ) {
3519
3519
ret = TSK_ERR_NO_MEMORY ;
3520
3520
goto out ;
3521
3521
}
3522
-
3523
- stack [0 ] = u ;
3524
- while (stack_top >= 0 ) {
3525
- v = stack [stack_top ];
3526
- stack_top -- ;
3527
- if (tsk_treeseq_is_sample (self -> tree_sequence , v )) {
3522
+ ret = tsk_tree_preorder (self , u , nodes , & num_nodes );
3523
+ if (ret != 0 ) {
3524
+ goto out ;
3525
+ }
3526
+ for (j = 0 ; j < num_nodes ; j ++ ) {
3527
+ v = nodes [j ];
3528
+ if (flags [v ] & TSK_NODE_IS_SAMPLE ) {
3528
3529
count ++ ;
3529
3530
}
3530
- v = self -> left_child [v ];
3531
- while (v != TSK_NULL ) {
3532
- stack_top ++ ;
3533
- stack [stack_top ] = v ;
3534
- v = self -> right_sib [v ];
3535
- }
3536
3531
}
3537
3532
* num_samples = count ;
3538
3533
out :
3539
- tsk_safe_free (stack );
3534
+ tsk_safe_free (nodes );
3540
3535
return ret ;
3541
3536
}
3542
3537
@@ -3649,14 +3644,14 @@ tsk_tree_get_sites(
3649
3644
static int
3650
3645
tsk_tree_get_depth_unsafe (const tsk_tree_t * self , tsk_id_t u )
3651
3646
{
3652
-
3653
3647
tsk_id_t v ;
3648
+ const tsk_id_t * restrict parent = self -> parent ;
3654
3649
int depth = 0 ;
3655
3650
3656
3651
if (u == self -> virtual_root ) {
3657
3652
return -1 ;
3658
3653
}
3659
- for (v = self -> parent [u ]; v != TSK_NULL ; v = self -> parent [v ]) {
3654
+ for (v = parent [u ]; v != TSK_NULL ; v = parent [v ]) {
3660
3655
depth ++ ;
3661
3656
}
3662
3657
return depth ;
@@ -4443,6 +4438,9 @@ get_smallest_set_bit(uint64_t v)
4443
4438
* use a general cost matrix, in which case we'll use the Sankoff algorithm. For
4444
4439
* now this is unused.
4445
4440
*
4441
+ * We should also vectorise the function so that several sites can be processed
4442
+ * at once.
4443
+ *
4446
4444
* The algorithm used here is Hartigan parsimony, "Minimum Mutation Fits to a
4447
4445
* Given Tree", Biometrics 1973.
4448
4446
*/
@@ -4458,30 +4456,34 @@ tsk_tree_map_mutations(tsk_tree_t *self, int8_t *genotypes,
4458
4456
int8_t state ;
4459
4457
};
4460
4458
const tsk_size_t num_samples = self -> tree_sequence -> num_samples ;
4461
- const tsk_size_t num_nodes = self -> num_nodes ;
4462
4459
const tsk_id_t * restrict left_child = self -> left_child ;
4463
4460
const tsk_id_t * restrict right_sib = self -> right_sib ;
4464
- const tsk_id_t * restrict parent = self -> parent ;
4461
+ const tsk_size_t N = tsk_treeseq_get_num_nodes ( self -> tree_sequence ) ;
4465
4462
const tsk_flags_t * restrict node_flags = self -> tree_sequence -> tables -> nodes .flags ;
4466
- uint64_t optimal_root_set ;
4467
- uint64_t * restrict optimal_set = tsk_calloc (num_nodes , sizeof (* optimal_set ));
4468
- tsk_id_t * restrict postorder_stack
4469
- = tsk_malloc (num_nodes * sizeof (* postorder_stack ));
4463
+ tsk_id_t * nodes = tsk_malloc (tsk_tree_get_size_bound (self ) * sizeof (* nodes ));
4464
+ /* Note: to use less memory here and to improve cache performance we should
4465
+ * probably change to allocating exactly the number of nodes returned by
4466
+ * a preorder traversal, and then lay the memory out in this order. So, we'd
4467
+ * need a map from node ID to its index in the preorder traversal, but this
4468
+ * is trivial to compute. Probably doesn't matter so much at the moment
4469
+ * when we're doing a single site, but it would make a big difference if
4470
+ * we were vectorising over lots of sites. */
4471
+ uint64_t * restrict optimal_set = tsk_calloc (N + 1 , sizeof (* optimal_set ));
4470
4472
struct stack_elem * restrict preorder_stack
4471
- = tsk_malloc (num_nodes * sizeof (* preorder_stack ));
4472
- tsk_id_t postorder_parent , root , u , v ;
4473
+ = tsk_malloc (tsk_tree_get_size_bound ( self ) * sizeof (* preorder_stack ));
4474
+ tsk_id_t root , u , v ;
4473
4475
/* The largest possible number of transitions is one over every sample */
4474
4476
tsk_state_transition_t * transitions = tsk_malloc (num_samples * sizeof (* transitions ));
4475
4477
int8_t allele , ancestral_state ;
4476
4478
int stack_top ;
4477
4479
struct stack_elem s ;
4478
- tsk_size_t j , num_transitions , max_allele_count ;
4480
+ tsk_size_t j , num_transitions , max_allele_count , num_nodes ;
4479
4481
tsk_size_t allele_count [HARTIGAN_MAX_ALLELES ];
4480
4482
tsk_size_t non_missing = 0 ;
4481
4483
int8_t num_alleles = 0 ;
4482
4484
4483
- if (optimal_set == NULL || preorder_stack == NULL || postorder_stack == NULL
4484
- || transitions == NULL ) {
4485
+ if (optimal_set == NULL || preorder_stack == NULL || transitions == NULL
4486
+ || nodes == NULL ) {
4485
4487
ret = TSK_ERR_NO_MEMORY ;
4486
4488
goto out ;
4487
4489
}
@@ -4518,68 +4520,33 @@ tsk_tree_map_mutations(tsk_tree_t *self, int8_t *genotypes,
4518
4520
}
4519
4521
}
4520
4522
4521
- for (root = self -> left_root ; root != TSK_NULL ; root = self -> right_sib [root ]) {
4522
- /* Do a post order traversal */
4523
- postorder_stack [0 ] = root ;
4524
- stack_top = 0 ;
4525
- postorder_parent = TSK_NULL ;
4526
- while (stack_top >= 0 ) {
4527
- u = postorder_stack [stack_top ];
4528
- if (left_child [u ] != TSK_NULL && u != postorder_parent ) {
4529
- for (v = left_child [u ]; v != TSK_NULL ; v = right_sib [v ]) {
4530
- stack_top ++ ;
4531
- postorder_stack [stack_top ] = v ;
4532
- }
4533
- } else {
4534
- stack_top -- ;
4535
- postorder_parent = parent [u ];
4536
-
4537
- /* Visit u */
4538
- tsk_memset (
4539
- allele_count , 0 , ((size_t ) num_alleles ) * sizeof (* allele_count ));
4540
- for (v = left_child [u ]; v != TSK_NULL ; v = right_sib [v ]) {
4541
- for (allele = 0 ; allele < num_alleles ; allele ++ ) {
4542
- allele_count [allele ] += bit_is_set (optimal_set [v ], allele );
4543
- }
4544
- }
4545
- if (!(node_flags [u ] & TSK_NODE_IS_SAMPLE )) {
4546
- max_allele_count = 0 ;
4547
- for (allele = 0 ; allele < num_alleles ; allele ++ ) {
4548
- max_allele_count
4549
- = TSK_MAX (max_allele_count , allele_count [allele ]);
4550
- }
4551
- for (allele = 0 ; allele < num_alleles ; allele ++ ) {
4552
- if (allele_count [allele ] == max_allele_count ) {
4553
- optimal_set [u ] = set_bit (optimal_set [u ], allele );
4554
- }
4555
- }
4556
- }
4557
- }
4558
- }
4523
+ ret = tsk_tree_postorder (self , self -> virtual_root , nodes , & num_nodes );
4524
+ if (ret != 0 ) {
4525
+ goto out ;
4559
4526
}
4560
-
4561
- if (!(options & TSK_MM_FIXED_ANCESTRAL_STATE )) {
4562
- optimal_root_set = 0 ;
4563
- /* TODO it's annoying that this is essentially the same as the
4564
- * visit function above. It would be nice if we had an extra
4565
- * node that was the parent of all roots, then the algorithm
4566
- * would work as-is */
4527
+ for (j = 0 ; j < num_nodes ; j ++ ) {
4528
+ u = nodes [j ];
4567
4529
tsk_memset (allele_count , 0 , ((size_t ) num_alleles ) * sizeof (* allele_count ));
4568
- for (root = self -> left_root ; root != TSK_NULL ; root = right_sib [root ]) {
4530
+ for (v = left_child [ u ]; v != TSK_NULL ; v = right_sib [v ]) {
4569
4531
for (allele = 0 ; allele < num_alleles ; allele ++ ) {
4570
- allele_count [allele ] += bit_is_set (optimal_set [root ], allele );
4532
+ allele_count [allele ] += bit_is_set (optimal_set [v ], allele );
4571
4533
}
4572
4534
}
4573
- max_allele_count = 0 ;
4574
- for (allele = 0 ; allele < num_alleles ; allele ++ ) {
4575
- max_allele_count = TSK_MAX (max_allele_count , allele_count [allele ]);
4576
- }
4577
- for (allele = 0 ; allele < num_alleles ; allele ++ ) {
4578
- if (allele_count [allele ] == max_allele_count ) {
4579
- optimal_root_set = set_bit (optimal_root_set , allele );
4535
+ /* the virtual root has no flags defined */
4536
+ if (u == (tsk_id_t ) N || !(node_flags [u ] & TSK_NODE_IS_SAMPLE )) {
4537
+ max_allele_count = 0 ;
4538
+ for (allele = 0 ; allele < num_alleles ; allele ++ ) {
4539
+ max_allele_count = TSK_MAX (max_allele_count , allele_count [allele ]);
4540
+ }
4541
+ for (allele = 0 ; allele < num_alleles ; allele ++ ) {
4542
+ if (allele_count [allele ] == max_allele_count ) {
4543
+ optimal_set [u ] = set_bit (optimal_set [u ], allele );
4544
+ }
4580
4545
}
4581
4546
}
4582
- ancestral_state = get_smallest_set_bit (optimal_root_set );
4547
+ }
4548
+ if (!(options & TSK_MM_FIXED_ANCESTRAL_STATE )) {
4549
+ ancestral_state = get_smallest_set_bit (optimal_set [N ]);
4583
4550
}
4584
4551
4585
4552
num_transitions = 0 ;
@@ -4622,8 +4589,8 @@ tsk_tree_map_mutations(tsk_tree_t *self, int8_t *genotypes,
4622
4589
if (preorder_stack != NULL ) {
4623
4590
free (preorder_stack );
4624
4591
}
4625
- if (postorder_stack != NULL ) {
4626
- free (postorder_stack );
4592
+ if (nodes != NULL ) {
4593
+ free (nodes );
4627
4594
}
4628
4595
return ret ;
4629
4596
}
@@ -4888,7 +4855,7 @@ fill_kc_vectors(const tsk_tree_t *t, kc_vectors *kc_vecs)
4888
4855
int ret = 0 ;
4889
4856
const tsk_treeseq_t * ts = t -> tree_sequence ;
4890
4857
4891
- stack = tsk_malloc (t -> num_nodes * sizeof (* stack ));
4858
+ stack = tsk_malloc (tsk_tree_get_size_bound ( t ) * sizeof (* stack ));
4892
4859
if (stack == NULL ) {
4893
4860
ret = TSK_ERR_NO_MEMORY ;
4894
4861
goto out ;
@@ -5094,7 +5061,7 @@ update_kc_subtree_state(
5094
5061
tsk_id_t * stack = NULL ;
5095
5062
int ret = 0 ;
5096
5063
5097
- stack = tsk_malloc (t -> num_nodes * sizeof (* stack ));
5064
+ stack = tsk_malloc (tsk_tree_get_size_bound ( t ) * sizeof (* stack ));
5098
5065
if (stack == NULL ) {
5099
5066
ret = TSK_ERR_NO_MEMORY ;
5100
5067
goto out ;
0 commit comments