11#include <btllib/hashing_internals.hpp>
12#include <btllib/status.hpp>
14namespace btllib::hashing_internals {
23base_forward_hash(
const char* seq,
25 const uint64_t* primitive_tab = SEED_TAB,
26 const uint64_t* dimer_tab = DIMER_TAB,
27 const uint64_t* trimer_tab = TRIMER_TAB,
28 const uint64_t* tetramer_tab = TETRAMER_TAB,
29 const uint8_t* convert_tab = CONVERT_TAB)
32 for (
unsigned i = 0; i < k - 3; i += 4) {
33 h_val = srol(h_val, 4);
35 loc += 64 * convert_tab[(
unsigned char)seq[i]];
36 loc += 16 * convert_tab[(
unsigned char)seq[i + 1]];
37 loc += 4 * convert_tab[(
unsigned char)seq[i + 2]];
38 loc += convert_tab[(
unsigned char)seq[i + 3]];
39 h_val ^= tetramer_tab[loc];
41 const unsigned remainder = k % 4;
43 h_val = srol(h_val, remainder);
46 uint8_t trimer_loc = 0;
47 trimer_loc += 16 * convert_tab[(
unsigned char)seq[k - 3]];
48 trimer_loc += 4 * convert_tab[(
unsigned char)seq[k - 2]];
49 trimer_loc += convert_tab[(
unsigned char)seq[k - 1]];
50 h_val ^= trimer_tab[trimer_loc];
51 }
else if (remainder == 2) {
52 uint8_t dimer_loc = 0;
53 dimer_loc += 4 * convert_tab[(
unsigned char)seq[k - 2]];
54 dimer_loc += convert_tab[(
unsigned char)seq[k - 1]];
55 h_val ^= dimer_tab[dimer_loc];
56 }
else if (remainder == 1) {
57 h_val ^= primitive_tab[(
unsigned char)seq[k - 1]];
72next_forward_hash(uint64_t fh_val,
74 unsigned char char_out,
75 unsigned char char_in,
76 const uint64_t* primitive_tab = SEED_TAB,
77 const uint64_t*
const* right_table = MS_TAB_33R,
78 const uint64_t*
const* left_table = MS_TAB_31L)
80 uint64_t h_val = srol(fh_val);
81 h_val ^= primitive_tab[char_in];
82 h_val ^= srol_table(char_out, k, right_table, left_table);
95prev_forward_hash(uint64_t fh_val,
97 unsigned char char_out,
98 unsigned char char_in,
99 const uint64_t* primitive_tab = SEED_TAB,
100 const uint64_t*
const* right_table = MS_TAB_33R,
101 const uint64_t*
const* left_table = MS_TAB_31L)
103 uint64_t h_val = fh_val ^ srol_table(char_in, k, right_table, left_table);
104 h_val ^= primitive_tab[char_out];
117base_reverse_hash(
const char* seq,
119 const uint64_t* primitive_tab = SEED_TAB,
120 const uint64_t* dimer_tab = DIMER_TAB,
121 const uint64_t* trimer_tab = TRIMER_TAB,
122 const uint64_t* tetramer_tab = TETRAMER_TAB,
123 const uint8_t* rc_convert_tab = RC_CONVERT_TAB)
126 const unsigned remainder = k % 4;
127 if (remainder == 3) {
128 uint8_t trimer_loc = 0;
129 trimer_loc += 16 * rc_convert_tab[(
unsigned char)seq[k - 1]];
130 trimer_loc += 4 * rc_convert_tab[(
unsigned char)seq[k - 2]];
131 trimer_loc += rc_convert_tab[(
unsigned char)seq[k - 3]];
132 h_val ^= trimer_tab[trimer_loc];
133 }
else if (remainder == 2) {
134 uint8_t dimer_loc = 0;
135 dimer_loc += 4 * rc_convert_tab[(
unsigned char)seq[k - 1]];
136 dimer_loc += rc_convert_tab[(
unsigned char)seq[k - 2]];
137 h_val ^= dimer_tab[dimer_loc];
138 }
else if (remainder == 1) {
139 h_val ^= primitive_tab[(
unsigned char)seq[k - 1] & CP_OFF];
141 for (
int i = (
int)(k - remainder) - 1; i >= 3; i -= 4) {
142 h_val = srol(h_val, 4);
144 loc += 64 * rc_convert_tab[(
unsigned char)seq[i]];
145 loc += 16 * rc_convert_tab[(
unsigned char)seq[i - 1]];
146 loc += 4 * rc_convert_tab[(
unsigned char)seq[i - 2]];
147 loc += rc_convert_tab[(
unsigned char)seq[i - 3]];
148 h_val ^= tetramer_tab[loc];
164next_reverse_hash(uint64_t rh_val,
166 unsigned char char_out,
167 unsigned char char_in,
168 const uint64_t* primitive_tab = SEED_TAB,
169 const uint64_t*
const* right_table = MS_TAB_33R,
170 const uint64_t*
const* left_table = MS_TAB_31L)
173 rh_val ^ srol_table(char_in & CP_OFF, k, right_table, left_table);
174 h_val ^= primitive_tab[char_out & CP_OFF];
188prev_reverse_hash(uint64_t rh_val,
190 unsigned char char_out,
191 unsigned char char_in,
192 const uint64_t* primitive_tab = SEED_TAB,
193 const uint64_t*
const* right_table = MS_TAB_33R,
194 const uint64_t*
const* left_table = MS_TAB_31L)
196 uint64_t h_val = srol(rh_val);
197 h_val ^= primitive_tab[char_in & CP_OFF];
198 h_val ^= srol_table(char_out & CP_OFF, k, right_table, left_table);
217sub_hash(uint64_t fh_val,
219 const char* kmer_seq,
220 const std::vector<unsigned>& positions,
221 const std::vector<unsigned char>& new_bases,
225 const uint64_t*
const* right_table = MS_TAB_33R,
226 const uint64_t*
const* left_table = MS_TAB_31L)
230 for (
size_t i = 0; i < positions.size(); i++) {
231 const auto pos = positions[i];
232 const auto new_base = new_bases[i];
234 fh_val ^= srol_table(
235 (
unsigned char)kmer_seq[pos], k - 1 - pos, right_table, left_table);
236 fh_val ^= srol_table(new_base, k - 1 - pos, right_table, left_table);
238 rh_val ^= srol_table(
239 (
unsigned char)kmer_seq[pos] & CP_OFF, pos, right_table, left_table);
240 rh_val ^= srol_table(new_base & CP_OFF, pos, right_table, left_table);
243 b_val = canonical(fh_val, rh_val);
244 extend_hashes(b_val, k, m, h_val);
251using hashing_internals::base_forward_hash;
252using hashing_internals::base_reverse_hash;
253using hashing_internals::extend_hashes;
254using hashing_internals::next_forward_hash;
255using hashing_internals::next_reverse_hash;
256using hashing_internals::prev_forward_hash;
257using hashing_internals::prev_reverse_hash;
258using hashing_internals::SEED_N;
259using hashing_internals::SEED_TAB;
260using hashing_internals::sub_hash;
279 hashing_internals::NUM_HASHES_TYPE num_hashes,
280 hashing_internals::K_TYPE k,
284 , num_hashes(num_hashes)
288 , hash_arr(new uint64_t[num_hashes])
290 check_error(k == 0,
"NtHash: k must be greater than 0");
292 "NtHash: sequence length (" + std::to_string(this->seq_len) +
293 ") is smaller than k (" + std::to_string(k) +
")");
295 "NtHash: passed position (" + std::to_string(pos) +
296 ") is larger than sequence length (" +
297 std::to_string(this->seq_len) +
")");
308 hashing_internals::NUM_HASHES_TYPE num_hashes,
309 hashing_internals::K_TYPE k,
311 :
NtHash(seq.data(), seq.size(), num_hashes, k, pos)
317 , seq_len(obj.seq_len)
318 , num_hashes(obj.num_hashes)
321 , initialized(obj.initialized)
322 , fwd_hash(obj.fwd_hash)
323 , rev_hash(obj.rev_hash)
324 , hash_arr(new uint64_t[obj.num_hashes])
327 hash_arr.get(), obj.hash_arr.get(), num_hashes *
sizeof(uint64_t));
349 if (pos >= seq_len - k) {
352 if (hashing_internals::SEED_TAB[(
unsigned char)seq[pos + k]] ==
353 hashing_internals::SEED_N) {
357 fwd_hash = next_forward_hash(fwd_hash, k, seq[pos], seq[pos + k]);
358 rev_hash = next_reverse_hash(rev_hash, k, seq[pos], seq[pos + k]);
359 extend_hashes(fwd_hash, rev_hash, k, num_hashes, hash_arr.get());
376 if (SEED_TAB[(
unsigned char)seq[pos - 1]] == SEED_N && pos >= k) {
380 if (SEED_TAB[(
unsigned char)seq[pos - 1]] == SEED_N) {
383 fwd_hash = prev_forward_hash(fwd_hash, k, seq[pos + k - 1], seq[pos - 1]);
384 rev_hash = prev_reverse_hash(rev_hash, k, seq[pos + k - 1], seq[pos - 1]);
385 extend_hashes(fwd_hash, rev_hash, k, num_hashes, hash_arr.get());
398 if (pos >= seq_len - k) {
401 return peek(seq[pos + k]);
427 if (SEED_TAB[(
unsigned char)char_in] == SEED_N) {
430 const uint64_t fwd = next_forward_hash(fwd_hash, k, seq[pos], char_in);
431 const uint64_t rev = next_reverse_hash(rev_hash, k, seq[pos], char_in);
432 extend_hashes(fwd, rev, k, num_hashes, hash_arr.get());
445 if (SEED_TAB[(
unsigned char)char_in] == SEED_N) {
448 const unsigned char char_out = seq[pos + k - 1];
449 const uint64_t fwd = prev_forward_hash(fwd_hash, k, char_out, char_in);
450 const uint64_t rev = prev_reverse_hash(rev_hash, k, char_out, char_in);
451 extend_hashes(fwd, rev, k, num_hashes, hash_arr.get());
455 void sub(
const std::vector<unsigned>& positions,
456 const std::vector<unsigned char>& new_bases)
472 const uint64_t*
hashes()
const {
return hash_arr.get(); }
485 hashing_internals::NUM_HASHES_TYPE
get_hash_num()
const {
return num_hashes; }
491 hashing_internals::K_TYPE
get_k()
const {
return k; }
507 const size_t seq_len;
508 hashing_internals::NUM_HASHES_TYPE num_hashes;
509 hashing_internals::K_TYPE k;
512 uint64_t fwd_hash = 0;
513 uint64_t rev_hash = 0;
514 std::unique_ptr<uint64_t[]> hash_arr;
523 while (pos <= seq_len - k + 1 && has_n) {
525 for (
unsigned i = 0; i < k && pos <= seq_len - k + 1; i++) {
526 if (SEED_TAB[(
unsigned char)seq[pos + k - i - 1]] == SEED_N) {
532 if (pos > seq_len - k) {
535 fwd_hash = base_forward_hash(seq + pos, k);
536 rev_hash = base_reverse_hash(seq + pos, k);
537 extend_hashes(fwd_hash, rev_hash, k, num_hashes, hash_arr.get());
562 hashing_internals::NUM_HASHES_TYPE num_hashes,
563 hashing_internals::K_TYPE k,
565 : seq(seq.data() + pos, seq.data() + pos + k)
566 , num_hashes(num_hashes)
568 , fwd_hash(base_forward_hash(seq.data(), k))
569 , rev_hash(base_reverse_hash(seq.data(), k))
570 , hash_arr(new uint64_t[num_hashes])
572 check_error(k == 0,
"BlindNtHash: k must be greater than 0");
573 extend_hashes(fwd_hash, rev_hash, k, num_hashes, hash_arr.get());
578 , num_hashes(obj.num_hashes)
580 , fwd_hash(obj.fwd_hash)
581 , rev_hash(obj.rev_hash)
582 , hash_arr(new uint64_t[obj.num_hashes])
585 hash_arr.get(), obj.hash_arr.get(), num_hashes *
sizeof(uint64_t));
598 fwd_hash = next_forward_hash(fwd_hash, seq.size(), seq.front(), char_in);
599 rev_hash = next_reverse_hash(rev_hash, seq.size(), seq.front(), char_in);
600 extend_hashes(fwd_hash, rev_hash, seq.size(), num_hashes, hash_arr.get());
602 seq.push_back(char_in);
611 fwd_hash = prev_forward_hash(fwd_hash, seq.size(), seq.back(), char_in);
612 rev_hash = prev_reverse_hash(rev_hash, seq.size(), seq.back(), char_in);
613 extend_hashes(fwd_hash, rev_hash, seq.size(), num_hashes, hash_arr.get());
615 seq.push_front(char_in);
624 const hashing_internals::K_TYPE k = seq.size();
625 const uint64_t fwd = next_forward_hash(fwd_hash, k, seq.front(), char_in);
626 const uint64_t rev = next_reverse_hash(rev_hash, k, seq.front(), char_in);
627 extend_hashes(fwd, rev, seq.size(), num_hashes, hash_arr.get());
635 const hashing_internals::K_TYPE k = seq.size();
636 const uint64_t fwd = prev_forward_hash(fwd_hash, k, seq.back(), char_in);
637 const uint64_t rev = prev_reverse_hash(rev_hash, k, seq.back(), char_in);
638 extend_hashes(fwd, rev, seq.size(), num_hashes, hash_arr.get());
645 const uint64_t*
hashes()
const {
return hash_arr.get(); }
658 hashing_internals::NUM_HASHES_TYPE
get_hash_num()
const {
return num_hashes; }
664 hashing_internals::K_TYPE
get_k()
const {
return seq.size(); }
679 std::deque<char> seq;
680 hashing_internals::NUM_HASHES_TYPE num_hashes;
684 std::unique_ptr<uint64_t[]> hash_arr;
Definition nthash_kmer.hpp:550
long get_pos() const
Definition nthash_kmer.hpp:652
uint64_t get_forward_hash() const
Definition nthash_kmer.hpp:670
hashing_internals::K_TYPE get_k() const
Definition nthash_kmer.hpp:664
void peek(char char_in)
Definition nthash_kmer.hpp:622
uint64_t get_reverse_hash() const
Definition nthash_kmer.hpp:676
void roll(char char_in)
Definition nthash_kmer.hpp:596
const uint64_t * hashes() const
Definition nthash_kmer.hpp:645
hashing_internals::NUM_HASHES_TYPE get_hash_num() const
Definition nthash_kmer.hpp:658
BlindNtHash(const std::string &seq, hashing_internals::NUM_HASHES_TYPE num_hashes, hashing_internals::K_TYPE k, long pos=0)
Definition nthash_kmer.hpp:561
void peek_back(char char_in)
Definition nthash_kmer.hpp:633
void roll_back(char char_in)
Definition nthash_kmer.hpp:609
Definition nthash_kmer.hpp:266
bool peek()
Definition nthash_kmer.hpp:396
bool peek_back()
Definition nthash_kmer.hpp:408
bool peek(char char_in)
Definition nthash_kmer.hpp:422
bool roll()
Definition nthash_kmer.hpp:344
const uint64_t * hashes() const
Definition nthash_kmer.hpp:472
hashing_internals::NUM_HASHES_TYPE get_hash_num() const
Definition nthash_kmer.hpp:485
hashing_internals::K_TYPE get_k() const
Definition nthash_kmer.hpp:491
NtHash(const char *seq, size_t seq_len, hashing_internals::NUM_HASHES_TYPE num_hashes, hashing_internals::K_TYPE k, size_t pos=0)
Definition nthash_kmer.hpp:277
bool peek_back(char char_in)
Definition nthash_kmer.hpp:440
uint64_t get_reverse_hash() const
Definition nthash_kmer.hpp:503
size_t get_pos() const
Definition nthash_kmer.hpp:479
NtHash(const std::string &seq, hashing_internals::NUM_HASHES_TYPE num_hashes, hashing_internals::K_TYPE k, size_t pos=0)
Definition nthash_kmer.hpp:307
bool roll_back()
Definition nthash_kmer.hpp:368
uint64_t get_forward_hash() const
Definition nthash_kmer.hpp:497
void check_error(bool condition, const std::string &msg)