mirror of
https://github.com/metabarcoding/obitools4.git
synced 2026-11-09 09:24:41 +00:00
Introduces the BandedLCS function for efficient LCS scoring, supporting both scalar and SIMD implementations. Adds comprehensive unit tests, benchmarking utilities, and error handling for sequence constraints.
54 lines
1.3 KiB
Go
54 lines
1.3 KiB
Go
package obialign
|
|
|
|
import "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq"
|
|
|
|
// bandedLCSScalar is the portable reference of the banded DP, row by row. It
|
|
// returns the packed cell (lB, lA). len(a) >= len(b) >= 1.
|
|
//
|
|
// Cells outside the band hold 0 (unavailable). Row i spans the columns
|
|
// [i+kmin, i+kmax] clipped to [1, lA]; the cell just left of that span and
|
|
// the one just right of it are reset so that the next row never reads a stale
|
|
// value.
|
|
func bandedLCSScalar(a, b []byte, kmin, kmax int, ws *bandedLCSWorkspace) uint32 {
|
|
lA, lB := len(a), len(b)
|
|
|
|
prev := growUint32(ws.rows[0], lA+2)
|
|
cur := growUint32(ws.rows[1], lA+2)
|
|
ws.rows[0], ws.rows[1] = prev, cur
|
|
|
|
for j := 0; j <= lA; j++ {
|
|
prev[j] = 0
|
|
if j <= kmax {
|
|
prev[j] = lcsLenBase - uint32(j)
|
|
}
|
|
}
|
|
prev[lA+1] = 0
|
|
|
|
for i := 1; i <= lB; i++ {
|
|
if -i >= kmin {
|
|
cur[0] = lcsLenBase - uint32(i)
|
|
} else {
|
|
cur[0] = 0
|
|
}
|
|
jlo := max(1, i+kmin)
|
|
jhi := min(lA, i+kmax)
|
|
if jlo > 1 {
|
|
cur[jlo-1] = 0
|
|
}
|
|
bi := b[i-1]
|
|
for j := jlo; j <= jhi; j++ {
|
|
d := prev[j-1]
|
|
if obiseq.SameIUPACNuc(a[j-1], bi) {
|
|
d += lcsScoreUnit
|
|
}
|
|
m := max(d, prev[j], cur[j-1], 1)
|
|
cur[j] = m - 1
|
|
}
|
|
if jhi < lA {
|
|
cur[jhi+1] = 0
|
|
}
|
|
prev, cur = cur, prev
|
|
}
|
|
return prev[lA]
|
|
}
|