...

Source file src/index/suffixarray/sais2.go

Documentation: index/suffixarray

		 1  // Copyright 2019 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 4  
		 5  // Code generated by go generate; DO NOT EDIT.
		 6  
		 7  package suffixarray
		 8  
		 9  func text_64(text []byte, sa []int64) {
		10  	if int(int64(len(text))) != len(text) || len(text) != len(sa) {
		11  		panic("suffixarray: misuse of text_64")
		12  	}
		13  	sais_8_64(text, 256, sa, make([]int64, 2*256))
		14  }
		15  
		16  func sais_8_64(text []byte, textMax int, sa, tmp []int64) {
		17  	if len(sa) != len(text) || len(tmp) < int(textMax) {
		18  		panic("suffixarray: misuse of sais_8_64")
		19  	}
		20  
		21  	// Trivial base cases. Sorting 0 or 1 things is easy.
		22  	if len(text) == 0 {
		23  		return
		24  	}
		25  	if len(text) == 1 {
		26  		sa[0] = 0
		27  		return
		28  	}
		29  
		30  	// Establish slices indexed by text character
		31  	// holding character frequency and bucket-sort offsets.
		32  	// If there's only enough tmp for one slice,
		33  	// we make it the bucket offsets and recompute
		34  	// the character frequency each time we need it.
		35  	var freq, bucket []int64
		36  	if len(tmp) >= 2*textMax {
		37  		freq, bucket = tmp[:textMax], tmp[textMax:2*textMax]
		38  		freq[0] = -1 // mark as uninitialized
		39  	} else {
		40  		freq, bucket = nil, tmp[:textMax]
		41  	}
		42  
		43  	// The SAIS algorithm.
		44  	// Each of these calls makes one scan through sa.
		45  	// See the individual functions for documentation
		46  	// about each's role in the algorithm.
		47  	numLMS := placeLMS_8_64(text, sa, freq, bucket)
		48  	if numLMS <= 1 {
		49  		// 0 or 1 items are already sorted. Do nothing.
		50  	} else {
		51  		induceSubL_8_64(text, sa, freq, bucket)
		52  		induceSubS_8_64(text, sa, freq, bucket)
		53  		length_8_64(text, sa, numLMS)
		54  		maxID := assignID_8_64(text, sa, numLMS)
		55  		if maxID < numLMS {
		56  			map_64(sa, numLMS)
		57  			recurse_64(sa, tmp, numLMS, maxID)
		58  			unmap_8_64(text, sa, numLMS)
		59  		} else {
		60  			// If maxID == numLMS, then each LMS-substring
		61  			// is unique, so the relative ordering of two LMS-suffixes
		62  			// is determined by just the leading LMS-substring.
		63  			// That is, the LMS-suffix sort order matches the
		64  			// (simpler) LMS-substring sort order.
		65  			// Copy the original LMS-substring order into the
		66  			// suffix array destination.
		67  			copy(sa, sa[len(sa)-numLMS:])
		68  		}
		69  		expand_8_64(text, freq, bucket, sa, numLMS)
		70  	}
		71  	induceL_8_64(text, sa, freq, bucket)
		72  	induceS_8_64(text, sa, freq, bucket)
		73  
		74  	// Mark for caller that we overwrote tmp.
		75  	tmp[0] = -1
		76  }
		77  
		78  func sais_32(text []int32, textMax int, sa, tmp []int32) {
		79  	if len(sa) != len(text) || len(tmp) < int(textMax) {
		80  		panic("suffixarray: misuse of sais_32")
		81  	}
		82  
		83  	// Trivial base cases. Sorting 0 or 1 things is easy.
		84  	if len(text) == 0 {
		85  		return
		86  	}
		87  	if len(text) == 1 {
		88  		sa[0] = 0
		89  		return
		90  	}
		91  
		92  	// Establish slices indexed by text character
		93  	// holding character frequency and bucket-sort offsets.
		94  	// If there's only enough tmp for one slice,
		95  	// we make it the bucket offsets and recompute
		96  	// the character frequency each time we need it.
		97  	var freq, bucket []int32
		98  	if len(tmp) >= 2*textMax {
		99  		freq, bucket = tmp[:textMax], tmp[textMax:2*textMax]
	 100  		freq[0] = -1 // mark as uninitialized
	 101  	} else {
	 102  		freq, bucket = nil, tmp[:textMax]
	 103  	}
	 104  
	 105  	// The SAIS algorithm.
	 106  	// Each of these calls makes one scan through sa.
	 107  	// See the individual functions for documentation
	 108  	// about each's role in the algorithm.
	 109  	numLMS := placeLMS_32(text, sa, freq, bucket)
	 110  	if numLMS <= 1 {
	 111  		// 0 or 1 items are already sorted. Do nothing.
	 112  	} else {
	 113  		induceSubL_32(text, sa, freq, bucket)
	 114  		induceSubS_32(text, sa, freq, bucket)
	 115  		length_32(text, sa, numLMS)
	 116  		maxID := assignID_32(text, sa, numLMS)
	 117  		if maxID < numLMS {
	 118  			map_32(sa, numLMS)
	 119  			recurse_32(sa, tmp, numLMS, maxID)
	 120  			unmap_32(text, sa, numLMS)
	 121  		} else {
	 122  			// If maxID == numLMS, then each LMS-substring
	 123  			// is unique, so the relative ordering of two LMS-suffixes
	 124  			// is determined by just the leading LMS-substring.
	 125  			// That is, the LMS-suffix sort order matches the
	 126  			// (simpler) LMS-substring sort order.
	 127  			// Copy the original LMS-substring order into the
	 128  			// suffix array destination.
	 129  			copy(sa, sa[len(sa)-numLMS:])
	 130  		}
	 131  		expand_32(text, freq, bucket, sa, numLMS)
	 132  	}
	 133  	induceL_32(text, sa, freq, bucket)
	 134  	induceS_32(text, sa, freq, bucket)
	 135  
	 136  	// Mark for caller that we overwrote tmp.
	 137  	tmp[0] = -1
	 138  }
	 139  
	 140  func sais_64(text []int64, textMax int, sa, tmp []int64) {
	 141  	if len(sa) != len(text) || len(tmp) < int(textMax) {
	 142  		panic("suffixarray: misuse of sais_64")
	 143  	}
	 144  
	 145  	// Trivial base cases. Sorting 0 or 1 things is easy.
	 146  	if len(text) == 0 {
	 147  		return
	 148  	}
	 149  	if len(text) == 1 {
	 150  		sa[0] = 0
	 151  		return
	 152  	}
	 153  
	 154  	// Establish slices indexed by text character
	 155  	// holding character frequency and bucket-sort offsets.
	 156  	// If there's only enough tmp for one slice,
	 157  	// we make it the bucket offsets and recompute
	 158  	// the character frequency each time we need it.
	 159  	var freq, bucket []int64
	 160  	if len(tmp) >= 2*textMax {
	 161  		freq, bucket = tmp[:textMax], tmp[textMax:2*textMax]
	 162  		freq[0] = -1 // mark as uninitialized
	 163  	} else {
	 164  		freq, bucket = nil, tmp[:textMax]
	 165  	}
	 166  
	 167  	// The SAIS algorithm.
	 168  	// Each of these calls makes one scan through sa.
	 169  	// See the individual functions for documentation
	 170  	// about each's role in the algorithm.
	 171  	numLMS := placeLMS_64(text, sa, freq, bucket)
	 172  	if numLMS <= 1 {
	 173  		// 0 or 1 items are already sorted. Do nothing.
	 174  	} else {
	 175  		induceSubL_64(text, sa, freq, bucket)
	 176  		induceSubS_64(text, sa, freq, bucket)
	 177  		length_64(text, sa, numLMS)
	 178  		maxID := assignID_64(text, sa, numLMS)
	 179  		if maxID < numLMS {
	 180  			map_64(sa, numLMS)
	 181  			recurse_64(sa, tmp, numLMS, maxID)
	 182  			unmap_64(text, sa, numLMS)
	 183  		} else {
	 184  			// If maxID == numLMS, then each LMS-substring
	 185  			// is unique, so the relative ordering of two LMS-suffixes
	 186  			// is determined by just the leading LMS-substring.
	 187  			// That is, the LMS-suffix sort order matches the
	 188  			// (simpler) LMS-substring sort order.
	 189  			// Copy the original LMS-substring order into the
	 190  			// suffix array destination.
	 191  			copy(sa, sa[len(sa)-numLMS:])
	 192  		}
	 193  		expand_64(text, freq, bucket, sa, numLMS)
	 194  	}
	 195  	induceL_64(text, sa, freq, bucket)
	 196  	induceS_64(text, sa, freq, bucket)
	 197  
	 198  	// Mark for caller that we overwrote tmp.
	 199  	tmp[0] = -1
	 200  }
	 201  
	 202  func freq_8_64(text []byte, freq, bucket []int64) []int64 {
	 203  	if freq != nil && freq[0] >= 0 {
	 204  		return freq // already computed
	 205  	}
	 206  	if freq == nil {
	 207  		freq = bucket
	 208  	}
	 209  
	 210  	freq = freq[:256] // eliminate bounds check for freq[c] below
	 211  	for i := range freq {
	 212  		freq[i] = 0
	 213  	}
	 214  	for _, c := range text {
	 215  		freq[c]++
	 216  	}
	 217  	return freq
	 218  }
	 219  
	 220  func freq_32(text []int32, freq, bucket []int32) []int32 {
	 221  	if freq != nil && freq[0] >= 0 {
	 222  		return freq // already computed
	 223  	}
	 224  	if freq == nil {
	 225  		freq = bucket
	 226  	}
	 227  
	 228  	for i := range freq {
	 229  		freq[i] = 0
	 230  	}
	 231  	for _, c := range text {
	 232  		freq[c]++
	 233  	}
	 234  	return freq
	 235  }
	 236  
	 237  func freq_64(text []int64, freq, bucket []int64) []int64 {
	 238  	if freq != nil && freq[0] >= 0 {
	 239  		return freq // already computed
	 240  	}
	 241  	if freq == nil {
	 242  		freq = bucket
	 243  	}
	 244  
	 245  	for i := range freq {
	 246  		freq[i] = 0
	 247  	}
	 248  	for _, c := range text {
	 249  		freq[c]++
	 250  	}
	 251  	return freq
	 252  }
	 253  
	 254  func bucketMin_8_64(text []byte, freq, bucket []int64) {
	 255  	freq = freq_8_64(text, freq, bucket)
	 256  	freq = freq[:256]		 // establish len(freq) = 256, so 0 ≤ i < 256 below
	 257  	bucket = bucket[:256] // eliminate bounds check for bucket[i] below
	 258  	total := int64(0)
	 259  	for i, n := range freq {
	 260  		bucket[i] = total
	 261  		total += n
	 262  	}
	 263  }
	 264  
	 265  func bucketMin_32(text []int32, freq, bucket []int32) {
	 266  	freq = freq_32(text, freq, bucket)
	 267  	total := int32(0)
	 268  	for i, n := range freq {
	 269  		bucket[i] = total
	 270  		total += n
	 271  	}
	 272  }
	 273  
	 274  func bucketMin_64(text []int64, freq, bucket []int64) {
	 275  	freq = freq_64(text, freq, bucket)
	 276  	total := int64(0)
	 277  	for i, n := range freq {
	 278  		bucket[i] = total
	 279  		total += n
	 280  	}
	 281  }
	 282  
	 283  func bucketMax_8_64(text []byte, freq, bucket []int64) {
	 284  	freq = freq_8_64(text, freq, bucket)
	 285  	freq = freq[:256]		 // establish len(freq) = 256, so 0 ≤ i < 256 below
	 286  	bucket = bucket[:256] // eliminate bounds check for bucket[i] below
	 287  	total := int64(0)
	 288  	for i, n := range freq {
	 289  		total += n
	 290  		bucket[i] = total
	 291  	}
	 292  }
	 293  
	 294  func bucketMax_32(text []int32, freq, bucket []int32) {
	 295  	freq = freq_32(text, freq, bucket)
	 296  	total := int32(0)
	 297  	for i, n := range freq {
	 298  		total += n
	 299  		bucket[i] = total
	 300  	}
	 301  }
	 302  
	 303  func bucketMax_64(text []int64, freq, bucket []int64) {
	 304  	freq = freq_64(text, freq, bucket)
	 305  	total := int64(0)
	 306  	for i, n := range freq {
	 307  		total += n
	 308  		bucket[i] = total
	 309  	}
	 310  }
	 311  
	 312  func placeLMS_8_64(text []byte, sa, freq, bucket []int64) int {
	 313  	bucketMax_8_64(text, freq, bucket)
	 314  
	 315  	numLMS := 0
	 316  	lastB := int64(-1)
	 317  	bucket = bucket[:256] // eliminate bounds check for bucket[c1] below
	 318  
	 319  	// The next stanza of code (until the blank line) loop backward
	 320  	// over text, stopping to execute a code body at each position i
	 321  	// such that text[i] is an L-character and text[i+1] is an S-character.
	 322  	// That is, i+1 is the position of the start of an LMS-substring.
	 323  	// These could be hoisted out into a function with a callback,
	 324  	// but at a significant speed cost. Instead, we just write these
	 325  	// seven lines a few times in this source file. The copies below
	 326  	// refer back to the pattern established by this original as the
	 327  	// "LMS-substring iterator".
	 328  	//
	 329  	// In every scan through the text, c0, c1 are successive characters of text.
	 330  	// In this backward scan, c0 == text[i] and c1 == text[i+1].
	 331  	// By scanning backward, we can keep track of whether the current
	 332  	// position is type-S or type-L according to the usual definition:
	 333  	//
	 334  	//	- position len(text) is type S with text[len(text)] == -1 (the sentinel)
	 335  	//	- position i is type S if text[i] < text[i+1], or if text[i] == text[i+1] && i+1 is type S.
	 336  	//	- position i is type L if text[i] > text[i+1], or if text[i] == text[i+1] && i+1 is type L.
	 337  	//
	 338  	// The backward scan lets us maintain the current type,
	 339  	// update it when we see c0 != c1, and otherwise leave it alone.
	 340  	// We want to identify all S positions with a preceding L.
	 341  	// Position len(text) is one such position by definition, but we have
	 342  	// nowhere to write it down, so we eliminate it by untruthfully
	 343  	// setting isTypeS = false at the start of the loop.
	 344  	c0, c1, isTypeS := byte(0), byte(0), false
	 345  	for i := len(text) - 1; i >= 0; i-- {
	 346  		c0, c1 = text[i], c0
	 347  		if c0 < c1 {
	 348  			isTypeS = true
	 349  		} else if c0 > c1 && isTypeS {
	 350  			isTypeS = false
	 351  
	 352  			// Bucket the index i+1 for the start of an LMS-substring.
	 353  			b := bucket[c1] - 1
	 354  			bucket[c1] = b
	 355  			sa[b] = int64(i + 1)
	 356  			lastB = b
	 357  			numLMS++
	 358  		}
	 359  	}
	 360  
	 361  	// We recorded the LMS-substring starts but really want the ends.
	 362  	// Luckily, with two differences, the start indexes and the end indexes are the same.
	 363  	// The first difference is that the rightmost LMS-substring's end index is len(text),
	 364  	// so the caller must pretend that sa[-1] == len(text), as noted above.
	 365  	// The second difference is that the first leftmost LMS-substring start index
	 366  	// does not end an earlier LMS-substring, so as an optimization we can omit
	 367  	// that leftmost LMS-substring start index (the last one we wrote).
	 368  	//
	 369  	// Exception: if numLMS <= 1, the caller is not going to bother with
	 370  	// the recursion at all and will treat the result as containing LMS-substring starts.
	 371  	// In that case, we don't remove the final entry.
	 372  	if numLMS > 1 {
	 373  		sa[lastB] = 0
	 374  	}
	 375  	return numLMS
	 376  }
	 377  
	 378  func placeLMS_32(text []int32, sa, freq, bucket []int32) int {
	 379  	bucketMax_32(text, freq, bucket)
	 380  
	 381  	numLMS := 0
	 382  	lastB := int32(-1)
	 383  
	 384  	// The next stanza of code (until the blank line) loop backward
	 385  	// over text, stopping to execute a code body at each position i
	 386  	// such that text[i] is an L-character and text[i+1] is an S-character.
	 387  	// That is, i+1 is the position of the start of an LMS-substring.
	 388  	// These could be hoisted out into a function with a callback,
	 389  	// but at a significant speed cost. Instead, we just write these
	 390  	// seven lines a few times in this source file. The copies below
	 391  	// refer back to the pattern established by this original as the
	 392  	// "LMS-substring iterator".
	 393  	//
	 394  	// In every scan through the text, c0, c1 are successive characters of text.
	 395  	// In this backward scan, c0 == text[i] and c1 == text[i+1].
	 396  	// By scanning backward, we can keep track of whether the current
	 397  	// position is type-S or type-L according to the usual definition:
	 398  	//
	 399  	//	- position len(text) is type S with text[len(text)] == -1 (the sentinel)
	 400  	//	- position i is type S if text[i] < text[i+1], or if text[i] == text[i+1] && i+1 is type S.
	 401  	//	- position i is type L if text[i] > text[i+1], or if text[i] == text[i+1] && i+1 is type L.
	 402  	//
	 403  	// The backward scan lets us maintain the current type,
	 404  	// update it when we see c0 != c1, and otherwise leave it alone.
	 405  	// We want to identify all S positions with a preceding L.
	 406  	// Position len(text) is one such position by definition, but we have
	 407  	// nowhere to write it down, so we eliminate it by untruthfully
	 408  	// setting isTypeS = false at the start of the loop.
	 409  	c0, c1, isTypeS := int32(0), int32(0), false
	 410  	for i := len(text) - 1; i >= 0; i-- {
	 411  		c0, c1 = text[i], c0
	 412  		if c0 < c1 {
	 413  			isTypeS = true
	 414  		} else if c0 > c1 && isTypeS {
	 415  			isTypeS = false
	 416  
	 417  			// Bucket the index i+1 for the start of an LMS-substring.
	 418  			b := bucket[c1] - 1
	 419  			bucket[c1] = b
	 420  			sa[b] = int32(i + 1)
	 421  			lastB = b
	 422  			numLMS++
	 423  		}
	 424  	}
	 425  
	 426  	// We recorded the LMS-substring starts but really want the ends.
	 427  	// Luckily, with two differences, the start indexes and the end indexes are the same.
	 428  	// The first difference is that the rightmost LMS-substring's end index is len(text),
	 429  	// so the caller must pretend that sa[-1] == len(text), as noted above.
	 430  	// The second difference is that the first leftmost LMS-substring start index
	 431  	// does not end an earlier LMS-substring, so as an optimization we can omit
	 432  	// that leftmost LMS-substring start index (the last one we wrote).
	 433  	//
	 434  	// Exception: if numLMS <= 1, the caller is not going to bother with
	 435  	// the recursion at all and will treat the result as containing LMS-substring starts.
	 436  	// In that case, we don't remove the final entry.
	 437  	if numLMS > 1 {
	 438  		sa[lastB] = 0
	 439  	}
	 440  	return numLMS
	 441  }
	 442  
	 443  func placeLMS_64(text []int64, sa, freq, bucket []int64) int {
	 444  	bucketMax_64(text, freq, bucket)
	 445  
	 446  	numLMS := 0
	 447  	lastB := int64(-1)
	 448  
	 449  	// The next stanza of code (until the blank line) loop backward
	 450  	// over text, stopping to execute a code body at each position i
	 451  	// such that text[i] is an L-character and text[i+1] is an S-character.
	 452  	// That is, i+1 is the position of the start of an LMS-substring.
	 453  	// These could be hoisted out into a function with a callback,
	 454  	// but at a significant speed cost. Instead, we just write these
	 455  	// seven lines a few times in this source file. The copies below
	 456  	// refer back to the pattern established by this original as the
	 457  	// "LMS-substring iterator".
	 458  	//
	 459  	// In every scan through the text, c0, c1 are successive characters of text.
	 460  	// In this backward scan, c0 == text[i] and c1 == text[i+1].
	 461  	// By scanning backward, we can keep track of whether the current
	 462  	// position is type-S or type-L according to the usual definition:
	 463  	//
	 464  	//	- position len(text) is type S with text[len(text)] == -1 (the sentinel)
	 465  	//	- position i is type S if text[i] < text[i+1], or if text[i] == text[i+1] && i+1 is type S.
	 466  	//	- position i is type L if text[i] > text[i+1], or if text[i] == text[i+1] && i+1 is type L.
	 467  	//
	 468  	// The backward scan lets us maintain the current type,
	 469  	// update it when we see c0 != c1, and otherwise leave it alone.
	 470  	// We want to identify all S positions with a preceding L.
	 471  	// Position len(text) is one such position by definition, but we have
	 472  	// nowhere to write it down, so we eliminate it by untruthfully
	 473  	// setting isTypeS = false at the start of the loop.
	 474  	c0, c1, isTypeS := int64(0), int64(0), false
	 475  	for i := len(text) - 1; i >= 0; i-- {
	 476  		c0, c1 = text[i], c0
	 477  		if c0 < c1 {
	 478  			isTypeS = true
	 479  		} else if c0 > c1 && isTypeS {
	 480  			isTypeS = false
	 481  
	 482  			// Bucket the index i+1 for the start of an LMS-substring.
	 483  			b := bucket[c1] - 1
	 484  			bucket[c1] = b
	 485  			sa[b] = int64(i + 1)
	 486  			lastB = b
	 487  			numLMS++
	 488  		}
	 489  	}
	 490  
	 491  	// We recorded the LMS-substring starts but really want the ends.
	 492  	// Luckily, with two differences, the start indexes and the end indexes are the same.
	 493  	// The first difference is that the rightmost LMS-substring's end index is len(text),
	 494  	// so the caller must pretend that sa[-1] == len(text), as noted above.
	 495  	// The second difference is that the first leftmost LMS-substring start index
	 496  	// does not end an earlier LMS-substring, so as an optimization we can omit
	 497  	// that leftmost LMS-substring start index (the last one we wrote).
	 498  	//
	 499  	// Exception: if numLMS <= 1, the caller is not going to bother with
	 500  	// the recursion at all and will treat the result as containing LMS-substring starts.
	 501  	// In that case, we don't remove the final entry.
	 502  	if numLMS > 1 {
	 503  		sa[lastB] = 0
	 504  	}
	 505  	return numLMS
	 506  }
	 507  
	 508  func induceSubL_8_64(text []byte, sa, freq, bucket []int64) {
	 509  	// Initialize positions for left side of character buckets.
	 510  	bucketMin_8_64(text, freq, bucket)
	 511  	bucket = bucket[:256] // eliminate bounds check for bucket[cB] below
	 512  
	 513  	// As we scan the array left-to-right, each sa[i] = j > 0 is a correctly
	 514  	// sorted suffix array entry (for text[j:]) for which we know that j-1 is type L.
	 515  	// Because j-1 is type L, inserting it into sa now will sort it correctly.
	 516  	// But we want to distinguish a j-1 with j-2 of type L from type S.
	 517  	// We can process the former but want to leave the latter for the caller.
	 518  	// We record the difference by negating j-1 if it is preceded by type S.
	 519  	// Either way, the insertion (into the text[j-1] bucket) is guaranteed to
	 520  	// happen at sa[i´] for some i´ > i, that is, in the portion of sa we have
	 521  	// yet to scan. A single pass therefore sees indexes j, j-1, j-2, j-3,
	 522  	// and so on, in sorted but not necessarily adjacent order, until it finds
	 523  	// one preceded by an index of type S, at which point it must stop.
	 524  	//
	 525  	// As we scan through the array, we clear the worked entries (sa[i] > 0) to zero,
	 526  	// and we flip sa[i] < 0 to -sa[i], so that the loop finishes with sa containing
	 527  	// only the indexes of the leftmost L-type indexes for each LMS-substring.
	 528  	//
	 529  	// The suffix array sa therefore serves simultaneously as input, output,
	 530  	// and a miraculously well-tailored work queue.
	 531  
	 532  	// placeLMS_8_64 left out the implicit entry sa[-1] == len(text),
	 533  	// corresponding to the identified type-L index len(text)-1.
	 534  	// Process it before the left-to-right scan of sa proper.
	 535  	// See body in loop for commentary.
	 536  	k := len(text) - 1
	 537  	c0, c1 := text[k-1], text[k]
	 538  	if c0 < c1 {
	 539  		k = -k
	 540  	}
	 541  
	 542  	// Cache recently used bucket index:
	 543  	// we're processing suffixes in sorted order
	 544  	// and accessing buckets indexed by the
	 545  	// byte before the sorted order, which still
	 546  	// has very good locality.
	 547  	// Invariant: b is cached, possibly dirty copy of bucket[cB].
	 548  	cB := c1
	 549  	b := bucket[cB]
	 550  	sa[b] = int64(k)
	 551  	b++
	 552  
	 553  	for i := 0; i < len(sa); i++ {
	 554  		j := int(sa[i])
	 555  		if j == 0 {
	 556  			// Skip empty entry.
	 557  			continue
	 558  		}
	 559  		if j < 0 {
	 560  			// Leave discovered type-S index for caller.
	 561  			sa[i] = int64(-j)
	 562  			continue
	 563  		}
	 564  		sa[i] = 0
	 565  
	 566  		// Index j was on work queue, meaning k := j-1 is L-type,
	 567  		// so we can now place k correctly into sa.
	 568  		// If k-1 is L-type, queue k for processing later in this loop.
	 569  		// If k-1 is S-type (text[k-1] < text[k]), queue -k to save for the caller.
	 570  		k := j - 1
	 571  		c0, c1 := text[k-1], text[k]
	 572  		if c0 < c1 {
	 573  			k = -k
	 574  		}
	 575  
	 576  		if cB != c1 {
	 577  			bucket[cB] = b
	 578  			cB = c1
	 579  			b = bucket[cB]
	 580  		}
	 581  		sa[b] = int64(k)
	 582  		b++
	 583  	}
	 584  }
	 585  
	 586  func induceSubL_32(text []int32, sa, freq, bucket []int32) {
	 587  	// Initialize positions for left side of character buckets.
	 588  	bucketMin_32(text, freq, bucket)
	 589  
	 590  	// As we scan the array left-to-right, each sa[i] = j > 0 is a correctly
	 591  	// sorted suffix array entry (for text[j:]) for which we know that j-1 is type L.
	 592  	// Because j-1 is type L, inserting it into sa now will sort it correctly.
	 593  	// But we want to distinguish a j-1 with j-2 of type L from type S.
	 594  	// We can process the former but want to leave the latter for the caller.
	 595  	// We record the difference by negating j-1 if it is preceded by type S.
	 596  	// Either way, the insertion (into the text[j-1] bucket) is guaranteed to
	 597  	// happen at sa[i´] for some i´ > i, that is, in the portion of sa we have
	 598  	// yet to scan. A single pass therefore sees indexes j, j-1, j-2, j-3,
	 599  	// and so on, in sorted but not necessarily adjacent order, until it finds
	 600  	// one preceded by an index of type S, at which point it must stop.
	 601  	//
	 602  	// As we scan through the array, we clear the worked entries (sa[i] > 0) to zero,
	 603  	// and we flip sa[i] < 0 to -sa[i], so that the loop finishes with sa containing
	 604  	// only the indexes of the leftmost L-type indexes for each LMS-substring.
	 605  	//
	 606  	// The suffix array sa therefore serves simultaneously as input, output,
	 607  	// and a miraculously well-tailored work queue.
	 608  
	 609  	// placeLMS_32 left out the implicit entry sa[-1] == len(text),
	 610  	// corresponding to the identified type-L index len(text)-1.
	 611  	// Process it before the left-to-right scan of sa proper.
	 612  	// See body in loop for commentary.
	 613  	k := len(text) - 1
	 614  	c0, c1 := text[k-1], text[k]
	 615  	if c0 < c1 {
	 616  		k = -k
	 617  	}
	 618  
	 619  	// Cache recently used bucket index:
	 620  	// we're processing suffixes in sorted order
	 621  	// and accessing buckets indexed by the
	 622  	// int32 before the sorted order, which still
	 623  	// has very good locality.
	 624  	// Invariant: b is cached, possibly dirty copy of bucket[cB].
	 625  	cB := c1
	 626  	b := bucket[cB]
	 627  	sa[b] = int32(k)
	 628  	b++
	 629  
	 630  	for i := 0; i < len(sa); i++ {
	 631  		j := int(sa[i])
	 632  		if j == 0 {
	 633  			// Skip empty entry.
	 634  			continue
	 635  		}
	 636  		if j < 0 {
	 637  			// Leave discovered type-S index for caller.
	 638  			sa[i] = int32(-j)
	 639  			continue
	 640  		}
	 641  		sa[i] = 0
	 642  
	 643  		// Index j was on work queue, meaning k := j-1 is L-type,
	 644  		// so we can now place k correctly into sa.
	 645  		// If k-1 is L-type, queue k for processing later in this loop.
	 646  		// If k-1 is S-type (text[k-1] < text[k]), queue -k to save for the caller.
	 647  		k := j - 1
	 648  		c0, c1 := text[k-1], text[k]
	 649  		if c0 < c1 {
	 650  			k = -k
	 651  		}
	 652  
	 653  		if cB != c1 {
	 654  			bucket[cB] = b
	 655  			cB = c1
	 656  			b = bucket[cB]
	 657  		}
	 658  		sa[b] = int32(k)
	 659  		b++
	 660  	}
	 661  }
	 662  
	 663  func induceSubL_64(text []int64, sa, freq, bucket []int64) {
	 664  	// Initialize positions for left side of character buckets.
	 665  	bucketMin_64(text, freq, bucket)
	 666  
	 667  	// As we scan the array left-to-right, each sa[i] = j > 0 is a correctly
	 668  	// sorted suffix array entry (for text[j:]) for which we know that j-1 is type L.
	 669  	// Because j-1 is type L, inserting it into sa now will sort it correctly.
	 670  	// But we want to distinguish a j-1 with j-2 of type L from type S.
	 671  	// We can process the former but want to leave the latter for the caller.
	 672  	// We record the difference by negating j-1 if it is preceded by type S.
	 673  	// Either way, the insertion (into the text[j-1] bucket) is guaranteed to
	 674  	// happen at sa[i´] for some i´ > i, that is, in the portion of sa we have
	 675  	// yet to scan. A single pass therefore sees indexes j, j-1, j-2, j-3,
	 676  	// and so on, in sorted but not necessarily adjacent order, until it finds
	 677  	// one preceded by an index of type S, at which point it must stop.
	 678  	//
	 679  	// As we scan through the array, we clear the worked entries (sa[i] > 0) to zero,
	 680  	// and we flip sa[i] < 0 to -sa[i], so that the loop finishes with sa containing
	 681  	// only the indexes of the leftmost L-type indexes for each LMS-substring.
	 682  	//
	 683  	// The suffix array sa therefore serves simultaneously as input, output,
	 684  	// and a miraculously well-tailored work queue.
	 685  
	 686  	// placeLMS_64 left out the implicit entry sa[-1] == len(text),
	 687  	// corresponding to the identified type-L index len(text)-1.
	 688  	// Process it before the left-to-right scan of sa proper.
	 689  	// See body in loop for commentary.
	 690  	k := len(text) - 1
	 691  	c0, c1 := text[k-1], text[k]
	 692  	if c0 < c1 {
	 693  		k = -k
	 694  	}
	 695  
	 696  	// Cache recently used bucket index:
	 697  	// we're processing suffixes in sorted order
	 698  	// and accessing buckets indexed by the
	 699  	// int64 before the sorted order, which still
	 700  	// has very good locality.
	 701  	// Invariant: b is cached, possibly dirty copy of bucket[cB].
	 702  	cB := c1
	 703  	b := bucket[cB]
	 704  	sa[b] = int64(k)
	 705  	b++
	 706  
	 707  	for i := 0; i < len(sa); i++ {
	 708  		j := int(sa[i])
	 709  		if j == 0 {
	 710  			// Skip empty entry.
	 711  			continue
	 712  		}
	 713  		if j < 0 {
	 714  			// Leave discovered type-S index for caller.
	 715  			sa[i] = int64(-j)
	 716  			continue
	 717  		}
	 718  		sa[i] = 0
	 719  
	 720  		// Index j was on work queue, meaning k := j-1 is L-type,
	 721  		// so we can now place k correctly into sa.
	 722  		// If k-1 is L-type, queue k for processing later in this loop.
	 723  		// If k-1 is S-type (text[k-1] < text[k]), queue -k to save for the caller.
	 724  		k := j - 1
	 725  		c0, c1 := text[k-1], text[k]
	 726  		if c0 < c1 {
	 727  			k = -k
	 728  		}
	 729  
	 730  		if cB != c1 {
	 731  			bucket[cB] = b
	 732  			cB = c1
	 733  			b = bucket[cB]
	 734  		}
	 735  		sa[b] = int64(k)
	 736  		b++
	 737  	}
	 738  }
	 739  
	 740  func induceSubS_8_64(text []byte, sa, freq, bucket []int64) {
	 741  	// Initialize positions for right side of character buckets.
	 742  	bucketMax_8_64(text, freq, bucket)
	 743  	bucket = bucket[:256] // eliminate bounds check for bucket[cB] below
	 744  
	 745  	// Analogous to induceSubL_8_64 above,
	 746  	// as we scan the array right-to-left, each sa[i] = j > 0 is a correctly
	 747  	// sorted suffix array entry (for text[j:]) for which we know that j-1 is type S.
	 748  	// Because j-1 is type S, inserting it into sa now will sort it correctly.
	 749  	// But we want to distinguish a j-1 with j-2 of type S from type L.
	 750  	// We can process the former but want to leave the latter for the caller.
	 751  	// We record the difference by negating j-1 if it is preceded by type L.
	 752  	// Either way, the insertion (into the text[j-1] bucket) is guaranteed to
	 753  	// happen at sa[i´] for some i´ < i, that is, in the portion of sa we have
	 754  	// yet to scan. A single pass therefore sees indexes j, j-1, j-2, j-3,
	 755  	// and so on, in sorted but not necessarily adjacent order, until it finds
	 756  	// one preceded by an index of type L, at which point it must stop.
	 757  	// That index (preceded by one of type L) is an LMS-substring start.
	 758  	//
	 759  	// As we scan through the array, we clear the worked entries (sa[i] > 0) to zero,
	 760  	// and we flip sa[i] < 0 to -sa[i] and compact into the top of sa,
	 761  	// so that the loop finishes with the top of sa containing exactly
	 762  	// the LMS-substring start indexes, sorted by LMS-substring.
	 763  
	 764  	// Cache recently used bucket index:
	 765  	cB := byte(0)
	 766  	b := bucket[cB]
	 767  
	 768  	top := len(sa)
	 769  	for i := len(sa) - 1; i >= 0; i-- {
	 770  		j := int(sa[i])
	 771  		if j == 0 {
	 772  			// Skip empty entry.
	 773  			continue
	 774  		}
	 775  		sa[i] = 0
	 776  		if j < 0 {
	 777  			// Leave discovered LMS-substring start index for caller.
	 778  			top--
	 779  			sa[top] = int64(-j)
	 780  			continue
	 781  		}
	 782  
	 783  		// Index j was on work queue, meaning k := j-1 is S-type,
	 784  		// so we can now place k correctly into sa.
	 785  		// If k-1 is S-type, queue k for processing later in this loop.
	 786  		// If k-1 is L-type (text[k-1] > text[k]), queue -k to save for the caller.
	 787  		k := j - 1
	 788  		c1 := text[k]
	 789  		c0 := text[k-1]
	 790  		if c0 > c1 {
	 791  			k = -k
	 792  		}
	 793  
	 794  		if cB != c1 {
	 795  			bucket[cB] = b
	 796  			cB = c1
	 797  			b = bucket[cB]
	 798  		}
	 799  		b--
	 800  		sa[b] = int64(k)
	 801  	}
	 802  }
	 803  
	 804  func induceSubS_32(text []int32, sa, freq, bucket []int32) {
	 805  	// Initialize positions for right side of character buckets.
	 806  	bucketMax_32(text, freq, bucket)
	 807  
	 808  	// Analogous to induceSubL_32 above,
	 809  	// as we scan the array right-to-left, each sa[i] = j > 0 is a correctly
	 810  	// sorted suffix array entry (for text[j:]) for which we know that j-1 is type S.
	 811  	// Because j-1 is type S, inserting it into sa now will sort it correctly.
	 812  	// But we want to distinguish a j-1 with j-2 of type S from type L.
	 813  	// We can process the former but want to leave the latter for the caller.
	 814  	// We record the difference by negating j-1 if it is preceded by type L.
	 815  	// Either way, the insertion (into the text[j-1] bucket) is guaranteed to
	 816  	// happen at sa[i´] for some i´ < i, that is, in the portion of sa we have
	 817  	// yet to scan. A single pass therefore sees indexes j, j-1, j-2, j-3,
	 818  	// and so on, in sorted but not necessarily adjacent order, until it finds
	 819  	// one preceded by an index of type L, at which point it must stop.
	 820  	// That index (preceded by one of type L) is an LMS-substring start.
	 821  	//
	 822  	// As we scan through the array, we clear the worked entries (sa[i] > 0) to zero,
	 823  	// and we flip sa[i] < 0 to -sa[i] and compact into the top of sa,
	 824  	// so that the loop finishes with the top of sa containing exactly
	 825  	// the LMS-substring start indexes, sorted by LMS-substring.
	 826  
	 827  	// Cache recently used bucket index:
	 828  	cB := int32(0)
	 829  	b := bucket[cB]
	 830  
	 831  	top := len(sa)
	 832  	for i := len(sa) - 1; i >= 0; i-- {
	 833  		j := int(sa[i])
	 834  		if j == 0 {
	 835  			// Skip empty entry.
	 836  			continue
	 837  		}
	 838  		sa[i] = 0
	 839  		if j < 0 {
	 840  			// Leave discovered LMS-substring start index for caller.
	 841  			top--
	 842  			sa[top] = int32(-j)
	 843  			continue
	 844  		}
	 845  
	 846  		// Index j was on work queue, meaning k := j-1 is S-type,
	 847  		// so we can now place k correctly into sa.
	 848  		// If k-1 is S-type, queue k for processing later in this loop.
	 849  		// If k-1 is L-type (text[k-1] > text[k]), queue -k to save for the caller.
	 850  		k := j - 1
	 851  		c1 := text[k]
	 852  		c0 := text[k-1]
	 853  		if c0 > c1 {
	 854  			k = -k
	 855  		}
	 856  
	 857  		if cB != c1 {
	 858  			bucket[cB] = b
	 859  			cB = c1
	 860  			b = bucket[cB]
	 861  		}
	 862  		b--
	 863  		sa[b] = int32(k)
	 864  	}
	 865  }
	 866  
	 867  func induceSubS_64(text []int64, sa, freq, bucket []int64) {
	 868  	// Initialize positions for right side of character buckets.
	 869  	bucketMax_64(text, freq, bucket)
	 870  
	 871  	// Analogous to induceSubL_64 above,
	 872  	// as we scan the array right-to-left, each sa[i] = j > 0 is a correctly
	 873  	// sorted suffix array entry (for text[j:]) for which we know that j-1 is type S.
	 874  	// Because j-1 is type S, inserting it into sa now will sort it correctly.
	 875  	// But we want to distinguish a j-1 with j-2 of type S from type L.
	 876  	// We can process the former but want to leave the latter for the caller.
	 877  	// We record the difference by negating j-1 if it is preceded by type L.
	 878  	// Either way, the insertion (into the text[j-1] bucket) is guaranteed to
	 879  	// happen at sa[i´] for some i´ < i, that is, in the portion of sa we have
	 880  	// yet to scan. A single pass therefore sees indexes j, j-1, j-2, j-3,
	 881  	// and so on, in sorted but not necessarily adjacent order, until it finds
	 882  	// one preceded by an index of type L, at which point it must stop.
	 883  	// That index (preceded by one of type L) is an LMS-substring start.
	 884  	//
	 885  	// As we scan through the array, we clear the worked entries (sa[i] > 0) to zero,
	 886  	// and we flip sa[i] < 0 to -sa[i] and compact into the top of sa,
	 887  	// so that the loop finishes with the top of sa containing exactly
	 888  	// the LMS-substring start indexes, sorted by LMS-substring.
	 889  
	 890  	// Cache recently used bucket index:
	 891  	cB := int64(0)
	 892  	b := bucket[cB]
	 893  
	 894  	top := len(sa)
	 895  	for i := len(sa) - 1; i >= 0; i-- {
	 896  		j := int(sa[i])
	 897  		if j == 0 {
	 898  			// Skip empty entry.
	 899  			continue
	 900  		}
	 901  		sa[i] = 0
	 902  		if j < 0 {
	 903  			// Leave discovered LMS-substring start index for caller.
	 904  			top--
	 905  			sa[top] = int64(-j)
	 906  			continue
	 907  		}
	 908  
	 909  		// Index j was on work queue, meaning k := j-1 is S-type,
	 910  		// so we can now place k correctly into sa.
	 911  		// If k-1 is S-type, queue k for processing later in this loop.
	 912  		// If k-1 is L-type (text[k-1] > text[k]), queue -k to save for the caller.
	 913  		k := j - 1
	 914  		c1 := text[k]
	 915  		c0 := text[k-1]
	 916  		if c0 > c1 {
	 917  			k = -k
	 918  		}
	 919  
	 920  		if cB != c1 {
	 921  			bucket[cB] = b
	 922  			cB = c1
	 923  			b = bucket[cB]
	 924  		}
	 925  		b--
	 926  		sa[b] = int64(k)
	 927  	}
	 928  }
	 929  
	 930  func length_8_64(text []byte, sa []int64, numLMS int) {
	 931  	end := 0 // index of current LMS-substring end (0 indicates final LMS-substring)
	 932  
	 933  	// The encoding of N text bytes into a “length” word
	 934  	// adds 1 to each byte, packs them into the bottom
	 935  	// N*8 bits of a word, and then bitwise inverts the result.
	 936  	// That is, the text sequence A B C (hex 41 42 43)
	 937  	// encodes as ^uint64(0x42_43_44).
	 938  	// LMS-substrings can never start or end with 0xFF.
	 939  	// Adding 1 ensures the encoded byte sequence never
	 940  	// starts or ends with 0x00, so that present bytes can be
	 941  	// distinguished from zero-padding in the top bits,
	 942  	// so the length need not be separately encoded.
	 943  	// Inverting the bytes increases the chance that a
	 944  	// 4-byte encoding will still be ≥ len(text).
	 945  	// In particular, if the first byte is ASCII (<= 0x7E, so +1 <= 0x7F)
	 946  	// then the high bit of the inversion will be set,
	 947  	// making it clearly not a valid length (it would be a negative one).
	 948  	//
	 949  	// cx holds the pre-inverted encoding (the packed incremented bytes).
	 950  	cx := uint64(0) // byte-only
	 951  
	 952  	// This stanza (until the blank line) is the "LMS-substring iterator",
	 953  	// described in placeLMS_8_64 above, with one line added to maintain cx.
	 954  	c0, c1, isTypeS := byte(0), byte(0), false
	 955  	for i := len(text) - 1; i >= 0; i-- {
	 956  		c0, c1 = text[i], c0
	 957  		cx = cx<<8 | uint64(c1+1) // byte-only
	 958  		if c0 < c1 {
	 959  			isTypeS = true
	 960  		} else if c0 > c1 && isTypeS {
	 961  			isTypeS = false
	 962  
	 963  			// Index j = i+1 is the start of an LMS-substring.
	 964  			// Compute length or encoded text to store in sa[j/2].
	 965  			j := i + 1
	 966  			var code int64
	 967  			if end == 0 {
	 968  				code = 0
	 969  			} else {
	 970  				code = int64(end - j)
	 971  				if code <= 64/8 && ^cx >= uint64(len(text)) { // byte-only
	 972  					code = int64(^cx) // byte-only
	 973  				} // byte-only
	 974  			}
	 975  			sa[j>>1] = code
	 976  			end = j + 1
	 977  			cx = uint64(c1 + 1) // byte-only
	 978  		}
	 979  	}
	 980  }
	 981  
	 982  func length_32(text []int32, sa []int32, numLMS int) {
	 983  	end := 0 // index of current LMS-substring end (0 indicates final LMS-substring)
	 984  
	 985  	// The encoding of N text int32s into a “length” word
	 986  	// adds 1 to each int32, packs them into the bottom
	 987  	// N*8 bits of a word, and then bitwise inverts the result.
	 988  	// That is, the text sequence A B C (hex 41 42 43)
	 989  	// encodes as ^uint32(0x42_43_44).
	 990  	// LMS-substrings can never start or end with 0xFF.
	 991  	// Adding 1 ensures the encoded int32 sequence never
	 992  	// starts or ends with 0x00, so that present int32s can be
	 993  	// distinguished from zero-padding in the top bits,
	 994  	// so the length need not be separately encoded.
	 995  	// Inverting the int32s increases the chance that a
	 996  	// 4-int32 encoding will still be ≥ len(text).
	 997  	// In particular, if the first int32 is ASCII (<= 0x7E, so +1 <= 0x7F)
	 998  	// then the high bit of the inversion will be set,
	 999  	// making it clearly not a valid length (it would be a negative one).
	1000  	//
	1001  	// cx holds the pre-inverted encoding (the packed incremented int32s).
	1002  
	1003  	// This stanza (until the blank line) is the "LMS-substring iterator",
	1004  	// described in placeLMS_32 above, with one line added to maintain cx.
	1005  	c0, c1, isTypeS := int32(0), int32(0), false
	1006  	for i := len(text) - 1; i >= 0; i-- {
	1007  		c0, c1 = text[i], c0
	1008  		if c0 < c1 {
	1009  			isTypeS = true
	1010  		} else if c0 > c1 && isTypeS {
	1011  			isTypeS = false
	1012  
	1013  			// Index j = i+1 is the start of an LMS-substring.
	1014  			// Compute length or encoded text to store in sa[j/2].
	1015  			j := i + 1
	1016  			var code int32
	1017  			if end == 0 {
	1018  				code = 0
	1019  			} else {
	1020  				code = int32(end - j)
	1021  			}
	1022  			sa[j>>1] = code
	1023  			end = j + 1
	1024  		}
	1025  	}
	1026  }
	1027  
	1028  func length_64(text []int64, sa []int64, numLMS int) {
	1029  	end := 0 // index of current LMS-substring end (0 indicates final LMS-substring)
	1030  
	1031  	// The encoding of N text int64s into a “length” word
	1032  	// adds 1 to each int64, packs them into the bottom
	1033  	// N*8 bits of a word, and then bitwise inverts the result.
	1034  	// That is, the text sequence A B C (hex 41 42 43)
	1035  	// encodes as ^uint64(0x42_43_44).
	1036  	// LMS-substrings can never start or end with 0xFF.
	1037  	// Adding 1 ensures the encoded int64 sequence never
	1038  	// starts or ends with 0x00, so that present int64s can be
	1039  	// distinguished from zero-padding in the top bits,
	1040  	// so the length need not be separately encoded.
	1041  	// Inverting the int64s increases the chance that a
	1042  	// 4-int64 encoding will still be ≥ len(text).
	1043  	// In particular, if the first int64 is ASCII (<= 0x7E, so +1 <= 0x7F)
	1044  	// then the high bit of the inversion will be set,
	1045  	// making it clearly not a valid length (it would be a negative one).
	1046  	//
	1047  	// cx holds the pre-inverted encoding (the packed incremented int64s).
	1048  
	1049  	// This stanza (until the blank line) is the "LMS-substring iterator",
	1050  	// described in placeLMS_64 above, with one line added to maintain cx.
	1051  	c0, c1, isTypeS := int64(0), int64(0), false
	1052  	for i := len(text) - 1; i >= 0; i-- {
	1053  		c0, c1 = text[i], c0
	1054  		if c0 < c1 {
	1055  			isTypeS = true
	1056  		} else if c0 > c1 && isTypeS {
	1057  			isTypeS = false
	1058  
	1059  			// Index j = i+1 is the start of an LMS-substring.
	1060  			// Compute length or encoded text to store in sa[j/2].
	1061  			j := i + 1
	1062  			var code int64
	1063  			if end == 0 {
	1064  				code = 0
	1065  			} else {
	1066  				code = int64(end - j)
	1067  			}
	1068  			sa[j>>1] = code
	1069  			end = j + 1
	1070  		}
	1071  	}
	1072  }
	1073  
	1074  func assignID_8_64(text []byte, sa []int64, numLMS int) int {
	1075  	id := 0
	1076  	lastLen := int64(-1) // impossible
	1077  	lastPos := int64(0)
	1078  	for _, j := range sa[len(sa)-numLMS:] {
	1079  		// Is the LMS-substring at index j new, or is it the same as the last one we saw?
	1080  		n := sa[j/2]
	1081  		if n != lastLen {
	1082  			goto New
	1083  		}
	1084  		if uint64(n) >= uint64(len(text)) {
	1085  			// “Length” is really encoded full text, and they match.
	1086  			goto Same
	1087  		}
	1088  		{
	1089  			// Compare actual texts.
	1090  			n := int(n)
	1091  			this := text[j:][:n]
	1092  			last := text[lastPos:][:n]
	1093  			for i := 0; i < n; i++ {
	1094  				if this[i] != last[i] {
	1095  					goto New
	1096  				}
	1097  			}
	1098  			goto Same
	1099  		}
	1100  	New:
	1101  		id++
	1102  		lastPos = j
	1103  		lastLen = n
	1104  	Same:
	1105  		sa[j/2] = int64(id)
	1106  	}
	1107  	return id
	1108  }
	1109  
	1110  func assignID_32(text []int32, sa []int32, numLMS int) int {
	1111  	id := 0
	1112  	lastLen := int32(-1) // impossible
	1113  	lastPos := int32(0)
	1114  	for _, j := range sa[len(sa)-numLMS:] {
	1115  		// Is the LMS-substring at index j new, or is it the same as the last one we saw?
	1116  		n := sa[j/2]
	1117  		if n != lastLen {
	1118  			goto New
	1119  		}
	1120  		if uint32(n) >= uint32(len(text)) {
	1121  			// “Length” is really encoded full text, and they match.
	1122  			goto Same
	1123  		}
	1124  		{
	1125  			// Compare actual texts.
	1126  			n := int(n)
	1127  			this := text[j:][:n]
	1128  			last := text[lastPos:][:n]
	1129  			for i := 0; i < n; i++ {
	1130  				if this[i] != last[i] {
	1131  					goto New
	1132  				}
	1133  			}
	1134  			goto Same
	1135  		}
	1136  	New:
	1137  		id++
	1138  		lastPos = j
	1139  		lastLen = n
	1140  	Same:
	1141  		sa[j/2] = int32(id)
	1142  	}
	1143  	return id
	1144  }
	1145  
	1146  func assignID_64(text []int64, sa []int64, numLMS int) int {
	1147  	id := 0
	1148  	lastLen := int64(-1) // impossible
	1149  	lastPos := int64(0)
	1150  	for _, j := range sa[len(sa)-numLMS:] {
	1151  		// Is the LMS-substring at index j new, or is it the same as the last one we saw?
	1152  		n := sa[j/2]
	1153  		if n != lastLen {
	1154  			goto New
	1155  		}
	1156  		if uint64(n) >= uint64(len(text)) {
	1157  			// “Length” is really encoded full text, and they match.
	1158  			goto Same
	1159  		}
	1160  		{
	1161  			// Compare actual texts.
	1162  			n := int(n)
	1163  			this := text[j:][:n]
	1164  			last := text[lastPos:][:n]
	1165  			for i := 0; i < n; i++ {
	1166  				if this[i] != last[i] {
	1167  					goto New
	1168  				}
	1169  			}
	1170  			goto Same
	1171  		}
	1172  	New:
	1173  		id++
	1174  		lastPos = j
	1175  		lastLen = n
	1176  	Same:
	1177  		sa[j/2] = int64(id)
	1178  	}
	1179  	return id
	1180  }
	1181  
	1182  func map_64(sa []int64, numLMS int) {
	1183  	w := len(sa)
	1184  	for i := len(sa) / 2; i >= 0; i-- {
	1185  		j := sa[i]
	1186  		if j > 0 {
	1187  			w--
	1188  			sa[w] = j - 1
	1189  		}
	1190  	}
	1191  }
	1192  
	1193  func recurse_64(sa, oldTmp []int64, numLMS, maxID int) {
	1194  	dst, saTmp, text := sa[:numLMS], sa[numLMS:len(sa)-numLMS], sa[len(sa)-numLMS:]
	1195  
	1196  	// Set up temporary space for recursive call.
	1197  	// We must pass sais_64 a tmp buffer wiith at least maxID entries.
	1198  	//
	1199  	// The subproblem is guaranteed to have length at most len(sa)/2,
	1200  	// so that sa can hold both the subproblem and its suffix array.
	1201  	// Nearly all the time, however, the subproblem has length < len(sa)/3,
	1202  	// in which case there is a subproblem-sized middle of sa that
	1203  	// we can reuse for temporary space (saTmp).
	1204  	// When recurse_64 is called from sais_8_64, oldTmp is length 512
	1205  	// (from text_64), and saTmp will typically be much larger, so we'll use saTmp.
	1206  	// When deeper recursions come back to recurse_64, now oldTmp is
	1207  	// the saTmp from the top-most recursion, it is typically larger than
	1208  	// the current saTmp (because the current sa gets smaller and smaller
	1209  	// as the recursion gets deeper), and we keep reusing that top-most
	1210  	// large saTmp instead of the offered smaller ones.
	1211  	//
	1212  	// Why is the subproblem length so often just under len(sa)/3?
	1213  	// See Nong, Zhang, and Chen, section 3.6 for a plausible explanation.
	1214  	// In brief, the len(sa)/2 case would correspond to an SLSLSLSLSLSL pattern
	1215  	// in the input, perfect alternation of larger and smaller input bytes.
	1216  	// Real text doesn't do that. If each L-type index is randomly followed
	1217  	// by either an L-type or S-type index, then half the substrings will
	1218  	// be of the form SLS, but the other half will be longer. Of that half,
	1219  	// half (a quarter overall) will be SLLS; an eighth will be SLLLS, and so on.
	1220  	// Not counting the final S in each (which overlaps the first S in the next),
	1221  	// This works out to an average length 2×½ + 3×¼ + 4×⅛ + ... = 3.
	1222  	// The space we need is further reduced by the fact that many of the
	1223  	// short patterns like SLS will often be the same character sequences
	1224  	// repeated throughout the text, reducing maxID relative to numLMS.
	1225  	//
	1226  	// For short inputs, the averages may not run in our favor, but then we
	1227  	// can often fall back to using the length-512 tmp available in the
	1228  	// top-most call. (Also a short allocation would not be a big deal.)
	1229  	//
	1230  	// For pathological inputs, we fall back to allocating a new tmp of length
	1231  	// max(maxID, numLMS/2). This level of the recursion needs maxID,
	1232  	// and all deeper levels of the recursion will need no more than numLMS/2,
	1233  	// so this one allocation is guaranteed to suffice for the entire stack
	1234  	// of recursive calls.
	1235  	tmp := oldTmp
	1236  	if len(tmp) < len(saTmp) {
	1237  		tmp = saTmp
	1238  	}
	1239  	if len(tmp) < numLMS {
	1240  		// TestSAIS/forcealloc reaches this code.
	1241  		n := maxID
	1242  		if n < numLMS/2 {
	1243  			n = numLMS / 2
	1244  		}
	1245  		tmp = make([]int64, n)
	1246  	}
	1247  
	1248  	// sais_64 requires that the caller arrange to clear dst,
	1249  	// because in general the caller may know dst is
	1250  	// freshly-allocated and already cleared. But this one is not.
	1251  	for i := range dst {
	1252  		dst[i] = 0
	1253  	}
	1254  	sais_64(text, maxID, dst, tmp)
	1255  }
	1256  
	1257  func unmap_8_64(text []byte, sa []int64, numLMS int) {
	1258  	unmap := sa[len(sa)-numLMS:]
	1259  	j := len(unmap)
	1260  
	1261  	// "LMS-substring iterator" (see placeLMS_8_64 above).
	1262  	c0, c1, isTypeS := byte(0), byte(0), false
	1263  	for i := len(text) - 1; i >= 0; i-- {
	1264  		c0, c1 = text[i], c0
	1265  		if c0 < c1 {
	1266  			isTypeS = true
	1267  		} else if c0 > c1 && isTypeS {
	1268  			isTypeS = false
	1269  
	1270  			// Populate inverse map.
	1271  			j--
	1272  			unmap[j] = int64(i + 1)
	1273  		}
	1274  	}
	1275  
	1276  	// Apply inverse map to subproblem suffix array.
	1277  	sa = sa[:numLMS]
	1278  	for i := 0; i < len(sa); i++ {
	1279  		sa[i] = unmap[sa[i]]
	1280  	}
	1281  }
	1282  
	1283  func unmap_32(text []int32, sa []int32, numLMS int) {
	1284  	unmap := sa[len(sa)-numLMS:]
	1285  	j := len(unmap)
	1286  
	1287  	// "LMS-substring iterator" (see placeLMS_32 above).
	1288  	c0, c1, isTypeS := int32(0), int32(0), false
	1289  	for i := len(text) - 1; i >= 0; i-- {
	1290  		c0, c1 = text[i], c0
	1291  		if c0 < c1 {
	1292  			isTypeS = true
	1293  		} else if c0 > c1 && isTypeS {
	1294  			isTypeS = false
	1295  
	1296  			// Populate inverse map.
	1297  			j--
	1298  			unmap[j] = int32(i + 1)
	1299  		}
	1300  	}
	1301  
	1302  	// Apply inverse map to subproblem suffix array.
	1303  	sa = sa[:numLMS]
	1304  	for i := 0; i < len(sa); i++ {
	1305  		sa[i] = unmap[sa[i]]
	1306  	}
	1307  }
	1308  
	1309  func unmap_64(text []int64, sa []int64, numLMS int) {
	1310  	unmap := sa[len(sa)-numLMS:]
	1311  	j := len(unmap)
	1312  
	1313  	// "LMS-substring iterator" (see placeLMS_64 above).
	1314  	c0, c1, isTypeS := int64(0), int64(0), false
	1315  	for i := len(text) - 1; i >= 0; i-- {
	1316  		c0, c1 = text[i], c0
	1317  		if c0 < c1 {
	1318  			isTypeS = true
	1319  		} else if c0 > c1 && isTypeS {
	1320  			isTypeS = false
	1321  
	1322  			// Populate inverse map.
	1323  			j--
	1324  			unmap[j] = int64(i + 1)
	1325  		}
	1326  	}
	1327  
	1328  	// Apply inverse map to subproblem suffix array.
	1329  	sa = sa[:numLMS]
	1330  	for i := 0; i < len(sa); i++ {
	1331  		sa[i] = unmap[sa[i]]
	1332  	}
	1333  }
	1334  
	1335  func expand_8_64(text []byte, freq, bucket, sa []int64, numLMS int) {
	1336  	bucketMax_8_64(text, freq, bucket)
	1337  	bucket = bucket[:256] // eliminate bound check for bucket[c] below
	1338  
	1339  	// Loop backward through sa, always tracking
	1340  	// the next index to populate from sa[:numLMS].
	1341  	// When we get to one, populate it.
	1342  	// Zero the rest of the slots; they have dead values in them.
	1343  	x := numLMS - 1
	1344  	saX := sa[x]
	1345  	c := text[saX]
	1346  	b := bucket[c] - 1
	1347  	bucket[c] = b
	1348  
	1349  	for i := len(sa) - 1; i >= 0; i-- {
	1350  		if i != int(b) {
	1351  			sa[i] = 0
	1352  			continue
	1353  		}
	1354  		sa[i] = saX
	1355  
	1356  		// Load next entry to put down (if any).
	1357  		if x > 0 {
	1358  			x--
	1359  			saX = sa[x] // TODO bounds check
	1360  			c = text[saX]
	1361  			b = bucket[c] - 1
	1362  			bucket[c] = b
	1363  		}
	1364  	}
	1365  }
	1366  
	1367  func expand_32(text []int32, freq, bucket, sa []int32, numLMS int) {
	1368  	bucketMax_32(text, freq, bucket)
	1369  
	1370  	// Loop backward through sa, always tracking
	1371  	// the next index to populate from sa[:numLMS].
	1372  	// When we get to one, populate it.
	1373  	// Zero the rest of the slots; they have dead values in them.
	1374  	x := numLMS - 1
	1375  	saX := sa[x]
	1376  	c := text[saX]
	1377  	b := bucket[c] - 1
	1378  	bucket[c] = b
	1379  
	1380  	for i := len(sa) - 1; i >= 0; i-- {
	1381  		if i != int(b) {
	1382  			sa[i] = 0
	1383  			continue
	1384  		}
	1385  		sa[i] = saX
	1386  
	1387  		// Load next entry to put down (if any).
	1388  		if x > 0 {
	1389  			x--
	1390  			saX = sa[x] // TODO bounds check
	1391  			c = text[saX]
	1392  			b = bucket[c] - 1
	1393  			bucket[c] = b
	1394  		}
	1395  	}
	1396  }
	1397  
	1398  func expand_64(text []int64, freq, bucket, sa []int64, numLMS int) {
	1399  	bucketMax_64(text, freq, bucket)
	1400  
	1401  	// Loop backward through sa, always tracking
	1402  	// the next index to populate from sa[:numLMS].
	1403  	// When we get to one, populate it.
	1404  	// Zero the rest of the slots; they have dead values in them.
	1405  	x := numLMS - 1
	1406  	saX := sa[x]
	1407  	c := text[saX]
	1408  	b := bucket[c] - 1
	1409  	bucket[c] = b
	1410  
	1411  	for i := len(sa) - 1; i >= 0; i-- {
	1412  		if i != int(b) {
	1413  			sa[i] = 0
	1414  			continue
	1415  		}
	1416  		sa[i] = saX
	1417  
	1418  		// Load next entry to put down (if any).
	1419  		if x > 0 {
	1420  			x--
	1421  			saX = sa[x] // TODO bounds check
	1422  			c = text[saX]
	1423  			b = bucket[c] - 1
	1424  			bucket[c] = b
	1425  		}
	1426  	}
	1427  }
	1428  
	1429  func induceL_8_64(text []byte, sa, freq, bucket []int64) {
	1430  	// Initialize positions for left side of character buckets.
	1431  	bucketMin_8_64(text, freq, bucket)
	1432  	bucket = bucket[:256] // eliminate bounds check for bucket[cB] below
	1433  
	1434  	// This scan is similar to the one in induceSubL_8_64 above.
	1435  	// That one arranges to clear all but the leftmost L-type indexes.
	1436  	// This scan leaves all the L-type indexes and the original S-type
	1437  	// indexes, but it negates the positive leftmost L-type indexes
	1438  	// (the ones that induceS_8_64 needs to process).
	1439  
	1440  	// expand_8_64 left out the implicit entry sa[-1] == len(text),
	1441  	// corresponding to the identified type-L index len(text)-1.
	1442  	// Process it before the left-to-right scan of sa proper.
	1443  	// See body in loop for commentary.
	1444  	k := len(text) - 1
	1445  	c0, c1 := text[k-1], text[k]
	1446  	if c0 < c1 {
	1447  		k = -k
	1448  	}
	1449  
	1450  	// Cache recently used bucket index.
	1451  	cB := c1
	1452  	b := bucket[cB]
	1453  	sa[b] = int64(k)
	1454  	b++
	1455  
	1456  	for i := 0; i < len(sa); i++ {
	1457  		j := int(sa[i])
	1458  		if j <= 0 {
	1459  			// Skip empty or negated entry (including negated zero).
	1460  			continue
	1461  		}
	1462  
	1463  		// Index j was on work queue, meaning k := j-1 is L-type,
	1464  		// so we can now place k correctly into sa.
	1465  		// If k-1 is L-type, queue k for processing later in this loop.
	1466  		// If k-1 is S-type (text[k-1] < text[k]), queue -k to save for the caller.
	1467  		// If k is zero, k-1 doesn't exist, so we only need to leave it
	1468  		// for the caller. The caller can't tell the difference between
	1469  		// an empty slot and a non-empty zero, but there's no need
	1470  		// to distinguish them anyway: the final suffix array will end up
	1471  		// with one zero somewhere, and that will be a real zero.
	1472  		k := j - 1
	1473  		c1 := text[k]
	1474  		if k > 0 {
	1475  			if c0 := text[k-1]; c0 < c1 {
	1476  				k = -k
	1477  			}
	1478  		}
	1479  
	1480  		if cB != c1 {
	1481  			bucket[cB] = b
	1482  			cB = c1
	1483  			b = bucket[cB]
	1484  		}
	1485  		sa[b] = int64(k)
	1486  		b++
	1487  	}
	1488  }
	1489  
	1490  func induceL_32(text []int32, sa, freq, bucket []int32) {
	1491  	// Initialize positions for left side of character buckets.
	1492  	bucketMin_32(text, freq, bucket)
	1493  
	1494  	// This scan is similar to the one in induceSubL_32 above.
	1495  	// That one arranges to clear all but the leftmost L-type indexes.
	1496  	// This scan leaves all the L-type indexes and the original S-type
	1497  	// indexes, but it negates the positive leftmost L-type indexes
	1498  	// (the ones that induceS_32 needs to process).
	1499  
	1500  	// expand_32 left out the implicit entry sa[-1] == len(text),
	1501  	// corresponding to the identified type-L index len(text)-1.
	1502  	// Process it before the left-to-right scan of sa proper.
	1503  	// See body in loop for commentary.
	1504  	k := len(text) - 1
	1505  	c0, c1 := text[k-1], text[k]
	1506  	if c0 < c1 {
	1507  		k = -k
	1508  	}
	1509  
	1510  	// Cache recently used bucket index.
	1511  	cB := c1
	1512  	b := bucket[cB]
	1513  	sa[b] = int32(k)
	1514  	b++
	1515  
	1516  	for i := 0; i < len(sa); i++ {
	1517  		j := int(sa[i])
	1518  		if j <= 0 {
	1519  			// Skip empty or negated entry (including negated zero).
	1520  			continue
	1521  		}
	1522  
	1523  		// Index j was on work queue, meaning k := j-1 is L-type,
	1524  		// so we can now place k correctly into sa.
	1525  		// If k-1 is L-type, queue k for processing later in this loop.
	1526  		// If k-1 is S-type (text[k-1] < text[k]), queue -k to save for the caller.
	1527  		// If k is zero, k-1 doesn't exist, so we only need to leave it
	1528  		// for the caller. The caller can't tell the difference between
	1529  		// an empty slot and a non-empty zero, but there's no need
	1530  		// to distinguish them anyway: the final suffix array will end up
	1531  		// with one zero somewhere, and that will be a real zero.
	1532  		k := j - 1
	1533  		c1 := text[k]
	1534  		if k > 0 {
	1535  			if c0 := text[k-1]; c0 < c1 {
	1536  				k = -k
	1537  			}
	1538  		}
	1539  
	1540  		if cB != c1 {
	1541  			bucket[cB] = b
	1542  			cB = c1
	1543  			b = bucket[cB]
	1544  		}
	1545  		sa[b] = int32(k)
	1546  		b++
	1547  	}
	1548  }
	1549  
	1550  func induceL_64(text []int64, sa, freq, bucket []int64) {
	1551  	// Initialize positions for left side of character buckets.
	1552  	bucketMin_64(text, freq, bucket)
	1553  
	1554  	// This scan is similar to the one in induceSubL_64 above.
	1555  	// That one arranges to clear all but the leftmost L-type indexes.
	1556  	// This scan leaves all the L-type indexes and the original S-type
	1557  	// indexes, but it negates the positive leftmost L-type indexes
	1558  	// (the ones that induceS_64 needs to process).
	1559  
	1560  	// expand_64 left out the implicit entry sa[-1] == len(text),
	1561  	// corresponding to the identified type-L index len(text)-1.
	1562  	// Process it before the left-to-right scan of sa proper.
	1563  	// See body in loop for commentary.
	1564  	k := len(text) - 1
	1565  	c0, c1 := text[k-1], text[k]
	1566  	if c0 < c1 {
	1567  		k = -k
	1568  	}
	1569  
	1570  	// Cache recently used bucket index.
	1571  	cB := c1
	1572  	b := bucket[cB]
	1573  	sa[b] = int64(k)
	1574  	b++
	1575  
	1576  	for i := 0; i < len(sa); i++ {
	1577  		j := int(sa[i])
	1578  		if j <= 0 {
	1579  			// Skip empty or negated entry (including negated zero).
	1580  			continue
	1581  		}
	1582  
	1583  		// Index j was on work queue, meaning k := j-1 is L-type,
	1584  		// so we can now place k correctly into sa.
	1585  		// If k-1 is L-type, queue k for processing later in this loop.
	1586  		// If k-1 is S-type (text[k-1] < text[k]), queue -k to save for the caller.
	1587  		// If k is zero, k-1 doesn't exist, so we only need to leave it
	1588  		// for the caller. The caller can't tell the difference between
	1589  		// an empty slot and a non-empty zero, but there's no need
	1590  		// to distinguish them anyway: the final suffix array will end up
	1591  		// with one zero somewhere, and that will be a real zero.
	1592  		k := j - 1
	1593  		c1 := text[k]
	1594  		if k > 0 {
	1595  			if c0 := text[k-1]; c0 < c1 {
	1596  				k = -k
	1597  			}
	1598  		}
	1599  
	1600  		if cB != c1 {
	1601  			bucket[cB] = b
	1602  			cB = c1
	1603  			b = bucket[cB]
	1604  		}
	1605  		sa[b] = int64(k)
	1606  		b++
	1607  	}
	1608  }
	1609  
	1610  func induceS_8_64(text []byte, sa, freq, bucket []int64) {
	1611  	// Initialize positions for right side of character buckets.
	1612  	bucketMax_8_64(text, freq, bucket)
	1613  	bucket = bucket[:256] // eliminate bounds check for bucket[cB] below
	1614  
	1615  	cB := byte(0)
	1616  	b := bucket[cB]
	1617  
	1618  	for i := len(sa) - 1; i >= 0; i-- {
	1619  		j := int(sa[i])
	1620  		if j >= 0 {
	1621  			// Skip non-flagged entry.
	1622  			// (This loop can't see an empty entry; 0 means the real zero index.)
	1623  			continue
	1624  		}
	1625  
	1626  		// Negative j is a work queue entry; rewrite to positive j for final suffix array.
	1627  		j = -j
	1628  		sa[i] = int64(j)
	1629  
	1630  		// Index j was on work queue (encoded as -j but now decoded),
	1631  		// meaning k := j-1 is L-type,
	1632  		// so we can now place k correctly into sa.
	1633  		// If k-1 is S-type, queue -k for processing later in this loop.
	1634  		// If k-1 is L-type (text[k-1] > text[k]), queue k to save for the caller.
	1635  		// If k is zero, k-1 doesn't exist, so we only need to leave it
	1636  		// for the caller.
	1637  		k := j - 1
	1638  		c1 := text[k]
	1639  		if k > 0 {
	1640  			if c0 := text[k-1]; c0 <= c1 {
	1641  				k = -k
	1642  			}
	1643  		}
	1644  
	1645  		if cB != c1 {
	1646  			bucket[cB] = b
	1647  			cB = c1
	1648  			b = bucket[cB]
	1649  		}
	1650  		b--
	1651  		sa[b] = int64(k)
	1652  	}
	1653  }
	1654  
	1655  func induceS_32(text []int32, sa, freq, bucket []int32) {
	1656  	// Initialize positions for right side of character buckets.
	1657  	bucketMax_32(text, freq, bucket)
	1658  
	1659  	cB := int32(0)
	1660  	b := bucket[cB]
	1661  
	1662  	for i := len(sa) - 1; i >= 0; i-- {
	1663  		j := int(sa[i])
	1664  		if j >= 0 {
	1665  			// Skip non-flagged entry.
	1666  			// (This loop can't see an empty entry; 0 means the real zero index.)
	1667  			continue
	1668  		}
	1669  
	1670  		// Negative j is a work queue entry; rewrite to positive j for final suffix array.
	1671  		j = -j
	1672  		sa[i] = int32(j)
	1673  
	1674  		// Index j was on work queue (encoded as -j but now decoded),
	1675  		// meaning k := j-1 is L-type,
	1676  		// so we can now place k correctly into sa.
	1677  		// If k-1 is S-type, queue -k for processing later in this loop.
	1678  		// If k-1 is L-type (text[k-1] > text[k]), queue k to save for the caller.
	1679  		// If k is zero, k-1 doesn't exist, so we only need to leave it
	1680  		// for the caller.
	1681  		k := j - 1
	1682  		c1 := text[k]
	1683  		if k > 0 {
	1684  			if c0 := text[k-1]; c0 <= c1 {
	1685  				k = -k
	1686  			}
	1687  		}
	1688  
	1689  		if cB != c1 {
	1690  			bucket[cB] = b
	1691  			cB = c1
	1692  			b = bucket[cB]
	1693  		}
	1694  		b--
	1695  		sa[b] = int32(k)
	1696  	}
	1697  }
	1698  
	1699  func induceS_64(text []int64, sa, freq, bucket []int64) {
	1700  	// Initialize positions for right side of character buckets.
	1701  	bucketMax_64(text, freq, bucket)
	1702  
	1703  	cB := int64(0)
	1704  	b := bucket[cB]
	1705  
	1706  	for i := len(sa) - 1; i >= 0; i-- {
	1707  		j := int(sa[i])
	1708  		if j >= 0 {
	1709  			// Skip non-flagged entry.
	1710  			// (This loop can't see an empty entry; 0 means the real zero index.)
	1711  			continue
	1712  		}
	1713  
	1714  		// Negative j is a work queue entry; rewrite to positive j for final suffix array.
	1715  		j = -j
	1716  		sa[i] = int64(j)
	1717  
	1718  		// Index j was on work queue (encoded as -j but now decoded),
	1719  		// meaning k := j-1 is L-type,
	1720  		// so we can now place k correctly into sa.
	1721  		// If k-1 is S-type, queue -k for processing later in this loop.
	1722  		// If k-1 is L-type (text[k-1] > text[k]), queue k to save for the caller.
	1723  		// If k is zero, k-1 doesn't exist, so we only need to leave it
	1724  		// for the caller.
	1725  		k := j - 1
	1726  		c1 := text[k]
	1727  		if k > 0 {
	1728  			if c0 := text[k-1]; c0 <= c1 {
	1729  				k = -k
	1730  			}
	1731  		}
	1732  
	1733  		if cB != c1 {
	1734  			bucket[cB] = b
	1735  			cB = c1
	1736  			b = bucket[cB]
	1737  		}
	1738  		b--
	1739  		sa[b] = int64(k)
	1740  	}
	1741  }
	1742  

View as plain text