Remove bound checkings in inner loops

This commit is contained in:
Junegunn Choi 2017-08-26 01:28:39 +09:00
parent 55ee4186aa
commit 71fdb99a07
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627

View File

@ -328,7 +328,11 @@ func debugV2(T []rune, pattern []rune, F []int32, lastIdx int, H []int16, C []in
if idx+int(F[0]) < int(F[i]) { if idx+int(F[0]) < int(F[i]) {
p = 0 p = 0
} }
fmt.Printf("%2d ", p) if p > 0 {
fmt.Printf("%2d ", p)
} else {
fmt.Print(" ")
}
} }
fmt.Println() fmt.Println()
} }
@ -373,8 +377,10 @@ func FuzzyMatchV2(caseSensitive bool, normalize bool, forward bool, input *util.
// Phase 2. Calculate bonus for each point // Phase 2. Calculate bonus for each point
maxScore, maxScorePos := int16(0), 0 maxScore, maxScorePos := int16(0), 0
pidx, lastIdx := 0, 0 pidx, lastIdx := 0, 0
for pchar0, prevClass, inGap := pattern[0], charNonWord, false; idx < N; idx++ { pchar0, pchar, prevH0, prevClass, inGap := pattern[0], pattern[0], int16(0), charNonWord, false
char := T[idx] Tsub := T[idx:]
H0sub, C0sub, Bsub := H0[idx:][:len(Tsub)], C0[idx:][:len(Tsub)], B[idx:][:len(Tsub)]
for off, char := range Tsub {
var class charClass var class charClass
if char <= unicode.MaxASCII { if char <= unicode.MaxASCII {
class = charClassOfAscii(char) class = charClassOfAscii(char)
@ -394,41 +400,41 @@ func FuzzyMatchV2(caseSensitive bool, normalize bool, forward bool, input *util.
char = normalizeRune(char) char = normalizeRune(char)
} }
T[idx] = char Tsub[off] = char
bonus := bonusFor(prevClass, class) bonus := bonusFor(prevClass, class)
B[idx] = bonus Bsub[off] = bonus
prevClass = class prevClass = class
if char == pattern[util.Min(pidx, M-1)] { if char == pchar {
if pidx < M { if pidx < M {
F[pidx] = int32(idx) F[pidx] = int32(idx + off)
pidx++ pidx++
pchar = pattern[util.Min(pidx, M-1)]
} }
lastIdx = idx lastIdx = idx + off
} }
if char == pchar0 { if char == pchar0 {
score := scoreMatch + bonus*bonusFirstCharMultiplier score := scoreMatch + bonus*bonusFirstCharMultiplier
H0[idx] = score H0sub[off] = score
C0[idx] = 1 C0sub[off] = 1
if M == 1 && (forward && score > maxScore || !forward && score >= maxScore) { if M == 1 && (forward && score > maxScore || !forward && score >= maxScore) {
maxScore, maxScorePos = score, idx maxScore, maxScorePos = score, idx+off
if forward && bonus == bonusBoundary { if forward && bonus == bonusBoundary {
break break
} }
} }
inGap = false inGap = false
} else { } else {
if idx == 0 { if inGap {
H0[idx] = 0 H0sub[off] = util.Max16(prevH0+scoreGapExtention, 0)
} else if inGap {
H0[idx] = util.Max16(H0[idx-1]+scoreGapExtention, 0)
} else { } else {
H0[idx] = util.Max16(H0[idx-1]+scoreGapStart, 0) H0sub[off] = util.Max16(prevH0+scoreGapStart, 0)
} }
C0[idx] = 0 C0sub[off] = 0
inGap = true inGap = true
} }
prevH0 = H0sub[off]
} }
if pidx != M { if pidx != M {
return Result{-1, -1, 0}, nil return Result{-1, -1, 0}, nil
@ -453,47 +459,57 @@ func FuzzyMatchV2(caseSensitive bool, normalize bool, forward bool, input *util.
offset16, C := alloc16(offset16, slab, width*M) offset16, C := alloc16(offset16, slab, width*M)
copy(C, C0[f0:lastIdx+1]) copy(C, C0[f0:lastIdx+1])
for i := 1; i < M; i++ { Fsub := F[1:]
I := i * width Psub := pattern[1:][:len(Fsub)]
f := int(F[i]) for off, f := range Fsub {
f := int(f)
pchar := Psub[off]
pidx := off + 1
row := pidx * width
inGap := false inGap := false
for j := f; j <= lastIdx; j++ { Tsub := T[f : lastIdx+1]
j0 := j - f0 Bsub := B[f:][:len(Tsub)]
Csub := C[row+f-f0:][:len(Tsub)]
Cdiag := C[row+f-f0-1-width:][:len(Tsub)]
Hsub := H[row+f-f0:][:len(Tsub)]
Hdiag := H[row+f-f0-1-width:][:len(Tsub)]
Hleft := H[row+f-f0-1:][:len(Tsub)]
Hleft[0] = 0
for off, char := range Tsub {
col := off + f
var s1, s2, consecutive int16 var s1, s2, consecutive int16
if j > f { if inGap {
if inGap { s2 = Hleft[off] + scoreGapExtention
s2 = H[I+j0-1] + scoreGapExtention } else {
} else { s2 = Hleft[off] + scoreGapStart
s2 = H[I+j0-1] + scoreGapStart
}
} }
if pattern[i] == T[j] { if pchar == char {
s1 = H[I-width+j0-1] + scoreMatch s1 = Hdiag[off] + scoreMatch
b := B[j] b := Bsub[off]
consecutive = C[I-width+j0-1] + 1 consecutive = Cdiag[off] + 1
// Break consecutive chunk // Break consecutive chunk
if b == bonusBoundary { if b == bonusBoundary {
consecutive = 1 consecutive = 1
} else if consecutive > 1 { } else if consecutive > 1 {
b = util.Max16(b, util.Max16(bonusConsecutive, B[j-int(consecutive)+1])) b = util.Max16(b, util.Max16(bonusConsecutive, B[col-int(consecutive)+1]))
} }
if s1+b < s2 { if s1+b < s2 {
s1 += B[j] s1 += Bsub[off]
consecutive = 0 consecutive = 0
} else { } else {
s1 += b s1 += b
} }
} }
C[I+j0] = consecutive Csub[off] = consecutive
inGap = s1 < s2 inGap = s1 < s2
score := util.Max16(util.Max16(s1, s2), 0) score := util.Max16(util.Max16(s1, s2), 0)
if i == M-1 && (forward && score > maxScore || !forward && score >= maxScore) { if pidx == M-1 && (forward && score > maxScore || !forward && score >= maxScore) {
maxScore, maxScorePos = score, j maxScore, maxScorePos = score, col
} }
H[I+j0] = score Hsub[off] = score
} }
} }