 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			666 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			666 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package roaring
 | |
| 
 | |
| func difference(set1 []uint16, set2 []uint16, buffer []uint16) int {
 | |
| 	if len(set2) == 0 {
 | |
| 		buffer = buffer[:len(set1)]
 | |
| 		copy(buffer, set1)
 | |
| 		return len(set1)
 | |
| 	}
 | |
| 	if len(set1) == 0 {
 | |
| 		return 0
 | |
| 	}
 | |
| 	pos := 0
 | |
| 	k1 := 0
 | |
| 	k2 := 0
 | |
| 	buffer = buffer[:cap(buffer)]
 | |
| 	s1 := set1[k1]
 | |
| 	s2 := set2[k2]
 | |
| 	for {
 | |
| 		if s1 < s2 {
 | |
| 			buffer[pos] = s1
 | |
| 			pos++
 | |
| 			k1++
 | |
| 			if k1 >= len(set1) {
 | |
| 				break
 | |
| 			}
 | |
| 			s1 = set1[k1]
 | |
| 		} else if s1 == s2 {
 | |
| 			k1++
 | |
| 			k2++
 | |
| 			if k1 >= len(set1) {
 | |
| 				break
 | |
| 			}
 | |
| 			s1 = set1[k1]
 | |
| 			if k2 >= len(set2) {
 | |
| 				for ; k1 < len(set1); k1++ {
 | |
| 					buffer[pos] = set1[k1]
 | |
| 					pos++
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 			s2 = set2[k2]
 | |
| 		} else { // if (val1>val2)
 | |
| 			k2++
 | |
| 			if k2 >= len(set2) {
 | |
| 				for ; k1 < len(set1); k1++ {
 | |
| 					buffer[pos] = set1[k1]
 | |
| 					pos++
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 			s2 = set2[k2]
 | |
| 		}
 | |
| 	}
 | |
| 	return pos
 | |
| }
 | |
| 
 | |
| func exclusiveUnion2by2(set1 []uint16, set2 []uint16, buffer []uint16) int {
 | |
| 	if 0 == len(set2) {
 | |
| 		buffer = buffer[:len(set1)]
 | |
| 		copy(buffer, set1[:])
 | |
| 		return len(set1)
 | |
| 	}
 | |
| 	if 0 == len(set1) {
 | |
| 		buffer = buffer[:len(set2)]
 | |
| 		copy(buffer, set2[:])
 | |
| 		return len(set2)
 | |
| 	}
 | |
| 	pos := 0
 | |
| 	k1 := 0
 | |
| 	k2 := 0
 | |
| 	s1 := set1[k1]
 | |
| 	s2 := set2[k2]
 | |
| 	buffer = buffer[:cap(buffer)]
 | |
| 	for {
 | |
| 		if s1 < s2 {
 | |
| 			buffer[pos] = s1
 | |
| 			pos++
 | |
| 			k1++
 | |
| 			if k1 >= len(set1) {
 | |
| 				for ; k2 < len(set2); k2++ {
 | |
| 					buffer[pos] = set2[k2]
 | |
| 					pos++
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 			s1 = set1[k1]
 | |
| 		} else if s1 == s2 {
 | |
| 			k1++
 | |
| 			k2++
 | |
| 			if k1 >= len(set1) {
 | |
| 				for ; k2 < len(set2); k2++ {
 | |
| 					buffer[pos] = set2[k2]
 | |
| 					pos++
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 			if k2 >= len(set2) {
 | |
| 				for ; k1 < len(set1); k1++ {
 | |
| 					buffer[pos] = set1[k1]
 | |
| 					pos++
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 			s1 = set1[k1]
 | |
| 			s2 = set2[k2]
 | |
| 		} else { // if (val1>val2)
 | |
| 			buffer[pos] = s2
 | |
| 			pos++
 | |
| 			k2++
 | |
| 			if k2 >= len(set2) {
 | |
| 				for ; k1 < len(set1); k1++ {
 | |
| 					buffer[pos] = set1[k1]
 | |
| 					pos++
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 			s2 = set2[k2]
 | |
| 		}
 | |
| 	}
 | |
| 	return pos
 | |
| }
 | |
| 
 | |
| // union2by2Cardinality computes the cardinality of the union
 | |
| func union2by2Cardinality(set1 []uint16, set2 []uint16) int {
 | |
| 	pos := 0
 | |
| 	k1 := 0
 | |
| 	k2 := 0
 | |
| 	if 0 == len(set2) {
 | |
| 		return len(set1)
 | |
| 	}
 | |
| 	if 0 == len(set1) {
 | |
| 		return len(set2)
 | |
| 	}
 | |
| 	s1 := set1[k1]
 | |
| 	s2 := set2[k2]
 | |
| 	for {
 | |
| 		if s1 < s2 {
 | |
| 			pos++
 | |
| 			k1++
 | |
| 			if k1 >= len(set1) {
 | |
| 				pos += len(set2) - k2
 | |
| 				break
 | |
| 			}
 | |
| 			s1 = set1[k1]
 | |
| 		} else if s1 == s2 {
 | |
| 			pos++
 | |
| 			k1++
 | |
| 			k2++
 | |
| 			if k1 >= len(set1) {
 | |
| 				pos += len(set2) - k2
 | |
| 				break
 | |
| 			}
 | |
| 			if k2 >= len(set2) {
 | |
| 				pos += len(set1) - k1
 | |
| 				break
 | |
| 			}
 | |
| 			s1 = set1[k1]
 | |
| 			s2 = set2[k2]
 | |
| 		} else { // if (set1[k1]>set2[k2])
 | |
| 			pos++
 | |
| 			k2++
 | |
| 			if k2 >= len(set2) {
 | |
| 				pos += len(set1) - k1
 | |
| 				break
 | |
| 			}
 | |
| 			s2 = set2[k2]
 | |
| 		}
 | |
| 	}
 | |
| 	return pos
 | |
| }
 | |
| 
 | |
| func intersection2by2(
 | |
| 	set1 []uint16,
 | |
| 	set2 []uint16,
 | |
| 	buffer []uint16,
 | |
| ) int {
 | |
| 	if len(set1)*64 < len(set2) {
 | |
| 		return onesidedgallopingintersect2by2(set1, set2, buffer)
 | |
| 	} else if len(set2)*64 < len(set1) {
 | |
| 		return onesidedgallopingintersect2by2(set2, set1, buffer)
 | |
| 	} else {
 | |
| 		return localintersect2by2(set1, set2, buffer)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // intersection2by2Cardinality computes the cardinality of the intersection
 | |
| func intersection2by2Cardinality(
 | |
| 	set1 []uint16,
 | |
| 	set2 []uint16,
 | |
| ) int {
 | |
| 	if len(set1)*64 < len(set2) {
 | |
| 		return onesidedgallopingintersect2by2Cardinality(set1, set2)
 | |
| 	} else if len(set2)*64 < len(set1) {
 | |
| 		return onesidedgallopingintersect2by2Cardinality(set2, set1)
 | |
| 	} else {
 | |
| 		return localintersect2by2Cardinality(set1, set2)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // intersects2by2 computes whether the two sets intersect
 | |
| func intersects2by2(
 | |
| 	set1 []uint16,
 | |
| 	set2 []uint16,
 | |
| ) bool {
 | |
| 	// could be optimized if one set is much larger than the other one
 | |
| 	if (len(set1) == 0) || (len(set2) == 0) {
 | |
| 		return false
 | |
| 	}
 | |
| 	index1 := 0
 | |
| 	index2 := 0
 | |
| 	value1 := set1[index1]
 | |
| 	value2 := set2[index2]
 | |
| mainwhile:
 | |
| 	for {
 | |
| 
 | |
| 		if value2 < value1 {
 | |
| 			for {
 | |
| 				index2++
 | |
| 				if index2 == len(set2) {
 | |
| 					break mainwhile
 | |
| 				}
 | |
| 				value2 = set2[index2]
 | |
| 				if value2 >= value1 {
 | |
| 					break
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if value1 < value2 {
 | |
| 			for {
 | |
| 				index1++
 | |
| 				if index1 == len(set1) {
 | |
| 					break mainwhile
 | |
| 				}
 | |
| 				value1 = set1[index1]
 | |
| 				if value1 >= value2 {
 | |
| 					break
 | |
| 				}
 | |
| 			}
 | |
| 		} else {
 | |
| 			// (set2[k2] == set1[k1])
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func localintersect2by2(
 | |
| 	set1 []uint16,
 | |
| 	set2 []uint16,
 | |
| 	buffer []uint16,
 | |
| ) int {
 | |
| 	if (len(set1) == 0) || (len(set2) == 0) {
 | |
| 		return 0
 | |
| 	}
 | |
| 	k1 := 0
 | |
| 	k2 := 0
 | |
| 	pos := 0
 | |
| 	buffer = buffer[:cap(buffer)]
 | |
| 	s1 := set1[k1]
 | |
| 	s2 := set2[k2]
 | |
| mainwhile:
 | |
| 	for {
 | |
| 		if s2 < s1 {
 | |
| 			for {
 | |
| 				k2++
 | |
| 				if k2 == len(set2) {
 | |
| 					break mainwhile
 | |
| 				}
 | |
| 				s2 = set2[k2]
 | |
| 				if s2 >= s1 {
 | |
| 					break
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if s1 < s2 {
 | |
| 			for {
 | |
| 				k1++
 | |
| 				if k1 == len(set1) {
 | |
| 					break mainwhile
 | |
| 				}
 | |
| 				s1 = set1[k1]
 | |
| 				if s1 >= s2 {
 | |
| 					break
 | |
| 				}
 | |
| 			}
 | |
| 		} else {
 | |
| 			// (set2[k2] == set1[k1])
 | |
| 			buffer[pos] = s1
 | |
| 			pos++
 | |
| 			k1++
 | |
| 			if k1 == len(set1) {
 | |
| 				break
 | |
| 			}
 | |
| 			s1 = set1[k1]
 | |
| 			k2++
 | |
| 			if k2 == len(set2) {
 | |
| 				break
 | |
| 			}
 | |
| 			s2 = set2[k2]
 | |
| 		}
 | |
| 	}
 | |
| 	return pos
 | |
| }
 | |
| 
 | |
| // / localintersect2by2Cardinality computes the cardinality of the intersection
 | |
| func localintersect2by2Cardinality(
 | |
| 	set1 []uint16,
 | |
| 	set2 []uint16,
 | |
| ) int {
 | |
| 	if (len(set1) == 0) || (len(set2) == 0) {
 | |
| 		return 0
 | |
| 	}
 | |
| 	index1 := 0
 | |
| 	index2 := 0
 | |
| 	pos := 0
 | |
| 	value1 := set1[index1]
 | |
| 	value2 := set2[index2]
 | |
| mainwhile:
 | |
| 	for {
 | |
| 		if value2 < value1 {
 | |
| 			for {
 | |
| 				index2++
 | |
| 				if index2 == len(set2) {
 | |
| 					break mainwhile
 | |
| 				}
 | |
| 				value2 = set2[index2]
 | |
| 				if value2 >= value1 {
 | |
| 					break
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if value1 < value2 {
 | |
| 			for {
 | |
| 				index1++
 | |
| 				if index1 == len(set1) {
 | |
| 					break mainwhile
 | |
| 				}
 | |
| 				value1 = set1[index1]
 | |
| 				if value1 >= value2 {
 | |
| 					break
 | |
| 				}
 | |
| 			}
 | |
| 		} else {
 | |
| 			// (set2[k2] == set1[k1])
 | |
| 			pos++
 | |
| 			index1++
 | |
| 			if index1 == len(set1) {
 | |
| 				break
 | |
| 			}
 | |
| 			value1 = set1[index1]
 | |
| 			index2++
 | |
| 			if index2 == len(set2) {
 | |
| 				break
 | |
| 			}
 | |
| 			value2 = set2[index2]
 | |
| 		}
 | |
| 	}
 | |
| 	return pos
 | |
| }
 | |
| 
 | |
| func advanceUntil(
 | |
| 	array []uint16,
 | |
| 	pos int,
 | |
| 	length int,
 | |
| 	min uint16,
 | |
| ) int {
 | |
| 	lower := pos + 1
 | |
| 
 | |
| 	if lower >= length || array[lower] >= min {
 | |
| 		return lower
 | |
| 	}
 | |
| 
 | |
| 	spansize := 1
 | |
| 
 | |
| 	for lower+spansize < length && array[lower+spansize] < min {
 | |
| 		spansize *= 2
 | |
| 	}
 | |
| 	var upper int
 | |
| 	if lower+spansize < length {
 | |
| 		upper = lower + spansize
 | |
| 	} else {
 | |
| 		upper = length - 1
 | |
| 	}
 | |
| 
 | |
| 	if array[upper] == min {
 | |
| 		return upper
 | |
| 	}
 | |
| 
 | |
| 	if array[upper] < min {
 | |
| 		// means
 | |
| 		// array
 | |
| 		// has no
 | |
| 		// item
 | |
| 		// >= min
 | |
| 		// pos = array.length;
 | |
| 		return length
 | |
| 	}
 | |
| 
 | |
| 	// we know that the next-smallest span was too small
 | |
| 	lower += (spansize >> 1)
 | |
| 
 | |
| 	mid := 0
 | |
| 	for lower+1 != upper {
 | |
| 		mid = (lower + upper) >> 1
 | |
| 		if array[mid] == min {
 | |
| 			return mid
 | |
| 		} else if array[mid] < min {
 | |
| 			lower = mid
 | |
| 		} else {
 | |
| 			upper = mid
 | |
| 		}
 | |
| 	}
 | |
| 	return upper
 | |
| }
 | |
| 
 | |
| func onesidedgallopingintersect2by2(
 | |
| 	smallset []uint16,
 | |
| 	largeset []uint16,
 | |
| 	buffer []uint16,
 | |
| ) int {
 | |
| 	if 0 == len(smallset) {
 | |
| 		return 0
 | |
| 	}
 | |
| 	buffer = buffer[:cap(buffer)]
 | |
| 	k1 := 0
 | |
| 	k2 := 0
 | |
| 	pos := 0
 | |
| 	s1 := largeset[k1]
 | |
| 	s2 := smallset[k2]
 | |
| mainwhile:
 | |
| 
 | |
| 	for {
 | |
| 		if s1 < s2 {
 | |
| 			k1 = advanceUntil(largeset, k1, len(largeset), s2)
 | |
| 			if k1 == len(largeset) {
 | |
| 				break mainwhile
 | |
| 			}
 | |
| 			s1 = largeset[k1]
 | |
| 		}
 | |
| 		if s2 < s1 {
 | |
| 			k2++
 | |
| 			if k2 == len(smallset) {
 | |
| 				break mainwhile
 | |
| 			}
 | |
| 			s2 = smallset[k2]
 | |
| 		} else {
 | |
| 
 | |
| 			buffer[pos] = s2
 | |
| 			pos++
 | |
| 			k2++
 | |
| 			if k2 == len(smallset) {
 | |
| 				break
 | |
| 			}
 | |
| 			s2 = smallset[k2]
 | |
| 			k1 = advanceUntil(largeset, k1, len(largeset), s2)
 | |
| 			if k1 == len(largeset) {
 | |
| 				break mainwhile
 | |
| 			}
 | |
| 			s1 = largeset[k1]
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 	return pos
 | |
| }
 | |
| 
 | |
| func onesidedgallopingintersect2by2Cardinality(
 | |
| 	smallset []uint16,
 | |
| 	largeset []uint16,
 | |
| ) int {
 | |
| 	if 0 == len(smallset) {
 | |
| 		return 0
 | |
| 	}
 | |
| 	k1 := 0
 | |
| 	k2 := 0
 | |
| 	pos := 0
 | |
| 	s1 := largeset[k1]
 | |
| 	s2 := smallset[k2]
 | |
| mainwhile:
 | |
| 
 | |
| 	for {
 | |
| 		if s1 < s2 {
 | |
| 			k1 = advanceUntil(largeset, k1, len(largeset), s2)
 | |
| 			if k1 == len(largeset) {
 | |
| 				break mainwhile
 | |
| 			}
 | |
| 			s1 = largeset[k1]
 | |
| 		}
 | |
| 		if s2 < s1 {
 | |
| 			k2++
 | |
| 			if k2 == len(smallset) {
 | |
| 				break mainwhile
 | |
| 			}
 | |
| 			s2 = smallset[k2]
 | |
| 		} else {
 | |
| 
 | |
| 			pos++
 | |
| 			k2++
 | |
| 			if k2 == len(smallset) {
 | |
| 				break
 | |
| 			}
 | |
| 			s2 = smallset[k2]
 | |
| 			k1 = advanceUntil(largeset, k1, len(largeset), s2)
 | |
| 			if k1 == len(largeset) {
 | |
| 				break mainwhile
 | |
| 			}
 | |
| 			s1 = largeset[k1]
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 	return pos
 | |
| }
 | |
| 
 | |
| func binarySearch(array []uint16, ikey uint16) int {
 | |
| 	low := 0
 | |
| 	high := len(array) - 1
 | |
| 	for low+16 <= high {
 | |
| 		middleIndex := int(uint32(low+high) >> 1)
 | |
| 		middleValue := array[middleIndex]
 | |
| 		if middleValue < ikey {
 | |
| 			low = middleIndex + 1
 | |
| 		} else if middleValue > ikey {
 | |
| 			high = middleIndex - 1
 | |
| 		} else {
 | |
| 			return middleIndex
 | |
| 		}
 | |
| 	}
 | |
| 	for ; low <= high; low++ {
 | |
| 		val := array[low]
 | |
| 		if val >= ikey {
 | |
| 			if val == ikey {
 | |
| 				return low
 | |
| 			}
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 	return -(low + 1)
 | |
| }
 | |
| 
 | |
| // searchResult provides information about a search request.
 | |
| // The values will depend on the context of the search
 | |
| type searchResult struct {
 | |
| 	value      uint16
 | |
| 	index      int
 | |
| 	exactMatch bool
 | |
| }
 | |
| 
 | |
| // notFound returns a bool depending the search context
 | |
| // For cases `previousValue` and `nextValue` if target is present in the slice
 | |
| // this function will return `true` otherwise `false`
 | |
| // For `nextAbsentValue` and `previousAbsentValue` this will only return `False`
 | |
| func (sr *searchResult) notFound() bool {
 | |
| 	return !sr.exactMatch
 | |
| }
 | |
| 
 | |
| // outOfBounds indicates whether the target was outside the lower and upper bounds of the container
 | |
| func (sr *searchResult) outOfBounds() bool {
 | |
| 	return sr.index <= -1
 | |
| }
 | |
| 
 | |
| // binarySearchUntil is a helper function around binarySearchUntilWithBounds
 | |
| // The user does not have to pass in the lower and upper bound
 | |
| // The lower bound is taken to be `0` and the upper bound `len(array)-1`
 | |
| func binarySearchUntil(array []uint16, target uint16) searchResult {
 | |
| 	return binarySearchUntilWithBounds(array, target, 0, len(array)-1)
 | |
| }
 | |
| 
 | |
| // binarySearchUntilWithBounds returns a `searchResult`.
 | |
| // If an exact match is found the `searchResult{target, <index>, true}` will be returned, where `<index>` is
 | |
| // `target`s index in `array`, and `result.notFound()` evaluates to `false`.
 | |
| // If a match is not found, but `target` was in-bounds then the result.index will be the closest smaller value
 | |
| // Example: [ 8,9,11,12] if the target was 10, then `searchResult{9, 1, false}` will be returned.
 | |
| // If `target` was out of bounds `searchResult{0, -1, false}` will be returned.
 | |
| func binarySearchUntilWithBounds(array []uint16, target uint16, lowIndex int, maxIndex int) searchResult {
 | |
| 	highIndex := maxIndex
 | |
| 
 | |
| 	closestIndex := -1
 | |
| 
 | |
| 	if target < array[lowIndex] {
 | |
| 		return searchResult{0, closestIndex, false}
 | |
| 	}
 | |
| 
 | |
| 	if target > array[maxIndex] {
 | |
| 		return searchResult{0, len(array), false}
 | |
| 	}
 | |
| 
 | |
| 	for lowIndex <= highIndex {
 | |
| 		middleIndex := (lowIndex + highIndex) / 2
 | |
| 		middleValue := array[middleIndex]
 | |
| 
 | |
| 		if middleValue == target {
 | |
| 			return searchResult{middleValue, middleIndex, true}
 | |
| 		}
 | |
| 
 | |
| 		if target < middleValue {
 | |
| 
 | |
| 			if middleIndex > 0 && target > array[middleIndex-1] {
 | |
| 				return searchResult{array[middleIndex-1], middleIndex - 1, false}
 | |
| 			}
 | |
| 
 | |
| 			highIndex = middleIndex
 | |
| 		} else {
 | |
| 			if middleIndex < maxIndex && target < array[middleIndex+1] {
 | |
| 				return searchResult{middleValue, middleIndex, false}
 | |
| 			}
 | |
| 			lowIndex = middleIndex + 1
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	return searchResult{array[closestIndex], closestIndex, false}
 | |
| }
 | |
| 
 | |
| // binarySearchPast is a wrapper around binarySearchPastWithBounds
 | |
| // The user does not have to pass in the lower and upper bound
 | |
| // The lower bound is taken to be `0` and the upper bound `len(array)-1`
 | |
| func binarySearchPast(array []uint16, target uint16) searchResult {
 | |
| 	return binarySearchPastWithBounds(array, target, 0, len(array)-1)
 | |
| }
 | |
| 
 | |
| // binarySearchPastWithBounds looks for the smallest value larger than or equal to `target`
 | |
| // If `target` is out of bounds a `searchResult` indicating out of bounds is returned
 | |
| // `target` does not have to exist in the slice.
 | |
| //
 | |
| // Example:
 | |
| // Suppose the slice is [...10,13...] with `target` equal to 11
 | |
| // The searchResult will have searchResult.value = 13
 | |
| func binarySearchPastWithBounds(array []uint16, target uint16, lowIndex int, maxIndex int) searchResult {
 | |
| 	highIndex := maxIndex
 | |
| 
 | |
| 	closestIndex := -1
 | |
| 
 | |
| 	if target < array[lowIndex] {
 | |
| 		return searchResult{0, closestIndex, false}
 | |
| 	}
 | |
| 
 | |
| 	if target > array[maxIndex] {
 | |
| 		return searchResult{0, len(array), false}
 | |
| 	}
 | |
| 
 | |
| 	for lowIndex <= highIndex {
 | |
| 		middleIndex := (lowIndex + highIndex) / 2
 | |
| 		middleValue := array[middleIndex]
 | |
| 
 | |
| 		if middleValue == target {
 | |
| 			return searchResult{middleValue, middleIndex, true}
 | |
| 		}
 | |
| 
 | |
| 		if target < middleValue {
 | |
| 
 | |
| 			if middleIndex > 0 && target > array[middleIndex-1] {
 | |
| 				return searchResult{array[middleIndex], middleIndex, false}
 | |
| 			}
 | |
| 
 | |
| 			highIndex = middleIndex
 | |
| 		} else {
 | |
| 			if middleIndex < maxIndex && target < array[middleIndex+1] {
 | |
| 				return searchResult{array[middleIndex+1], middleIndex + 1, false}
 | |
| 			}
 | |
| 			lowIndex = middleIndex + 1
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	return searchResult{array[closestIndex], closestIndex, false}
 | |
| }
 |