@@ -88,24 +88,36 @@ export const interpolationSearch = (
8888 if ( arr . byteLength === 0 ) {
8989 return false ;
9090 }
91+ // top and tail the search space
9192 let low = 0 ;
9293 let high = arr . byteLength / ENTRY_SIZE - 1 ;
93- if ( high === low ) {
94- const current = new Uint8Array ( arr . buffer , arr . byteOffset , PATH_HASH_SIZE ) ;
95- if ( current . byteLength !== searchValue . byteLength ) {
96- throw new TypeError (
97- "Search value and current value are of different lengths"
98- ) ;
99- }
100- const cmp = compare ( current , searchValue ) ;
101- if ( cmp === 0 ) {
102- return new Uint8Array ( arr . buffer , arr . byteOffset , ENTRY_SIZE ) ;
103- } else {
104- return false ;
105- }
106- }
10794 const searchValueNumber = uint8ArrayToNumber ( searchValue ) ;
10895 while ( low <= high ) {
96+ if ( low === high ) {
97+ // search space has been reduced to a single element
98+ const current = new Uint8Array (
99+ arr . buffer ,
100+ arr . byteOffset + low * ENTRY_SIZE ,
101+ PATH_HASH_SIZE
102+ ) ;
103+ if ( current . byteLength !== searchValue . byteLength ) {
104+ throw new TypeError (
105+ "Search value and current value are of different lengths"
106+ ) ;
107+ }
108+ const cmp = compare ( current , searchValue ) ;
109+ if ( cmp === 0 ) {
110+ // and it's a match!
111+ return new Uint8Array (
112+ arr . buffer ,
113+ arr . byteOffset + low * ENTRY_SIZE ,
114+ ENTRY_SIZE
115+ ) ;
116+ } else {
117+ // and it's not a match!
118+ return false ;
119+ }
120+ }
109121 const lowValue = new Uint8Array (
110122 arr . buffer ,
111123 arr . byteOffset + low * ENTRY_SIZE ,
@@ -119,17 +131,19 @@ export const interpolationSearch = (
119131 const lowValueNumber = uint8ArrayToNumber ( lowValue ) ;
120132 const highValueNumber = uint8ArrayToNumber ( highValue ) ;
121133 const denominator = highValueNumber - lowValueNumber ;
122- if ( denominator < 0n ) {
123- return false ;
134+ if ( denominator <= 0n ) {
135+ throw new TypeError ( "Search space is unordered" ) ;
124136 }
125137 const numerator = searchValueNumber - lowValueNumber ;
126138 if ( numerator < 0n ) {
139+ // the lowest value in our search space is smaller than the search value (so it can't be in the search space)
127140 return false ;
128141 }
129142 const mid = Math . floor (
130143 Number ( BigInt ( low ) + ( BigInt ( high - low ) * numerator ) / denominator )
131144 ) ;
132145 if ( mid < low || mid > high ) {
146+ // our next guess is either entirely out of range of the search space or we've already searched it
133147 return false ;
134148 }
135149 const current = new Uint8Array (
@@ -150,8 +164,10 @@ export const interpolationSearch = (
150164 ENTRY_SIZE
151165 ) ;
152166 } else if ( cmp < 0 ) {
167+ // our estimate was too low so our search space now becomes mid+1 -> high
153168 low = mid + 1 ;
154169 } else {
170+ // our estimate was too high so our search space now becomes low -> mid-1
155171 high = mid - 1 ;
156172 }
157173 }
0 commit comments