2026-11-03 09:22:32 +11:00
|
|
|
package obisimilarity
|
2026-11-03 06:09:06 +11:00
|
|
|
|
2026-11-03 09:22:32 +11:00
|
|
|
// A block stores the 4-mer tables of a few sequences, transposed: the counter
|
2026-11-03 06:09:06 +11:00
|
|
|
// of the word w for the lane j is data[w*width+j]. A vector instruction then
|
2026-11-03 09:22:32 +11:00
|
|
|
// handles the same word for all the sequences of the block, and only the words
|
2026-11-03 06:09:06 +11:00
|
|
|
// that a sequence contains (a hundred for a short amplicon, out of 256) need
|
2026-11-03 09:22:32 +11:00
|
|
|
// to be visited to compare it with all the sequences of the block.
|
2026-11-03 06:09:06 +11:00
|
|
|
type tableBlock struct {
|
|
|
|
|
data []uint8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func newTableBlock(width int) tableBlock {
|
|
|
|
|
return tableBlock{data: make([]uint8, 256*width)}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set stores the table t as the lane `lane` of the block.
|
2026-11-03 09:22:32 +11:00
|
|
|
func (b *tableBlock) set(width, lane int, t *Table4) {
|
|
|
|
|
for w := range t.Count {
|
|
|
|
|
b.data[w*width+lane] = t.Count[w]
|
2026-11-03 06:09:06 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// common computes the sums of the minima of the counters of the sequence
|
|
|
|
|
// given by its words with every lane of the block (see blockCommon).
|
|
|
|
|
func (b *tableBlock) common(width int, words []uint16, out []uint8) {
|
|
|
|
|
blockCommon(b.data, width, words, out)
|
|
|
|
|
}
|
|
|
|
|
|
2026-11-03 09:22:32 +11:00
|
|
|
// SparseWords lists the words of a table as w<<8|count, so that the visit of
|
2026-11-03 06:09:06 +11:00
|
|
|
// a block only goes through the words present in the sequence. nil is
|
|
|
|
|
// returned when the counters add up to more than 255, which would overflow the
|
|
|
|
|
// 8-bit sums of the blocks.
|
2026-11-03 09:22:32 +11:00
|
|
|
func SparseWords(t *Table4) []uint16 {
|
2026-11-03 06:09:06 +11:00
|
|
|
words := make([]uint16, 0, 128)
|
|
|
|
|
mass := 0
|
2026-11-03 09:22:32 +11:00
|
|
|
for w, c := range t.Count {
|
2026-11-03 06:09:06 +11:00
|
|
|
if c > 0 {
|
|
|
|
|
words = append(words, uint16(w)<<8|uint16(c))
|
|
|
|
|
mass += int(c)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if mass > 255 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return words
|
|
|
|
|
}
|