static bool supernode_is_closed_cycle(const dBNode *nlist, size_t len, BinaryKmer bkmer0, BinaryKmer bkmer1, const dBGraph *db_graph) { Edges edges0, edges1; BinaryKmer shiftkmer; Nucleotide nuc; const size_t kmer_size = db_graph->kmer_size; edges0 = db_node_get_edges_union(db_graph, nlist[0].key); if(edges_get_indegree(edges0, nlist[0].orient) != 1) return false; edges1 = db_node_get_edges_union(db_graph, nlist[len-1].key); if(edges_get_outdegree(edges1, nlist[len-1].orient) != 1) return false; nuc = bkmer_get_last_nuc(bkmer0, nlist[0].orient, kmer_size); shiftkmer = bkmer_shift_add_last_nuc(bkmer1, nlist[len-1].orient, kmer_size, nuc); if(binary_kmers_are_equal(bkmer0, shiftkmer)) return true; shiftkmer = binary_kmer_reverse_complement(shiftkmer, kmer_size); return binary_kmers_are_equal(bkmer0, shiftkmer); }
// // Integrity checks // // Check an array of nodes denote a contigous path bool db_node_check_nodes(const dBNode *nodes, size_t num, const dBGraph *db_graph) { if(num == 0) return true; const size_t kmer_size = db_graph->kmer_size; BinaryKmer bkmer0, bkmer1, tmp; Nucleotide nuc; size_t i; bkmer0 = db_node_oriented_bkmer(db_graph, nodes[0]); for(i = 0; i+1 < num; i++) { bkmer1 = db_node_oriented_bkmer(db_graph, nodes[i+1]); nuc = binary_kmer_last_nuc(bkmer1); tmp = binary_kmer_left_shift_add(bkmer0, kmer_size, nuc); ctx_assert_ret(binary_kmers_are_equal(tmp, bkmer1)); bkmer0 = bkmer1; } return true; }
void hash_table_empty(HashTable *const ht) { size_t i; BinaryKmer *table = ht->table; for(i = 0; i < ht->capacity; i++) table[i] = unset_bkmer; memset(ht->buckets, 0, ht->num_of_buckets * sizeof(uint8_t[2])); HashTable data = { .table = ht->table, .num_of_buckets = ht->num_of_buckets, .hash_mask = ht->hash_mask, .bucket_size = ht->bucket_size, .capacity = ht->capacity, .buckets = ht->buckets, .num_kmers = 0, .collisions = {0}}; memcpy(ht, &data, sizeof(data)); } static inline const BinaryKmer* hash_table_find_in_bucket_mt(const HashTable *const ht, uint_fast32_t bucket, const BinaryKmer bkmer) { const BinaryKmer *ptr = ht_bckt_ptr(ht, bucket); const BinaryKmer *end = ptr + *(volatile __typeof(ht->buckets[0][0])*)&ht->buckets[bucket][HT_BSIZE]; while(ptr < end) { BinaryKmer tgt = *(volatile const BinaryKmer*)ptr; if(binary_kmers_are_equal(bkmer, tgt)) return ptr; ptr++; } return NULL; // Not found } /* static inline const BinaryKmer* hash_table_find_insert_in_bucket(const HashTable *const ht, uint_fast32_t bucket, const BinaryKmer bkmer, bool *found) { const BinaryKmer *ptr = ht_bckt_ptr(ht, bucket); const BinaryKmer *end = ptr + ht->buckets[bucket][HT_BSIZE]; const BinaryKmer *empty = NULL; for(; ptr < end && !binary_kmers_are_equal(bkmer, *ptr); ptr++) { if(!HASH_ENTRY_ASSIGNED(*ptr)) empty = ptr; } *found = (ptr < end); if(ptr == end && empty == NULL && ht->buckets[bucket][HT_BSIZE] < ht->bucket_size) { *empty = bkmer; ht->num_kmers++; ht->buckets[bucket][HT_BITEMS]++; ht->buckets[bucket][HT_BSIZE]++; } return ptr < end ? ptr : empty; } // Code to find/insert: // h = binary_kmer_hash(key,ht->seed+i) & ht->hash_mask; // ptr = hash_table_find_insert_in_bucket(ht, h, key, &f); // if(ptr != NULL) { // *found = f; // return ptr; // } */ // Remember to increment ht->num_kmers static inline BinaryKmer* hash_table_insert_in_bucket(HashTable *ht, uint_fast32_t bucket, const BinaryKmer bkmer) { ctx_assert(ht->buckets[bucket][HT_BITEMS] < ht->bucket_size); BinaryKmer *ptr = ht_bckt_ptr(ht, bucket); if(ht->buckets[bucket][HT_BSIZE] == ht->buckets[bucket][HT_BITEMS]) { ptr += ht->buckets[bucket][HT_BSIZE]; ht->buckets[bucket][HT_BSIZE]++; } else { // Find an entry that has been deleted from this bucket previously while(HASH_ENTRY_ASSIGNED(*ptr)) ptr++; } *ptr = bkmer; ht->buckets[bucket][HT_BITEMS]++; return ptr; }