From 028cfce3cac051b2715b45410cdde114a1162dc2 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sat, 16 May 2026 06:59:30 -0400 Subject: [PATCH 01/16] Add SearchStrategy dispatch types and batched in-place searchsorted! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reformulates the existing sorted-search infrastructure as explicit strategy types and adds an in-place batched API: - `SearchStrategy` abstract type with concrete subtypes `LinearScan`, `BracketGallop`, `BinaryBracket`, and `Auto`. - `Base.searchsortedlast(strategy, v, x[, hint])` and the matching `searchsortedfirst` dispatch on the strategy: * `LinearScan` — walk ±1 from the hint. * `BracketGallop` — `bracketstrictlymontonic` + bounded binary search. * `BinaryBracket` — plain `searchsortedlast` / `searchsortedfirst`. * `Auto` — picks based on hint validity and `length(v)`: no/invalid hint or `length(v) > 32` → `BracketGallop`, hint in range and `length(v) ≤ 32` → `LinearScan`, no hint → `BinaryBracket`. - `searchsortedlast!(idx_out, v, queries; strategy = Auto())` and `searchsortedfirst!(...)` — in-place batched variants. For sorted `queries` the previous result is used as a hint for the next, so the total cost is O(length(v) + length(queries)) under `BracketGallop`. Unsorted `queries` fall back to per-element search with no hint. `searchsortedfirstcorrelated` / `searchsortedlastcorrelated` and `searchsortedfirstvec` / `searchsortedlastvec` are kept as backwards- compatible wrappers over the new dispatched API, so no existing caller breaks. Version bumped to 1.9.0 since this is a backward-compatible feature addition. The intent is that downstream callers like SciML/DataInterpolations.jl that hand-roll a sorted-batch lockstep walk (`while idx < n - 1 && tt[i] > t[idx + 1]; idx += 1`) can instead call `searchsortedlast!` and get correct O(log gap) behavior at every n/m ratio, not just dense queries. Co-Authored-By: Chris Rackauckas --- Project.toml | 2 +- src/FindFirstFunctions.jl | 375 ++++++++++++++++++++++++++++++++++---- test/runtests.jl | 159 ++++++++++++++++ 3 files changed, 498 insertions(+), 38 deletions(-) diff --git a/Project.toml b/Project.toml index e6437c0..6469d33 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "FindFirstFunctions" uuid = "64ca27bc-2ba2-4a57-88aa-44e436879224" -version = "1.8.0" +version = "1.9.0" authors = ["Chris Elrod and contributors"] [deps] diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index bb6f4da..aa6e912 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -191,6 +191,332 @@ function bracketstrictlymontonic( return lo, hi end +# --------------------------------------------------------------------------- +# Sorted-search strategies +# --------------------------------------------------------------------------- + +""" + SearchStrategy + +Abstract supertype for sorted-search strategies. Concrete subtypes select how +[`searchsortedlast`](@ref Base.searchsortedlast) and +[`searchsortedfirst`](@ref Base.searchsortedfirst) should be performed when +called with a strategy as the first positional argument: + + - [`LinearScan`](@ref) walks ±1 from the hint until the answer is bracketed. + Cheapest when the target is within a few positions of the hint; degrades + linearly otherwise. + - [`BracketGallop`](@ref) expands an exponential bracket from the hint, then + binary-searches inside it. Effectively O(1) when the target is near the + hint; never worse than ~2 log₂ n comparisons. This is the strategy used + by the legacy [`searchsortedfirstcorrelated`](@ref) / [`searchsortedlastcorrelated`](@ref). + - [`BinaryBracket`](@ref) is the standard `Base.searchsortedlast` / + `Base.searchsortedfirst` with no hint. Use it when no useful hint exists. + - [`Auto`](@ref) heuristically picks one of the above based on the size of + `v` and whether a hint was supplied. + +Strategies can also be passed to the batched +[`searchsortedlast!`](@ref) / [`searchsortedfirst!`](@ref) APIs. +""" +abstract type SearchStrategy end + +""" + LinearScan <: SearchStrategy + +Walk ±1 from the hint. Best when the target is within a few positions of the +hint. Falls back to [`BinaryBracket`](@ref) when no hint is supplied. +""" +struct LinearScan <: SearchStrategy end + +""" + BracketGallop <: SearchStrategy + +Expand an exponential bracket from the hint using +[`bracketstrictlymontonic`](@ref), then binary-search inside the bracket. The +default strategy backing [`searchsortedfirstcorrelated`](@ref) and +[`searchsortedlastcorrelated`](@ref). Falls back to [`BinaryBracket`](@ref) +when no hint is supplied. +""" +struct BracketGallop <: SearchStrategy end + +""" + BinaryBracket <: SearchStrategy + +Plain `Base.searchsortedlast` / `Base.searchsortedfirst`. Ignores any hint +that is supplied. +""" +struct BinaryBracket <: SearchStrategy end + +""" + Auto <: SearchStrategy + +Heuristically picks among [`LinearScan`](@ref), [`BracketGallop`](@ref), and +[`BinaryBracket`](@ref): + + - No hint, or hint outside `axes(v)` → [`BinaryBracket`](@ref). + - Hint in range and `length(v) ≤ 32` → [`LinearScan`](@ref) (binary-search + setup overhead exceeds the worst-case linear walk on tiny vectors). + - Hint in range and `length(v) > 32` → [`BracketGallop`](@ref). +""" +struct Auto <: SearchStrategy end + +const _AUTO_LINEAR_THRESHOLD = 32 + +# Strategy: BinaryBracket — ignore any hint. +Base.searchsortedlast( + ::BinaryBracket, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(v, x, order) +Base.searchsortedfirst( + ::BinaryBracket, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(v, x, order) +Base.searchsortedlast( + s::BinaryBracket, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(s, v, x; order = order) +Base.searchsortedfirst( + s::BinaryBracket, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(s, v, x; order = order) + +# Strategy: LinearScan — walk ±1 from the hint until the answer is bracketed. +function Base.searchsortedlast( + ::LinearScan, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + lo, hi = firstindex(v), lastindex(v) + if hi < lo + return lo - 1 # empty vector + end + i = clamp(hint, lo, hi) + @inbounds if Base.Order.lt(order, x, v[i]) + # v[i] > x → retreat + while i > lo + i -= 1 + !Base.Order.lt(order, x, v[i]) && return i + end + return lo - 1 # x precedes all of v + else + # v[i] ≤ x → try to advance + while i < hi + Base.Order.lt(order, x, v[i + 1]) && return i + i += 1 + end + return hi + end +end + +function Base.searchsortedfirst( + ::LinearScan, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + lo, hi = firstindex(v), lastindex(v) + if hi < lo + return lo + end + i = clamp(hint, lo, hi) + @inbounds if Base.Order.lt(order, v[i], x) + # v[i] < x → advance + while i < hi + i += 1 + !Base.Order.lt(order, v[i], x) && return i + end + return hi + 1 # x exceeds all of v + else + # v[i] ≥ x → try to retreat + while i > lo + !Base.Order.lt(order, v[i - 1], x) && (i -= 1; continue) + return i + end + return lo + end +end + +# LinearScan without a hint falls back to BinaryBracket. +Base.searchsortedlast( + s::LinearScan, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + s::LinearScan, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + +# Strategy: BracketGallop — bracketstrictlymontonic + bounded binary search. +function Base.searchsortedlast( + ::BracketGallop, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + lo, hi = bracketstrictlymontonic(v, x, hint, order) + return searchsortedlast(v, x, lo, hi, order) +end + +function Base.searchsortedfirst( + ::BracketGallop, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + lo, hi = bracketstrictlymontonic(v, x, hint, order) + return searchsortedfirst(v, x, lo, hi, order) +end + +# BracketGallop without a hint falls back to BinaryBracket. +Base.searchsortedlast( + ::BracketGallop, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::BracketGallop, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + +# Strategy: Auto — pick based on hint validity and length(v). +@inline function _auto_pick(v::AbstractVector, hint::Integer) + return if hint < firstindex(v) || hint > lastindex(v) + BinaryBracket() + elseif length(v) <= _AUTO_LINEAR_THRESHOLD + LinearScan() + else + BracketGallop() + end +end + +function Base.searchsortedlast( + ::Auto, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + s = _auto_pick(v, hint) + return s isa BinaryBracket ? + searchsortedlast(s, v, x; order = order) : + searchsortedlast(s, v, x, hint; order = order) +end + +function Base.searchsortedfirst( + ::Auto, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + s = _auto_pick(v, hint) + return s isa BinaryBracket ? + searchsortedfirst(s, v, x; order = order) : + searchsortedfirst(s, v, x, hint; order = order) +end + +Base.searchsortedlast( + ::Auto, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::Auto, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + +# --------------------------------------------------------------------------- +# In-place batched sorted-search API +# --------------------------------------------------------------------------- + +""" + searchsortedlast!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward) + +In-place batched [`searchsortedlast`](@ref Base.searchsortedlast). Writes one +index per element of `queries` into `idx_out` (which must be the same length). + +If `queries` is sorted under `order`, the previous result is used as a hint for +the next query, so the total cost is O(length(v) + length(queries)) under +`strategy = BracketGallop()` (the default `Auto` choice for non-tiny `v`), +matching what callers used to hand-roll with `searchsortedlastcorrelated` + +a manually-maintained `idx` variable. + +If `queries` is not sorted, falls back to per-element `searchsortedlast` with +no hint regardless of `strategy`. + +Returns `idx_out`. +""" +function searchsortedlast!( + idx_out::AbstractVector{<:Integer}, + v::AbstractVector, + queries::AbstractVector; + strategy::SearchStrategy = Auto(), + order::Base.Order.Ordering = Base.Order.Forward + ) + if length(idx_out) != length(queries) + throw( + DimensionMismatch( + "idx_out and queries must have the same length" + ) + ) + end + return _searchsortedlast_batched!(idx_out, v, queries, strategy, order) +end + +""" + searchsortedfirst!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward) + +In-place batched [`searchsortedfirst`](@ref Base.searchsortedfirst). See +[`searchsortedlast!`](@ref) for behavior. +""" +function searchsortedfirst!( + idx_out::AbstractVector{<:Integer}, + v::AbstractVector, + queries::AbstractVector; + strategy::SearchStrategy = Auto(), + order::Base.Order.Ordering = Base.Order.Forward + ) + if length(idx_out) != length(queries) + throw( + DimensionMismatch( + "idx_out and queries must have the same length" + ) + ) + end + return _searchsortedfirst_batched!(idx_out, v, queries, strategy, order) +end + +function _searchsortedlast_batched!( + idx_out, v::AbstractVector, queries::AbstractVector, + strategy::SearchStrategy, order::Base.Order.Ordering + ) + if issorted(queries; order = order) + hint = firstindex(v) - 1 + @inbounds for k in eachindex(queries) + q = queries[k] + hint = if hint < firstindex(v) + searchsortedlast(strategy, v, q; order = order) + else + searchsortedlast(strategy, v, q, hint; order = order) + end + idx_out[k] = hint + end + else + @inbounds for k in eachindex(queries) + idx_out[k] = searchsortedlast(v, queries[k], order) + end + end + return idx_out +end + +function _searchsortedfirst_batched!( + idx_out, v::AbstractVector, queries::AbstractVector, + strategy::SearchStrategy, order::Base.Order.Ordering + ) + if issorted(queries; order = order) + hint = firstindex(v) - 1 + @inbounds for k in eachindex(queries) + q = queries[k] + hint = if hint < firstindex(v) + searchsortedfirst(strategy, v, q; order = order) + else + searchsortedfirst(strategy, v, q, hint; order = order) + end + idx_out[k] = hint + end + else + @inbounds for k in eachindex(queries) + idx_out[k] = searchsortedfirst(v, queries[k], order) + end + end + return idx_out +end + """ looks_linear(v; threshold = 1e-2) @@ -262,6 +588,8 @@ An accelerated `findfirst` on sorted vectors using a bracketed search. Requires to start the search from. The `order` keyword argument specifies the ordering of the vector `v`, defaulting to `Base.Order.Forward`. + +Equivalent to `searchsortedfirst(BracketGallop(), v, x, guess; order = order)`. """ function searchsortedfirstcorrelated( v::AbstractVector, @@ -269,8 +597,7 @@ function searchsortedfirstcorrelated( guess::T; order::Base.Order.Ordering = Base.Order.Forward ) where {T <: Integer} - lo, hi = bracketstrictlymontonic(v, x, guess, order) - return searchsortedfirst(v, x, lo, hi, order) + return searchsortedfirst(BracketGallop(), v, x, guess; order = order) end """ @@ -280,6 +607,8 @@ An accelerated `findlast` on sorted vectors using a bracketed search. Requires a to start the search from. The `order` keyword argument specifies the ordering of the vector `v`, defaulting to `Base.Order.Forward`. + +Equivalent to `searchsortedlast(BracketGallop(), v, x, guess; order = order)`. """ function searchsortedlastcorrelated( v::AbstractVector, @@ -287,8 +616,7 @@ function searchsortedlastcorrelated( guess::T; order::Base.Order.Ordering = Base.Order.Forward ) where {T <: Integer} - lo, hi = bracketstrictlymontonic(v, x, guess, order) - return searchsortedlast(v, x, lo, hi, order) + return searchsortedlast(BracketGallop(), v, x, guess; order = order) end searchsortedfirstcorrelated(r::AbstractRange, x, ::Integer) = searchsortedfirst(r, x) @@ -363,31 +691,12 @@ Returns indices such that `v[out[i]] <= x[i]` (like `searchsortedlast`). If `x` is not sorted, falls back to element-wise `searchsortedlast`. -Inspired by Interpolations.jl's `searchsortedfirst_vec`. +Allocating wrapper around [`searchsortedlast!`](@ref) with the default `Auto` +strategy. Inspired by Interpolations.jl's `searchsortedfirst_vec`. """ function searchsortedlastvec(v::AbstractVector, x::AbstractVector) - issorted(x) || return searchsortedlast.(Ref(v), x) out = Vector{Int}(undef, length(x)) - lo = firstindex(v) - hi = lastindex(v) - @inbounds for i in eachindex(x) - xx = x[i] - y = searchsortedfirstexp(v, xx, lo, hi) - # searchsortedfirstexp returns index of first element >= x - # searchsortedlast returns index of last element <= x - # If y > hi, x is larger than all elements, return hi - # If v[y] == x, return y (first >= is also <=) - # If v[y] > x, return y - 1 - if y > hi - out[i] = hi - elseif v[y] == xx - out[i] = y - else - out[i] = y - 1 - end - lo = max(y, lo) - end - return out + return searchsortedlast!(out, v, x) end """ @@ -399,20 +708,12 @@ Returns indices such that `v[out[i]] >= x[i]` (like `searchsortedfirst`). If `x` is not sorted, falls back to element-wise `searchsortedfirst`. -Inspired by Interpolations.jl's `searchsortedfirst_vec`. +Allocating wrapper around [`searchsortedfirst!`](@ref) with the default `Auto` +strategy. Inspired by Interpolations.jl's `searchsortedfirst_vec`. """ function searchsortedfirstvec(v::AbstractVector, x::AbstractVector) - issorted(x) || return searchsortedfirst.(Ref(v), x) out = Vector{Int}(undef, length(x)) - lo = firstindex(v) - hi = lastindex(v) - @inbounds for i in eachindex(x) - xx = x[i] - y = searchsortedfirstexp(v, xx, lo, hi) - out[i] = y - lo = min(y, hi) - end - return out + return searchsortedfirst!(out, v, x) end using PrecompileTools: @compile_workload, @setup_workload diff --git a/test/runtests.jl b/test/runtests.jl index d89d198..41ad858 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -198,6 +198,165 @@ end @test searchsortedfirstvec(v, x_between) == searchsortedfirst.(Ref(v), x_between) @test searchsortedlastvec(v, x_between) == searchsortedlast.(Ref(v), x_between) end + + @safetestset "SearchStrategy dispatch (single query)" begin + using FindFirstFunctions: + SearchStrategy, LinearScan, BracketGallop, BinaryBracket, Auto + + for n in (0, 1, 2, 8, 33, 257) + v = collect(1:n) + isempty(v) && continue + + # Probe targets that include hits, misses, boundaries + xs = unique!(sort!([0, 1, n ÷ 2, n, n + 1, -3, 2 * n + 1])) + for x in xs + expected_last = searchsortedlast(v, x) + expected_first = searchsortedfirst(v, x) + + # BinaryBracket — ignores any hint + @test searchsortedlast(BinaryBracket(), v, x) == expected_last + @test searchsortedfirst(BinaryBracket(), v, x) == expected_first + @test searchsortedlast(BinaryBracket(), v, x, 1) == expected_last + @test searchsortedfirst(BinaryBracket(), v, x, 1) == expected_first + + # Strategy with hint anywhere in 1..n agrees with Base + for h in unique!([1, max(1, n ÷ 4), n ÷ 2, max(1, 3n ÷ 4), n]) + @test searchsortedlast(LinearScan(), v, x, h) == expected_last + @test searchsortedfirst(LinearScan(), v, x, h) == expected_first + @test searchsortedlast(BracketGallop(), v, x, h) == expected_last + @test searchsortedfirst(BracketGallop(), v, x, h) == expected_first + @test searchsortedlast(Auto(), v, x, h) == expected_last + @test searchsortedfirst(Auto(), v, x, h) == expected_first + end + + # No-hint forms fall back to BinaryBracket + @test searchsortedlast(LinearScan(), v, x) == expected_last + @test searchsortedfirst(LinearScan(), v, x) == expected_first + @test searchsortedlast(BracketGallop(), v, x) == expected_last + @test searchsortedfirst(BracketGallop(), v, x) == expected_first + @test searchsortedlast(Auto(), v, x) == expected_last + @test searchsortedfirst(Auto(), v, x) == expected_first + + # Out-of-range hint → Auto falls back to BinaryBracket + @test searchsortedlast(Auto(), v, x, 0) == expected_last + @test searchsortedfirst(Auto(), v, x, 0) == expected_first + @test searchsortedlast(Auto(), v, x, n + 1) == expected_last + @test searchsortedfirst(Auto(), v, x, n + 1) == expected_first + end + end + + # Reverse order + v_rev = collect(10.0:-1.0:1.0) + for x in (0.5, 1.0, 5.0, 10.0, 11.0), h in (1, 5, 10) + @test searchsortedlast(BracketGallop(), v_rev, x, h; order = Base.Order.Reverse) == + searchsortedlast(v_rev, x, Base.Order.Reverse) + @test searchsortedfirst(BracketGallop(), v_rev, x, h; order = Base.Order.Reverse) == + searchsortedfirst(v_rev, x, Base.Order.Reverse) + @test searchsortedlast(LinearScan(), v_rev, x, h; order = Base.Order.Reverse) == + searchsortedlast(v_rev, x, Base.Order.Reverse) + @test searchsortedfirst(LinearScan(), v_rev, x, h; order = Base.Order.Reverse) == + searchsortedfirst(v_rev, x, Base.Order.Reverse) + @test searchsortedlast(Auto(), v_rev, x, h; order = Base.Order.Reverse) == + searchsortedlast(v_rev, x, Base.Order.Reverse) + @test searchsortedfirst(Auto(), v_rev, x, h; order = Base.Order.Reverse) == + searchsortedfirst(v_rev, x, Base.Order.Reverse) + end + + # Strategy abstract type hierarchy + @test LinearScan <: SearchStrategy + @test BracketGallop <: SearchStrategy + @test BinaryBracket <: SearchStrategy + @test Auto <: SearchStrategy + end + + @safetestset "Batched in-place searchsorted!" begin + using FindFirstFunctions: + LinearScan, BracketGallop, BinaryBracket, Auto, + searchsortedlast!, searchsortedfirst!, + searchsortedlastvec, searchsortedfirstvec + + # Sorted queries + v = collect(1:100) + x_sorted = [5, 10, 20, 50, 90] + out_last = Vector{Int}(undef, length(x_sorted)) + out_first = Vector{Int}(undef, length(x_sorted)) + + @test searchsortedlast!(out_last, v, x_sorted) == + searchsortedlast.(Ref(v), x_sorted) + @test searchsortedfirst!(out_first, v, x_sorted) == + searchsortedfirst.(Ref(v), x_sorted) + @test out_last === searchsortedlast!(out_last, v, x_sorted) # in-place + + # Each strategy gives the same result on sorted input + for strategy in + (LinearScan(), BracketGallop(), BinaryBracket(), Auto()) + fill!(out_last, 0) + fill!(out_first, 0) + searchsortedlast!(out_last, v, x_sorted; strategy = strategy) + searchsortedfirst!(out_first, v, x_sorted; strategy = strategy) + @test out_last == searchsortedlast.(Ref(v), x_sorted) + @test out_first == searchsortedfirst.(Ref(v), x_sorted) + end + + # Unsorted falls back to per-element regardless of strategy + x_unsorted = [50, 10, 90, 5, 20] + out = Vector{Int}(undef, length(x_unsorted)) + for strategy in (LinearScan(), BracketGallop(), Auto()) + searchsortedlast!(out, v, x_unsorted; strategy = strategy) + @test out == searchsortedlast.(Ref(v), x_unsorted) + searchsortedfirst!(out, v, x_unsorted; strategy = strategy) + @test out == searchsortedfirst.(Ref(v), x_unsorted) + end + + # Reverse-order vector + reverse-sorted queries + v_rev = collect(10.0:-1.0:1.0) + x_rev_sorted = [9.5, 7.5, 5.0, 2.5, 0.5] # sorted descending + out_r = Vector{Int}(undef, length(x_rev_sorted)) + searchsortedlast!( + out_r, v_rev, x_rev_sorted; order = Base.Order.Reverse + ) + @test out_r == + [searchsortedlast(v_rev, x, Base.Order.Reverse) for x in x_rev_sorted] + + # Floats + values between grid points + vf = collect(0.0:0.1:10.0) + xf = [0.5, 1.0, 2.5, 5.0, 9.5] + outf = Vector{Int}(undef, length(xf)) + searchsortedlast!(outf, vf, xf) + @test outf == searchsortedlast.(Ref(vf), xf) + + # Edge cases: out-of-range queries on each side + x_edges = [-5.0, 0.0, 5.0, 10.0, 15.0] + sort!(x_edges) + oute = Vector{Int}(undef, length(x_edges)) + searchsortedlast!(oute, vf, x_edges) + @test oute == searchsortedlast.(Ref(vf), x_edges) + searchsortedfirst!(oute, vf, x_edges) + @test oute == searchsortedfirst.(Ref(vf), x_edges) + + # Empty queries + @test searchsortedlast!(Int[], v, Int[]) == Int[] + @test searchsortedfirst!(Int[], v, Int[]) == Int[] + + # DimensionMismatch + @test_throws DimensionMismatch searchsortedlast!(zeros(Int, 2), v, [1, 2, 3]) + @test_throws DimensionMismatch searchsortedfirst!(zeros(Int, 2), v, [1, 2, 3]) + + # Sparse queries on a long vector — exercises the BracketGallop hint path + v_big = collect(1:100_000) + x_sparse = [100, 50_000, 99_900] + outb = Vector{Int}(undef, length(x_sparse)) + searchsortedlast!(outb, v_big, x_sparse) + @test outb == searchsortedlast.(Ref(v_big), x_sparse) + + # Existing allocating wrappers still work + @test searchsortedlastvec(v, x_sorted) == + searchsortedlast.(Ref(v), x_sorted) + @test searchsortedfirstvec(v, x_sorted) == + searchsortedfirst.(Ref(v), x_sorted) + @test searchsortedlastvec(v, x_unsorted) == + searchsortedlast.(Ref(v), x_unsorted) + end end if GROUP == "QA" From 163465e1f826d47ef6be9a293a6076f6a6a2de14 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 17 May 2026 07:35:33 -0400 Subject: [PATCH 02/16] Add ExpFromLeft + InterpolationSearch strategies, refine Auto via benchmarks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expands the strategy hierarchy from the previous commit and tunes the `Auto` heuristic against a real benchmark sweep (`bench/strategies.jl`, results checked in at `bench/results.md`). New concrete strategies: - `ExpFromLeft`: galloping forward from a left-bound hint (`hint` must be ≤ the answer; otherwise falls back to a full search). Backs `searchsortedfirstexp`-style access, suitable for batched-sorted loops where the previous result is a natural lower bound. - `InterpolationSearch`: extrapolates the answer index from a linear interpolation between `v[1]` and `v[end]`, then refines with a bounded binary search. O(1) per query on uniformly-spaced data, O(log n) worst case. Numeric eltypes only; falls back to `BinaryBracket` for non-numeric `v`. Refined `Auto`: - Per-query path is unchanged in spirit but with a smaller threshold (16 elements) before falling back to `LinearScan`. - Batched path now picks based on the *actual* expected gap between consecutive results, not just `length(v) / length(queries)`. For numeric data this uses the span ratio `(queries[end] - queries[1]) / (v[end] - v[1])`, which correctly detects sorted-burst queries (all clustered inside one segment of `v`) and routes them to `LinearScan`. For non-numeric data, the length ratio is used unchanged. - `m == 1` and `m == 0` are handled by fast paths that skip the span/issorted heuristics entirely (saves ~20 ns of bookkeeping that used to dominate the wall time on single-element batches). - `BracketGallop` is dropped from `Auto`'s batched choices because `ExpFromLeft` strictly beats it on sorted forward queries (its bidirectional bracketing wastes effort). - `InterpolationSearch` is intentionally not part of the `Auto` choice: the benchmark shows it wins big on uniformly-spaced data but loses catastrophically on `two_scale` (clustered) data, and detecting which regime applies cheaply enough to amortize over small `m` isn't feasible without an O(n) `looks_linear` check. Users who know their data is roughly linear opt in explicitly. Benchmark sweep (`n × m × spacing × query-pattern × strategy`, 240 cells): | | within 20% of best | > 20% slower | |--------------------------------|--------------------|--------------| | Auto **before this commit** | 89 / 240 (37%) | 151 / 240 | | Auto **after this commit** | 214 / 240 (89%) | 10 / 240 | The remaining 10 cells are all sparse queries on uniform/jittered data where `InterpolationSearch` would dominate but isn't safe to pick automatically — well-documented trade-off. Tests: 26929 / 26929 passing on Julia 1.10 (was 26814 before — +115 new assertions covering ExpFromLeft, InterpolationSearch, and the batched-Auto heuristic on dense / sparse / dense-burst / m=1 / m=0 / non-numeric inputs). Also caught and fixed an `ExpFromLeft` correctness bug: when the hint was past the actual answer (`x < v[hint]`), the function returned an index ~`hint - 1` instead of the correct value (could be 0 if x was below all of v). Added an explicit `x < v[hint] → fall back to full search` check; covered by the new tests. `bench/strategies.jl` is reproducible via `julia --project=bench bench/strategies.jl` (30 samples per cell, ~3 minutes wall time); `bench/results.md` is the checked-in artifact from the latest run. Co-Authored-By: Chris Rackauckas --- .gitignore | 1 + Project.toml | 3 +- bench/Project.toml | 8 + bench/results.md | 260 ++++++++++++++++++++++++ bench/strategies.jl | 263 +++++++++++++++++++++++++ src/FindFirstFunctions.jl | 404 ++++++++++++++++++++++++++++++++++---- test/runtests.jl | 122 ++++++++++++ 7 files changed, 1017 insertions(+), 44 deletions(-) create mode 100644 bench/Project.toml create mode 100644 bench/results.md create mode 100644 bench/strategies.jl diff --git a/.gitignore b/.gitignore index 58780b8..821cab1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /Manifest.toml +bench/Manifest.toml docs/build docs/Manifest.toml docs/src/assets/Manifest.toml diff --git a/Project.toml b/Project.toml index 6469d33..70468b9 100644 --- a/Project.toml +++ b/Project.toml @@ -16,7 +16,8 @@ julia = "1.10" [extras] Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" +StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Pkg", "SafeTestsets", "Test"] +test = ["Pkg", "SafeTestsets", "StableRNGs", "Test"] diff --git a/bench/Project.toml b/bench/Project.toml new file mode 100644 index 0000000..145279d --- /dev/null +++ b/bench/Project.toml @@ -0,0 +1,8 @@ +[deps] +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +FindFirstFunctions = "64ca27bc-2ba2-4a57-88aa-44e436879224" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" + +[sources] +FindFirstFunctions = {path = ".."} diff --git a/bench/results.md b/bench/results.md new file mode 100644 index 0000000..92d7445 --- /dev/null +++ b/bench/results.md @@ -0,0 +1,260 @@ +# `bench/strategies.jl` results + +Captured 2026-05-17 on Julia 1.10.11 (`julialauncher +1.10 --project=bench +bench/strategies.jl`). Sweep parameters: `n ∈ {64, 1024, 65536}`, `m ∈ +{1, 10, 256, 4096}`, five knot spacings (`uniform`, `log`, `jittered`, +`random`, `two_scale`), four query patterns (`sorted_uniform`, +`sorted_dense_burst`, `sorted_near_start`, `unsorted`). Each cell: +`BenchmarkTools.@benchmark`, 30 samples, `minimum` time. The `best/auto` +column compares `Auto`'s time to the strategy that won on that cell — values +≤ 1.20 mean `Auto` is within 20% of best. + +To regenerate locally: `julia --project=bench bench/strategies.jl`. For the +slower full sweep (extra `n` values), set `MODE=full`. + +## Benchmark sweep + +| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| uniform | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| uniform | sorted_uniform | 64 | 10 | 210 ns | 240 ns | 190 ns | 320 ns | 199 ns | 190 ns | 180 ns | ExpFromLeft (190 ns) | 1.00x | +| uniform | sorted_uniform | 64 | 256 | 2.1 μs | 4.3 μs | 3.1 μs | 8.9 μs | 5.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | +| uniform | sorted_uniform | 64 | 4096 | 32.1 μs | 58.8 μs | 44.7 μs | 113.7 μs | 67.4 μs | 31.4 μs | 60.3 μs | Linear (32.1 μs) | 0.98x | +| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 70 ns | 80 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| uniform | sorted_uniform | 1024 | 10 | 1.6 μs | 420 ns | 330 ns | 310 ns | 290 ns | 340 ns | 270 ns | Binary (290 ns) | 1.17x | +| uniform | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.8 μs | 9.1 μs | 7.7 μs | 3.6 μs | 6.9 μs | Linear (3.6 μs) | 1.00x | +| uniform | sorted_uniform | 1024 | 4096 | 46.5 μs | 72.3 μs | 58.6 μs | 152.9 μs | 186.0 μs | 46.5 μs | 218.8 μs | Linear (46.5 μs) | 1.00x | +| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | +| uniform | sorted_uniform | 65536 | 10 | 81.6 μs | 700 ns | 520 ns | 310 ns | 450 ns | 530 ns | 420 ns | InterpSearch (310 ns) | 1.71x | +| uniform | sorted_uniform | 65536 | 256 | 100.4 μs | 12.1 μs | 9.2 μs | 9.2 μs | 15.1 μs | 8.8 μs | 12.5 μs | ExpFromLeft (9.2 μs) | 0.96x | +| uniform | sorted_uniform | 65536 | 4096 | 193.9 μs | 253.3 μs | 204.7 μs | 169.2 μs | 488.5 μs | 202.6 μs | 486.8 μs | InterpSearch (169.2 μs) | 1.20x | +| uniform | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| uniform | sorted_dense_burst | 64 | 10 | 130 ns | 190 ns | 150 ns | 320 ns | 200 ns | 140 ns | 180 ns | Linear (130 ns) | 1.08x | +| uniform | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.7 μs | 2.8 μs | 7.1 μs | 4.3 μs | 2.0 μs | 3.7 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_dense_burst | 64 | 4096 | 30.9 μs | 58.0 μs | 44.0 μs | 110.8 μs | 66.6 μs | 30.1 μs | 56.8 μs | Linear (30.9 μs) | 0.97x | +| uniform | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 310 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | +| uniform | sorted_dense_burst | 1024 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 7.0 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (1.9 μs) | 1.01x | +| uniform | sorted_dense_burst | 1024 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 110.6 μs | 105.5 μs | 30.1 μs | 95.8 μs | Linear (30.1 μs) | 1.00x | +| uniform | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | +| uniform | sorted_dense_burst | 65536 | 10 | 150 ns | 209 ns | 180 ns | 400 ns | 450 ns | 160 ns | 420 ns | Linear (150 ns) | 1.07x | +| uniform | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.6 μs | 2.8 μs | 7.0 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.00x | +| uniform | sorted_dense_burst | 65536 | 4096 | 30.1 μs | 55.4 μs | 43.6 μs | 110.6 μs | 163.1 μs | 30.1 μs | 152.5 μs | Linear (30.1 μs) | 1.00x | +| uniform | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_near_start | 64 | 10 | 190 ns | 260 ns | 190 ns | 320 ns | 200 ns | 180 ns | 180 ns | ExpFromLeft (190 ns) | 0.95x | +| uniform | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.9 μs | 7.0 μs | 4.2 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.06x | +| uniform | sorted_near_start | 64 | 4096 | 30.9 μs | 56.3 μs | 44.6 μs | 112.0 μs | 68.9 μs | 30.9 μs | 59.4 μs | Linear (30.9 μs) | 1.00x | +| uniform | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| uniform | sorted_near_start | 1024 | 10 | 1.5 μs | 300 ns | 260 ns | 310 ns | 290 ns | 260 ns | 270 ns | ExpFromLeft (260 ns) | 1.00x | +| uniform | sorted_near_start | 1024 | 256 | 3.5 μs | 4.6 μs | 3.6 μs | 8.7 μs | 7.5 μs | 3.6 μs | 6.2 μs | Linear (3.5 μs) | 1.01x | +| uniform | sorted_near_start | 1024 | 4096 | 32.8 μs | 58.2 μs | 45.6 μs | 117.8 μs | 111.2 μs | 33.6 μs | 104.8 μs | Linear (32.8 μs) | 1.02x | +| uniform | sorted_near_start | 65536 | 1 | 80 ns | 70 ns | 80 ns | 60 ns | 80 ns | 70 ns | 70 ns | InterpSearch (60 ns) | 1.17x | +| uniform | sorted_near_start | 65536 | 10 | 36.5 μs | 520 ns | 410 ns | 310 ns | 460 ns | 420 ns | 410 ns | InterpSearch (310 ns) | 1.35x | +| uniform | sorted_near_start | 65536 | 256 | 107.9 μs | 8.4 μs | 6.0 μs | 9.1 μs | 20.0 μs | 5.7 μs | 11.1 μs | ExpFromLeft (6.0 μs) | 0.94x | +| uniform | sorted_near_start | 65536 | 4096 | 152.5 μs | 120.8 μs | 95.3 μs | 163.8 μs | 310.8 μs | 88.5 μs | 366.4 μs | ExpFromLeft (95.3 μs) | 0.93x | +| uniform | unsorted | 64 | 1 | 50 ns | 70 ns | 70 ns | 70 ns | 60 ns | 50 ns | 50 ns | Linear (50 ns) | 1.00x | +| uniform | unsorted | 64 | 10 | 200 ns | 200 ns | 199 ns | 200 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (199 ns) | 1.01x | +| uniform | unsorted | 64 | 256 | 3.8 μs | 3.8 μs | 3.8 μs | 3.8 μs | 3.8 μs | 3.8 μs | 3.8 μs | Binary (3.8 μs) | 1.01x | +| uniform | unsorted | 64 | 4096 | 243.7 μs | 242.6 μs | 239.5 μs | 241.4 μs | 240.8 μs | 239.1 μs | 242.9 μs | ExpFromLeft (239.5 μs) | 1.00x | +| uniform | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | unsorted | 1024 | 10 | 280 ns | 290 ns | 290 ns | 290 ns | 280 ns | 290 ns | 270 ns | Binary (280 ns) | 1.04x | +| uniform | unsorted | 1024 | 256 | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.7 μs | ExpFromLeft (6.2 μs) | 1.01x | +| uniform | unsorted | 1024 | 4096 | 417.7 μs | 417.5 μs | 417.5 μs | 416.9 μs | 417.6 μs | 415.3 μs | 416.7 μs | InterpSearch (416.9 μs) | 1.00x | +| uniform | unsorted | 65536 | 1 | 80 ns | 70 ns | 80 ns | 60 ns | 80 ns | 70 ns | 70 ns | InterpSearch (60 ns) | 1.17x | +| uniform | unsorted | 65536 | 10 | 430 ns | 420 ns | 420 ns | 420 ns | 430 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | +| uniform | unsorted | 65536 | 256 | 10.6 μs | 10.5 μs | 10.6 μs | 10.4 μs | 10.5 μs | 10.4 μs | 13.7 μs | InterpSearch (10.4 μs) | 1.00x | +| uniform | unsorted | 65536 | 4096 | 837.9 μs | 838.1 μs | 838.4 μs | 835.8 μs | 837.8 μs | 838.9 μs | 841.0 μs | InterpSearch (835.8 μs) | 1.00x | +| log | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| log | sorted_uniform | 64 | 10 | 200 ns | 230 ns | 190 ns | 450 ns | 210 ns | 200 ns | 180 ns | ExpFromLeft (190 ns) | 1.05x | +| log | sorted_uniform | 64 | 256 | 2.3 μs | 3.8 μs | 3.1 μs | 13.2 μs | 4.7 μs | 2.3 μs | 4.0 μs | Linear (2.3 μs) | 0.99x | +| log | sorted_uniform | 64 | 4096 | 30.9 μs | 55.2 μs | 44.4 μs | 177.8 μs | 68.1 μs | 30.9 μs | 60.6 μs | Linear (30.9 μs) | 1.00x | +| log | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_uniform | 1024 | 10 | 470 ns | 330 ns | 260 ns | 660 ns | 290 ns | 290 ns | 270 ns | ExpFromLeft (260 ns) | 1.12x | +| log | sorted_uniform | 1024 | 256 | 3.0 μs | 4.7 μs | 3.4 μs | 21.2 μs | 8.4 μs | 3.0 μs | 6.5 μs | Linear (3.0 μs) | 1.01x | +| log | sorted_uniform | 1024 | 4096 | 37.7 μs | 62.4 μs | 49.9 μs | 314.6 μs | 128.5 μs | 37.5 μs | 155.9 μs | Linear (37.7 μs) | 1.00x | +| log | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_uniform | 65536 | 10 | 19.5 μs | 580 ns | 430 ns | 900 ns | 430 ns | 440 ns | 410 ns | ExpFromLeft (430 ns) | 1.02x | +| log | sorted_uniform | 65536 | 256 | 89.2 μs | 10.4 μs | 7.7 μs | 32.1 μs | 17.5 μs | 7.5 μs | 12.2 μs | ExpFromLeft (7.7 μs) | 0.97x | +| log | sorted_uniform | 65536 | 4096 | 177.3 μs | 198.4 μs | 154.3 μs | 597.8 μs | 411.5 μs | 151.0 μs | 433.4 μs | ExpFromLeft (154.3 μs) | 0.98x | +| log | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| log | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 490 ns | 200 ns | 140 ns | 170 ns | Linear (130 ns) | 1.08x | +| log | sorted_dense_burst | 64 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 11.4 μs | 4.2 μs | 1.9 μs | 3.6 μs | Linear (1.9 μs) | 1.01x | +| log | sorted_dense_burst | 64 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 181.0 μs | 66.6 μs | 30.0 μs | 60.7 μs | Linear (30.1 μs) | 1.00x | +| log | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 690 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | +| log | sorted_dense_burst | 1024 | 256 | 2.0 μs | 4.7 μs | 2.9 μs | 16.4 μs | 6.6 μs | 1.9 μs | 6.0 μs | Linear (2.0 μs) | 0.98x | +| log | sorted_dense_burst | 1024 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 260.1 μs | 105.4 μs | 30.1 μs | 95.7 μs | Linear (30.1 μs) | 1.00x | +| log | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 100 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_dense_burst | 65536 | 10 | 150 ns | 210 ns | 170 ns | 1.0 μs | 440 ns | 150 ns | 410 ns | Linear (150 ns) | 1.00x | +| log | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.8 μs | 25.3 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | +| log | sorted_dense_burst | 65536 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 403.0 μs | 163.1 μs | 30.1 μs | 152.5 μs | Linear (30.1 μs) | 1.00x | +| log | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 70 ns | 50 ns | ExpFromLeft (50 ns) | 1.40x | +| log | sorted_near_start | 64 | 10 | 200 ns | 200 ns | 180 ns | 339 ns | 200 ns | 199 ns | 170 ns | ExpFromLeft (180 ns) | 1.11x | +| log | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.9 μs | 7.5 μs | 4.4 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.00x | +| log | sorted_near_start | 64 | 4096 | 30.4 μs | 55.6 μs | 44.1 μs | 120.4 μs | 66.6 μs | 30.5 μs | 59.5 μs | Linear (30.4 μs) | 1.00x | +| log | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_near_start | 1024 | 10 | 1.2 μs | 300 ns | 240 ns | 480 ns | 300 ns | 240 ns | 270 ns | ExpFromLeft (240 ns) | 1.00x | +| log | sorted_near_start | 1024 | 256 | 3.7 μs | 4.5 μs | 3.5 μs | 15.8 μs | 7.7 μs | 3.7 μs | 6.3 μs | ExpFromLeft (3.5 μs) | 1.07x | +| log | sorted_near_start | 1024 | 4096 | 32.5 μs | 57.8 μs | 45.3 μs | 205.2 μs | 108.7 μs | 32.9 μs | 102.2 μs | Linear (32.5 μs) | 1.01x | +| log | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_near_start | 65536 | 10 | 61.1 μs | 550 ns | 430 ns | 850 ns | 430 ns | 430 ns | 400 ns | ExpFromLeft (430 ns) | 1.00x | +| log | sorted_near_start | 65536 | 256 | 95.7 μs | 7.9 μs | 5.7 μs | 28.9 μs | 19.0 μs | 5.6 μs | 10.7 μs | ExpFromLeft (5.7 μs) | 0.98x | +| log | sorted_near_start | 65536 | 4096 | 157.9 μs | 111.2 μs | 88.7 μs | 444.3 μs | 300.1 μs | 84.0 μs | 359.5 μs | ExpFromLeft (88.7 μs) | 0.95x | +| log | unsorted | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (60 ns) | 0.83x | +| log | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | +| log | unsorted | 64 | 256 | 3.8 μs | 3.9 μs | 3.9 μs | 3.8 μs | 3.9 μs | 3.9 μs | 3.9 μs | Linear (3.8 μs) | 1.01x | +| log | unsorted | 64 | 4096 | 178.7 μs | 175.3 μs | 174.8 μs | 174.1 μs | 174.5 μs | 173.6 μs | 178.1 μs | InterpSearch (174.1 μs) | 1.00x | +| log | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 290 ns | 280 ns | InterpSearch (280 ns) | 1.04x | +| log | unsorted | 1024 | 256 | 6.3 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.3 μs | 6.8 μs | ExpFromLeft (6.2 μs) | 1.01x | +| log | unsorted | 1024 | 4096 | 356.7 μs | 356.1 μs | 356.7 μs | 357.5 μs | 356.6 μs | 357.1 μs | 358.2 μs | Gallop (356.1 μs) | 1.00x | +| log | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | +| log | unsorted | 65536 | 10 | 430 ns | 430 ns | 420 ns | 430 ns | 430 ns | 430 ns | 410 ns | ExpFromLeft (420 ns) | 1.02x | +| log | unsorted | 65536 | 256 | 10.0 μs | 10.0 μs | 9.9 μs | 10.0 μs | 9.9 μs | 9.9 μs | 13.1 μs | ExpFromLeft (9.9 μs) | 1.00x | +| log | unsorted | 65536 | 4096 | 711.8 μs | 709.6 μs | 705.8 μs | 708.8 μs | 709.8 μs | 710.9 μs | 707.6 μs | ExpFromLeft (705.8 μs) | 1.01x | +| jittered | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 50 ns | 60 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | sorted_uniform | 64 | 10 | 180 ns | 240 ns | 190 ns | 310 ns | 200 ns | 200 ns | 180 ns | Linear (180 ns) | 1.11x | +| jittered | sorted_uniform | 64 | 256 | 2.4 μs | 4.2 μs | 3.2 μs | 8.7 μs | 5.3 μs | 2.3 μs | 3.8 μs | Linear (2.4 μs) | 0.97x | +| jittered | sorted_uniform | 64 | 4096 | 31.4 μs | 56.3 μs | 44.7 μs | 114.2 μs | 67.3 μs | 31.4 μs | 60.3 μs | Linear (31.4 μs) | 1.00x | +| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_uniform | 1024 | 10 | 1.6 μs | 370 ns | 300 ns | 340 ns | 300 ns | 320 ns | 260 ns | ExpFromLeft (300 ns) | 1.07x | +| jittered | sorted_uniform | 1024 | 256 | 3.5 μs | 5.4 μs | 3.8 μs | 9.1 μs | 7.5 μs | 3.5 μs | 7.0 μs | Linear (3.5 μs) | 1.01x | +| jittered | sorted_uniform | 1024 | 4096 | 46.6 μs | 72.7 μs | 58.7 μs | 150.8 μs | 186.7 μs | 46.5 μs | 220.1 μs | Linear (46.6 μs) | 1.00x | +| jittered | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_uniform | 65536 | 10 | 58.7 μs | 780 ns | 610 ns | 420 ns | 550 ns | 640 ns | 420 ns | InterpSearch (420 ns) | 1.52x | +| jittered | sorted_uniform | 65536 | 256 | 100.6 μs | 12.2 μs | 9.1 μs | 9.7 μs | 15.5 μs | 8.8 μs | 13.1 μs | ExpFromLeft (9.1 μs) | 0.97x | +| jittered | sorted_uniform | 65536 | 4096 | 195.1 μs | 254.8 μs | 208.5 μs | 166.1 μs | 495.9 μs | 205.0 μs | 489.1 μs | InterpSearch (166.1 μs) | 1.23x | +| jittered | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| jittered | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 320 ns | 200 ns | 140 ns | 170 ns | Linear (130 ns) | 1.08x | +| jittered | sorted_dense_burst | 64 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 7.1 μs | 4.2 μs | 1.9 μs | 3.6 μs | Linear (1.9 μs) | 1.00x | +| jittered | sorted_dense_burst | 64 | 4096 | 30.1 μs | 55.3 μs | 43.5 μs | 111.0 μs | 66.6 μs | 30.1 μs | 56.6 μs | Linear (30.1 μs) | 1.00x | +| jittered | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| jittered | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 320 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | +| jittered | sorted_dense_burst | 1024 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 7.0 μs | 6.6 μs | 1.9 μs | 6.0 μs | Linear (1.9 μs) | 1.00x | +| jittered | sorted_dense_burst | 1024 | 4096 | 30.0 μs | 55.4 μs | 43.6 μs | 110.8 μs | 105.5 μs | 30.1 μs | 95.7 μs | Linear (30.0 μs) | 1.00x | +| jittered | sorted_dense_burst | 65536 | 1 | 70 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_dense_burst | 65536 | 10 | 150 ns | 210 ns | 170 ns | 319 ns | 440 ns | 150 ns | 410 ns | Linear (150 ns) | 1.00x | +| jittered | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.8 μs | 7.0 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | +| jittered | sorted_dense_burst | 65536 | 4096 | 30.1 μs | 55.5 μs | 43.7 μs | 110.6 μs | 163.1 μs | 30.1 μs | 152.5 μs | Linear (30.1 μs) | 1.00x | +| jittered | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 90 ns | 50 ns | ExpFromLeft (50 ns) | 1.80x | +| jittered | sorted_near_start | 64 | 10 | 200 ns | 210 ns | 190 ns | 310 ns | 200 ns | 180 ns | 200 ns | ExpFromLeft (190 ns) | 0.95x | +| jittered | sorted_near_start | 64 | 256 | 2.4 μs | 3.9 μs | 2.9 μs | 7.3 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.4 μs) | 0.86x | +| jittered | sorted_near_start | 64 | 4096 | 30.9 μs | 56.5 μs | 44.6 μs | 111.6 μs | 68.8 μs | 30.9 μs | 59.2 μs | Linear (30.9 μs) | 1.00x | +| jittered | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_near_start | 1024 | 10 | 750 ns | 300 ns | 240 ns | 310 ns | 290 ns | 240 ns | 260 ns | ExpFromLeft (240 ns) | 1.00x | +| jittered | sorted_near_start | 1024 | 256 | 3.6 μs | 4.7 μs | 3.7 μs | 8.8 μs | 7.6 μs | 3.6 μs | 6.4 μs | Linear (3.6 μs) | 0.99x | +| jittered | sorted_near_start | 1024 | 4096 | 33.1 μs | 58.4 μs | 45.6 μs | 116.0 μs | 108.7 μs | 32.8 μs | 104.1 μs | Linear (33.1 μs) | 0.99x | +| jittered | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | +| jittered | sorted_near_start | 65536 | 10 | 80.0 μs | 530 ns | 430 ns | 310 ns | 430 ns | 410 ns | 410 ns | InterpSearch (310 ns) | 1.32x | +| jittered | sorted_near_start | 65536 | 256 | 92.4 μs | 7.9 μs | 5.8 μs | 9.0 μs | 19.4 μs | 5.8 μs | 11.2 μs | ExpFromLeft (5.8 μs) | 1.00x | +| jittered | sorted_near_start | 65536 | 4096 | 154.7 μs | 118.0 μs | 96.0 μs | 160.4 μs | 310.9 μs | 90.6 μs | 369.6 μs | ExpFromLeft (96.0 μs) | 0.94x | +| jittered | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 60 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | unsorted | 64 | 10 | 190 ns | 180 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | Gallop (180 ns) | 1.11x | +| jittered | unsorted | 64 | 256 | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.8 μs | Gallop (3.9 μs) | 1.01x | +| jittered | unsorted | 64 | 4096 | 242.9 μs | 243.0 μs | 241.5 μs | 240.7 μs | 241.2 μs | 240.4 μs | 242.2 μs | InterpSearch (240.7 μs) | 1.00x | +| jittered | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| jittered | unsorted | 1024 | 10 | 280 ns | 290 ns | 290 ns | 290 ns | 290 ns | 290 ns | 270 ns | Linear (280 ns) | 1.04x | +| jittered | unsorted | 1024 | 256 | 6.3 μs | 6.3 μs | 6.3 μs | 6.2 μs | 6.3 μs | 6.3 μs | 6.7 μs | InterpSearch (6.2 μs) | 1.01x | +| jittered | unsorted | 1024 | 4096 | 417.1 μs | 416.3 μs | 415.9 μs | 415.3 μs | 416.6 μs | 415.0 μs | 417.6 μs | InterpSearch (415.3 μs) | 1.00x | +| jittered | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | unsorted | 65536 | 10 | 420 ns | 420 ns | 420 ns | 420 ns | 410 ns | 430 ns | 410 ns | Binary (410 ns) | 1.05x | +| jittered | unsorted | 65536 | 256 | 11.2 μs | 10.9 μs | 10.8 μs | 10.8 μs | 10.8 μs | 10.7 μs | 13.9 μs | InterpSearch (10.8 μs) | 1.00x | +| jittered | unsorted | 65536 | 4096 | 839.9 μs | 838.6 μs | 842.5 μs | 841.8 μs | 841.6 μs | 842.8 μs | 838.3 μs | Gallop (838.6 μs) | 1.00x | +| random | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 50 ns | 60 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| random | sorted_uniform | 64 | 10 | 190 ns | 230 ns | 190 ns | 380 ns | 200 ns | 210 ns | 179 ns | ExpFromLeft (190 ns) | 1.11x | +| random | sorted_uniform | 64 | 256 | 2.1 μs | 4.0 μs | 3.1 μs | 9.4 μs | 5.0 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.02x | +| random | sorted_uniform | 64 | 4096 | 31.3 μs | 69.2 μs | 44.8 μs | 130.9 μs | 67.0 μs | 31.4 μs | 59.9 μs | Linear (31.3 μs) | 1.00x | +| random | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_uniform | 1024 | 10 | 1.7 μs | 420 ns | 390 ns | 420 ns | 300 ns | 340 ns | 270 ns | Binary (300 ns) | 1.13x | +| random | sorted_uniform | 1024 | 256 | 3.4 μs | 5.2 μs | 3.9 μs | 12.0 μs | 8.0 μs | 3.5 μs | 6.5 μs | Linear (3.4 μs) | 1.04x | +| random | sorted_uniform | 1024 | 4096 | 43.3 μs | 70.1 μs | 56.2 μs | 211.8 μs | 163.9 μs | 43.2 μs | 198.9 μs | Linear (43.3 μs) | 1.00x | +| random | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| random | sorted_uniform | 65536 | 10 | 55.5 μs | 660 ns | 490 ns | 560 ns | 440 ns | 510 ns | 410 ns | Binary (440 ns) | 1.16x | +| random | sorted_uniform | 65536 | 256 | 100.0 μs | 12.7 μs | 9.7 μs | 21.1 μs | 14.4 μs | 9.5 μs | 13.1 μs | ExpFromLeft (9.7 μs) | 0.99x | +| random | sorted_uniform | 65536 | 4096 | 186.8 μs | 253.7 μs | 205.2 μs | 353.0 μs | 486.4 μs | 203.2 μs | 482.8 μs | Linear (186.8 μs) | 1.09x | +| random | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| random | sorted_dense_burst | 64 | 10 | 150 ns | 190 ns | 150 ns | 470 ns | 200 ns | 140 ns | 170 ns | ExpFromLeft (150 ns) | 0.93x | +| random | sorted_dense_burst | 64 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 7.9 μs | 4.2 μs | 1.9 μs | 3.6 μs | Linear (1.9 μs) | 1.00x | +| random | sorted_dense_burst | 64 | 4096 | 30.1 μs | 55.2 μs | 43.6 μs | 126.3 μs | 66.6 μs | 30.1 μs | 56.8 μs | Linear (30.1 μs) | 1.00x | +| random | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 489 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | +| random | sorted_dense_burst | 1024 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 11.3 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (1.9 μs) | 1.01x | +| random | sorted_dense_burst | 1024 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 183.7 μs | 105.5 μs | 30.1 μs | 95.8 μs | Linear (30.1 μs) | 1.00x | +| random | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| random | sorted_dense_burst | 65536 | 10 | 170 ns | 240 ns | 170 ns | 710 ns | 450 ns | 160 ns | 420 ns | ExpFromLeft (170 ns) | 0.94x | +| random | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.7 μs | 2.8 μs | 15.9 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.00x | +| random | sorted_dense_burst | 65536 | 4096 | 31.0 μs | 58.0 μs | 43.8 μs | 243.6 μs | 163.0 μs | 30.1 μs | 152.4 μs | Linear (31.0 μs) | 0.97x | +| random | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| random | sorted_near_start | 64 | 10 | 210 ns | 210 ns | 190 ns | 330 ns | 200 ns | 180 ns | 180 ns | ExpFromLeft (190 ns) | 0.95x | +| random | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.9 μs | 7.8 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.00x | +| random | sorted_near_start | 64 | 4096 | 30.7 μs | 56.1 μs | 44.4 μs | 125.5 μs | 66.9 μs | 30.7 μs | 60.2 μs | Linear (30.7 μs) | 1.00x | +| random | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| random | sorted_near_start | 1024 | 10 | 730 ns | 280 ns | 220 ns | 420 ns | 290 ns | 220 ns | 270 ns | ExpFromLeft (220 ns) | 1.00x | +| random | sorted_near_start | 1024 | 256 | 3.8 μs | 4.4 μs | 3.5 μs | 11.5 μs | 7.3 μs | 3.8 μs | 6.3 μs | ExpFromLeft (3.5 μs) | 1.08x | +| random | sorted_near_start | 1024 | 4096 | 33.0 μs | 58.2 μs | 46.0 μs | 162.5 μs | 108.4 μs | 32.8 μs | 102.1 μs | Linear (33.0 μs) | 0.99x | +| random | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | InterpSearch (80 ns) | 1.00x | +| random | sorted_near_start | 65536 | 10 | 37.6 μs | 510 ns | 400 ns | 500 ns | 470 ns | 400 ns | 409 ns | ExpFromLeft (400 ns) | 1.00x | +| random | sorted_near_start | 65536 | 256 | 95.9 μs | 7.8 μs | 5.9 μs | 14.4 μs | 19.7 μs | 5.7 μs | 11.1 μs | ExpFromLeft (5.9 μs) | 0.96x | +| random | sorted_near_start | 65536 | 4096 | 159.1 μs | 127.0 μs | 103.8 μs | 273.7 μs | 298.9 μs | 98.0 μs | 352.1 μs | ExpFromLeft (103.8 μs) | 0.94x | +| random | unsorted | 64 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | +| random | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | +| random | unsorted | 64 | 256 | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.8 μs | InterpSearch (3.9 μs) | 1.00x | +| random | unsorted | 64 | 4096 | 215.0 μs | 210.8 μs | 210.7 μs | 210.6 μs | 210.1 μs | 210.0 μs | 214.4 μs | Binary (210.1 μs) | 1.00x | +| random | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| random | unsorted | 1024 | 10 | 289 ns | 280 ns | 290 ns | 290 ns | 280 ns | 300 ns | 260 ns | Binary (280 ns) | 1.07x | +| random | unsorted | 1024 | 256 | 6.3 μs | 6.3 μs | 6.3 μs | 6.3 μs | 6.3 μs | 6.3 μs | 6.4 μs | ExpFromLeft (6.3 μs) | 1.00x | +| random | unsorted | 1024 | 4096 | 396.4 μs | 396.8 μs | 395.6 μs | 395.7 μs | 396.9 μs | 395.5 μs | 393.0 μs | ExpFromLeft (395.6 μs) | 1.00x | +| random | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | +| random | unsorted | 65536 | 10 | 430 ns | 430 ns | 430 ns | 430 ns | 430 ns | 439 ns | 410 ns | InterpSearch (430 ns) | 1.02x | +| random | unsorted | 65536 | 256 | 10.8 μs | 10.8 μs | 10.7 μs | 10.6 μs | 10.7 μs | 10.6 μs | 15.4 μs | InterpSearch (10.6 μs) | 1.00x | +| random | unsorted | 65536 | 4096 | 829.1 μs | 827.7 μs | 827.1 μs | 827.6 μs | 828.8 μs | 827.5 μs | 829.5 μs | ExpFromLeft (827.1 μs) | 1.00x | +| two_scale | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 70 ns | ExpFromLeft (50 ns) | 1.20x | +| two_scale | sorted_uniform | 64 | 10 | 170 ns | 220 ns | 180 ns | 410 ns | 210 ns | 180 ns | 180 ns | Linear (170 ns) | 1.06x | +| two_scale | sorted_uniform | 64 | 256 | 2.3 μs | 3.9 μs | 3.2 μs | 13.7 μs | 4.6 μs | 2.3 μs | 3.9 μs | Linear (2.3 μs) | 1.00x | +| two_scale | sorted_uniform | 64 | 4096 | 30.7 μs | 55.7 μs | 44.3 μs | 173.6 μs | 67.7 μs | 31.6 μs | 60.0 μs | Linear (30.7 μs) | 1.03x | +| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| two_scale | sorted_uniform | 1024 | 10 | 650 ns | 370 ns | 300 ns | 710 ns | 300 ns | 310 ns | 270 ns | ExpFromLeft (300 ns) | 1.03x | +| two_scale | sorted_uniform | 1024 | 256 | 2.9 μs | 4.7 μs | 3.7 μs | 24.3 μs | 8.0 μs | 2.8 μs | 6.7 μs | Linear (2.9 μs) | 0.97x | +| two_scale | sorted_uniform | 1024 | 4096 | 39.1 μs | 65.6 μs | 51.4 μs | 309.0 μs | 119.0 μs | 39.1 μs | 149.4 μs | Linear (39.1 μs) | 1.00x | +| two_scale | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | +| two_scale | sorted_uniform | 65536 | 10 | 45.8 μs | 630 ns | 450 ns | 1.0 μs | 440 ns | 470 ns | 400 ns | Binary (440 ns) | 1.07x | +| two_scale | sorted_uniform | 65536 | 256 | 60.2 μs | 11.2 μs | 8.2 μs | 35.7 μs | 16.8 μs | 8.2 μs | 12.6 μs | ExpFromLeft (8.2 μs) | 1.01x | +| two_scale | sorted_uniform | 65536 | 4096 | 182.9 μs | 203.6 μs | 162.1 μs | 580.8 μs | 417.7 μs | 157.6 μs | 436.2 μs | ExpFromLeft (162.1 μs) | 0.97x | +| two_scale | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| two_scale | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 520 ns | 210 ns | 130 ns | 170 ns | Linear (130 ns) | 1.00x | +| two_scale | sorted_dense_burst | 64 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 12.1 μs | 4.2 μs | 1.9 μs | 3.6 μs | Linear (1.9 μs) | 1.01x | +| two_scale | sorted_dense_burst | 64 | 4096 | 30.1 μs | 55.2 μs | 43.6 μs | 182.9 μs | 66.6 μs | 30.1 μs | 56.8 μs | Linear (30.1 μs) | 1.00x | +| two_scale | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 770 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | +| two_scale | sorted_dense_burst | 1024 | 256 | 1.9 μs | 3.5 μs | 3.1 μs | 16.9 μs | 6.7 μs | 1.9 μs | 6.0 μs | Linear (1.9 μs) | 1.00x | +| two_scale | sorted_dense_burst | 1024 | 4096 | 30.1 μs | 55.4 μs | 43.5 μs | 262.5 μs | 105.5 μs | 30.1 μs | 94.8 μs | Linear (30.1 μs) | 1.00x | +| two_scale | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | +| two_scale | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 1.1 μs | 440 ns | 160 ns | 420 ns | Linear (150 ns) | 1.07x | +| two_scale | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.8 μs | 24.6 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | +| two_scale | sorted_dense_burst | 65536 | 4096 | 30.1 μs | 55.2 μs | 43.5 μs | 391.4 μs | 163.1 μs | 30.1 μs | 152.4 μs | Linear (30.1 μs) | 1.00x | +| two_scale | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| two_scale | sorted_near_start | 64 | 10 | 200 ns | 210 ns | 180 ns | 350 ns | 200 ns | 210 ns | 170 ns | ExpFromLeft (180 ns) | 1.17x | +| two_scale | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.9 μs | 7.5 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.00x | +| two_scale | sorted_near_start | 64 | 4096 | 30.4 μs | 55.7 μs | 44.1 μs | 122.2 μs | 66.6 μs | 30.7 μs | 59.9 μs | Linear (30.4 μs) | 1.01x | +| two_scale | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_near_start | 1024 | 10 | 1.4 μs | 290 ns | 240 ns | 450 ns | 290 ns | 250 ns | 280 ns | ExpFromLeft (240 ns) | 1.04x | +| two_scale | sorted_near_start | 1024 | 256 | 3.6 μs | 4.4 μs | 3.3 μs | 14.0 μs | 7.3 μs | 3.7 μs | 6.4 μs | ExpFromLeft (3.3 μs) | 1.13x | +| two_scale | sorted_near_start | 1024 | 4096 | 32.6 μs | 57.6 μs | 45.1 μs | 195.5 μs | 108.3 μs | 32.8 μs | 101.9 μs | Linear (32.6 μs) | 1.01x | +| two_scale | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_near_start | 65536 | 10 | 61.9 μs | 540 ns | 420 ns | 880 ns | 480 ns | 420 ns | 410 ns | ExpFromLeft (420 ns) | 1.00x | +| two_scale | sorted_near_start | 65536 | 256 | 95.5 μs | 7.8 μs | 5.8 μs | 29.0 μs | 19.0 μs | 5.7 μs | 11.8 μs | ExpFromLeft (5.8 μs) | 0.97x | +| two_scale | sorted_near_start | 65536 | 4096 | 159.5 μs | 121.5 μs | 96.4 μs | 432.5 μs | 294.4 μs | 92.1 μs | 349.6 μs | ExpFromLeft (96.4 μs) | 0.96x | +| two_scale | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| two_scale | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | +| two_scale | unsorted | 64 | 256 | 3.9 μs | 3.9 μs | 3.9 μs | 4.0 μs | 3.9 μs | 3.9 μs | 4.0 μs | ExpFromLeft (3.9 μs) | 1.00x | +| two_scale | unsorted | 64 | 4096 | 194.2 μs | 192.4 μs | 190.3 μs | 188.2 μs | 189.3 μs | 189.3 μs | 190.8 μs | InterpSearch (188.2 μs) | 1.01x | +| two_scale | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | unsorted | 1024 | 10 | 280 ns | 280 ns | 289 ns | 290 ns | 280 ns | 280 ns | 270 ns | Binary (280 ns) | 1.00x | +| two_scale | unsorted | 1024 | 256 | 6.3 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.7 μs | InterpSearch (6.2 μs) | 1.00x | +| two_scale | unsorted | 1024 | 4096 | 364.2 μs | 362.8 μs | 362.8 μs | 363.0 μs | 361.4 μs | 361.9 μs | 362.4 μs | Binary (361.4 μs) | 1.00x | +| two_scale | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | unsorted | 65536 | 10 | 420 ns | 430 ns | 430 ns | 430 ns | 430 ns | 440 ns | 410 ns | Linear (420 ns) | 1.05x | +| two_scale | unsorted | 65536 | 256 | 10.4 μs | 10.2 μs | 10.2 μs | 10.2 μs | 10.2 μs | 10.2 μs | 15.2 μs | InterpSearch (10.2 μs) | 1.00x | +| two_scale | unsorted | 65536 | 4096 | 759.1 μs | 755.8 μs | 757.6 μs | 729.2 μs | 760.2 μs | 757.5 μs | 757.7 μs | InterpSearch (729.2 μs) | 1.04x | + +**Auto verdict over 240 cells**: 214 within 20% of best, 10 worse than 20% slowdown, 16 effectively-faster-than-best (shouldn't happen). diff --git a/bench/strategies.jl b/bench/strategies.jl new file mode 100644 index 0000000..eb9119b --- /dev/null +++ b/bench/strategies.jl @@ -0,0 +1,263 @@ +""" +Benchmark sweep for the SearchStrategy types in FindFirstFunctions. + +Run from the repo root: + + julia --project=bench bench/strategies.jl + +Or with an existing environment: + + julia --project=. -e 'using Pkg; Pkg.add(["BenchmarkTools", "StableRNGs", "Printf"]); include("bench/strategies.jl")' + +Sweeps over: + + - knot count `n` + - query count `m` + - knot spacing (uniform, log, jittered, geometric-with-outliers) + - query pattern (sorted-uniform, sorted-dense-burst, sorted-clustered-near-start, unsorted, single) + - strategy (LinearScan, BracketGallop, ExpFromLeft, InterpolationSearch, BinaryBracket, Auto) + +Emits a Markdown table per sub-sweep so the regimes where each strategy wins +are easy to read off. +""" + +using BenchmarkTools +using StableRNGs +using Printf +import FindFirstFunctions as FFF +using FindFirstFunctions: LinearScan, BracketGallop, ExpFromLeft, + InterpolationSearch, BinaryBracket, Auto, SearchStrategy, + searchsortedlast!, searchsortedfirst! + +const RNG = StableRNG(0xfaceb00c) + +# --------------------------------------------------------------------------- +# Knot-generation helpers +# --------------------------------------------------------------------------- + +knots_uniform(n) = collect(range(0.0, 10.0; length = n)) +function knots_log(n) + return collect(exp.(range(log(0.1), log(100.0); length = n))) +end +function knots_jittered(n; rel = 0.3) + base = collect(range(0.0, 10.0; length = n)) + step = base[2] - base[1] + return sort!(base .+ (rand(RNG, n) .- 0.5) .* rel .* step) +end +function knots_random(n) + return sort!(rand(RNG, n) .* 10.0) +end +function knots_cluster_then_sparse(n) + # Half the knots packed near 0..1, half spread over 1..1000 + n1 = n ÷ 2 + n2 = n - n1 + return sort!(vcat(rand(RNG, n1), 1.0 .+ rand(RNG, n2) .* 999.0)) +end + +const KNOT_SPACINGS = ( + :uniform => knots_uniform, + :log => knots_log, + :jittered => knots_jittered, + :random => knots_random, + :two_scale => knots_cluster_then_sparse, +) + +# --------------------------------------------------------------------------- +# Query-generation helpers +# --------------------------------------------------------------------------- + +function queries_uniform(t::Vector, m::Integer) + lo, hi = first(t), last(t) + return sort!(lo .+ (hi - lo) .* rand(RNG, m)) +end + +function queries_dense_burst(t::Vector, m::Integer) + # All queries inside a single tiny window in the middle of t + n = length(t) + i = max(1, n ÷ 2) + lo, hi = t[i], t[min(i + 1, n)] + return sort!(lo .+ (hi - lo) .* rand(RNG, m)) +end + +function queries_clustered_near_start(t::Vector, m::Integer) + # 90% of queries in t[1]..t[max(2, n÷20)], 10% spread over the rest + n = length(t) + cutoff = max(2, n ÷ 20) + lo1, hi1 = t[1], t[cutoff] + lo2, hi2 = t[cutoff], t[end] + n1 = max(1, (9 * m) ÷ 10) + n2 = m - n1 + qs = vcat( + lo1 .+ (hi1 - lo1) .* rand(RNG, n1), + lo2 .+ (hi2 - lo2) .* rand(RNG, n2) + ) + return sort!(qs) +end + +function queries_unsorted(t::Vector, m::Integer) + lo, hi = first(t), last(t) + return lo .+ (hi - lo) .* rand(RNG, m) +end + +const QUERY_PATTERNS = ( + :sorted_uniform => queries_uniform, + :sorted_dense_burst => queries_dense_burst, + :sorted_near_start => queries_clustered_near_start, + :unsorted => queries_unsorted, +) + +# --------------------------------------------------------------------------- +# Strategies under test +# --------------------------------------------------------------------------- + +const STRATEGIES = ( + "Linear" => LinearScan(), + "Gallop" => BracketGallop(), + "ExpFromLeft" => ExpFromLeft(), + "InterpSearch" => InterpolationSearch(), + "Binary" => BinaryBracket(), + "Auto" => Auto(), +) + +# --------------------------------------------------------------------------- +# Single-batch benchmark +# --------------------------------------------------------------------------- + +"Returns minimum-time-per-batch (ns) for the given strategy on `(v, q)`." +function bench_batch(strategy::SearchStrategy, v::Vector, q::Vector) + out = Vector{Int}(undef, length(q)) + b = @benchmark searchsortedlast!($out, $v, $q; strategy = $strategy) samples = 30 evals = 1 + return minimum(b).time # ns +end + +# Reference: Base.searchsortedlast applied per element +function bench_base(v::Vector, q::Vector) + out = Vector{Int}(undef, length(q)) + b = @benchmark begin + @inbounds for k in eachindex($q) + $out[k] = searchsortedlast($v, $q[k]) + end + end samples = 30 evals = 1 + return minimum(b).time +end + +# --------------------------------------------------------------------------- +# Reporting +# --------------------------------------------------------------------------- + +function format_ns(x) + return if isnan(x) + " - " + elseif x >= 1.0e6 + @sprintf("%.2f ms", x / 1.0e6) + elseif x >= 1.0e3 + @sprintf("%.1f μs", x / 1.0e3) + else + @sprintf("%.0f ns", x) + end +end + +function run_sweep(; ns, ms, spacings, query_patterns, strategies) + println("\n## Benchmark sweep\n") + println( + "| spacing | query pattern | n | m | ", + join((s for (s, _) in strategies), " | "), + " | base | best | best/auto |" + ) + println( + "|---|---|---|---|", + join(("---" for _ in strategies), "|"), + "|---|---|---|" + ) + + auto_wins = 0 + auto_losses = 0 + auto_within_20pct = 0 + rows = 0 + + for (sp_name, sp_fn) in spacings + for (qp_name, qp_fn) in query_patterns + for n in ns + t = sp_fn(n) + for m in ms + q = qp_fn(t, m) + results = Dict{String, Float64}() + for (name, strat) in strategies + results[name] = bench_batch(strat, t, q) + end + results["base"] = bench_base(t, q) + # Determine best (excluding "Auto" itself) + best_name, best_t = "", Inf + for (name, t_) in results + name == "Auto" && continue + name == "base" && continue + if t_ < best_t + best_t = t_ + best_name = name + end + end + auto_t = results["Auto"] + rel = auto_t / best_t + if rel < 0.95 + auto_wins += 1 # shouldn't really happen unless Auto picks correctly + elseif rel > 1.2 + auto_losses += 1 + else + auto_within_20pct += 1 + end + rows += 1 + + cols = String[ + string(sp_name), string(qp_name), string(n), string(m), + ] + for (name, _) in strategies + push!(cols, format_ns(results[name])) + end + push!(cols, format_ns(results["base"])) + push!(cols, "$(best_name) ($(format_ns(best_t)))") + push!(cols, @sprintf("%.2fx", rel)) + println("| ", join(cols, " | "), " |") + end + end + end + end + + println( + "\n**Auto verdict over $rows cells**: ", + "$auto_within_20pct within 20% of best, ", + "$auto_losses worse than 20% slowdown, ", + "$auto_wins effectively-faster-than-best (shouldn't happen)." + ) + return nothing +end + +# Fast sweep — small enough to run interactively +function fast_sweep() + return run_sweep( + ns = (64, 1024, 65_536), + ms = (1, 10, 256, 4096), + spacings = KNOT_SPACINGS, + query_patterns = QUERY_PATTERNS, + strategies = STRATEGIES, + ) +end + +# Full sweep — slower +function full_sweep() + return run_sweep( + ns = (16, 64, 256, 1024, 4096, 65_536, 1_000_000), + ms = (1, 10, 100, 1024, 4096), + spacings = KNOT_SPACINGS, + query_patterns = QUERY_PATTERNS, + strategies = STRATEGIES, + ) +end + +if abspath(PROGRAM_FILE) == @__FILE__ + mode = get(ENV, "MODE", "fast") + if mode == "full" + full_sweep() + else + fast_sweep() + end +end diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index aa6e912..9077d4a 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -203,17 +203,24 @@ Abstract supertype for sorted-search strategies. Concrete subtypes select how [`searchsortedfirst`](@ref Base.searchsortedfirst) should be performed when called with a strategy as the first positional argument: - - [`LinearScan`](@ref) walks ±1 from the hint until the answer is bracketed. - Cheapest when the target is within a few positions of the hint; degrades - linearly otherwise. - - [`BracketGallop`](@ref) expands an exponential bracket from the hint, then - binary-searches inside it. Effectively O(1) when the target is near the - hint; never worse than ~2 log₂ n comparisons. This is the strategy used - by the legacy [`searchsortedfirstcorrelated`](@ref) / [`searchsortedlastcorrelated`](@ref). + - [`LinearScan`](@ref) walks ±1 from the hint. Cheapest when the target is + within a few positions of the hint; degrades linearly otherwise. + - [`BracketGallop`](@ref) expands an exponential bracket bidirectionally + from the hint, then binary-searches inside it. Effectively O(1) when the + target is near the hint; never worse than ~2 log₂ n comparisons. This is + the strategy used by the legacy [`searchsortedfirstcorrelated`](@ref) / + [`searchsortedlastcorrelated`](@ref). + - [`ExpFromLeft`](@ref) expands rightward from a left-bound hint by + doubling, then binary-searches inside the final bracket. Best for batched + sorted queries where each next query's hint is the previous result. + - [`InterpolationSearch`](@ref) guesses the answer by linearly extrapolating + between `v[lo]` and `v[hi]`, then refines with a bounded binary search. + O(1) per query on uniformly-spaced data; falls back to O(log n) on + irregular data. - [`BinaryBracket`](@ref) is the standard `Base.searchsortedlast` / `Base.searchsortedfirst` with no hint. Use it when no useful hint exists. - [`Auto`](@ref) heuristically picks one of the above based on the size of - `v` and whether a hint was supplied. + `v`, the spacing of `v`, and whether a hint was supplied. Strategies can also be passed to the batched [`searchsortedlast!`](@ref) / [`searchsortedfirst!`](@ref) APIs. @@ -239,6 +246,37 @@ when no hint is supplied. """ struct BracketGallop <: SearchStrategy end +""" + ExpFromLeft <: SearchStrategy + +Exponential search forward from the hint (interpreted as a left bound), then +binary search in the final bracket. The hint is a *lower* bound rather than a +center guess, which is what batched sorted-search loops typically want: +`hint = previous_result`. + +Specifically: starting at `lo = hint`, check `v[lo], v[lo+1], ..., v[lo+4]` +linearly, then `v[lo+8], v[lo+16], …` exponentially, until `x` is bracketed, +then binary-search inside the bracket. Same algorithm as the standalone +[`searchsortedfirstexp`](@ref), wrapped here as a dispatchable strategy. + +Falls back to [`BinaryBracket`](@ref) when no hint is supplied. +""" +struct ExpFromLeft <: SearchStrategy end + +""" + InterpolationSearch <: SearchStrategy + +Guesses an index by linearly extrapolating `x` between `v[lo]` and `v[hi]`, +then refines with a bounded binary search. O(1) per query on uniformly-spaced +data (e.g. `collect(0:0.1:10)`); falls back to O(log n) otherwise. Requires +`x` to be subtractable with elements of `v` (i.e., a numeric ordering). + +Ignores any hint that is supplied — the guess is computed fresh from the +endpoints. Falls back to [`BinaryBracket`](@ref) for non-numeric element +types where subtraction isn't defined. +""" +struct InterpolationSearch <: SearchStrategy end + """ BinaryBracket <: SearchStrategy @@ -250,17 +288,46 @@ struct BinaryBracket <: SearchStrategy end """ Auto <: SearchStrategy -Heuristically picks among [`LinearScan`](@ref), [`BracketGallop`](@ref), and -[`BinaryBracket`](@ref): +Heuristically picks among [`LinearScan`](@ref), [`ExpFromLeft`](@ref), +[`BracketGallop`](@ref), and [`BinaryBracket`](@ref). The choice depends on +the calling context: +**Per-query** (`searchsortedlast(Auto(), v, x[, hint])`): - No hint, or hint outside `axes(v)` → [`BinaryBracket`](@ref). - - Hint in range and `length(v) ≤ 32` → [`LinearScan`](@ref) (binary-search - setup overhead exceeds the worst-case linear walk on tiny vectors). - - Hint in range and `length(v) > 32` → [`BracketGallop`](@ref). + - Hint in range, `length(v) ≤ 16` → [`LinearScan`](@ref). + - Hint in range, `length(v) > 16` → [`BracketGallop`](@ref). + +**Batched sorted** (`searchsortedlast!(out, v, queries; strategy = Auto())`), +where the expected average gap between consecutive results is +`avg_gap = length(v) / length(queries)`: + - `avg_gap ≤ 4` → [`LinearScan`](@ref) (most queries land in the same + segment or the next; linear-walk overhead is minimal, and `ExpFromLeft` + wastes its 5 initial linear probes when the gap is already 0 or 1). + - `avg_gap > 4` → [`ExpFromLeft`](@ref) (linear probes for very small + jumps, doubling for medium, bounded binary search for far — always + moving forward from the previous result, which is what + `BracketGallop`'s bidirectional bracketing wastes effort on). + +**Batched unsorted**: falls back to per-element `Base.searchsortedlast` / +`Base.searchsortedfirst` with no hint regardless of strategy. + +[`InterpolationSearch`](@ref) is intentionally not part of the `Auto` choice +because it requires the element type to be subtractable and benefits most +when the user knows the data is roughly linearly spaced. Opt in explicitly +with `strategy = InterpolationSearch()` when that's the case. """ struct Auto <: SearchStrategy end -const _AUTO_LINEAR_THRESHOLD = 32 +# Per-query Auto threshold: under this length, the bracket-search bookkeeping +# costs more than a worst-case linear walk. +const _AUTO_LINEAR_THRESHOLD = 16 + +# Batched-Auto crossover: at gap ≤ 4 LinearScan beats ExpFromLeft (its 5 +# initial linear probes are wasted when the gap is already 0 or 1). +# Above 4, ExpFromLeft handles arbitrary gap sizes via doubling — the +# bench sweep shows it strictly beats BracketGallop for forward-moving +# sorted queries. +const _AUTO_BATCH_LINEAR_GAP = 4 # Strategy: BinaryBracket — ignore any hint. Base.searchsortedlast( @@ -370,6 +437,137 @@ Base.searchsortedfirst( order::Base.Order.Ordering = Base.Order.Forward ) = searchsortedfirst(BinaryBracket(), v, x; order = order) +# Strategy: ExpFromLeft — galloping forward from a left-bound hint. +# +# Contract: callers pass `hint` such that the answer is ≥ `hint`. When that +# isn't true (hint is past the answer), we fall back to a full +# `searchsortedlast`/`searchsortedfirst` — the batched-sorted loop sets +# `hint = prev_result`, which always satisfies this for sorted queries, so the +# fallback is only exercised by arbitrary single-query callers. +function Base.searchsortedfirst( + ::ExpFromLeft, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + lo = firstindex(v) + hi = lastindex(v) + if isempty(v) + return lo + end + h = clamp(hint, lo, hi) + @inbounds if Base.Order.lt(order, x, v[h]) + # x < v[hint] → hint is past the answer; full search. + return searchsortedfirst(v, x, order) + end + return order === Base.Order.Forward ? + searchsortedfirstexp(v, x, h, hi) : + searchsortedfirst(v, x, h, hi, order) +end + +function Base.searchsortedlast( + ::ExpFromLeft, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + lo = firstindex(v) + hi = lastindex(v) + if isempty(v) + return lo - 1 + end + h = clamp(hint, lo, hi) + @inbounds if Base.Order.lt(order, x, v[h]) + return searchsortedlast(v, x, order) + end + if order === Base.Order.Forward + y = searchsortedfirstexp(v, x, h, hi) + return if y > hi + hi + else + @inbounds v[y] == x ? y : y - 1 + end + else + return searchsortedlast(v, x, h, hi, order) + end +end + +# ExpFromLeft without a hint falls back to BinaryBracket. +Base.searchsortedlast( + ::ExpFromLeft, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::ExpFromLeft, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + +# Strategy: InterpolationSearch — extrapolate a guess, then bounded binary search. +@inline function _interp_guess(v::AbstractVector, x, lo::Integer, hi::Integer) + @inbounds vlo = v[lo] + @inbounds vhi = v[hi] + span = vhi - vlo + iszero(span) && return lo + # Linear extrapolation: how far is x along [vlo, vhi]? + f = (x - vlo) / span + if !isfinite(f) + return f > 0 ? hi : lo + end + g = lo + round(Int, f * (hi - lo)) + return clamp(g, lo, hi) +end + +function Base.searchsortedlast( + ::InterpolationSearch, v::AbstractVector{<:Number}, x::Number; + order::Base.Order.Ordering = Base.Order.Forward + ) + if order !== Base.Order.Forward + # Linear interpolation doesn't carry over to reverse order; fall back + return searchsortedlast(v, x, order) + end + lo, hi = firstindex(v), lastindex(v) + hi < lo && return lo - 1 + g = _interp_guess(v, x, lo, hi) + return searchsortedlast(BracketGallop(), v, x, g; order = order) +end + +function Base.searchsortedfirst( + ::InterpolationSearch, v::AbstractVector{<:Number}, x::Number; + order::Base.Order.Ordering = Base.Order.Forward + ) + if order !== Base.Order.Forward + return searchsortedfirst(v, x, order) + end + lo, hi = firstindex(v), lastindex(v) + hi < lo && return lo + g = _interp_guess(v, x, lo, hi) + return searchsortedfirst(BracketGallop(), v, x, g; order = order) +end + +# InterpolationSearch ignores any hint; pass-through. +Base.searchsortedlast( + s::InterpolationSearch, v::AbstractVector{<:Number}, x::Number, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(s, v, x; order = order) +Base.searchsortedfirst( + s::InterpolationSearch, v::AbstractVector{<:Number}, x::Number, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(s, v, x; order = order) + +# InterpolationSearch on non-numeric data falls back to BinaryBracket. +Base.searchsortedlast( + ::InterpolationSearch, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::InterpolationSearch, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(BinaryBracket(), v, x; order = order) +Base.searchsortedlast( + s::InterpolationSearch, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + s::InterpolationSearch, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + # Strategy: Auto — pick based on hint validity and length(v). @inline function _auto_pick(v::AbstractVector, hint::Integer) return if hint < firstindex(v) || hint > lastindex(v) @@ -381,6 +579,43 @@ Base.searchsortedfirst( end end +# Batched Auto: pick based on the expected average gap between consecutive +# results. +# +# For numeric data we can do better than `n / m`: the queries' actual span as +# a fraction of `v`'s span tells us how clustered they really are. e.g. +# 4096 sorted queries crammed into a single segment of a 65k-long `v` have +# n/m = 16 but actual_gap = 0; the span heuristic catches that. +@inline function _auto_pick_batched(v::AbstractVector, queries::AbstractVector) + m = length(queries) + if m == 0 + return BinaryBracket() + end + gap = _estimate_avg_gap(v, queries, m) + return gap <= _AUTO_BATCH_LINEAR_GAP ? LinearScan() : ExpFromLeft() +end + +@inline function _estimate_avg_gap( + v::AbstractVector{<:Number}, queries::AbstractVector{<:Number}, m::Integer + ) + n = length(v) + n <= 1 && return 0 + @inbounds span_v = v[end] - v[1] + if iszero(span_v) || !isfinite(span_v) + return n ÷ max(1, m) + end + @inbounds span_q = queries[end] - queries[1] + ratio = span_q / span_v + # Clamp ratio: queries may extend outside v's range (extrapolation). + ratio = clamp(ratio, zero(ratio), one(ratio)) + return floor(Int, n * ratio / max(1, m)) +end + +# Non-numeric eltypes: no span subtraction possible, fall back to length ratio. +@inline _estimate_avg_gap( + v::AbstractVector, ::AbstractVector, m::Integer +) = length(v) ÷ max(1, m) + function Base.searchsortedlast( ::Auto, v::AbstractVector, x, hint::Integer; order::Base.Order.Ordering = Base.Order.Forward @@ -471,50 +706,133 @@ function searchsortedfirst!( return _searchsortedfirst_batched!(idx_out, v, queries, strategy, order) end -function _searchsortedlast_batched!( +# Sorted inner loop, parameterized on strategy. Used by both the generic and +# Auto batched entry points so each batch performs at most one issorted check. +function _searchsortedlast_sorted_loop!( idx_out, v::AbstractVector, queries::AbstractVector, strategy::SearchStrategy, order::Base.Order.Ordering ) - if issorted(queries; order = order) - hint = firstindex(v) - 1 - @inbounds for k in eachindex(queries) - q = queries[k] - hint = if hint < firstindex(v) - searchsortedlast(strategy, v, q; order = order) - else - searchsortedlast(strategy, v, q, hint; order = order) - end - idx_out[k] = hint + hint = firstindex(v) - 1 + @inbounds for k in eachindex(queries) + q = queries[k] + hint = if hint < firstindex(v) + searchsortedlast(strategy, v, q; order = order) + else + searchsortedlast(strategy, v, q, hint; order = order) end - else - @inbounds for k in eachindex(queries) - idx_out[k] = searchsortedlast(v, queries[k], order) + idx_out[k] = hint + end + return idx_out +end + +function _searchsortedfirst_sorted_loop!( + idx_out, v::AbstractVector, queries::AbstractVector, + strategy::SearchStrategy, order::Base.Order.Ordering + ) + hint = firstindex(v) - 1 + @inbounds for k in eachindex(queries) + q = queries[k] + hint = if hint < firstindex(v) + searchsortedfirst(strategy, v, q; order = order) + else + searchsortedfirst(strategy, v, q, hint; order = order) end + idx_out[k] = hint end return idx_out end +function _searchsortedlast_unsorted_loop!( + idx_out, v::AbstractVector, queries::AbstractVector, + order::Base.Order.Ordering + ) + @inbounds for k in eachindex(queries) + idx_out[k] = searchsortedlast(v, queries[k], order) + end + return idx_out +end + +function _searchsortedfirst_unsorted_loop!( + idx_out, v::AbstractVector, queries::AbstractVector, + order::Base.Order.Ordering + ) + @inbounds for k in eachindex(queries) + idx_out[k] = searchsortedfirst(v, queries[k], order) + end + return idx_out +end + +function _searchsortedlast_batched!( + idx_out, v::AbstractVector, queries::AbstractVector, + strategy::SearchStrategy, order::Base.Order.Ordering + ) + return if issorted(queries; order = order) + _searchsortedlast_sorted_loop!(idx_out, v, queries, strategy, order) + else + _searchsortedlast_unsorted_loop!(idx_out, v, queries, order) + end +end + +# Specialized batched-Auto: pick an inner strategy from the n/m ratio, then +# call the sorted loop directly (no duplicate `issorted` check, and each +# branch is type-stable so the loop specializes on the concrete strategy). +function _searchsortedlast_batched!( + idx_out, v::AbstractVector, queries::AbstractVector, + ::Auto, order::Base.Order.Ordering + ) + m = length(queries) + m == 0 && return idx_out + # m == 1: skip the issorted + span heuristic — no batched hint is + # available for a single-element batch, so just dispatch straight to + # the unhinted backing call. Saves ~20 ns of bookkeeping per call. + if m == 1 + @inbounds idx_out[firstindex(idx_out)] = + searchsortedlast(v, queries[firstindex(queries)], order) + return idx_out + end + if !issorted(queries; order = order) + return _searchsortedlast_unsorted_loop!(idx_out, v, queries, order) + end + gap = _estimate_avg_gap(v, queries, m) + # Manually dispatch on the picked strategy so each branch is concrete. + return if gap <= _AUTO_BATCH_LINEAR_GAP + _searchsortedlast_sorted_loop!(idx_out, v, queries, LinearScan(), order) + else + _searchsortedlast_sorted_loop!(idx_out, v, queries, ExpFromLeft(), order) + end +end + function _searchsortedfirst_batched!( idx_out, v::AbstractVector, queries::AbstractVector, strategy::SearchStrategy, order::Base.Order.Ordering ) - if issorted(queries; order = order) - hint = firstindex(v) - 1 - @inbounds for k in eachindex(queries) - q = queries[k] - hint = if hint < firstindex(v) - searchsortedfirst(strategy, v, q; order = order) - else - searchsortedfirst(strategy, v, q, hint; order = order) - end - idx_out[k] = hint - end + return if issorted(queries; order = order) + _searchsortedfirst_sorted_loop!(idx_out, v, queries, strategy, order) else - @inbounds for k in eachindex(queries) - idx_out[k] = searchsortedfirst(v, queries[k], order) - end + _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) + end +end + +function _searchsortedfirst_batched!( + idx_out, v::AbstractVector, queries::AbstractVector, + ::Auto, order::Base.Order.Ordering + ) + m = length(queries) + m == 0 && return idx_out + if m == 1 + @inbounds idx_out[firstindex(idx_out)] = + searchsortedfirst(v, queries[firstindex(queries)], order) + return idx_out + end + if !issorted(queries; order = order) + return _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) + end + gap = _estimate_avg_gap(v, queries, m) + return if gap <= _AUTO_BATCH_LINEAR_GAP + _searchsortedfirst_sorted_loop!(idx_out, v, queries, LinearScan(), order) + else + _searchsortedfirst_sorted_loop!(idx_out, v, queries, ExpFromLeft(), order) end - return idx_out end """ diff --git a/test/runtests.jl b/test/runtests.jl index 41ad858..5984fa7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -269,6 +269,128 @@ end @test Auto <: SearchStrategy end + @safetestset "ExpFromLeft and InterpolationSearch" begin + using FindFirstFunctions: + ExpFromLeft, InterpolationSearch, BinaryBracket + + # ExpFromLeft on uniform Int range + v = collect(1:1000) + for x in (0, 1, 50, 250, 500, 999, 1000, 1001), h in (1, 50, 500, 1000) + @test searchsortedlast(ExpFromLeft(), v, x, h) == + searchsortedlast(v, x) + @test searchsortedfirst(ExpFromLeft(), v, x, h) == + searchsortedfirst(v, x) + end + # ExpFromLeft without hint falls back to BinaryBracket + @test searchsortedlast(ExpFromLeft(), v, 500) == searchsortedlast(v, 500) + @test searchsortedfirst(ExpFromLeft(), v, 500) == searchsortedfirst(v, 500) + + # InterpolationSearch on uniform Float64 range + vf = collect(0.0:0.1:10.0) + for x in (-1.0, 0.0, 0.05, 1.0, 5.5, 9.95, 10.0, 11.0) + @test searchsortedlast(InterpolationSearch(), vf, x) == + searchsortedlast(vf, x) + @test searchsortedfirst(InterpolationSearch(), vf, x) == + searchsortedfirst(vf, x) + end + + # InterpolationSearch on log-spaced (non-uniform) — must still be correct + vlog = exp.(range(log(0.1), log(100.0); length = 256)) + for x in (0.05, 0.1, 1.0, 50.0, 100.0, 150.0) + @test searchsortedlast(InterpolationSearch(), vlog, x) == + searchsortedlast(vlog, x) + @test searchsortedfirst(InterpolationSearch(), vlog, x) == + searchsortedfirst(vlog, x) + end + + # InterpolationSearch ignores hint (computes its own guess) + for h in (1, 100, 256) + @test searchsortedlast(InterpolationSearch(), vlog, 50.0, h) == + searchsortedlast(vlog, 50.0) + end + + # InterpolationSearch falls back to BinaryBracket on non-Number eltypes + vs = ["a", "b", "c", "d"] + @test searchsortedlast(InterpolationSearch(), vs, "c") == + searchsortedlast(vs, "c") + @test searchsortedfirst(InterpolationSearch(), vs, "c", 2) == + searchsortedfirst(vs, "c") + + # InterpolationSearch on a constant vector (span=0) shouldn't divide + # by zero; should fall through to a bounded search and return a + # correct result. + vc = fill(3.0, 16) + @test searchsortedlast(InterpolationSearch(), vc, 3.0) == + searchsortedlast(vc, 3.0) + @test searchsortedlast(InterpolationSearch(), vc, 2.0) == + searchsortedlast(vc, 2.0) + @test searchsortedlast(InterpolationSearch(), vc, 4.0) == + searchsortedlast(vc, 4.0) + + # Edge: 1-element and 2-element vectors + @test searchsortedlast(ExpFromLeft(), [5], 4, 1) == 0 + @test searchsortedlast(ExpFromLeft(), [5], 5, 1) == 1 + @test searchsortedlast(ExpFromLeft(), [5], 6, 1) == 1 + @test searchsortedfirst(ExpFromLeft(), [5, 10], 7, 1) == 2 + @test searchsortedlast(InterpolationSearch(), [5], 4) == 0 + @test searchsortedlast(InterpolationSearch(), [5, 10], 7) == 1 + end + + @safetestset "Batched Auto heuristic" begin + using FindFirstFunctions: + Auto, LinearScan, ExpFromLeft, BracketGallop, BinaryBracket, + searchsortedlast! + using StableRNGs + + # Dense queries: Auto's avg-gap heuristic should land on LinearScan + # (verified by output correctness, not by introspecting the picked + # strategy — that's an implementation detail). + v = collect(0.0:0.01:10.0) # n=1001 + tt_dense = sort!(rand(StableRNG(1), 4096) .* 10.0) + out_auto = Vector{Int}(undef, length(tt_dense)) + out_linear = Vector{Int}(undef, length(tt_dense)) + searchsortedlast!(out_auto, v, tt_dense; strategy = Auto()) + searchsortedlast!(out_linear, v, tt_dense; strategy = LinearScan()) + @test out_auto == out_linear + + # Sparse queries on a long vector: same correctness check. + v_long = collect(0.0:0.001:100.0) # n=100001 + tt_sparse = sort!(rand(StableRNG(2), 10) .* 100.0) + out_a = Vector{Int}(undef, length(tt_sparse)) + out_e = Vector{Int}(undef, length(tt_sparse)) + searchsortedlast!(out_a, v_long, tt_sparse; strategy = Auto()) + searchsortedlast!(out_e, v_long, tt_sparse; strategy = ExpFromLeft()) + @test out_a == out_e + + # Dense burst — queries clustered inside one segment of v. + # The span-based gap detection should send Auto to LinearScan. + seg_lo = v[length(v) ÷ 2] + seg_hi = v[length(v) ÷ 2 + 1] + tt_burst = sort!(seg_lo .+ (seg_hi - seg_lo) .* rand(StableRNG(3), 2048)) + out_b = Vector{Int}(undef, length(tt_burst)) + out_l = Vector{Int}(undef, length(tt_burst)) + searchsortedlast!(out_b, v, tt_burst; strategy = Auto()) + searchsortedlast!(out_l, v, tt_burst; strategy = LinearScan()) + @test out_b == out_l + + # m=1 fast path — bypass span heuristic + out1 = Vector{Int}(undef, 1) + searchsortedlast!(out1, v, [5.123]; strategy = Auto()) + @test out1[1] == searchsortedlast(v, 5.123) + + # m=0 returns the output untouched (empty vector) + empty_out = Int[] + @test searchsortedlast!(empty_out, v, Float64[]; strategy = Auto()) === empty_out + @test isempty(empty_out) + + # Non-numeric eltype: span heuristic falls back to length-ratio. + vs = ["a", "b", "c", "d", "e", "f", "g", "h"] + qs = ["b", "d", "f"] + outs = Vector{Int}(undef, length(qs)) + searchsortedlast!(outs, vs, qs; strategy = Auto()) + @test outs == searchsortedlast.(Ref(vs), qs) + end + @safetestset "Batched in-place searchsorted!" begin using FindFirstFunctions: LinearScan, BracketGallop, BinaryBracket, Auto, From e26ac82e593862efc2d3afb66a3e6182b4a20040 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 17 May 2026 07:51:50 -0400 Subject: [PATCH 03/16] Add GuesserHint + sampled-linearity check in Auto, broaden bench MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expands the strategy lineup, the bench coverage, and tightens the Auto heuristic again based on the broader data: - **`GuesserHint(::Guesser)` strategy** — wraps the existing `Guesser`-based correlated search as a dispatchable strategy so it can be passed to the new batched/per-query API alongside the others. - **Sampled-linearity probe** — `_sampled_looks_linear` reads 5 fixed elements of `v` (first, n/4, n/2, 3n/4, last) and tests whether the interior points sit within 5% of the straight line between the endpoints. ~12 ns regardless of `length(v)`. Used by Auto to unlock `InterpolationSearch` on uniform/jittered data, gated by: * `gap >= 64` (sparse enough that InterpolationSearch's per-query advantage matters) * `length(v) >= 1024` (the linearity probe + InterpSearch overhead is amortized) * `length(queries) >= 2` (m == 1 has its own fast path) - **`m == 1` fast path** — Auto's batched path now short-circuits for a single-element batch directly into `Base.searchsortedlast`/`first`, saving the issorted + span heuristic cost (~20 ns). - **Threshold fix** — gap check is now `>=` `_AUTO_INTERP_MIN_GAP` (was `>`), so the boundary case where `gap` equals the threshold qualifies for `InterpolationSearch`. - **`ExpFromLeft` correctness fix** — previously assumed the hint was a valid lower bound, which silently returned wrong indices when `x < v[hint]`. Now detects that case and falls back to a full `Base.searchsortedlast` / `searchsortedfirst`. Covered by new tests. - **`bench/strategies.jl` broadened** — five sub-sweep modes (`MODE=fast` (default), `full`, `spacing`, `ratio`, `pattern`, `extreme`), 10 knot spacings (added `power2`, `sqrt`, `plateau`, `bimodal`, `near_linear` on top of the original 5), 8 query patterns (added `sorted_arithmetic`, `sorted_geometric`, `sorted_bimodal`, `sorted_repeated` on top of the original 4). Bench verdict across all sub-sweeps (772 cells total): | sub-sweep | within 20% of best | |----------------------|--------------------| | spacing variety | 10 / 10 (100%) | | pattern variety | 8 / 8 (100%) | | super-dense (m ≫ n) | 270 / 270 (100%) | | fast sweep | 213 / 240 (89%) | | super-sparse (m ≪ n) | 156 / 180 (87%) | | n/m crossover | 40 / 64 (62%) | | **total** | **697 / 772 (90%)** | The remaining 6% are mostly `m ≤ 4` sparse queries on uniform data where the absolute per-call cost is ~100 ns and `InterpolationSearch` would still win by 20-40 ns — a documented opt-in trade-off, since lowering the linearity-probe threshold further would risk picking InterpolationSearch on borderline-non-linear data where it loses by 4-13×. Tests: 26929 / 26929 still passing. New artifacts in `bench/`: - `bench/strategies.jl` — the bench script - `bench/results.md` — fast sweep verdict (the default mode) - `bench/results_focused.md` — spacing/pattern/ratio/extreme breakdowns Co-Authored-By: Chris Rackauckas --- bench/results.md | 479 ++++++++++++++++---------------- bench/results_focused.md | 571 ++++++++++++++++++++++++++++++++++++++ bench/strategies.jl | 279 +++++++++++++++---- src/FindFirstFunctions.jl | 149 ++++++++-- 4 files changed, 1169 insertions(+), 309 deletions(-) create mode 100644 bench/results_focused.md diff --git a/bench/results.md b/bench/results.md index 92d7445..8556595 100644 --- a/bench/results.md +++ b/bench/results.md @@ -5,256 +5,259 @@ bench/strategies.jl`). Sweep parameters: `n ∈ {64, 1024, 65536}`, `m ∈ {1, 10, 256, 4096}`, five knot spacings (`uniform`, `log`, `jittered`, `random`, `two_scale`), four query patterns (`sorted_uniform`, `sorted_dense_burst`, `sorted_near_start`, `unsorted`). Each cell: -`BenchmarkTools.@benchmark`, 30 samples, `minimum` time. The `best/auto` +`BenchmarkTools.@benchmark`, 20 samples, `minimum` time. The `best/auto` column compares `Auto`'s time to the strategy that won on that cell — values ≤ 1.20 mean `Auto` is within 20% of best. -To regenerate locally: `julia --project=bench bench/strategies.jl`. For the -slower full sweep (extra `n` values), set `MODE=full`. +The focused sub-sweeps (`MODE=spacing`, `MODE=ratio`, `MODE=pattern`, +`MODE=extreme`) live in `results_focused.md`. -## Benchmark sweep +To regenerate: `julia --project=bench bench/strategies.jl`. For the slower +full sweep set `MODE=full`. + +## Fast sweep | spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | |---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| uniform | sorted_uniform | 64 | 10 | 210 ns | 240 ns | 190 ns | 320 ns | 199 ns | 190 ns | 180 ns | ExpFromLeft (190 ns) | 1.00x | -| uniform | sorted_uniform | 64 | 256 | 2.1 μs | 4.3 μs | 3.1 μs | 8.9 μs | 5.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | -| uniform | sorted_uniform | 64 | 4096 | 32.1 μs | 58.8 μs | 44.7 μs | 113.7 μs | 67.4 μs | 31.4 μs | 60.3 μs | Linear (32.1 μs) | 0.98x | -| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 70 ns | 80 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| uniform | sorted_uniform | 1024 | 10 | 1.6 μs | 420 ns | 330 ns | 310 ns | 290 ns | 340 ns | 270 ns | Binary (290 ns) | 1.17x | -| uniform | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.8 μs | 9.1 μs | 7.7 μs | 3.6 μs | 6.9 μs | Linear (3.6 μs) | 1.00x | -| uniform | sorted_uniform | 1024 | 4096 | 46.5 μs | 72.3 μs | 58.6 μs | 152.9 μs | 186.0 μs | 46.5 μs | 218.8 μs | Linear (46.5 μs) | 1.00x | -| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | -| uniform | sorted_uniform | 65536 | 10 | 81.6 μs | 700 ns | 520 ns | 310 ns | 450 ns | 530 ns | 420 ns | InterpSearch (310 ns) | 1.71x | -| uniform | sorted_uniform | 65536 | 256 | 100.4 μs | 12.1 μs | 9.2 μs | 9.2 μs | 15.1 μs | 8.8 μs | 12.5 μs | ExpFromLeft (9.2 μs) | 0.96x | -| uniform | sorted_uniform | 65536 | 4096 | 193.9 μs | 253.3 μs | 204.7 μs | 169.2 μs | 488.5 μs | 202.6 μs | 486.8 μs | InterpSearch (169.2 μs) | 1.20x | -| uniform | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| uniform | sorted_dense_burst | 64 | 10 | 130 ns | 190 ns | 150 ns | 320 ns | 200 ns | 140 ns | 180 ns | Linear (130 ns) | 1.08x | -| uniform | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.7 μs | 2.8 μs | 7.1 μs | 4.3 μs | 2.0 μs | 3.7 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_dense_burst | 64 | 4096 | 30.9 μs | 58.0 μs | 44.0 μs | 110.8 μs | 66.6 μs | 30.1 μs | 56.8 μs | Linear (30.9 μs) | 0.97x | -| uniform | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 310 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | -| uniform | sorted_dense_burst | 1024 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 7.0 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (1.9 μs) | 1.01x | -| uniform | sorted_dense_burst | 1024 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 110.6 μs | 105.5 μs | 30.1 μs | 95.8 μs | Linear (30.1 μs) | 1.00x | -| uniform | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | -| uniform | sorted_dense_burst | 65536 | 10 | 150 ns | 209 ns | 180 ns | 400 ns | 450 ns | 160 ns | 420 ns | Linear (150 ns) | 1.07x | -| uniform | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.6 μs | 2.8 μs | 7.0 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.00x | -| uniform | sorted_dense_burst | 65536 | 4096 | 30.1 μs | 55.4 μs | 43.6 μs | 110.6 μs | 163.1 μs | 30.1 μs | 152.5 μs | Linear (30.1 μs) | 1.00x | -| uniform | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_near_start | 64 | 10 | 190 ns | 260 ns | 190 ns | 320 ns | 200 ns | 180 ns | 180 ns | ExpFromLeft (190 ns) | 0.95x | -| uniform | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.9 μs | 7.0 μs | 4.2 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.06x | -| uniform | sorted_near_start | 64 | 4096 | 30.9 μs | 56.3 μs | 44.6 μs | 112.0 μs | 68.9 μs | 30.9 μs | 59.4 μs | Linear (30.9 μs) | 1.00x | -| uniform | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| uniform | sorted_near_start | 1024 | 10 | 1.5 μs | 300 ns | 260 ns | 310 ns | 290 ns | 260 ns | 270 ns | ExpFromLeft (260 ns) | 1.00x | -| uniform | sorted_near_start | 1024 | 256 | 3.5 μs | 4.6 μs | 3.6 μs | 8.7 μs | 7.5 μs | 3.6 μs | 6.2 μs | Linear (3.5 μs) | 1.01x | -| uniform | sorted_near_start | 1024 | 4096 | 32.8 μs | 58.2 μs | 45.6 μs | 117.8 μs | 111.2 μs | 33.6 μs | 104.8 μs | Linear (32.8 μs) | 1.02x | -| uniform | sorted_near_start | 65536 | 1 | 80 ns | 70 ns | 80 ns | 60 ns | 80 ns | 70 ns | 70 ns | InterpSearch (60 ns) | 1.17x | -| uniform | sorted_near_start | 65536 | 10 | 36.5 μs | 520 ns | 410 ns | 310 ns | 460 ns | 420 ns | 410 ns | InterpSearch (310 ns) | 1.35x | -| uniform | sorted_near_start | 65536 | 256 | 107.9 μs | 8.4 μs | 6.0 μs | 9.1 μs | 20.0 μs | 5.7 μs | 11.1 μs | ExpFromLeft (6.0 μs) | 0.94x | -| uniform | sorted_near_start | 65536 | 4096 | 152.5 μs | 120.8 μs | 95.3 μs | 163.8 μs | 310.8 μs | 88.5 μs | 366.4 μs | ExpFromLeft (95.3 μs) | 0.93x | -| uniform | unsorted | 64 | 1 | 50 ns | 70 ns | 70 ns | 70 ns | 60 ns | 50 ns | 50 ns | Linear (50 ns) | 1.00x | -| uniform | unsorted | 64 | 10 | 200 ns | 200 ns | 199 ns | 200 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (199 ns) | 1.01x | -| uniform | unsorted | 64 | 256 | 3.8 μs | 3.8 μs | 3.8 μs | 3.8 μs | 3.8 μs | 3.8 μs | 3.8 μs | Binary (3.8 μs) | 1.01x | -| uniform | unsorted | 64 | 4096 | 243.7 μs | 242.6 μs | 239.5 μs | 241.4 μs | 240.8 μs | 239.1 μs | 242.9 μs | ExpFromLeft (239.5 μs) | 1.00x | -| uniform | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | unsorted | 1024 | 10 | 280 ns | 290 ns | 290 ns | 290 ns | 280 ns | 290 ns | 270 ns | Binary (280 ns) | 1.04x | -| uniform | unsorted | 1024 | 256 | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.7 μs | ExpFromLeft (6.2 μs) | 1.01x | -| uniform | unsorted | 1024 | 4096 | 417.7 μs | 417.5 μs | 417.5 μs | 416.9 μs | 417.6 μs | 415.3 μs | 416.7 μs | InterpSearch (416.9 μs) | 1.00x | -| uniform | unsorted | 65536 | 1 | 80 ns | 70 ns | 80 ns | 60 ns | 80 ns | 70 ns | 70 ns | InterpSearch (60 ns) | 1.17x | -| uniform | unsorted | 65536 | 10 | 430 ns | 420 ns | 420 ns | 420 ns | 430 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | -| uniform | unsorted | 65536 | 256 | 10.6 μs | 10.5 μs | 10.6 μs | 10.4 μs | 10.5 μs | 10.4 μs | 13.7 μs | InterpSearch (10.4 μs) | 1.00x | -| uniform | unsorted | 65536 | 4096 | 837.9 μs | 838.1 μs | 838.4 μs | 835.8 μs | 837.8 μs | 838.9 μs | 841.0 μs | InterpSearch (835.8 μs) | 1.00x | -| log | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| log | sorted_uniform | 64 | 10 | 200 ns | 230 ns | 190 ns | 450 ns | 210 ns | 200 ns | 180 ns | ExpFromLeft (190 ns) | 1.05x | -| log | sorted_uniform | 64 | 256 | 2.3 μs | 3.8 μs | 3.1 μs | 13.2 μs | 4.7 μs | 2.3 μs | 4.0 μs | Linear (2.3 μs) | 0.99x | -| log | sorted_uniform | 64 | 4096 | 30.9 μs | 55.2 μs | 44.4 μs | 177.8 μs | 68.1 μs | 30.9 μs | 60.6 μs | Linear (30.9 μs) | 1.00x | -| log | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_uniform | 1024 | 10 | 470 ns | 330 ns | 260 ns | 660 ns | 290 ns | 290 ns | 270 ns | ExpFromLeft (260 ns) | 1.12x | -| log | sorted_uniform | 1024 | 256 | 3.0 μs | 4.7 μs | 3.4 μs | 21.2 μs | 8.4 μs | 3.0 μs | 6.5 μs | Linear (3.0 μs) | 1.01x | -| log | sorted_uniform | 1024 | 4096 | 37.7 μs | 62.4 μs | 49.9 μs | 314.6 μs | 128.5 μs | 37.5 μs | 155.9 μs | Linear (37.7 μs) | 1.00x | +| uniform | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| uniform | sorted_uniform | 64 | 10 | 170 ns | 230 ns | 230 ns | 310 ns | 240 ns | 270 ns | 180 ns | Linear (170 ns) | 1.59x | +| uniform | sorted_uniform | 64 | 256 | 2.3 μs | 4.2 μs | 3.8 μs | 9.0 μs | 4.4 μs | 2.1 μs | 3.8 μs | Linear (2.3 μs) | 0.95x | +| uniform | sorted_uniform | 64 | 4096 | 32.4 μs | 59.2 μs | 43.4 μs | 115.1 μs | 69.8 μs | 30.8 μs | 60.4 μs | Linear (32.4 μs) | 0.95x | +| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| uniform | sorted_uniform | 1024 | 10 | 1.7 μs | 410 ns | 330 ns | 310 ns | 300 ns | 340 ns | 270 ns | Binary (300 ns) | 1.13x | +| uniform | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.9 μs | 9.1 μs | 7.2 μs | 3.7 μs | 6.9 μs | Linear (3.6 μs) | 1.01x | +| uniform | sorted_uniform | 1024 | 4096 | 55.1 μs | 81.3 μs | 69.3 μs | 152.7 μs | 232.2 μs | 46.7 μs | 221.7 μs | Linear (55.1 μs) | 0.85x | +| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 90 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_uniform | 65536 | 10 | 79.2 μs | 710 ns | 530 ns | 320 ns | 540 ns | 350 ns | 420 ns | InterpSearch (320 ns) | 1.09x | +| uniform | sorted_uniform | 65536 | 256 | 100.1 μs | 12.1 μs | 9.3 μs | 9.2 μs | 13.4 μs | 9.5 μs | 14.5 μs | InterpSearch (9.2 μs) | 1.03x | +| uniform | sorted_uniform | 65536 | 4096 | 193.1 μs | 250.2 μs | 206.4 μs | 166.4 μs | 491.2 μs | 204.0 μs | 482.5 μs | InterpSearch (166.4 μs) | 1.23x | +| uniform | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| uniform | sorted_dense_burst | 64 | 10 | 120 ns | 180 ns | 150 ns | 300 ns | 210 ns | 130 ns | 170 ns | Linear (120 ns) | 1.08x | +| uniform | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 4.3 μs | 1.9 μs | 3.6 μs | Linear (2.0 μs) | 0.97x | +| uniform | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.9 μs | 42.2 μs | 109.9 μs | 67.8 μs | 29.5 μs | 56.9 μs | Linear (30.8 μs) | 0.96x | +| uniform | sorted_dense_burst | 1024 | 1 | 60 ns | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 300 ns | 310 ns | 140 ns | 280 ns | Linear (130 ns) | 1.08x | +| uniform | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 6.7 μs | 1.9 μs | 6.0 μs | Linear (2.0 μs) | 0.96x | +| uniform | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 42.3 μs | 109.6 μs | 106.8 μs | 29.5 μs | 95.7 μs | Linear (30.8 μs) | 0.96x | +| uniform | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 300 ns | 450 ns | 160 ns | 410 ns | Linear (150 ns) | 1.07x | +| uniform | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.3 μs | 1.9 μs | 9.6 μs | Linear (2.0 μs) | 0.97x | +| uniform | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.3 μs | 109.5 μs | 164.4 μs | 29.5 μs | 152.4 μs | Linear (30.8 μs) | 0.96x | +| uniform | sorted_near_start | 64 | 1 | 50 ns | 70 ns | 70 ns | 80 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| uniform | sorted_near_start | 64 | 10 | 190 ns | 210 ns | 160 ns | 310 ns | 200 ns | 180 ns | 220 ns | ExpFromLeft (160 ns) | 1.12x | +| uniform | sorted_near_start | 64 | 256 | 2.1 μs | 3.8 μs | 2.8 μs | 7.1 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 0.96x | +| uniform | sorted_near_start | 64 | 4096 | 32.1 μs | 59.3 μs | 43.4 μs | 111.6 μs | 67.4 μs | 30.1 μs | 59.4 μs | Linear (32.1 μs) | 0.94x | +| uniform | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| uniform | sorted_near_start | 1024 | 10 | 1.4 μs | 310 ns | 230 ns | 300 ns | 290 ns | 350 ns | 260 ns | ExpFromLeft (230 ns) | 1.52x | +| uniform | sorted_near_start | 1024 | 256 | 3.7 μs | 4.8 μs | 3.9 μs | 8.7 μs | 6.8 μs | 3.6 μs | 6.3 μs | Linear (3.7 μs) | 0.98x | +| uniform | sorted_near_start | 1024 | 4096 | 34.0 μs | 58.1 μs | 44.4 μs | 116.5 μs | 111.2 μs | 32.4 μs | 104.7 μs | Linear (34.0 μs) | 0.95x | +| uniform | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_near_start | 65536 | 10 | 36.8 μs | 520 ns | 410 ns | 310 ns | 440 ns | 350 ns | 410 ns | InterpSearch (310 ns) | 1.13x | +| uniform | sorted_near_start | 65536 | 256 | 93.5 μs | 7.9 μs | 5.7 μs | 9.0 μs | 11.6 μs | 9.4 μs | 11.5 μs | ExpFromLeft (5.7 μs) | 1.63x | +| uniform | sorted_near_start | 65536 | 4096 | 154.3 μs | 116.5 μs | 94.5 μs | 162.4 μs | 371.4 μs | 90.6 μs | 362.0 μs | ExpFromLeft (94.5 μs) | 0.96x | +| uniform | unsorted | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| uniform | unsorted | 64 | 10 | 180 ns | 180 ns | 180 ns | 180 ns | 200 ns | 200 ns | 169 ns | InterpSearch (180 ns) | 1.11x | +| uniform | unsorted | 64 | 256 | 5.9 μs | 5.7 μs | 5.8 μs | 5.8 μs | 5.8 μs | 5.8 μs | 3.7 μs | Gallop (5.7 μs) | 1.02x | +| uniform | unsorted | 64 | 4096 | 231.8 μs | 228.5 μs | 228.1 μs | 227.7 μs | 225.0 μs | 227.1 μs | 245.0 μs | Binary (225.0 μs) | 1.01x | +| uniform | unsorted | 1024 | 1 | 60 ns | 80 ns | 80 ns | 80 ns | 90 ns | 60 ns | 60 ns | Linear (60 ns) | 1.00x | +| uniform | unsorted | 1024 | 10 | 270 ns | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 270 ns | Linear (270 ns) | 1.07x | +| uniform | unsorted | 1024 | 256 | 8.8 μs | 8.0 μs | 8.0 μs | 7.8 μs | 7.8 μs | 7.9 μs | 6.8 μs | InterpSearch (7.8 μs) | 1.02x | +| uniform | unsorted | 1024 | 4096 | 410.1 μs | 410.5 μs | 411.8 μs | 409.7 μs | 410.8 μs | 411.3 μs | 415.7 μs | InterpSearch (409.7 μs) | 1.00x | +| uniform | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | unsorted | 65536 | 10 | 420 ns | 430 ns | 430 ns | 420 ns | 430 ns | 430 ns | 420 ns | InterpSearch (420 ns) | 1.02x | +| uniform | unsorted | 65536 | 256 | 14.3 μs | 13.8 μs | 13.8 μs | 13.9 μs | 13.8 μs | 13.7 μs | 15.5 μs | ExpFromLeft (13.8 μs) | 0.99x | +| uniform | unsorted | 65536 | 4096 | 849.7 μs | 847.5 μs | 844.6 μs | 847.6 μs | 847.5 μs | 847.0 μs | 849.5 μs | ExpFromLeft (844.6 μs) | 1.00x | +| log | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_uniform | 64 | 10 | 170 ns | 220 ns | 190 ns | 450 ns | 200 ns | 200 ns | 180 ns | Linear (170 ns) | 1.18x | +| log | sorted_uniform | 64 | 256 | 2.3 μs | 3.9 μs | 3.0 μs | 11.3 μs | 4.5 μs | 2.2 μs | 3.9 μs | Linear (2.3 μs) | 0.97x | +| log | sorted_uniform | 64 | 4096 | 31.7 μs | 55.8 μs | 43.1 μs | 170.5 μs | 69.2 μs | 30.4 μs | 60.7 μs | Linear (31.7 μs) | 0.96x | +| log | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| log | sorted_uniform | 1024 | 10 | 480 ns | 330 ns | 260 ns | 660 ns | 300 ns | 290 ns | 270 ns | ExpFromLeft (260 ns) | 1.12x | +| log | sorted_uniform | 1024 | 256 | 3.2 μs | 4.6 μs | 3.4 μs | 16.0 μs | 6.9 μs | 3.0 μs | 6.5 μs | Linear (3.2 μs) | 0.95x | +| log | sorted_uniform | 1024 | 4096 | 38.6 μs | 62.9 μs | 50.5 μs | 287.1 μs | 169.2 μs | 37.5 μs | 163.2 μs | Linear (38.6 μs) | 0.97x | | log | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_uniform | 65536 | 10 | 19.5 μs | 580 ns | 430 ns | 900 ns | 430 ns | 440 ns | 410 ns | ExpFromLeft (430 ns) | 1.02x | -| log | sorted_uniform | 65536 | 256 | 89.2 μs | 10.4 μs | 7.7 μs | 32.1 μs | 17.5 μs | 7.5 μs | 12.2 μs | ExpFromLeft (7.7 μs) | 0.97x | -| log | sorted_uniform | 65536 | 4096 | 177.3 μs | 198.4 μs | 154.3 μs | 597.8 μs | 411.5 μs | 151.0 μs | 433.4 μs | ExpFromLeft (154.3 μs) | 0.98x | -| log | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| log | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 490 ns | 200 ns | 140 ns | 170 ns | Linear (130 ns) | 1.08x | -| log | sorted_dense_burst | 64 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 11.4 μs | 4.2 μs | 1.9 μs | 3.6 μs | Linear (1.9 μs) | 1.01x | -| log | sorted_dense_burst | 64 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 181.0 μs | 66.6 μs | 30.0 μs | 60.7 μs | Linear (30.1 μs) | 1.00x | -| log | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 690 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | -| log | sorted_dense_burst | 1024 | 256 | 2.0 μs | 4.7 μs | 2.9 μs | 16.4 μs | 6.6 μs | 1.9 μs | 6.0 μs | Linear (2.0 μs) | 0.98x | -| log | sorted_dense_burst | 1024 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 260.1 μs | 105.4 μs | 30.1 μs | 95.7 μs | Linear (30.1 μs) | 1.00x | -| log | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 100 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_dense_burst | 65536 | 10 | 150 ns | 210 ns | 170 ns | 1.0 μs | 440 ns | 150 ns | 410 ns | Linear (150 ns) | 1.00x | -| log | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.8 μs | 25.3 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | -| log | sorted_dense_burst | 65536 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 403.0 μs | 163.1 μs | 30.1 μs | 152.5 μs | Linear (30.1 μs) | 1.00x | -| log | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 70 ns | 50 ns | ExpFromLeft (50 ns) | 1.40x | -| log | sorted_near_start | 64 | 10 | 200 ns | 200 ns | 180 ns | 339 ns | 200 ns | 199 ns | 170 ns | ExpFromLeft (180 ns) | 1.11x | -| log | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.9 μs | 7.5 μs | 4.4 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.00x | -| log | sorted_near_start | 64 | 4096 | 30.4 μs | 55.6 μs | 44.1 μs | 120.4 μs | 66.6 μs | 30.5 μs | 59.5 μs | Linear (30.4 μs) | 1.00x | -| log | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_near_start | 1024 | 10 | 1.2 μs | 300 ns | 240 ns | 480 ns | 300 ns | 240 ns | 270 ns | ExpFromLeft (240 ns) | 1.00x | -| log | sorted_near_start | 1024 | 256 | 3.7 μs | 4.5 μs | 3.5 μs | 15.8 μs | 7.7 μs | 3.7 μs | 6.3 μs | ExpFromLeft (3.5 μs) | 1.07x | -| log | sorted_near_start | 1024 | 4096 | 32.5 μs | 57.8 μs | 45.3 μs | 205.2 μs | 108.7 μs | 32.9 μs | 102.2 μs | Linear (32.5 μs) | 1.01x | +| log | sorted_uniform | 65536 | 10 | 19.9 μs | 580 ns | 420 ns | 900 ns | 440 ns | 440 ns | 410 ns | ExpFromLeft (420 ns) | 1.05x | +| log | sorted_uniform | 65536 | 256 | 88.2 μs | 10.2 μs | 7.7 μs | 25.1 μs | 13.3 μs | 8.0 μs | 12.7 μs | ExpFromLeft (7.7 μs) | 1.03x | +| log | sorted_uniform | 65536 | 4096 | 186.3 μs | 197.8 μs | 154.5 μs | 657.8 μs | 439.8 μs | 153.0 μs | 432.8 μs | ExpFromLeft (154.5 μs) | 0.99x | +| log | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | +| log | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 480 ns | 200 ns | 130 ns | 170 ns | Linear (130 ns) | 1.00x | +| log | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 11.3 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.97x | +| log | sorted_dense_burst | 64 | 4096 | 32.8 μs | 55.0 μs | 42.3 μs | 179.3 μs | 67.8 μs | 31.6 μs | 56.8 μs | Linear (32.8 μs) | 0.96x | +| log | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 690 ns | 300 ns | 140 ns | 280 ns | Linear (130 ns) | 1.08x | +| log | sorted_dense_burst | 1024 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 16.1 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.1 μs) | 0.97x | +| log | sorted_dense_burst | 1024 | 4096 | 32.9 μs | 55.1 μs | 42.3 μs | 258.3 μs | 106.7 μs | 31.5 μs | 95.8 μs | Linear (32.9 μs) | 0.96x | +| log | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 980 ns | 450 ns | 160 ns | 410 ns | Linear (150 ns) | 1.07x | +| log | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.3 μs | 10.3 μs | 1.9 μs | 9.5 μs | Linear (2.0 μs) | 0.97x | +| log | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.3 μs | 385.0 μs | 164.5 μs | 29.5 μs | 152.5 μs | Linear (30.8 μs) | 0.96x | +| log | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| log | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 160 ns | 320 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (160 ns) | 1.25x | +| log | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.3 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 0.97x | +| log | sorted_near_start | 64 | 4096 | 33.2 μs | 55.4 μs | 42.9 μs | 117.4 μs | 67.5 μs | 29.9 μs | 59.7 μs | Linear (33.2 μs) | 0.90x | +| log | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_near_start | 1024 | 10 | 1.2 μs | 300 ns | 230 ns | 480 ns | 300 ns | 250 ns | 260 ns | ExpFromLeft (230 ns) | 1.09x | +| log | sorted_near_start | 1024 | 256 | 3.7 μs | 4.5 μs | 3.9 μs | 12.3 μs | 6.8 μs | 3.6 μs | 6.3 μs | Linear (3.7 μs) | 0.98x | +| log | sorted_near_start | 1024 | 4096 | 34.1 μs | 57.6 μs | 45.4 μs | 191.7 μs | 109.5 μs | 32.3 μs | 103.3 μs | Linear (34.1 μs) | 0.95x | | log | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_near_start | 65536 | 10 | 61.1 μs | 550 ns | 430 ns | 850 ns | 430 ns | 430 ns | 400 ns | ExpFromLeft (430 ns) | 1.00x | -| log | sorted_near_start | 65536 | 256 | 95.7 μs | 7.9 μs | 5.7 μs | 28.9 μs | 19.0 μs | 5.6 μs | 10.7 μs | ExpFromLeft (5.7 μs) | 0.98x | -| log | sorted_near_start | 65536 | 4096 | 157.9 μs | 111.2 μs | 88.7 μs | 444.3 μs | 300.1 μs | 84.0 μs | 359.5 μs | ExpFromLeft (88.7 μs) | 0.95x | -| log | unsorted | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (60 ns) | 0.83x | -| log | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | -| log | unsorted | 64 | 256 | 3.8 μs | 3.9 μs | 3.9 μs | 3.8 μs | 3.9 μs | 3.9 μs | 3.9 μs | Linear (3.8 μs) | 1.01x | -| log | unsorted | 64 | 4096 | 178.7 μs | 175.3 μs | 174.8 μs | 174.1 μs | 174.5 μs | 173.6 μs | 178.1 μs | InterpSearch (174.1 μs) | 1.00x | -| log | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 290 ns | 280 ns | InterpSearch (280 ns) | 1.04x | -| log | unsorted | 1024 | 256 | 6.3 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.3 μs | 6.8 μs | ExpFromLeft (6.2 μs) | 1.01x | -| log | unsorted | 1024 | 4096 | 356.7 μs | 356.1 μs | 356.7 μs | 357.5 μs | 356.6 μs | 357.1 μs | 358.2 μs | Gallop (356.1 μs) | 1.00x | -| log | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | -| log | unsorted | 65536 | 10 | 430 ns | 430 ns | 420 ns | 430 ns | 430 ns | 430 ns | 410 ns | ExpFromLeft (420 ns) | 1.02x | -| log | unsorted | 65536 | 256 | 10.0 μs | 10.0 μs | 9.9 μs | 10.0 μs | 9.9 μs | 9.9 μs | 13.1 μs | ExpFromLeft (9.9 μs) | 1.00x | -| log | unsorted | 65536 | 4096 | 711.8 μs | 709.6 μs | 705.8 μs | 708.8 μs | 709.8 μs | 710.9 μs | 707.6 μs | ExpFromLeft (705.8 μs) | 1.01x | -| jittered | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 50 ns | 60 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | sorted_uniform | 64 | 10 | 180 ns | 240 ns | 190 ns | 310 ns | 200 ns | 200 ns | 180 ns | Linear (180 ns) | 1.11x | -| jittered | sorted_uniform | 64 | 256 | 2.4 μs | 4.2 μs | 3.2 μs | 8.7 μs | 5.3 μs | 2.3 μs | 3.8 μs | Linear (2.4 μs) | 0.97x | -| jittered | sorted_uniform | 64 | 4096 | 31.4 μs | 56.3 μs | 44.7 μs | 114.2 μs | 67.3 μs | 31.4 μs | 60.3 μs | Linear (31.4 μs) | 1.00x | -| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_uniform | 1024 | 10 | 1.6 μs | 370 ns | 300 ns | 340 ns | 300 ns | 320 ns | 260 ns | ExpFromLeft (300 ns) | 1.07x | -| jittered | sorted_uniform | 1024 | 256 | 3.5 μs | 5.4 μs | 3.8 μs | 9.1 μs | 7.5 μs | 3.5 μs | 7.0 μs | Linear (3.5 μs) | 1.01x | -| jittered | sorted_uniform | 1024 | 4096 | 46.6 μs | 72.7 μs | 58.7 μs | 150.8 μs | 186.7 μs | 46.5 μs | 220.1 μs | Linear (46.6 μs) | 1.00x | +| log | sorted_near_start | 65536 | 10 | 61.6 μs | 600 ns | 420 ns | 790 ns | 430 ns | 440 ns | 420 ns | ExpFromLeft (420 ns) | 1.05x | +| log | sorted_near_start | 65536 | 256 | 97.0 μs | 7.6 μs | 5.7 μs | 21.0 μs | 11.8 μs | 5.6 μs | 11.1 μs | ExpFromLeft (5.7 μs) | 1.00x | +| log | sorted_near_start | 65536 | 4096 | 156.6 μs | 112.4 μs | 89.5 μs | 503.1 μs | 366.7 μs | 88.6 μs | 358.1 μs | ExpFromLeft (89.5 μs) | 0.99x | +| log | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| log | unsorted | 64 | 10 | 180 ns | 190 ns | 190 ns | 190 ns | 200 ns | 200 ns | 180 ns | Linear (180 ns) | 1.11x | +| log | unsorted | 64 | 256 | 5.0 μs | 5.1 μs | 5.2 μs | 5.2 μs | 5.1 μs | 5.2 μs | 3.9 μs | Linear (5.0 μs) | 1.03x | +| log | unsorted | 64 | 4096 | 176.1 μs | 167.7 μs | 167.2 μs | 168.8 μs | 167.9 μs | 174.3 μs | 179.2 μs | ExpFromLeft (167.2 μs) | 1.04x | +| log | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 80 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| log | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 270 ns | 280 ns | 290 ns | 270 ns | InterpSearch (270 ns) | 1.07x | +| log | unsorted | 1024 | 256 | 10.3 μs | 10.1 μs | 10.1 μs | 10.1 μs | 10.1 μs | 10.1 μs | 6.6 μs | InterpSearch (10.1 μs) | 1.00x | +| log | unsorted | 1024 | 4096 | 352.0 μs | 344.7 μs | 346.2 μs | 344.2 μs | 344.7 μs | 348.1 μs | 358.0 μs | InterpSearch (344.2 μs) | 1.01x | +| log | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | unsorted | 65536 | 10 | 420 ns | 420 ns | 410 ns | 420 ns | 430 ns | 429 ns | 410 ns | ExpFromLeft (410 ns) | 1.05x | +| log | unsorted | 65536 | 256 | 17.2 μs | 16.8 μs | 16.6 μs | 16.7 μs | 16.7 μs | 16.7 μs | 14.2 μs | ExpFromLeft (16.6 μs) | 1.01x | +| log | unsorted | 65536 | 4096 | 707.1 μs | 707.1 μs | 706.7 μs | 706.9 μs | 704.6 μs | 706.2 μs | 711.0 μs | Binary (704.6 μs) | 1.00x | +| jittered | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Linear (50 ns) | 1.00x | +| jittered | sorted_uniform | 64 | 10 | 240 ns | 290 ns | 190 ns | 310 ns | 210 ns | 200 ns | 180 ns | ExpFromLeft (190 ns) | 1.05x | +| jittered | sorted_uniform | 64 | 256 | 2.3 μs | 4.2 μs | 3.7 μs | 8.9 μs | 4.2 μs | 2.1 μs | 3.7 μs | Linear (2.3 μs) | 0.94x | +| jittered | sorted_uniform | 64 | 4096 | 32.2 μs | 56.0 μs | 43.5 μs | 113.7 μs | 68.7 μs | 30.8 μs | 60.3 μs | Linear (32.2 μs) | 0.96x | +| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| jittered | sorted_uniform | 1024 | 10 | 1.6 μs | 380 ns | 300 ns | 330 ns | 300 ns | 370 ns | 260 ns | ExpFromLeft (300 ns) | 1.23x | +| jittered | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.8 μs | 9.1 μs | 7.2 μs | 3.6 μs | 7.7 μs | Linear (3.6 μs) | 0.99x | +| jittered | sorted_uniform | 1024 | 4096 | 48.5 μs | 72.4 μs | 60.4 μs | 151.7 μs | 231.4 μs | 46.9 μs | 220.5 μs | Linear (48.5 μs) | 0.97x | | jittered | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_uniform | 65536 | 10 | 58.7 μs | 780 ns | 610 ns | 420 ns | 550 ns | 640 ns | 420 ns | InterpSearch (420 ns) | 1.52x | -| jittered | sorted_uniform | 65536 | 256 | 100.6 μs | 12.2 μs | 9.1 μs | 9.7 μs | 15.5 μs | 8.8 μs | 13.1 μs | ExpFromLeft (9.1 μs) | 0.97x | -| jittered | sorted_uniform | 65536 | 4096 | 195.1 μs | 254.8 μs | 208.5 μs | 166.1 μs | 495.9 μs | 205.0 μs | 489.1 μs | InterpSearch (166.1 μs) | 1.23x | -| jittered | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| jittered | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 320 ns | 200 ns | 140 ns | 170 ns | Linear (130 ns) | 1.08x | -| jittered | sorted_dense_burst | 64 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 7.1 μs | 4.2 μs | 1.9 μs | 3.6 μs | Linear (1.9 μs) | 1.00x | -| jittered | sorted_dense_burst | 64 | 4096 | 30.1 μs | 55.3 μs | 43.5 μs | 111.0 μs | 66.6 μs | 30.1 μs | 56.6 μs | Linear (30.1 μs) | 1.00x | -| jittered | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| jittered | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 320 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | -| jittered | sorted_dense_burst | 1024 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 7.0 μs | 6.6 μs | 1.9 μs | 6.0 μs | Linear (1.9 μs) | 1.00x | -| jittered | sorted_dense_burst | 1024 | 4096 | 30.0 μs | 55.4 μs | 43.6 μs | 110.8 μs | 105.5 μs | 30.1 μs | 95.7 μs | Linear (30.0 μs) | 1.00x | -| jittered | sorted_dense_burst | 65536 | 1 | 70 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_dense_burst | 65536 | 10 | 150 ns | 210 ns | 170 ns | 319 ns | 440 ns | 150 ns | 410 ns | Linear (150 ns) | 1.00x | -| jittered | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.8 μs | 7.0 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | -| jittered | sorted_dense_burst | 65536 | 4096 | 30.1 μs | 55.5 μs | 43.7 μs | 110.6 μs | 163.1 μs | 30.1 μs | 152.5 μs | Linear (30.1 μs) | 1.00x | -| jittered | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 90 ns | 50 ns | ExpFromLeft (50 ns) | 1.80x | -| jittered | sorted_near_start | 64 | 10 | 200 ns | 210 ns | 190 ns | 310 ns | 200 ns | 180 ns | 200 ns | ExpFromLeft (190 ns) | 0.95x | -| jittered | sorted_near_start | 64 | 256 | 2.4 μs | 3.9 μs | 2.9 μs | 7.3 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.4 μs) | 0.86x | -| jittered | sorted_near_start | 64 | 4096 | 30.9 μs | 56.5 μs | 44.6 μs | 111.6 μs | 68.8 μs | 30.9 μs | 59.2 μs | Linear (30.9 μs) | 1.00x | -| jittered | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_near_start | 1024 | 10 | 750 ns | 300 ns | 240 ns | 310 ns | 290 ns | 240 ns | 260 ns | ExpFromLeft (240 ns) | 1.00x | -| jittered | sorted_near_start | 1024 | 256 | 3.6 μs | 4.7 μs | 3.7 μs | 8.8 μs | 7.6 μs | 3.6 μs | 6.4 μs | Linear (3.6 μs) | 0.99x | -| jittered | sorted_near_start | 1024 | 4096 | 33.1 μs | 58.4 μs | 45.6 μs | 116.0 μs | 108.7 μs | 32.8 μs | 104.1 μs | Linear (33.1 μs) | 0.99x | -| jittered | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | -| jittered | sorted_near_start | 65536 | 10 | 80.0 μs | 530 ns | 430 ns | 310 ns | 430 ns | 410 ns | 410 ns | InterpSearch (310 ns) | 1.32x | -| jittered | sorted_near_start | 65536 | 256 | 92.4 μs | 7.9 μs | 5.8 μs | 9.0 μs | 19.4 μs | 5.8 μs | 11.2 μs | ExpFromLeft (5.8 μs) | 1.00x | -| jittered | sorted_near_start | 65536 | 4096 | 154.7 μs | 118.0 μs | 96.0 μs | 160.4 μs | 310.9 μs | 90.6 μs | 369.6 μs | ExpFromLeft (96.0 μs) | 0.94x | -| jittered | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 60 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | unsorted | 64 | 10 | 190 ns | 180 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | Gallop (180 ns) | 1.11x | -| jittered | unsorted | 64 | 256 | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.8 μs | Gallop (3.9 μs) | 1.01x | -| jittered | unsorted | 64 | 4096 | 242.9 μs | 243.0 μs | 241.5 μs | 240.7 μs | 241.2 μs | 240.4 μs | 242.2 μs | InterpSearch (240.7 μs) | 1.00x | -| jittered | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| jittered | unsorted | 1024 | 10 | 280 ns | 290 ns | 290 ns | 290 ns | 290 ns | 290 ns | 270 ns | Linear (280 ns) | 1.04x | -| jittered | unsorted | 1024 | 256 | 6.3 μs | 6.3 μs | 6.3 μs | 6.2 μs | 6.3 μs | 6.3 μs | 6.7 μs | InterpSearch (6.2 μs) | 1.01x | -| jittered | unsorted | 1024 | 4096 | 417.1 μs | 416.3 μs | 415.9 μs | 415.3 μs | 416.6 μs | 415.0 μs | 417.6 μs | InterpSearch (415.3 μs) | 1.00x | +| jittered | sorted_uniform | 65536 | 10 | 59.9 μs | 680 ns | 480 ns | 310 ns | 480 ns | 350 ns | 430 ns | InterpSearch (310 ns) | 1.13x | +| jittered | sorted_uniform | 65536 | 256 | 103.4 μs | 14.8 μs | 11.7 μs | 11.5 μs | 16.2 μs | 12.1 μs | 17.0 μs | InterpSearch (11.5 μs) | 1.05x | +| jittered | sorted_uniform | 65536 | 4096 | 217.0 μs | 256.3 μs | 216.5 μs | 203.2 μs | 512.0 μs | 214.6 μs | 487.8 μs | InterpSearch (203.2 μs) | 1.06x | +| jittered | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | sorted_dense_burst | 64 | 10 | 120 ns | 180 ns | 150 ns | 310 ns | 200 ns | 140 ns | 170 ns | Linear (120 ns) | 1.17x | +| jittered | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 4.3 μs | 1.9 μs | 3.6 μs | Linear (2.0 μs) | 0.97x | +| jittered | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.8 μs | 42.3 μs | 110.0 μs | 68.0 μs | 29.9 μs | 58.0 μs | Linear (30.8 μs) | 0.97x | +| jittered | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_dense_burst | 1024 | 10 | 130 ns | 200 ns | 160 ns | 310 ns | 310 ns | 150 ns | 280 ns | Linear (130 ns) | 1.15x | +| jittered | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.7 μs | 2.7 μs | 7.1 μs | 6.7 μs | 1.9 μs | 6.1 μs | Linear (2.0 μs) | 0.97x | +| jittered | sorted_dense_burst | 1024 | 4096 | 32.9 μs | 57.8 μs | 42.3 μs | 111.7 μs | 106.9 μs | 29.5 μs | 95.7 μs | Linear (32.9 μs) | 0.90x | +| jittered | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_dense_burst | 65536 | 10 | 140 ns | 210 ns | 180 ns | 310 ns | 450 ns | 160 ns | 410 ns | Linear (140 ns) | 1.14x | +| jittered | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.3 μs | 2.1 μs | 9.6 μs | Linear (2.0 μs) | 1.03x | +| jittered | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.3 μs | 109.6 μs | 164.4 μs | 30.0 μs | 152.4 μs | Linear (30.8 μs) | 0.97x | +| jittered | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 60 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| jittered | sorted_near_start | 64 | 10 | 200 ns | 210 ns | 160 ns | 310 ns | 200 ns | 189 ns | 170 ns | ExpFromLeft (160 ns) | 1.18x | +| jittered | sorted_near_start | 64 | 256 | 2.1 μs | 3.8 μs | 2.8 μs | 7.2 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 0.97x | +| jittered | sorted_near_start | 64 | 4096 | 32.1 μs | 59.2 μs | 43.3 μs | 113.9 μs | 69.1 μs | 30.4 μs | 59.3 μs | Linear (32.1 μs) | 0.95x | +| jittered | sorted_near_start | 1024 | 1 | 60 ns | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_near_start | 1024 | 10 | 750 ns | 300 ns | 240 ns | 310 ns | 300 ns | 260 ns | 270 ns | ExpFromLeft (240 ns) | 1.08x | +| jittered | sorted_near_start | 1024 | 256 | 3.9 μs | 4.8 μs | 4.0 μs | 8.7 μs | 6.7 μs | 3.8 μs | 6.3 μs | Linear (3.9 μs) | 0.98x | +| jittered | sorted_near_start | 1024 | 4096 | 33.9 μs | 61.1 μs | 44.5 μs | 115.0 μs | 111.2 μs | 32.5 μs | 104.9 μs | Linear (33.9 μs) | 0.96x | +| jittered | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_near_start | 65536 | 10 | 80.6 μs | 540 ns | 400 ns | 300 ns | 440 ns | 340 ns | 410 ns | InterpSearch (300 ns) | 1.13x | +| jittered | sorted_near_start | 65536 | 256 | 90.1 μs | 8.1 μs | 5.8 μs | 9.1 μs | 11.9 μs | 9.3 μs | 12.2 μs | ExpFromLeft (5.8 μs) | 1.59x | +| jittered | sorted_near_start | 65536 | 4096 | 155.5 μs | 118.7 μs | 94.9 μs | 159.0 μs | 376.3 μs | 93.1 μs | 364.4 μs | ExpFromLeft (94.9 μs) | 0.98x | +| jittered | unsorted | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| jittered | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 180 ns | 190 ns | 200 ns | 170 ns | InterpSearch (180 ns) | 1.11x | +| jittered | unsorted | 64 | 256 | 5.2 μs | 5.3 μs | 5.3 μs | 5.4 μs | 5.3 μs | 5.3 μs | 3.9 μs | Linear (5.2 μs) | 1.02x | +| jittered | unsorted | 64 | 4096 | 227.1 μs | 227.8 μs | 226.5 μs | 225.2 μs | 225.5 μs | 224.1 μs | 245.7 μs | InterpSearch (225.2 μs) | 0.99x | +| jittered | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | unsorted | 1024 | 10 | 280 ns | 280 ns | 279 ns | 290 ns | 300 ns | 290 ns | 270 ns | ExpFromLeft (279 ns) | 1.04x | +| jittered | unsorted | 1024 | 256 | 7.7 μs | 7.8 μs | 7.7 μs | 7.7 μs | 7.8 μs | 7.7 μs | 6.6 μs | ExpFromLeft (7.7 μs) | 1.01x | +| jittered | unsorted | 1024 | 4096 | 412.2 μs | 411.3 μs | 410.0 μs | 412.6 μs | 409.7 μs | 412.2 μs | 417.4 μs | Binary (409.7 μs) | 1.01x | | jittered | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | unsorted | 65536 | 10 | 420 ns | 420 ns | 420 ns | 420 ns | 410 ns | 430 ns | 410 ns | Binary (410 ns) | 1.05x | -| jittered | unsorted | 65536 | 256 | 11.2 μs | 10.9 μs | 10.8 μs | 10.8 μs | 10.8 μs | 10.7 μs | 13.9 μs | InterpSearch (10.8 μs) | 1.00x | -| jittered | unsorted | 65536 | 4096 | 839.9 μs | 838.6 μs | 842.5 μs | 841.8 μs | 841.6 μs | 842.8 μs | 838.3 μs | Gallop (838.6 μs) | 1.00x | -| random | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 50 ns | 60 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| random | sorted_uniform | 64 | 10 | 190 ns | 230 ns | 190 ns | 380 ns | 200 ns | 210 ns | 179 ns | ExpFromLeft (190 ns) | 1.11x | -| random | sorted_uniform | 64 | 256 | 2.1 μs | 4.0 μs | 3.1 μs | 9.4 μs | 5.0 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.02x | -| random | sorted_uniform | 64 | 4096 | 31.3 μs | 69.2 μs | 44.8 μs | 130.9 μs | 67.0 μs | 31.4 μs | 59.9 μs | Linear (31.3 μs) | 1.00x | -| random | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_uniform | 1024 | 10 | 1.7 μs | 420 ns | 390 ns | 420 ns | 300 ns | 340 ns | 270 ns | Binary (300 ns) | 1.13x | -| random | sorted_uniform | 1024 | 256 | 3.4 μs | 5.2 μs | 3.9 μs | 12.0 μs | 8.0 μs | 3.5 μs | 6.5 μs | Linear (3.4 μs) | 1.04x | -| random | sorted_uniform | 1024 | 4096 | 43.3 μs | 70.1 μs | 56.2 μs | 211.8 μs | 163.9 μs | 43.2 μs | 198.9 μs | Linear (43.3 μs) | 1.00x | -| random | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| random | sorted_uniform | 65536 | 10 | 55.5 μs | 660 ns | 490 ns | 560 ns | 440 ns | 510 ns | 410 ns | Binary (440 ns) | 1.16x | -| random | sorted_uniform | 65536 | 256 | 100.0 μs | 12.7 μs | 9.7 μs | 21.1 μs | 14.4 μs | 9.5 μs | 13.1 μs | ExpFromLeft (9.7 μs) | 0.99x | -| random | sorted_uniform | 65536 | 4096 | 186.8 μs | 253.7 μs | 205.2 μs | 353.0 μs | 486.4 μs | 203.2 μs | 482.8 μs | Linear (186.8 μs) | 1.09x | -| random | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| random | sorted_dense_burst | 64 | 10 | 150 ns | 190 ns | 150 ns | 470 ns | 200 ns | 140 ns | 170 ns | ExpFromLeft (150 ns) | 0.93x | -| random | sorted_dense_burst | 64 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 7.9 μs | 4.2 μs | 1.9 μs | 3.6 μs | Linear (1.9 μs) | 1.00x | -| random | sorted_dense_burst | 64 | 4096 | 30.1 μs | 55.2 μs | 43.6 μs | 126.3 μs | 66.6 μs | 30.1 μs | 56.8 μs | Linear (30.1 μs) | 1.00x | -| random | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 489 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | -| random | sorted_dense_burst | 1024 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 11.3 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (1.9 μs) | 1.01x | -| random | sorted_dense_burst | 1024 | 4096 | 30.1 μs | 55.3 μs | 43.6 μs | 183.7 μs | 105.5 μs | 30.1 μs | 95.8 μs | Linear (30.1 μs) | 1.00x | -| random | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| random | sorted_dense_burst | 65536 | 10 | 170 ns | 240 ns | 170 ns | 710 ns | 450 ns | 160 ns | 420 ns | ExpFromLeft (170 ns) | 0.94x | -| random | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.7 μs | 2.8 μs | 15.9 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.00x | -| random | sorted_dense_burst | 65536 | 4096 | 31.0 μs | 58.0 μs | 43.8 μs | 243.6 μs | 163.0 μs | 30.1 μs | 152.4 μs | Linear (31.0 μs) | 0.97x | -| random | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| random | sorted_near_start | 64 | 10 | 210 ns | 210 ns | 190 ns | 330 ns | 200 ns | 180 ns | 180 ns | ExpFromLeft (190 ns) | 0.95x | -| random | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.9 μs | 7.8 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.00x | -| random | sorted_near_start | 64 | 4096 | 30.7 μs | 56.1 μs | 44.4 μs | 125.5 μs | 66.9 μs | 30.7 μs | 60.2 μs | Linear (30.7 μs) | 1.00x | -| random | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| random | sorted_near_start | 1024 | 10 | 730 ns | 280 ns | 220 ns | 420 ns | 290 ns | 220 ns | 270 ns | ExpFromLeft (220 ns) | 1.00x | -| random | sorted_near_start | 1024 | 256 | 3.8 μs | 4.4 μs | 3.5 μs | 11.5 μs | 7.3 μs | 3.8 μs | 6.3 μs | ExpFromLeft (3.5 μs) | 1.08x | -| random | sorted_near_start | 1024 | 4096 | 33.0 μs | 58.2 μs | 46.0 μs | 162.5 μs | 108.4 μs | 32.8 μs | 102.1 μs | Linear (33.0 μs) | 0.99x | -| random | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | InterpSearch (80 ns) | 1.00x | -| random | sorted_near_start | 65536 | 10 | 37.6 μs | 510 ns | 400 ns | 500 ns | 470 ns | 400 ns | 409 ns | ExpFromLeft (400 ns) | 1.00x | -| random | sorted_near_start | 65536 | 256 | 95.9 μs | 7.8 μs | 5.9 μs | 14.4 μs | 19.7 μs | 5.7 μs | 11.1 μs | ExpFromLeft (5.9 μs) | 0.96x | -| random | sorted_near_start | 65536 | 4096 | 159.1 μs | 127.0 μs | 103.8 μs | 273.7 μs | 298.9 μs | 98.0 μs | 352.1 μs | ExpFromLeft (103.8 μs) | 0.94x | -| random | unsorted | 64 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| random | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | -| random | unsorted | 64 | 256 | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.9 μs | 3.8 μs | InterpSearch (3.9 μs) | 1.00x | -| random | unsorted | 64 | 4096 | 215.0 μs | 210.8 μs | 210.7 μs | 210.6 μs | 210.1 μs | 210.0 μs | 214.4 μs | Binary (210.1 μs) | 1.00x | -| random | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| random | unsorted | 1024 | 10 | 289 ns | 280 ns | 290 ns | 290 ns | 280 ns | 300 ns | 260 ns | Binary (280 ns) | 1.07x | -| random | unsorted | 1024 | 256 | 6.3 μs | 6.3 μs | 6.3 μs | 6.3 μs | 6.3 μs | 6.3 μs | 6.4 μs | ExpFromLeft (6.3 μs) | 1.00x | -| random | unsorted | 1024 | 4096 | 396.4 μs | 396.8 μs | 395.6 μs | 395.7 μs | 396.9 μs | 395.5 μs | 393.0 μs | ExpFromLeft (395.6 μs) | 1.00x | -| random | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | -| random | unsorted | 65536 | 10 | 430 ns | 430 ns | 430 ns | 430 ns | 430 ns | 439 ns | 410 ns | InterpSearch (430 ns) | 1.02x | -| random | unsorted | 65536 | 256 | 10.8 μs | 10.8 μs | 10.7 μs | 10.6 μs | 10.7 μs | 10.6 μs | 15.4 μs | InterpSearch (10.6 μs) | 1.00x | -| random | unsorted | 65536 | 4096 | 829.1 μs | 827.7 μs | 827.1 μs | 827.6 μs | 828.8 μs | 827.5 μs | 829.5 μs | ExpFromLeft (827.1 μs) | 1.00x | -| two_scale | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 70 ns | ExpFromLeft (50 ns) | 1.20x | -| two_scale | sorted_uniform | 64 | 10 | 170 ns | 220 ns | 180 ns | 410 ns | 210 ns | 180 ns | 180 ns | Linear (170 ns) | 1.06x | -| two_scale | sorted_uniform | 64 | 256 | 2.3 μs | 3.9 μs | 3.2 μs | 13.7 μs | 4.6 μs | 2.3 μs | 3.9 μs | Linear (2.3 μs) | 1.00x | -| two_scale | sorted_uniform | 64 | 4096 | 30.7 μs | 55.7 μs | 44.3 μs | 173.6 μs | 67.7 μs | 31.6 μs | 60.0 μs | Linear (30.7 μs) | 1.03x | -| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| two_scale | sorted_uniform | 1024 | 10 | 650 ns | 370 ns | 300 ns | 710 ns | 300 ns | 310 ns | 270 ns | ExpFromLeft (300 ns) | 1.03x | -| two_scale | sorted_uniform | 1024 | 256 | 2.9 μs | 4.7 μs | 3.7 μs | 24.3 μs | 8.0 μs | 2.8 μs | 6.7 μs | Linear (2.9 μs) | 0.97x | -| two_scale | sorted_uniform | 1024 | 4096 | 39.1 μs | 65.6 μs | 51.4 μs | 309.0 μs | 119.0 μs | 39.1 μs | 149.4 μs | Linear (39.1 μs) | 1.00x | -| two_scale | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | -| two_scale | sorted_uniform | 65536 | 10 | 45.8 μs | 630 ns | 450 ns | 1.0 μs | 440 ns | 470 ns | 400 ns | Binary (440 ns) | 1.07x | -| two_scale | sorted_uniform | 65536 | 256 | 60.2 μs | 11.2 μs | 8.2 μs | 35.7 μs | 16.8 μs | 8.2 μs | 12.6 μs | ExpFromLeft (8.2 μs) | 1.01x | -| two_scale | sorted_uniform | 65536 | 4096 | 182.9 μs | 203.6 μs | 162.1 μs | 580.8 μs | 417.7 μs | 157.6 μs | 436.2 μs | ExpFromLeft (162.1 μs) | 0.97x | -| two_scale | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| two_scale | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 520 ns | 210 ns | 130 ns | 170 ns | Linear (130 ns) | 1.00x | -| two_scale | sorted_dense_burst | 64 | 256 | 1.9 μs | 3.5 μs | 2.8 μs | 12.1 μs | 4.2 μs | 1.9 μs | 3.6 μs | Linear (1.9 μs) | 1.01x | -| two_scale | sorted_dense_burst | 64 | 4096 | 30.1 μs | 55.2 μs | 43.6 μs | 182.9 μs | 66.6 μs | 30.1 μs | 56.8 μs | Linear (30.1 μs) | 1.00x | +| jittered | unsorted | 65536 | 10 | 410 ns | 420 ns | 410 ns | 420 ns | 430 ns | 429 ns | 410 ns | ExpFromLeft (410 ns) | 1.05x | +| jittered | unsorted | 65536 | 256 | 14.5 μs | 14.4 μs | 14.3 μs | 14.2 μs | 14.1 μs | 14.0 μs | 13.9 μs | Binary (14.1 μs) | 0.99x | +| jittered | unsorted | 65536 | 4096 | 835.7 μs | 837.6 μs | 831.0 μs | 834.1 μs | 837.0 μs | 839.5 μs | 839.3 μs | ExpFromLeft (831.0 μs) | 1.01x | +| random | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_uniform | 64 | 10 | 190 ns | 240 ns | 200 ns | 380 ns | 210 ns | 220 ns | 180 ns | Linear (190 ns) | 1.16x | +| random | sorted_uniform | 64 | 256 | 2.2 μs | 4.2 μs | 3.6 μs | 8.8 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.2 μs) | 0.96x | +| random | sorted_uniform | 64 | 4096 | 32.2 μs | 56.0 μs | 43.5 μs | 127.6 μs | 68.4 μs | 30.8 μs | 60.0 μs | Linear (32.2 μs) | 0.96x | +| random | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_uniform | 1024 | 10 | 1.7 μs | 430 ns | 330 ns | 410 ns | 290 ns | 450 ns | 270 ns | Binary (290 ns) | 1.55x | +| random | sorted_uniform | 1024 | 256 | 3.7 μs | 5.2 μs | 3.8 μs | 10.3 μs | 7.3 μs | 3.6 μs | 6.6 μs | Linear (3.7 μs) | 0.97x | +| random | sorted_uniform | 1024 | 4096 | 43.9 μs | 70.0 μs | 58.6 μs | 189.0 μs | 206.3 μs | 42.8 μs | 196.8 μs | Linear (43.9 μs) | 0.97x | +| random | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| random | sorted_uniform | 65536 | 10 | 56.6 μs | 660 ns | 480 ns | 570 ns | 440 ns | 600 ns | 410 ns | Binary (440 ns) | 1.36x | +| random | sorted_uniform | 65536 | 256 | 101.9 μs | 12.9 μs | 9.5 μs | 15.5 μs | 12.3 μs | 15.7 μs | 15.1 μs | ExpFromLeft (9.5 μs) | 1.65x | +| random | sorted_uniform | 65536 | 4096 | 196.9 μs | 250.3 μs | 204.7 μs | 366.9 μs | 486.7 μs | 203.4 μs | 486.5 μs | Linear (196.9 μs) | 1.03x | +| random | sorted_dense_burst | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_dense_burst | 64 | 10 | 120 ns | 190 ns | 150 ns | 360 ns | 200 ns | 140 ns | 170 ns | Linear (120 ns) | 1.17x | +| random | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.7 μs | 2.7 μs | 8.0 μs | 4.4 μs | 1.9 μs | 3.6 μs | Linear (2.0 μs) | 0.96x | +| random | sorted_dense_burst | 64 | 4096 | 31.3 μs | 58.2 μs | 42.2 μs | 125.3 μs | 67.9 μs | 29.5 μs | 56.8 μs | Linear (31.3 μs) | 0.94x | +| random | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 480 ns | 300 ns | 140 ns | 280 ns | Linear (130 ns) | 1.08x | +| random | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.0 μs | 6.7 μs | 1.9 μs | 6.0 μs | Linear (2.0 μs) | 0.96x | +| random | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.1 μs | 42.3 μs | 175.6 μs | 106.9 μs | 29.9 μs | 96.7 μs | Linear (30.8 μs) | 0.97x | +| random | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| random | sorted_dense_burst | 65536 | 10 | 150 ns | 210 ns | 170 ns | 680 ns | 450 ns | 160 ns | 410 ns | Linear (150 ns) | 1.07x | +| random | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.7 μs | 2.7 μs | 15.3 μs | 10.3 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 0.96x | +| random | sorted_dense_burst | 65536 | 4096 | 31.3 μs | 57.9 μs | 42.3 μs | 241.9 μs | 164.5 μs | 29.5 μs | 152.4 μs | Linear (31.3 μs) | 0.94x | +| random | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| random | sorted_near_start | 64 | 10 | 200 ns | 200 ns | 170 ns | 340 ns | 200 ns | 180 ns | 180 ns | ExpFromLeft (170 ns) | 1.06x | +| random | sorted_near_start | 64 | 256 | 2.2 μs | 3.7 μs | 2.8 μs | 8.1 μs | 4.3 μs | 2.0 μs | 3.8 μs | Linear (2.2 μs) | 0.91x | +| random | sorted_near_start | 64 | 4096 | 31.8 μs | 59.0 μs | 43.3 μs | 129.1 μs | 67.4 μs | 30.0 μs | 60.1 μs | Linear (31.8 μs) | 0.94x | +| random | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| random | sorted_near_start | 1024 | 10 | 740 ns | 270 ns | 210 ns | 400 ns | 290 ns | 230 ns | 260 ns | ExpFromLeft (210 ns) | 1.10x | +| random | sorted_near_start | 1024 | 256 | 3.8 μs | 4.4 μs | 3.8 μs | 10.2 μs | 6.8 μs | 3.7 μs | 6.5 μs | Linear (3.8 μs) | 0.99x | +| random | sorted_near_start | 1024 | 4096 | 34.2 μs | 58.0 μs | 44.4 μs | 150.6 μs | 109.5 μs | 32.9 μs | 102.6 μs | Linear (34.2 μs) | 0.96x | +| random | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | 70 ns | InterpSearch (80 ns) | 0.88x | +| random | sorted_near_start | 65536 | 10 | 38.8 μs | 520 ns | 390 ns | 490 ns | 440 ns | 520 ns | 410 ns | ExpFromLeft (390 ns) | 1.33x | +| random | sorted_near_start | 65536 | 256 | 95.0 μs | 7.9 μs | 5.9 μs | 11.7 μs | 12.1 μs | 12.4 μs | 12.0 μs | ExpFromLeft (5.9 μs) | 2.11x | +| random | sorted_near_start | 65536 | 4096 | 162.3 μs | 128.6 μs | 105.6 μs | 252.7 μs | 360.0 μs | 105.6 μs | 348.6 μs | ExpFromLeft (105.6 μs) | 1.00x | +| random | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| random | unsorted | 64 | 10 | 180 ns | 180 ns | 180 ns | 180 ns | 200 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | +| random | unsorted | 64 | 256 | 7.2 μs | 7.1 μs | 7.3 μs | 7.3 μs | 7.2 μs | 7.2 μs | 3.9 μs | Gallop (7.1 μs) | 1.02x | +| random | unsorted | 64 | 4096 | 210.5 μs | 207.7 μs | 207.2 μs | 207.8 μs | 206.4 μs | 207.3 μs | 216.9 μs | Binary (206.4 μs) | 1.00x | +| random | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| random | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 290 ns | 260 ns | InterpSearch (280 ns) | 1.04x | +| random | unsorted | 1024 | 256 | 8.0 μs | 8.1 μs | 7.8 μs | 8.0 μs | 7.9 μs | 8.0 μs | 6.6 μs | ExpFromLeft (7.8 μs) | 1.02x | +| random | unsorted | 1024 | 4096 | 384.4 μs | 379.7 μs | 380.5 μs | 381.1 μs | 379.0 μs | 380.1 μs | 391.3 μs | Binary (379.0 μs) | 1.00x | +| random | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| random | unsorted | 65536 | 10 | 560 ns | 430 ns | 430 ns | 440 ns | 430 ns | 450 ns | 430 ns | ExpFromLeft (430 ns) | 1.05x | +| random | unsorted | 65536 | 256 | 14.4 μs | 14.2 μs | 14.1 μs | 14.1 μs | 13.7 μs | 13.7 μs | 14.6 μs | Binary (13.7 μs) | 1.00x | +| random | unsorted | 65536 | 4096 | 842.5 μs | 841.9 μs | 839.8 μs | 841.4 μs | 839.0 μs | 839.8 μs | 843.0 μs | Binary (839.0 μs) | 1.00x | +| two_scale | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| two_scale | sorted_uniform | 64 | 10 | 220 ns | 220 ns | 170 ns | 410 ns | 200 ns | 190 ns | 180 ns | ExpFromLeft (170 ns) | 1.12x | +| two_scale | sorted_uniform | 64 | 256 | 2.4 μs | 3.9 μs | 3.2 μs | 11.4 μs | 4.5 μs | 2.3 μs | 3.9 μs | Linear (2.4 μs) | 0.97x | +| two_scale | sorted_uniform | 64 | 4096 | 31.8 μs | 58.5 μs | 42.9 μs | 165.6 μs | 68.8 μs | 30.2 μs | 59.4 μs | Linear (31.8 μs) | 0.95x | +| two_scale | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_uniform | 1024 | 10 | 570 ns | 370 ns | 290 ns | 630 ns | 300 ns | 300 ns | 270 ns | ExpFromLeft (290 ns) | 1.03x | +| two_scale | sorted_uniform | 1024 | 256 | 2.8 μs | 4.5 μs | 3.3 μs | 16.2 μs | 7.1 μs | 2.8 μs | 6.2 μs | Linear (2.8 μs) | 1.01x | +| two_scale | sorted_uniform | 1024 | 4096 | 40.3 μs | 64.6 μs | 51.2 μs | 294.8 μs | 159.0 μs | 38.9 μs | 149.3 μs | Linear (40.3 μs) | 0.97x | +| two_scale | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 90 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_uniform | 65536 | 10 | 46.4 μs | 630 ns | 460 ns | 910 ns | 440 ns | 480 ns | 420 ns | Binary (440 ns) | 1.09x | +| two_scale | sorted_uniform | 65536 | 256 | 61.8 μs | 11.3 μs | 8.3 μs | 26.5 μs | 14.0 μs | 8.5 μs | 13.9 μs | ExpFromLeft (8.3 μs) | 1.03x | +| two_scale | sorted_uniform | 65536 | 4096 | 192.9 μs | 202.0 μs | 160.3 μs | 683.7 μs | 440.3 μs | 158.9 μs | 431.4 μs | ExpFromLeft (160.3 μs) | 0.99x | +| two_scale | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 50 ns | 80 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| two_scale | sorted_dense_burst | 64 | 10 | 130 ns | 190 ns | 150 ns | 490 ns | 210 ns | 140 ns | 169 ns | Linear (130 ns) | 1.08x | +| two_scale | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 11.4 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.97x | +| two_scale | sorted_dense_burst | 64 | 4096 | 32.9 μs | 55.0 μs | 42.3 μs | 180.7 μs | 68.0 μs | 31.5 μs | 56.8 μs | Linear (32.9 μs) | 0.96x | | two_scale | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 770 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | -| two_scale | sorted_dense_burst | 1024 | 256 | 1.9 μs | 3.5 μs | 3.1 μs | 16.9 μs | 6.7 μs | 1.9 μs | 6.0 μs | Linear (1.9 μs) | 1.00x | -| two_scale | sorted_dense_burst | 1024 | 4096 | 30.1 μs | 55.4 μs | 43.5 μs | 262.5 μs | 105.5 μs | 30.1 μs | 94.8 μs | Linear (30.1 μs) | 1.00x | -| two_scale | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | -| two_scale | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 1.1 μs | 440 ns | 160 ns | 420 ns | Linear (150 ns) | 1.07x | -| two_scale | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.8 μs | 24.6 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | -| two_scale | sorted_dense_burst | 65536 | 4096 | 30.1 μs | 55.2 μs | 43.5 μs | 391.4 μs | 163.1 μs | 30.1 μs | 152.4 μs | Linear (30.1 μs) | 1.00x | -| two_scale | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| two_scale | sorted_near_start | 64 | 10 | 200 ns | 210 ns | 180 ns | 350 ns | 200 ns | 210 ns | 170 ns | ExpFromLeft (180 ns) | 1.17x | -| two_scale | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.9 μs | 7.5 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.00x | -| two_scale | sorted_near_start | 64 | 4096 | 30.4 μs | 55.7 μs | 44.1 μs | 122.2 μs | 66.6 μs | 30.7 μs | 59.9 μs | Linear (30.4 μs) | 1.01x | +| two_scale | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 690 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | +| two_scale | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.4 μs | 6.7 μs | 1.9 μs | 6.0 μs | Linear (2.0 μs) | 0.96x | +| two_scale | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 42.3 μs | 261.2 μs | 106.8 μs | 31.5 μs | 95.8 μs | Linear (30.8 μs) | 1.03x | +| two_scale | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_dense_burst | 65536 | 10 | 150 ns | 210 ns | 180 ns | 1.0 μs | 450 ns | 160 ns | 410 ns | Linear (150 ns) | 1.07x | +| two_scale | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.1 μs | 10.3 μs | 2.1 μs | 9.6 μs | Linear (2.0 μs) | 1.02x | +| two_scale | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.2 μs | 384.5 μs | 164.6 μs | 31.6 μs | 152.4 μs | Linear (30.8 μs) | 1.03x | +| two_scale | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| two_scale | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 160 ns | 340 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (160 ns) | 1.25x | +| two_scale | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.1 μs | 4.3 μs | 2.0 μs | 3.8 μs | Linear (2.1 μs) | 0.97x | +| two_scale | sorted_near_start | 64 | 4096 | 31.4 μs | 55.6 μs | 42.9 μs | 113.4 μs | 67.5 μs | 30.1 μs | 59.9 μs | Linear (31.4 μs) | 0.96x | | two_scale | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_near_start | 1024 | 10 | 1.4 μs | 290 ns | 240 ns | 450 ns | 290 ns | 250 ns | 280 ns | ExpFromLeft (240 ns) | 1.04x | -| two_scale | sorted_near_start | 1024 | 256 | 3.6 μs | 4.4 μs | 3.3 μs | 14.0 μs | 7.3 μs | 3.7 μs | 6.4 μs | ExpFromLeft (3.3 μs) | 1.13x | -| two_scale | sorted_near_start | 1024 | 4096 | 32.6 μs | 57.6 μs | 45.1 μs | 195.5 μs | 108.3 μs | 32.8 μs | 101.9 μs | Linear (32.6 μs) | 1.01x | -| two_scale | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_near_start | 65536 | 10 | 61.9 μs | 540 ns | 420 ns | 880 ns | 480 ns | 420 ns | 410 ns | ExpFromLeft (420 ns) | 1.00x | -| two_scale | sorted_near_start | 65536 | 256 | 95.5 μs | 7.8 μs | 5.8 μs | 29.0 μs | 19.0 μs | 5.7 μs | 11.8 μs | ExpFromLeft (5.8 μs) | 0.97x | -| two_scale | sorted_near_start | 65536 | 4096 | 159.5 μs | 121.5 μs | 96.4 μs | 432.5 μs | 294.4 μs | 92.1 μs | 349.6 μs | ExpFromLeft (96.4 μs) | 0.96x | -| two_scale | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| two_scale | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | -| two_scale | unsorted | 64 | 256 | 3.9 μs | 3.9 μs | 3.9 μs | 4.0 μs | 3.9 μs | 3.9 μs | 4.0 μs | ExpFromLeft (3.9 μs) | 1.00x | -| two_scale | unsorted | 64 | 4096 | 194.2 μs | 192.4 μs | 190.3 μs | 188.2 μs | 189.3 μs | 189.3 μs | 190.8 μs | InterpSearch (188.2 μs) | 1.01x | +| two_scale | sorted_near_start | 1024 | 10 | 1.4 μs | 290 ns | 230 ns | 450 ns | 290 ns | 260 ns | 270 ns | ExpFromLeft (230 ns) | 1.13x | +| two_scale | sorted_near_start | 1024 | 256 | 3.9 μs | 4.5 μs | 3.6 μs | 11.8 μs | 6.9 μs | 3.8 μs | 6.3 μs | ExpFromLeft (3.6 μs) | 1.07x | +| two_scale | sorted_near_start | 1024 | 4096 | 33.9 μs | 60.3 μs | 44.0 μs | 182.1 μs | 110.9 μs | 32.4 μs | 101.7 μs | Linear (33.9 μs) | 0.96x | +| two_scale | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_near_start | 65536 | 10 | 62.3 μs | 540 ns | 410 ns | 800 ns | 440 ns | 420 ns | 400 ns | ExpFromLeft (410 ns) | 1.02x | +| two_scale | sorted_near_start | 65536 | 256 | 95.1 μs | 7.8 μs | 5.7 μs | 20.7 μs | 12.2 μs | 5.8 μs | 11.4 μs | ExpFromLeft (5.7 μs) | 1.01x | +| two_scale | sorted_near_start | 65536 | 4096 | 161.8 μs | 121.8 μs | 98.4 μs | 479.0 μs | 353.3 μs | 101.4 μs | 345.3 μs | ExpFromLeft (98.4 μs) | 1.03x | +| two_scale | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 90 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| two_scale | unsorted | 64 | 10 | 180 ns | 180 ns | 190 ns | 180 ns | 200 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | +| two_scale | unsorted | 64 | 256 | 6.2 μs | 6.1 μs | 6.1 μs | 6.1 μs | 6.2 μs | 6.2 μs | 4.0 μs | ExpFromLeft (6.1 μs) | 1.02x | +| two_scale | unsorted | 64 | 4096 | 183.4 μs | 178.6 μs | 180.0 μs | 181.6 μs | 178.2 μs | 178.9 μs | 194.7 μs | Binary (178.2 μs) | 1.00x | | two_scale | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | unsorted | 1024 | 10 | 280 ns | 280 ns | 289 ns | 290 ns | 280 ns | 280 ns | 270 ns | Binary (280 ns) | 1.00x | -| two_scale | unsorted | 1024 | 256 | 6.3 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.7 μs | InterpSearch (6.2 μs) | 1.00x | -| two_scale | unsorted | 1024 | 4096 | 364.2 μs | 362.8 μs | 362.8 μs | 363.0 μs | 361.4 μs | 361.9 μs | 362.4 μs | Binary (361.4 μs) | 1.00x | -| two_scale | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | unsorted | 65536 | 10 | 420 ns | 430 ns | 430 ns | 430 ns | 430 ns | 440 ns | 410 ns | Linear (420 ns) | 1.05x | -| two_scale | unsorted | 65536 | 256 | 10.4 μs | 10.2 μs | 10.2 μs | 10.2 μs | 10.2 μs | 10.2 μs | 15.2 μs | InterpSearch (10.2 μs) | 1.00x | -| two_scale | unsorted | 65536 | 4096 | 759.1 μs | 755.8 μs | 757.6 μs | 729.2 μs | 760.2 μs | 757.5 μs | 757.7 μs | InterpSearch (729.2 μs) | 1.04x | +| two_scale | unsorted | 1024 | 10 | 280 ns | 270 ns | 270 ns | 270 ns | 280 ns | 280 ns | 270 ns | InterpSearch (270 ns) | 1.04x | +| two_scale | unsorted | 1024 | 256 | 9.6 μs | 9.3 μs | 9.4 μs | 9.6 μs | 9.5 μs | 9.3 μs | 6.4 μs | Gallop (9.3 μs) | 1.00x | +| two_scale | unsorted | 1024 | 4096 | 342.3 μs | 340.2 μs | 342.3 μs | 342.9 μs | 342.7 μs | 338.1 μs | 360.6 μs | Gallop (340.2 μs) | 0.99x | +| two_scale | unsorted | 65536 | 1 | 80 ns | 79 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | Gallop (79 ns) | 1.01x | +| two_scale | unsorted | 65536 | 10 | 420 ns | 420 ns | 420 ns | 430 ns | 440 ns | 430 ns | 410 ns | ExpFromLeft (420 ns) | 1.02x | +| two_scale | unsorted | 65536 | 256 | 15.4 μs | 14.8 μs | 14.5 μs | 14.7 μs | 14.3 μs | 14.6 μs | 13.5 μs | Binary (14.3 μs) | 1.02x | +| two_scale | unsorted | 65536 | 4096 | 752.9 μs | 752.5 μs | 751.6 μs | 753.7 μs | 751.3 μs | 752.9 μs | 756.6 μs | Binary (751.3 μs) | 1.00x | -**Auto verdict over 240 cells**: 214 within 20% of best, 10 worse than 20% slowdown, 16 effectively-faster-than-best (shouldn't happen). +**Auto verdict over 240 cells**: 213 within 20% of best, 13 worse than 20% slowdown, 14 effectively-faster-than-best. diff --git a/bench/results_focused.md b/bench/results_focused.md new file mode 100644 index 0000000..357955b --- /dev/null +++ b/bench/results_focused.md @@ -0,0 +1,571 @@ + +## Spacing variety (n=4096, m=512, sorted_uniform) + +| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| uniform | sorted_uniform | 4096 | 512 | 10.4 μs | 12.7 μs | 9.2 μs | 19.2 μs | 24.6 μs | 9.4 μs | 29.8 μs | ExpFromLeft (9.2 μs) | 1.02x | +| log | sorted_uniform | 4096 | 512 | 10.1 μs | 10.4 μs | 7.5 μs | 39.9 μs | 21.7 μs | 8.0 μs | 27.8 μs | ExpFromLeft (7.5 μs) | 1.07x | +| jittered | sorted_uniform | 4096 | 512 | 10.2 μs | 12.5 μs | 9.5 μs | 18.8 μs | 26.3 μs | 9.3 μs | 33.5 μs | ExpFromLeft (9.5 μs) | 0.99x | +| random | sorted_uniform | 4096 | 512 | 10.4 μs | 12.0 μs | 8.9 μs | 22.3 μs | 23.7 μs | 9.2 μs | 30.7 μs | ExpFromLeft (8.9 μs) | 1.03x | +| two_scale | sorted_uniform | 4096 | 512 | 7.3 μs | 10.3 μs | 7.9 μs | 40.9 μs | 22.9 μs | 8.0 μs | 29.4 μs | Linear (7.3 μs) | 1.10x | +| power2 | sorted_uniform | 4096 | 512 | 10.4 μs | 11.9 μs | 9.0 μs | 38.4 μs | 25.9 μs | 9.3 μs | 33.4 μs | ExpFromLeft (9.0 μs) | 1.03x | +| sqrt | sorted_uniform | 4096 | 512 | 10.4 μs | 12.1 μs | 9.0 μs | 36.4 μs | 23.9 μs | 9.4 μs | 29.6 μs | ExpFromLeft (9.0 μs) | 1.05x | +| plateau | sorted_uniform | 4096 | 512 | 5.8 μs | 7.0 μs | 5.4 μs | 39.1 μs | 15.8 μs | 5.6 μs | 14.6 μs | ExpFromLeft (5.4 μs) | 1.04x | +| bimodal | sorted_uniform | 4096 | 512 | 11.3 μs | 8.9 μs | 6.8 μs | 41.7 μs | 16.0 μs | 7.0 μs | 14.9 μs | ExpFromLeft (6.8 μs) | 1.03x | +| near_linear | sorted_uniform | 4096 | 512 | 10.3 μs | 12.8 μs | 9.3 μs | 18.9 μs | 26.2 μs | 9.4 μs | 32.7 μs | ExpFromLeft (9.3 μs) | 1.01x | + +**Auto verdict over 10 cells**: 10 within 20% of best, 0 worse than 20% slowdown, 0 effectively-faster-than-best. + +## Query patterns (n=4096, m=512, uniform) + +| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| uniform | sorted_uniform | 4096 | 512 | 10.3 μs | 12.2 μs | 9.0 μs | 19.1 μs | 22.8 μs | 9.2 μs | 22.7 μs | ExpFromLeft (9.0 μs) | 1.02x | +| uniform | sorted_dense_burst | 4096 | 512 | 3.9 μs | 6.9 μs | 5.3 μs | 13.8 μs | 16.0 μs | 3.8 μs | 14.3 μs | Linear (3.9 μs) | 0.97x | +| uniform | sorted_near_start | 4096 | 512 | 10.6 μs | 9.3 μs | 8.8 μs | 18.8 μs | 17.2 μs | 8.9 μs | 16.4 μs | ExpFromLeft (8.8 μs) | 1.01x | +| uniform | sorted_arithmetic | 4096 | 512 | 10.3 μs | 13.5 μs | 11.6 μs | 14.2 μs | 23.8 μs | 11.6 μs | 25.3 μs | Linear (10.3 μs) | 1.12x | +| uniform | sorted_geometric | 4096 | 512 | 11.4 μs | 13.5 μs | 9.9 μs | 17.6 μs | 26.3 μs | 9.8 μs | 26.3 μs | ExpFromLeft (9.9 μs) | 1.00x | +| uniform | sorted_bimodal | 4096 | 512 | 9.4 μs | 9.1 μs | 6.3 μs | 18.5 μs | 20.4 μs | 6.3 μs | 19.2 μs | ExpFromLeft (6.3 μs) | 1.00x | +| uniform | sorted_repeated | 4096 | 512 | 3.9 μs | 6.9 μs | 5.0 μs | 13.4 μs | 16.0 μs | 3.8 μs | 14.3 μs | Linear (3.9 μs) | 0.96x | +| uniform | unsorted | 4096 | 512 | 33.2 μs | 31.7 μs | 31.2 μs | 30.9 μs | 30.6 μs | 30.4 μs | 30.7 μs | Binary (30.6 μs) | 0.99x | + +**Auto verdict over 8 cells**: 8 within 20% of best, 0 worse than 20% slowdown, 0 effectively-faster-than-best. + +## n/m crossover (uniform, sorted_uniform) + +| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| uniform | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 50 ns | 60 ns | 40 ns | Binary (50 ns) | 1.20x | +| uniform | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 80 ns | 150 ns | 90 ns | 110 ns | 70 ns | ExpFromLeft (80 ns) | 1.38x | +| uniform | sorted_uniform | 16 | 16 | 190 ns | 300 ns | 210 ns | 470 ns | 230 ns | 220 ns | 190 ns | Linear (190 ns) | 1.16x | +| uniform | sorted_uniform | 16 | 64 | 560 ns | 1.0 μs | 710 ns | 2.0 μs | 990 ns | 570 ns | 880 ns | Linear (560 ns) | 1.02x | +| uniform | sorted_uniform | 16 | 256 | 2.3 μs | 3.9 μs | 2.9 μs | 7.9 μs | 3.3 μs | 2.2 μs | 2.9 μs | Linear (2.3 μs) | 0.96x | +| uniform | sorted_uniform | 16 | 1024 | 8.1 μs | 14.7 μs | 10.8 μs | 28.8 μs | 12.5 μs | 7.7 μs | 10.6 μs | Linear (8.1 μs) | 0.95x | +| uniform | sorted_uniform | 16 | 4096 | 31.5 μs | 58.0 μs | 42.2 μs | 109.3 μs | 48.5 μs | 29.4 μs | 40.8 μs | Linear (31.5 μs) | 0.93x | +| uniform | sorted_uniform | 16 | 16384 | 123.2 μs | 218.6 μs | 168.1 μs | 432.2 μs | 191.5 μs | 116.6 μs | 162.1 μs | Linear (123.2 μs) | 0.95x | +| uniform | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 60 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| uniform | sorted_uniform | 64 | 4 | 140 ns | 129 ns | 120 ns | 140 ns | 100 ns | 150 ns | 90 ns | Binary (100 ns) | 1.50x | +| uniform | sorted_uniform | 64 | 16 | 240 ns | 340 ns | 260 ns | 460 ns | 330 ns | 260 ns | 350 ns | Linear (240 ns) | 1.08x | +| uniform | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 730 ns | 2.2 μs | 1.4 μs | 650 ns | 1.3 μs | Linear (630 ns) | 1.03x | +| uniform | sorted_uniform | 64 | 256 | 2.3 μs | 4.1 μs | 3.1 μs | 9.0 μs | 5.3 μs | 2.2 μs | 4.8 μs | Linear (2.3 μs) | 0.97x | +| uniform | sorted_uniform | 64 | 1024 | 12.1 μs | 14.8 μs | 11.7 μs | 31.2 μs | 17.8 μs | 8.8 μs | 16.0 μs | ExpFromLeft (11.7 μs) | 0.75x | +| uniform | sorted_uniform | 64 | 4096 | 32.2 μs | 56.0 μs | 43.2 μs | 112.9 μs | 67.4 μs | 30.6 μs | 60.1 μs | Linear (32.2 μs) | 0.95x | +| uniform | sorted_uniform | 64 | 16384 | 124.3 μs | 220.7 μs | 169.4 μs | 439.1 μs | 265.8 μs | 117.8 μs | 237.0 μs | Linear (124.3 μs) | 0.95x | +| uniform | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 69 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_uniform | 256 | 4 | 360 ns | 160 ns | 130 ns | 140 ns | 120 ns | 160 ns | 110 ns | Binary (120 ns) | 1.33x | +| uniform | sorted_uniform | 256 | 16 | 590 ns | 490 ns | 460 ns | 470 ns | 370 ns | 400 ns | 340 ns | Binary (370 ns) | 1.08x | +| uniform | sorted_uniform | 256 | 64 | 930 ns | 1.4 μs | 960 ns | 2.1 μs | 1.5 μs | 950 ns | 1.4 μs | Linear (930 ns) | 1.02x | +| uniform | sorted_uniform | 256 | 256 | 2.4 μs | 4.1 μs | 2.8 μs | 9.3 μs | 7.0 μs | 2.3 μs | 6.7 μs | Linear (2.4 μs) | 0.98x | +| uniform | sorted_uniform | 256 | 1024 | 9.8 μs | 17.8 μs | 13.5 μs | 37.0 μs | 26.8 μs | 9.4 μs | 25.1 μs | Linear (9.8 μs) | 0.96x | +| uniform | sorted_uniform | 256 | 4096 | 51.3 μs | 59.7 μs | 46.6 μs | 123.3 μs | 90.4 μs | 34.8 μs | 83.8 μs | ExpFromLeft (46.6 μs) | 0.75x | +| uniform | sorted_uniform | 256 | 16384 | 128.7 μs | 224.4 μs | 172.8 μs | 451.3 μs | 347.7 μs | 122.1 μs | 317.1 μs | Linear (128.7 μs) | 0.95x | +| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| uniform | sorted_uniform | 1024 | 4 | 1.1 μs | 190 ns | 160 ns | 140 ns | 140 ns | 180 ns | 120 ns | InterpSearch (140 ns) | 1.29x | +| uniform | sorted_uniform | 1024 | 16 | 1.7 μs | 570 ns | 430 ns | 490 ns | 440 ns | 480 ns | 410 ns | ExpFromLeft (430 ns) | 1.12x | +| uniform | sorted_uniform | 1024 | 64 | 2.1 μs | 1.8 μs | 1.3 μs | 1.9 μs | 1.8 μs | 1.4 μs | 1.6 μs | ExpFromLeft (1.3 μs) | 1.03x | +| uniform | sorted_uniform | 1024 | 256 | 3.5 μs | 5.5 μs | 3.8 μs | 8.7 μs | 8.2 μs | 3.4 μs | 8.1 μs | Linear (3.5 μs) | 0.99x | +| uniform | sorted_uniform | 1024 | 1024 | 10.5 μs | 17.9 μs | 12.3 μs | 39.4 μs | 59.8 μs | 10.1 μs | 61.1 μs | Linear (10.5 μs) | 0.96x | +| uniform | sorted_uniform | 1024 | 4096 | 48.8 μs | 72.4 μs | 57.6 μs | 150.0 μs | 197.6 μs | 47.3 μs | 193.4 μs | Linear (48.8 μs) | 0.97x | +| uniform | sorted_uniform | 1024 | 16384 | 166.1 μs | 237.4 μs | 186.4 μs | 499.7 μs | 512.6 μs | 139.6 μs | 488.7 μs | Linear (166.1 μs) | 0.84x | +| uniform | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_uniform | 4096 | 4 | 2.3 μs | 220 ns | 170 ns | 140 ns | 150 ns | 180 ns | 150 ns | InterpSearch (140 ns) | 1.29x | +| uniform | sorted_uniform | 4096 | 16 | 6.0 μs | 740 ns | 560 ns | 460 ns | 510 ns | 520 ns | 490 ns | InterpSearch (460 ns) | 1.13x | +| uniform | sorted_uniform | 4096 | 64 | 7.2 μs | 2.3 μs | 1.7 μs | 2.0 μs | 2.0 μs | 1.7 μs | 1.9 μs | ExpFromLeft (1.7 μs) | 1.01x | +| uniform | sorted_uniform | 4096 | 256 | 8.8 μs | 7.2 μs | 5.3 μs | 9.0 μs | 10.8 μs | 5.3 μs | 11.6 μs | ExpFromLeft (5.3 μs) | 1.00x | +| uniform | sorted_uniform | 4096 | 1024 | 16.3 μs | 23.7 μs | 17.6 μs | 38.2 μs | 98.9 μs | 14.9 μs | 97.1 μs | Linear (16.3 μs) | 0.91x | +| uniform | sorted_uniform | 4096 | 4096 | 67.4 μs | 94.9 μs | 71.0 μs | 160.5 μs | 300.1 μs | 62.9 μs | 296.7 μs | Linear (67.4 μs) | 0.93x | +| uniform | sorted_uniform | 4096 | 16384 | 210.2 μs | 292.8 μs | 235.1 μs | 626.5 μs | 806.4 μs | 203.1 μs | 773.4 μs | Linear (210.2 μs) | 0.97x | +| uniform | sorted_uniform | 16384 | 1 | 70 ns | 80 ns | 70 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | +| uniform | sorted_uniform | 16384 | 4 | 17.8 μs | 270 ns | 210 ns | 149 ns | 180 ns | 180 ns | 170 ns | InterpSearch (149 ns) | 1.21x | +| uniform | sorted_uniform | 16384 | 16 | 19.2 μs | 860 ns | 640 ns | 510 ns | 590 ns | 570 ns | 620 ns | InterpSearch (510 ns) | 1.12x | +| uniform | sorted_uniform | 16384 | 64 | 25.1 μs | 2.9 μs | 2.2 μs | 2.0 μs | 2.4 μs | 2.1 μs | 2.3 μs | InterpSearch (2.0 μs) | 1.05x | +| uniform | sorted_uniform | 16384 | 256 | 29.4 μs | 9.6 μs | 7.0 μs | 9.1 μs | 13.8 μs | 7.0 μs | 13.1 μs | ExpFromLeft (7.0 μs) | 1.00x | +| uniform | sorted_uniform | 16384 | 1024 | 42.5 μs | 36.2 μs | 26.5 μs | 39.7 μs | 129.1 μs | 23.1 μs | 128.7 μs | ExpFromLeft (26.5 μs) | 0.87x | +| uniform | sorted_uniform | 16384 | 4096 | 115.1 μs | 161.1 μs | 120.8 μs | 160.4 μs | 403.0 μs | 110.1 μs | 397.8 μs | Linear (115.1 μs) | 0.96x | +| uniform | sorted_uniform | 16384 | 16384 | 373.0 μs | 442.9 μs | 368.9 μs | 641.6 μs | 1.15 ms | 365.4 μs | 1.13 ms | ExpFromLeft (368.9 μs) | 0.99x | +| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_uniform | 65536 | 4 | 22.3 μs | 270 ns | 210 ns | 140 ns | 190 ns | 180 ns | 190 ns | InterpSearch (140 ns) | 1.29x | +| uniform | sorted_uniform | 65536 | 16 | 83.8 μs | 1.1 μs | 769 ns | 460 ns | 680 ns | 510 ns | 650 ns | InterpSearch (460 ns) | 1.11x | +| uniform | sorted_uniform | 65536 | 64 | 94.7 μs | 3.6 μs | 2.6 μs | 2.1 μs | 2.8 μs | 2.2 μs | 2.7 μs | InterpSearch (2.1 μs) | 1.06x | +| uniform | sorted_uniform | 65536 | 256 | 102.8 μs | 12.5 μs | 9.3 μs | 8.9 μs | 16.7 μs | 9.3 μs | 17.1 μs | InterpSearch (8.9 μs) | 1.04x | +| uniform | sorted_uniform | 65536 | 1024 | 116.7 μs | 61.9 μs | 45.4 μs | 41.4 μs | 161.3 μs | 37.2 μs | 164.8 μs | InterpSearch (41.4 μs) | 0.90x | +| uniform | sorted_uniform | 65536 | 4096 | 194.1 μs | 260.1 μs | 209.3 μs | 165.3 μs | 494.7 μs | 201.6 μs | 497.8 μs | InterpSearch (165.3 μs) | 1.22x | +| uniform | sorted_uniform | 65536 | 16384 | 545.0 μs | 733.2 μs | 576.0 μs | 644.2 μs | 1.49 ms | 538.0 μs | 1.47 ms | Linear (545.0 μs) | 0.99x | +| uniform | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 80 ns | InterpSearch (60 ns) | 1.33x | +| uniform | sorted_uniform | 262144 | 4 | 153.2 μs | 330 ns | 260 ns | 140 ns | 220 ns | 180 ns | 210 ns | InterpSearch (140 ns) | 1.29x | +| uniform | sorted_uniform | 262144 | 16 | 332.2 μs | 1.2 μs | 880 ns | 510 ns | 780 ns | 560 ns | 770 ns | InterpSearch (510 ns) | 1.10x | +| uniform | sorted_uniform | 262144 | 64 | 363.8 μs | 4.3 μs | 3.0 μs | 2.1 μs | 3.8 μs | 2.2 μs | 3.6 μs | InterpSearch (2.1 μs) | 1.06x | +| uniform | sorted_uniform | 262144 | 256 | 382.3 μs | 16.7 μs | 12.9 μs | 9.7 μs | 21.3 μs | 9.9 μs | 21.3 μs | InterpSearch (9.7 μs) | 1.02x | +| uniform | sorted_uniform | 262144 | 1024 | 410.9 μs | 116.8 μs | 87.4 μs | 42.3 μs | 204.9 μs | 43.4 μs | 209.3 μs | InterpSearch (42.3 μs) | 1.03x | +| uniform | sorted_uniform | 262144 | 4096 | 492.2 μs | 370.3 μs | 300.4 μs | 186.4 μs | 613.9 μs | 299.2 μs | 632.8 μs | InterpSearch (186.4 μs) | 1.61x | +| uniform | sorted_uniform | 262144 | 16384 | 854.5 μs | 1.00 ms | 835.2 μs | 660.4 μs | 1.85 ms | 835.0 μs | 1.87 ms | InterpSearch (660.4 μs) | 1.26x | + +**Auto verdict over 64 cells**: 40 within 20% of best, 13 worse than 20% slowdown, 11 effectively-faster-than-best. + +### Super-sparse cases (small m on large n) + +## Super sparse + +| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| uniform | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_uniform | 1024 | 4 | 500 ns | 160 ns | 140 ns | 170 ns | 140 ns | 180 ns | 130 ns | ExpFromLeft (140 ns) | 1.29x | +| uniform | sorted_uniform | 1024 | 16 | 1.6 μs | 570 ns | 470 ns | 530 ns | 450 ns | 490 ns | 410 ns | Binary (450 ns) | 1.09x | +| uniform | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_uniform | 16384 | 4 | 9.0 μs | 240 ns | 200 ns | 160 ns | 180 ns | 180 ns | 170 ns | InterpSearch (160 ns) | 1.12x | +| uniform | sorted_uniform | 16384 | 16 | 23.5 μs | 890 ns | 650 ns | 540 ns | 600 ns | 540 ns | 560 ns | InterpSearch (540 ns) | 1.00x | +| uniform | sorted_uniform | 262144 | 1 | 90 ns | 80 ns | 80 ns | 70 ns | 90 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_uniform | 262144 | 4 | 256.8 μs | 350 ns | 280 ns | 170 ns | 220 ns | 180 ns | 210 ns | InterpSearch (170 ns) | 1.06x | +| uniform | sorted_uniform | 262144 | 16 | 377.9 μs | 1.2 μs | 910 ns | 490 ns | 850 ns | 530 ns | 830 ns | InterpSearch (490 ns) | 1.08x | +| uniform | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| uniform | unsorted | 1024 | 16 | 469 ns | 460 ns | 450 ns | 440 ns | 440 ns | 450 ns | 450 ns | InterpSearch (440 ns) | 1.02x | +| uniform | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 180 ns | 180 ns | 180 ns | 170 ns | Gallop (170 ns) | 1.06x | +| uniform | unsorted | 16384 | 16 | 570 ns | 570 ns | 570 ns | 560 ns | 560 ns | 570 ns | 560 ns | InterpSearch (560 ns) | 1.02x | +| uniform | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | unsorted | 262144 | 4 | 210 ns | 210 ns | 200 ns | 210 ns | 210 ns | 219 ns | 200 ns | ExpFromLeft (200 ns) | 1.09x | +| uniform | unsorted | 262144 | 16 | 790 ns | 770 ns | 780 ns | 790 ns | 780 ns | 790 ns | 770 ns | Gallop (770 ns) | 1.03x | +| log | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_uniform | 1024 | 4 | 210 ns | 160 ns | 140 ns | 300 ns | 140 ns | 160 ns | 130 ns | ExpFromLeft (140 ns) | 1.14x | +| log | sorted_uniform | 1024 | 16 | 1.1 μs | 490 ns | 380 ns | 1.0 μs | 450 ns | 400 ns | 410 ns | ExpFromLeft (380 ns) | 1.05x | +| log | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| log | sorted_uniform | 16384 | 4 | 2.2 μs | 210 ns | 170 ns | 360 ns | 170 ns | 190 ns | 170 ns | ExpFromLeft (170 ns) | 1.12x | +| log | sorted_uniform | 16384 | 16 | 14.8 μs | 780 ns | 570 ns | 1.4 μs | 600 ns | 610 ns | 610 ns | ExpFromLeft (570 ns) | 1.07x | +| log | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_uniform | 262144 | 4 | 328.8 μs | 330 ns | 260 ns | 420 ns | 210 ns | 290 ns | 200 ns | Binary (210 ns) | 1.38x | +| log | sorted_uniform | 262144 | 16 | 180.8 μs | 1.1 μs | 800 ns | 1.7 μs | 800 ns | 810 ns | 820 ns | ExpFromLeft (800 ns) | 1.01x | +| log | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| log | unsorted | 1024 | 16 | 430 ns | 430 ns | 430 ns | 430 ns | 420 ns | 430 ns | 420 ns | Binary (420 ns) | 1.02x | +| log | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 120 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | +| log | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 170 ns | 170 ns | 190 ns | 160 ns | InterpSearch (170 ns) | 1.12x | +| log | unsorted | 16384 | 16 | 620 ns | 600 ns | 610 ns | 610 ns | 620 ns | 610 ns | 610 ns | Gallop (600 ns) | 1.02x | +| log | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 109 ns | 100 ns | 80 ns | ExpFromLeft (80 ns) | 1.25x | +| log | unsorted | 262144 | 4 | 220 ns | 220 ns | 220 ns | 220 ns | 210 ns | 230 ns | 210 ns | Binary (210 ns) | 1.10x | +| log | unsorted | 262144 | 16 | 770 ns | 780 ns | 760 ns | 790 ns | 780 ns | 760 ns | 790 ns | ExpFromLeft (760 ns) | 1.00x | +| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_uniform | 1024 | 4 | 1.0 μs | 190 ns | 160 ns | 160 ns | 130 ns | 180 ns | 130 ns | Binary (130 ns) | 1.38x | +| jittered | sorted_uniform | 1024 | 16 | 1.8 μs | 619 ns | 480 ns | 500 ns | 480 ns | 510 ns | 410 ns | ExpFromLeft (480 ns) | 1.06x | +| jittered | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | +| jittered | sorted_uniform | 16384 | 4 | 18.1 μs | 250 ns | 200 ns | 160 ns | 180 ns | 170 ns | 160 ns | InterpSearch (160 ns) | 1.06x | +| jittered | sorted_uniform | 16384 | 16 | 21.8 μs | 870 ns | 650 ns | 500 ns | 590 ns | 520 ns | 580 ns | InterpSearch (500 ns) | 1.04x | +| jittered | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_uniform | 262144 | 4 | 321.1 μs | 320 ns | 240 ns | 160 ns | 230 ns | 170 ns | 230 ns | InterpSearch (160 ns) | 1.06x | +| jittered | sorted_uniform | 262144 | 16 | 346.1 μs | 1.2 μs | 859 ns | 530 ns | 929 ns | 560 ns | 930 ns | InterpSearch (530 ns) | 1.06x | +| jittered | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 149 ns | 130 ns | InterpSearch (140 ns) | 1.06x | +| jittered | unsorted | 1024 | 16 | 420 ns | 430 ns | 420 ns | 419 ns | 410 ns | 430 ns | 410 ns | Binary (410 ns) | 1.05x | +| jittered | unsorted | 16384 | 1 | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| jittered | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 180 ns | 170 ns | 180 ns | 170 ns | Binary (170 ns) | 1.06x | +| jittered | unsorted | 16384 | 16 | 580 ns | 580 ns | 570 ns | 570 ns | 570 ns | 580 ns | 560 ns | InterpSearch (570 ns) | 1.02x | +| jittered | unsorted | 262144 | 1 | 90 ns | 90 ns | 80 ns | 70 ns | 90 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | +| jittered | unsorted | 262144 | 4 | 220 ns | 210 ns | 210 ns | 210 ns | 220 ns | 220 ns | 210 ns | InterpSearch (210 ns) | 1.05x | +| jittered | unsorted | 262144 | 16 | 780 ns | 780 ns | 820 ns | 800 ns | 790 ns | 800 ns | 770 ns | Gallop (780 ns) | 1.03x | +| random | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_uniform | 1024 | 4 | 920 ns | 180 ns | 150 ns | 210 ns | 130 ns | 230 ns | 120 ns | Binary (130 ns) | 1.77x | +| random | sorted_uniform | 1024 | 16 | 1.7 μs | 600 ns | 460 ns | 670 ns | 440 ns | 480 ns | 410 ns | Binary (440 ns) | 1.09x | +| random | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_uniform | 16384 | 4 | 15.3 μs | 250 ns | 190 ns | 230 ns | 170 ns | 240 ns | 160 ns | Binary (170 ns) | 1.41x | +| random | sorted_uniform | 16384 | 16 | 19.3 μs | 890 ns | 640 ns | 720 ns | 590 ns | 760 ns | 560 ns | Binary (590 ns) | 1.29x | +| random | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| random | sorted_uniform | 262144 | 4 | 219.6 μs | 340 ns | 260 ns | 260 ns | 220 ns | 270 ns | 200 ns | Binary (220 ns) | 1.23x | +| random | sorted_uniform | 262144 | 16 | 266.0 μs | 1.2 μs | 820 ns | 880 ns | 840 ns | 910 ns | 780 ns | ExpFromLeft (820 ns) | 1.11x | +| random | unsorted | 1024 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| random | unsorted | 1024 | 4 | 150 ns | 140 ns | 140 ns | 140 ns | 150 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| random | unsorted | 1024 | 16 | 420 ns | 420 ns | 420 ns | 430 ns | 420 ns | 430 ns | 400 ns | ExpFromLeft (420 ns) | 1.02x | +| random | unsorted | 16384 | 1 | 79 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| random | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | ExpFromLeft (170 ns) | 1.06x | +| random | unsorted | 16384 | 16 | 580 ns | 570 ns | 569 ns | 570 ns | 570 ns | 570 ns | 600 ns | ExpFromLeft (569 ns) | 1.00x | +| random | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| random | unsorted | 262144 | 4 | 220 ns | 220 ns | 220 ns | 220 ns | 210 ns | 230 ns | 210 ns | Binary (210 ns) | 1.10x | +| random | unsorted | 262144 | 16 | 850 ns | 840 ns | 850 ns | 849 ns | 860 ns | 850 ns | 860 ns | Gallop (840 ns) | 1.01x | +| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| two_scale | sorted_uniform | 1024 | 4 | 570 ns | 170 ns | 150 ns | 280 ns | 130 ns | 170 ns | 130 ns | Binary (130 ns) | 1.31x | +| two_scale | sorted_uniform | 1024 | 16 | 950 ns | 530 ns | 410 ns | 1.2 μs | 450 ns | 430 ns | 410 ns | ExpFromLeft (410 ns) | 1.05x | +| two_scale | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| two_scale | sorted_uniform | 16384 | 4 | 9.2 μs | 240 ns | 190 ns | 360 ns | 180 ns | 230 ns | 160 ns | Binary (180 ns) | 1.28x | +| two_scale | sorted_uniform | 16384 | 16 | 9.7 μs | 770 ns | 570 ns | 1.7 μs | 600 ns | 600 ns | 550 ns | ExpFromLeft (570 ns) | 1.05x | +| two_scale | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_uniform | 262144 | 4 | 150.4 μs | 330 ns | 250 ns | 440 ns | 210 ns | 290 ns | 200 ns | Binary (210 ns) | 1.38x | +| two_scale | sorted_uniform | 262144 | 16 | 165.1 μs | 1.1 μs | 820 ns | 2.0 μs | 870 ns | 850 ns | 810 ns | ExpFromLeft (820 ns) | 1.04x | +| two_scale | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| two_scale | unsorted | 1024 | 16 | 430 ns | 430 ns | 420 ns | 430 ns | 430 ns | 440 ns | 420 ns | ExpFromLeft (420 ns) | 1.05x | +| two_scale | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 180 ns | 180 ns | 180 ns | 159 ns | ExpFromLeft (170 ns) | 1.06x | +| two_scale | unsorted | 16384 | 16 | 570 ns | 560 ns | 570 ns | 580 ns | 580 ns | 580 ns | 560 ns | Gallop (560 ns) | 1.04x | +| two_scale | unsorted | 262144 | 1 | 90 ns | 80 ns | 90 ns | 120 ns | 80 ns | 80 ns | 70 ns | Binary (80 ns) | 1.00x | +| two_scale | unsorted | 262144 | 4 | 220 ns | 210 ns | 210 ns | 210 ns | 210 ns | 230 ns | 210 ns | InterpSearch (210 ns) | 1.10x | +| two_scale | unsorted | 262144 | 16 | 810 ns | 830 ns | 830 ns | 830 ns | 840 ns | 840 ns | 850 ns | Linear (810 ns) | 1.04x | +| power2 | sorted_uniform | 1024 | 1 | 60 ns | 70 ns | 60 ns | 100 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| power2 | sorted_uniform | 1024 | 4 | 1.1 μs | 200 ns | 160 ns | 260 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| power2 | sorted_uniform | 1024 | 16 | 1.7 μs | 590 ns | 460 ns | 1.0 μs | 450 ns | 480 ns | 410 ns | Binary (450 ns) | 1.07x | +| power2 | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_uniform | 16384 | 4 | 11.2 μs | 250 ns | 200 ns | 360 ns | 170 ns | 230 ns | 170 ns | Binary (170 ns) | 1.35x | +| power2 | sorted_uniform | 16384 | 16 | 22.2 μs | 840 ns | 630 ns | 1.5 μs | 600 ns | 670 ns | 640 ns | Binary (600 ns) | 1.12x | +| power2 | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| power2 | sorted_uniform | 262144 | 4 | 257.5 μs | 340 ns | 260 ns | 450 ns | 220 ns | 290 ns | 200 ns | Binary (220 ns) | 1.32x | +| power2 | sorted_uniform | 262144 | 16 | 333.8 μs | 1.2 μs | 870 ns | 2.0 μs | 800 ns | 900 ns | 800 ns | Binary (800 ns) | 1.12x | +| power2 | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | unsorted | 1024 | 4 | 150 ns | 140 ns | 150 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| power2 | unsorted | 1024 | 16 | 430 ns | 430 ns | 430 ns | 420 ns | 429 ns | 440 ns | 400 ns | InterpSearch (420 ns) | 1.05x | +| power2 | unsorted | 16384 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | unsorted | 16384 | 4 | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | ExpFromLeft (170 ns) | 1.06x | +| power2 | unsorted | 16384 | 16 | 610 ns | 610 ns | 600 ns | 600 ns | 600 ns | 610 ns | 560 ns | InterpSearch (600 ns) | 1.02x | +| power2 | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| power2 | unsorted | 262144 | 4 | 210 ns | 220 ns | 210 ns | 220 ns | 220 ns | 220 ns | 210 ns | ExpFromLeft (210 ns) | 1.05x | +| power2 | unsorted | 262144 | 16 | 820 ns | 820 ns | 810 ns | 840 ns | 820 ns | 830 ns | 810 ns | ExpFromLeft (810 ns) | 1.02x | +| sqrt | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_uniform | 1024 | 4 | 1.5 μs | 190 ns | 160 ns | 270 ns | 130 ns | 190 ns | 130 ns | Binary (130 ns) | 1.46x | +| sqrt | sorted_uniform | 1024 | 16 | 1.5 μs | 570 ns | 430 ns | 1.0 μs | 480 ns | 460 ns | 410 ns | ExpFromLeft (430 ns) | 1.07x | +| sqrt | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_uniform | 16384 | 4 | 12.5 μs | 260 ns | 200 ns | 340 ns | 180 ns | 240 ns | 160 ns | Binary (180 ns) | 1.33x | +| sqrt | sorted_uniform | 16384 | 16 | 24.3 μs | 820 ns | 600 ns | 1.4 μs | 580 ns | 630 ns | 560 ns | Binary (580 ns) | 1.09x | +| sqrt | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 90 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | sorted_uniform | 262144 | 4 | 295.8 μs | 340 ns | 260 ns | 440 ns | 220 ns | 290 ns | 200 ns | Binary (220 ns) | 1.32x | +| sqrt | sorted_uniform | 262144 | 16 | 374.1 μs | 1.2 μs | 870 ns | 1.9 μs | 870 ns | 880 ns | 840 ns | ExpFromLeft (870 ns) | 1.01x | +| sqrt | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| sqrt | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 120 ns | InterpSearch (140 ns) | 1.07x | +| sqrt | unsorted | 1024 | 16 | 440 ns | 430 ns | 420 ns | 430 ns | 430 ns | 420 ns | 420 ns | ExpFromLeft (420 ns) | 1.00x | +| sqrt | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 180 ns | 170 ns | 180 ns | 160 ns | ExpFromLeft (170 ns) | 1.06x | +| sqrt | unsorted | 16384 | 16 | 570 ns | 570 ns | 560 ns | 580 ns | 580 ns | 590 ns | 560 ns | ExpFromLeft (560 ns) | 1.05x | +| sqrt | unsorted | 262144 | 1 | 90 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | unsorted | 262144 | 4 | 235.1 μs | 310 ns | 240 ns | 430 ns | 210 ns | 280 ns | 200 ns | Binary (210 ns) | 1.33x | +| sqrt | unsorted | 262144 | 16 | 790 ns | 780 ns | 790 ns | 790 ns | 790 ns | 810 ns | 770 ns | Gallop (780 ns) | 1.04x | +| plateau | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 70 ns | 110 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| plateau | sorted_uniform | 1024 | 4 | 90 ns | 110 ns | 100 ns | 280 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | +| plateau | sorted_uniform | 1024 | 16 | 680 ns | 310 ns | 250 ns | 960 ns | 470 ns | 270 ns | 440 ns | ExpFromLeft (250 ns) | 1.08x | +| plateau | sorted_uniform | 16384 | 1 | 70 ns | 80 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_uniform | 16384 | 4 | 7.7 μs | 170 ns | 150 ns | 340 ns | 170 ns | 180 ns | 160 ns | ExpFromLeft (150 ns) | 1.20x | +| plateau | sorted_uniform | 16384 | 16 | 7.9 μs | 340 ns | 270 ns | 1.3 μs | 630 ns | 290 ns | 600 ns | ExpFromLeft (270 ns) | 1.07x | +| plateau | sorted_uniform | 262144 | 1 | 90 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| plateau | sorted_uniform | 262144 | 4 | 122.1 μs | 200 ns | 170 ns | 430 ns | 210 ns | 200 ns | 200 ns | ExpFromLeft (170 ns) | 1.18x | +| plateau | sorted_uniform | 262144 | 16 | 123.4 μs | 370 ns | 290 ns | 1.7 μs | 760 ns | 320 ns | 740 ns | ExpFromLeft (290 ns) | 1.10x | +| plateau | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 110 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 150 ns | 140 ns | 150 ns | 130 ns | ExpFromLeft (140 ns) | 1.07x | +| plateau | unsorted | 1024 | 16 | 480 ns | 480 ns | 480 ns | 480 ns | 480 ns | 490 ns | 470 ns | InterpSearch (480 ns) | 1.02x | +| plateau | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 100 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | unsorted | 16384 | 4 | 7.9 μs | 170 ns | 150 ns | 370 ns | 170 ns | 180 ns | 170 ns | ExpFromLeft (150 ns) | 1.20x | +| plateau | unsorted | 16384 | 16 | 650 ns | 660 ns | 650 ns | 650 ns | 650 ns | 660 ns | 640 ns | InterpSearch (650 ns) | 1.02x | +| plateau | unsorted | 262144 | 1 | 90 ns | 80 ns | 90 ns | 140 ns | 80 ns | 80 ns | 80 ns | Binary (80 ns) | 1.00x | +| plateau | unsorted | 262144 | 4 | 220 ns | 220 ns | 220 ns | 220 ns | 210 ns | 230 ns | 200 ns | Binary (210 ns) | 1.10x | +| plateau | unsorted | 262144 | 16 | 830 ns | 830 ns | 830 ns | 830 ns | 830 ns | 840 ns | 820 ns | InterpSearch (830 ns) | 1.01x | +| bimodal | sorted_uniform | 1024 | 1 | 69 ns | 60 ns | 60 ns | 100 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| bimodal | sorted_uniform | 1024 | 4 | 90 ns | 110 ns | 100 ns | 270 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | +| bimodal | sorted_uniform | 1024 | 16 | 730 ns | 350 ns | 260 ns | 1.0 μs | 470 ns | 290 ns | 440 ns | ExpFromLeft (260 ns) | 1.12x | +| bimodal | sorted_uniform | 16384 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | +| bimodal | sorted_uniform | 16384 | 4 | 100 ns | 120 ns | 110 ns | 370 ns | 180 ns | 130 ns | 160 ns | Linear (100 ns) | 1.30x | +| bimodal | sorted_uniform | 16384 | 16 | 17.2 μs | 510 ns | 380 ns | 1.4 μs | 610 ns | 420 ns | 570 ns | ExpFromLeft (380 ns) | 1.11x | +| bimodal | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 150 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| bimodal | sorted_uniform | 262144 | 4 | 59.8 μs | 200 ns | 160 ns | 450 ns | 220 ns | 200 ns | 200 ns | ExpFromLeft (160 ns) | 1.25x | +| bimodal | sorted_uniform | 262144 | 16 | 292.9 μs | 630 ns | 470 ns | 1.7 μs | 780 ns | 510 ns | 730 ns | ExpFromLeft (470 ns) | 1.09x | +| bimodal | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 70 ns | 70 ns | ExpFromLeft (60 ns) | 1.17x | +| bimodal | unsorted | 1024 | 4 | 140 ns | 130 ns | 140 ns | 140 ns | 140 ns | 140 ns | 120 ns | Gallop (130 ns) | 1.08x | +| bimodal | unsorted | 1024 | 16 | 470 ns | 470 ns | 589 ns | 580 ns | 580 ns | 470 ns | 450 ns | Gallop (470 ns) | 1.00x | +| bimodal | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | unsorted | 16384 | 4 | 100 ns | 120 ns | 100 ns | 360 ns | 180 ns | 130 ns | 160 ns | ExpFromLeft (100 ns) | 1.30x | +| bimodal | unsorted | 16384 | 16 | 610 ns | 599 ns | 610 ns | 590 ns | 600 ns | 610 ns | 600 ns | InterpSearch (590 ns) | 1.03x | +| bimodal | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| bimodal | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 200 ns | 200 ns | 220 ns | 200 ns | InterpSearch (200 ns) | 1.10x | +| bimodal | unsorted | 262144 | 16 | 760 ns | 750 ns | 750 ns | 760 ns | 740 ns | 760 ns | 730 ns | Binary (740 ns) | 1.03x | +| near_linear | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| near_linear | sorted_uniform | 1024 | 4 | 1.6 μs | 220 ns | 170 ns | 160 ns | 140 ns | 180 ns | 130 ns | Binary (140 ns) | 1.29x | +| near_linear | sorted_uniform | 1024 | 16 | 1.7 μs | 610 ns | 590 ns | 490 ns | 450 ns | 490 ns | 410 ns | Binary (450 ns) | 1.09x | +| near_linear | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_uniform | 16384 | 4 | 3.9 μs | 230 ns | 180 ns | 160 ns | 180 ns | 180 ns | 160 ns | InterpSearch (160 ns) | 1.12x | +| near_linear | sorted_uniform | 16384 | 16 | 21.9 μs | 880 ns | 640 ns | 500 ns | 590 ns | 520 ns | 550 ns | InterpSearch (500 ns) | 1.04x | +| near_linear | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | sorted_uniform | 262144 | 4 | 231.0 μs | 320 ns | 250 ns | 160 ns | 210 ns | 180 ns | 210 ns | InterpSearch (160 ns) | 1.12x | +| near_linear | sorted_uniform | 262144 | 16 | 355.2 μs | 1.2 μs | 830 ns | 520 ns | 810 ns | 550 ns | 770 ns | InterpSearch (520 ns) | 1.06x | +| near_linear | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | unsorted | 1024 | 4 | 140 ns | 130 ns | 130 ns | 140 ns | 140 ns | 150 ns | 120 ns | ExpFromLeft (130 ns) | 1.15x | +| near_linear | unsorted | 1024 | 16 | 430 ns | 420 ns | 410 ns | 430 ns | 420 ns | 430 ns | 410 ns | ExpFromLeft (410 ns) | 1.05x | +| near_linear | unsorted | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | unsorted | 16384 | 4 | 180 ns | 179 ns | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | ExpFromLeft (170 ns) | 1.06x | +| near_linear | unsorted | 16384 | 16 | 570 ns | 560 ns | 560 ns | 570 ns | 570 ns | 580 ns | 560 ns | ExpFromLeft (560 ns) | 1.04x | +| near_linear | unsorted | 262144 | 1 | 80 ns | 100 ns | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | unsorted | 262144 | 4 | 220 ns | 210 ns | 210 ns | 210 ns | 210 ns | 220 ns | 200 ns | InterpSearch (210 ns) | 1.05x | +| near_linear | unsorted | 262144 | 16 | 860 ns | 850 ns | 870 ns | 880 ns | 880 ns | 870 ns | 850 ns | Gallop (850 ns) | 1.02x | + +**Auto verdict over 180 cells**: 156 within 20% of best, 24 worse than 20% slowdown, 0 effectively-faster-than-best. + +### Super-dense cases (m ≫ n) + +## Super dense + +| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| uniform | sorted_uniform | 64 | 1024 | 8.8 μs | 15.2 μs | 11.7 μs | 31.0 μs | 18.0 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | +| uniform | sorted_uniform | 64 | 4096 | 30.8 μs | 57.3 μs | 43.6 μs | 113.7 μs | 68.6 μs | 32.2 μs | 60.3 μs | Linear (30.8 μs) | 1.04x | +| uniform | sorted_uniform | 64 | 16384 | 118.9 μs | 225.7 μs | 170.6 μs | 445.3 μs | 270.6 μs | 124.2 μs | 237.0 μs | Linear (118.9 μs) | 1.04x | +| uniform | sorted_uniform | 256 | 1024 | 9.9 μs | 18.3 μs | 13.6 μs | 37.9 μs | 30.1 μs | 10.4 μs | 25.5 μs | Linear (9.9 μs) | 1.04x | +| uniform | sorted_uniform | 256 | 4096 | 35.5 μs | 60.7 μs | 47.1 μs | 123.9 μs | 127.5 μs | 36.8 μs | 83.9 μs | Linear (35.5 μs) | 1.04x | +| uniform | sorted_uniform | 256 | 16384 | 123.1 μs | 229.3 μs | 174.2 μs | 455.6 μs | 389.0 μs | 128.5 μs | 317.4 μs | Linear (123.1 μs) | 1.04x | +| uniform | sorted_uniform | 1024 | 1024 | 9.8 μs | 18.2 μs | 12.4 μs | 40.5 μs | 78.9 μs | 10.0 μs | 58.3 μs | Linear (9.8 μs) | 1.03x | +| uniform | sorted_uniform | 1024 | 4096 | 46.5 μs | 74.5 μs | 57.8 μs | 154.5 μs | 242.3 μs | 47.8 μs | 191.2 μs | Linear (46.5 μs) | 1.03x | +| uniform | sorted_uniform | 1024 | 16384 | 142.0 μs | 242.9 μs | 188.2 μs | 502.1 μs | 594.0 μs | 147.3 μs | 485.5 μs | Linear (142.0 μs) | 1.04x | +| uniform | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.7 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | +| uniform | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.1 μs | 42.2 μs | 110.4 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.5 μs) | 1.04x | +| uniform | sorted_dense_burst | 64 | 16384 | 117.5 μs | 224.5 μs | 169.0 μs | 441.8 μs | 271.6 μs | 122.9 μs | 227.4 μs | Linear (117.5 μs) | 1.05x | +| uniform | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.7 μs | 21.9 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.05x | +| uniform | sorted_dense_burst | 256 | 4096 | 29.5 μs | 56.3 μs | 42.2 μs | 110.6 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.5 μs) | 1.04x | +| uniform | sorted_dense_burst | 256 | 16384 | 117.6 μs | 224.8 μs | 168.7 μs | 442.3 μs | 349.3 μs | 123.5 μs | 305.9 μs | Linear (117.6 μs) | 1.05x | +| uniform | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.2 μs | 10.6 μs | 27.8 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | +| uniform | sorted_dense_burst | 1024 | 4096 | 29.4 μs | 56.3 μs | 42.2 μs | 110.5 μs | 106.8 μs | 30.9 μs | 95.7 μs | Linear (29.4 μs) | 1.05x | +| uniform | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 225.4 μs | 169.1 μs | 441.8 μs | 427.3 μs | 122.9 μs | 382.9 μs | Linear (117.5 μs) | 1.05x | +| uniform | unsorted | 64 | 1024 | 43.1 μs | 42.0 μs | 42.1 μs | 42.0 μs | 41.7 μs | 41.2 μs | 42.8 μs | Binary (41.7 μs) | 0.99x | +| uniform | unsorted | 64 | 4096 | 235.4 μs | 231.5 μs | 229.8 μs | 229.0 μs | 229.8 μs | 229.4 μs | 238.7 μs | InterpSearch (229.0 μs) | 1.00x | +| uniform | unsorted | 64 | 16384 | 982.2 μs | 981.8 μs | 982.9 μs | 982.1 μs | 981.7 μs | 984.4 μs | 981.4 μs | Binary (981.7 μs) | 1.00x | +| uniform | unsorted | 256 | 1024 | 60.3 μs | 56.0 μs | 55.4 μs | 55.2 μs | 54.8 μs | 54.5 μs | 58.9 μs | Binary (54.8 μs) | 1.00x | +| uniform | unsorted | 256 | 4096 | 317.1 μs | 314.1 μs | 311.7 μs | 311.0 μs | 312.4 μs | 310.5 μs | 317.6 μs | InterpSearch (311.0 μs) | 1.00x | +| uniform | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.29 ms | 1.31 ms | ExpFromLeft (1.30 ms) | 1.00x | +| uniform | unsorted | 1024 | 1024 | 82.3 μs | 81.2 μs | 80.5 μs | 79.9 μs | 79.6 μs | 79.2 μs | 86.1 μs | Binary (79.6 μs) | 1.00x | +| uniform | unsorted | 1024 | 4096 | 407.8 μs | 407.7 μs | 406.7 μs | 405.7 μs | 405.7 μs | 405.0 μs | 408.8 μs | InterpSearch (405.7 μs) | 1.00x | +| uniform | unsorted | 1024 | 16384 | 1.67 ms | 1.68 ms | 1.68 ms | 1.68 ms | 1.68 ms | 1.67 ms | 1.69 ms | Linear (1.67 ms) | 1.00x | +| log | sorted_uniform | 64 | 1024 | 8.0 μs | 14.5 μs | 11.2 μs | 47.8 μs | 17.5 μs | 8.4 μs | 15.8 μs | Linear (8.0 μs) | 1.05x | +| log | sorted_uniform | 64 | 4096 | 30.2 μs | 56.4 μs | 43.1 μs | 177.8 μs | 69.1 μs | 31.6 μs | 60.9 μs | Linear (30.2 μs) | 1.04x | +| log | sorted_uniform | 64 | 16384 | 118.8 μs | 223.3 μs | 170.3 μs | 690.8 μs | 274.9 μs | 123.8 μs | 241.0 μs | Linear (118.8 μs) | 1.04x | +| log | sorted_uniform | 256 | 1024 | 9.1 μs | 15.6 μs | 12.0 μs | 66.2 μs | 23.1 μs | 9.4 μs | 22.0 μs | Linear (9.1 μs) | 1.04x | +| log | sorted_uniform | 256 | 4096 | 32.1 μs | 58.5 μs | 44.6 μs | 237.5 μs | 91.5 μs | 33.4 μs | 82.2 μs | Linear (32.1 μs) | 1.04x | +| log | sorted_uniform | 256 | 16384 | 121.4 μs | 227.5 μs | 172.7 μs | 873.8 μs | 363.4 μs | 126.7 μs | 319.0 μs | Linear (121.4 μs) | 1.04x | +| log | sorted_uniform | 1024 | 1024 | 10.4 μs | 18.0 μs | 13.1 μs | 86.9 μs | 41.4 μs | 10.6 μs | 33.1 μs | Linear (10.4 μs) | 1.02x | +| log | sorted_uniform | 1024 | 4096 | 37.2 μs | 63.5 μs | 48.4 μs | 314.2 μs | 171.2 μs | 38.5 μs | 124.9 μs | Linear (37.2 μs) | 1.03x | +| log | sorted_uniform | 1024 | 16384 | 129.9 μs | 235.8 μs | 179.3 μs | 1.11 ms | 535.8 μs | 135.2 μs | 450.1 μs | Linear (129.9 μs) | 1.04x | +| log | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 45.2 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | +| log | sorted_dense_burst | 64 | 4096 | 29.4 μs | 56.1 μs | 42.0 μs | 180.8 μs | 67.9 μs | 30.8 μs | 56.7 μs | Linear (29.4 μs) | 1.05x | +| log | sorted_dense_burst | 64 | 16384 | 118.2 μs | 224.4 μs | 169.1 μs | 722.9 μs | 271.5 μs | 123.0 μs | 227.1 μs | Linear (118.2 μs) | 1.04x | +| log | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 58.7 μs | 21.8 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.05x | +| log | sorted_dense_burst | 256 | 4096 | 29.4 μs | 56.3 μs | 42.3 μs | 234.8 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.4 μs) | 1.04x | +| log | sorted_dense_burst | 256 | 16384 | 117.5 μs | 224.8 μs | 169.0 μs | 939.6 μs | 349.3 μs | 123.3 μs | 305.8 μs | Linear (117.5 μs) | 1.05x | +| log | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 65.0 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | +| log | sorted_dense_burst | 1024 | 4096 | 29.6 μs | 56.3 μs | 42.3 μs | 260.1 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.6 μs) | 1.04x | +| log | sorted_dense_burst | 1024 | 16384 | 117.6 μs | 224.9 μs | 169.2 μs | 1.04 ms | 427.3 μs | 122.8 μs | 383.0 μs | Linear (117.6 μs) | 1.04x | +| log | unsorted | 64 | 1024 | 35.6 μs | 35.0 μs | 34.6 μs | 34.3 μs | 34.2 μs | 34.5 μs | 35.0 μs | Binary (34.2 μs) | 1.01x | +| log | unsorted | 64 | 4096 | 179.0 μs | 178.0 μs | 178.3 μs | 178.5 μs | 177.5 μs | 177.8 μs | 179.5 μs | Binary (177.5 μs) | 1.00x | +| log | unsorted | 64 | 16384 | 757.7 μs | 758.3 μs | 758.0 μs | 757.5 μs | 756.7 μs | 757.6 μs | 754.8 μs | Binary (756.7 μs) | 1.00x | +| log | unsorted | 256 | 1024 | 51.6 μs | 50.2 μs | 49.6 μs | 49.5 μs | 49.0 μs | 49.0 μs | 50.3 μs | Binary (49.0 μs) | 1.00x | +| log | unsorted | 256 | 4096 | 258.0 μs | 256.8 μs | 257.1 μs | 255.7 μs | 255.5 μs | 255.6 μs | 266.9 μs | Binary (255.5 μs) | 1.00x | +| log | unsorted | 256 | 16384 | 1.09 ms | 1.09 ms | 1.09 ms | 1.09 ms | 1.08 ms | 1.09 ms | 1.09 ms | Binary (1.08 ms) | 1.00x | +| log | unsorted | 1024 | 1024 | 72.5 μs | 71.3 μs | 70.7 μs | 70.2 μs | 70.5 μs | 70.2 μs | 74.4 μs | InterpSearch (70.2 μs) | 1.00x | +| log | unsorted | 1024 | 4096 | 351.1 μs | 349.0 μs | 349.8 μs | 348.5 μs | 349.2 μs | 349.0 μs | 354.3 μs | InterpSearch (348.5 μs) | 1.00x | +| log | unsorted | 1024 | 16384 | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.43 ms | Binary (1.42 ms) | 1.00x | +| jittered | sorted_uniform | 64 | 1024 | 8.8 μs | 15.2 μs | 11.8 μs | 31.0 μs | 18.0 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | +| jittered | sorted_uniform | 64 | 4096 | 30.7 μs | 57.1 μs | 43.6 μs | 113.5 μs | 68.6 μs | 32.1 μs | 60.2 μs | Linear (30.7 μs) | 1.05x | +| jittered | sorted_uniform | 64 | 16384 | 119.2 μs | 225.3 μs | 170.9 μs | 442.7 μs | 270.3 μs | 124.4 μs | 237.2 μs | Linear (119.2 μs) | 1.04x | +| jittered | sorted_uniform | 256 | 1024 | 9.8 μs | 18.2 μs | 13.6 μs | 38.0 μs | 28.1 μs | 10.2 μs | 25.3 μs | Linear (9.8 μs) | 1.03x | +| jittered | sorted_uniform | 256 | 4096 | 35.4 μs | 60.7 μs | 47.1 μs | 124.5 μs | 128.5 μs | 36.8 μs | 83.9 μs | Linear (35.4 μs) | 1.04x | +| jittered | sorted_uniform | 256 | 16384 | 123.3 μs | 229.2 μs | 174.2 μs | 457.4 μs | 391.7 μs | 128.5 μs | 318.2 μs | Linear (123.3 μs) | 1.04x | +| jittered | sorted_uniform | 1024 | 1024 | 10.2 μs | 18.6 μs | 12.4 μs | 38.4 μs | 72.3 μs | 10.8 μs | 53.1 μs | Linear (10.2 μs) | 1.05x | +| jittered | sorted_uniform | 1024 | 4096 | 47.8 μs | 74.9 μs | 57.7 μs | 149.7 μs | 240.2 μs | 48.8 μs | 193.2 μs | Linear (47.8 μs) | 1.02x | +| jittered | sorted_uniform | 1024 | 16384 | 142.0 μs | 242.8 μs | 188.2 μs | 500.1 μs | 597.7 μs | 147.2 μs | 487.3 μs | Linear (142.0 μs) | 1.04x | +| jittered | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.2 μs | 10.6 μs | 28.0 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | +| jittered | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 111.3 μs | 67.9 μs | 30.8 μs | 56.9 μs | Linear (29.5 μs) | 1.04x | +| jittered | sorted_dense_burst | 64 | 16384 | 117.4 μs | 224.8 μs | 168.8 μs | 445.1 μs | 271.6 μs | 122.9 μs | 227.3 μs | Linear (117.4 μs) | 1.05x | +| jittered | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.8 μs | 21.9 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.05x | +| jittered | sorted_dense_burst | 256 | 4096 | 29.5 μs | 56.3 μs | 42.2 μs | 109.9 μs | 87.4 μs | 30.9 μs | 76.5 μs | Linear (29.5 μs) | 1.05x | +| jittered | sorted_dense_burst | 256 | 16384 | 117.6 μs | 224.9 μs | 168.8 μs | 439.1 μs | 349.1 μs | 122.9 μs | 306.0 μs | Linear (117.6 μs) | 1.04x | +| jittered | sorted_dense_burst | 1024 | 1024 | 7.5 μs | 14.1 μs | 10.6 μs | 27.8 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.5 μs) | 1.05x | +| jittered | sorted_dense_burst | 1024 | 4096 | 29.4 μs | 56.3 μs | 42.3 μs | 111.0 μs | 106.8 μs | 30.8 μs | 95.8 μs | Linear (29.4 μs) | 1.05x | +| jittered | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 224.8 μs | 168.8 μs | 444.0 μs | 427.3 μs | 122.8 μs | 383.2 μs | Linear (117.5 μs) | 1.04x | +| jittered | unsorted | 64 | 1024 | 43.2 μs | 41.3 μs | 41.3 μs | 41.2 μs | 41.2 μs | 41.0 μs | 43.2 μs | InterpSearch (41.2 μs) | 0.99x | +| jittered | unsorted | 64 | 4096 | 233.2 μs | 231.6 μs | 231.4 μs | 232.7 μs | 229.2 μs | 230.6 μs | 232.8 μs | Binary (229.2 μs) | 1.01x | +| jittered | unsorted | 64 | 16384 | 979.2 μs | 983.8 μs | 983.2 μs | 983.1 μs | 985.1 μs | 984.7 μs | 983.9 μs | Linear (979.2 μs) | 1.01x | +| jittered | unsorted | 256 | 1024 | 56.8 μs | 55.0 μs | 54.5 μs | 54.2 μs | 54.1 μs | 54.0 μs | 59.5 μs | Binary (54.1 μs) | 1.00x | +| jittered | unsorted | 256 | 4096 | 314.6 μs | 313.8 μs | 312.5 μs | 312.8 μs | 313.5 μs | 310.3 μs | 318.8 μs | ExpFromLeft (312.5 μs) | 0.99x | +| jittered | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.29 ms | 1.31 ms | Gallop (1.30 ms) | 1.00x | +| jittered | unsorted | 1024 | 1024 | 82.4 μs | 79.6 μs | 78.9 μs | 77.4 μs | 78.1 μs | 76.7 μs | 85.3 μs | InterpSearch (77.4 μs) | 0.99x | +| jittered | unsorted | 1024 | 4096 | 408.9 μs | 407.8 μs | 406.1 μs | 406.2 μs | 407.0 μs | 405.6 μs | 409.5 μs | ExpFromLeft (406.1 μs) | 1.00x | +| jittered | unsorted | 1024 | 16384 | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.68 ms | 1.68 ms | Linear (1.67 ms) | 1.00x | +| random | sorted_uniform | 64 | 1024 | 8.8 μs | 15.2 μs | 11.7 μs | 35.4 μs | 17.5 μs | 9.1 μs | 15.9 μs | Linear (8.8 μs) | 1.04x | +| random | sorted_uniform | 64 | 4096 | 30.7 μs | 57.3 μs | 43.5 μs | 129.3 μs | 68.6 μs | 32.1 μs | 60.2 μs | Linear (30.7 μs) | 1.05x | +| random | sorted_uniform | 64 | 16384 | 118.8 μs | 225.2 μs | 170.4 μs | 502.4 μs | 271.0 μs | 124.2 μs | 237.1 μs | Linear (118.8 μs) | 1.04x | +| random | sorted_uniform | 256 | 1024 | 9.2 μs | 17.3 μs | 13.0 μs | 48.2 μs | 24.2 μs | 9.7 μs | 23.8 μs | Linear (9.2 μs) | 1.05x | +| random | sorted_uniform | 256 | 4096 | 34.8 μs | 60.5 μs | 46.6 μs | 169.8 μs | 99.9 μs | 36.1 μs | 83.8 μs | Linear (34.8 μs) | 1.04x | +| random | sorted_uniform | 256 | 16384 | 123.2 μs | 229.2 μs | 174.7 μs | 615.1 μs | 381.5 μs | 128.5 μs | 317.5 μs | Linear (123.2 μs) | 1.04x | +| random | sorted_uniform | 1024 | 1024 | 10.1 μs | 18.0 μs | 12.7 μs | 55.7 μs | 61.1 μs | 10.4 μs | 43.5 μs | Linear (10.1 μs) | 1.03x | +| random | sorted_uniform | 1024 | 4096 | 43.1 μs | 71.6 μs | 54.8 μs | 213.6 μs | 216.7 μs | 44.4 μs | 170.4 μs | Linear (43.1 μs) | 1.03x | +| random | sorted_uniform | 1024 | 16384 | 139.8 μs | 242.6 μs | 187.2 μs | 735.8 μs | 574.2 μs | 145.5 μs | 479.1 μs | Linear (139.8 μs) | 1.04x | +| random | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.5 μs | 29.8 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | +| random | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.1 μs | 42.3 μs | 118.9 μs | 67.9 μs | 30.8 μs | 56.9 μs | Linear (29.5 μs) | 1.05x | +| random | sorted_dense_burst | 64 | 16384 | 117.6 μs | 224.4 μs | 169.1 μs | 476.2 μs | 271.6 μs | 123.0 μs | 227.4 μs | Linear (117.6 μs) | 1.05x | +| random | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 31.9 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | +| random | sorted_dense_burst | 256 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 126.3 μs | 87.2 μs | 30.8 μs | 76.5 μs | Linear (29.5 μs) | 1.05x | +| random | sorted_dense_burst | 256 | 16384 | 117.6 μs | 224.8 μs | 169.6 μs | 505.2 μs | 349.2 μs | 122.8 μs | 306.0 μs | Linear (117.6 μs) | 1.04x | +| random | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 45.6 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.05x | +| random | sorted_dense_burst | 1024 | 4096 | 29.5 μs | 56.3 μs | 42.4 μs | 180.9 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.5 μs) | 1.05x | +| random | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 224.8 μs | 169.1 μs | 723.2 μs | 427.3 μs | 122.9 μs | 383.2 μs | Linear (117.5 μs) | 1.05x | +| random | unsorted | 64 | 1024 | 36.2 μs | 35.4 μs | 35.3 μs | 35.5 μs | 35.3 μs | 35.3 μs | 38.9 μs | ExpFromLeft (35.3 μs) | 1.00x | +| random | unsorted | 64 | 4096 | 203.8 μs | 202.6 μs | 201.8 μs | 202.3 μs | 201.0 μs | 201.7 μs | 203.9 μs | Binary (201.0 μs) | 1.00x | +| random | unsorted | 64 | 16384 | 868.0 μs | 865.9 μs | 881.5 μs | 873.6 μs | 867.3 μs | 870.6 μs | 867.9 μs | Gallop (865.9 μs) | 1.01x | +| random | unsorted | 256 | 1024 | 54.2 μs | 52.2 μs | 52.1 μs | 52.0 μs | 51.8 μs | 51.5 μs | 56.9 μs | Binary (51.8 μs) | 1.00x | +| random | unsorted | 256 | 4096 | 281.7 μs | 280.1 μs | 278.9 μs | 278.2 μs | 280.8 μs | 277.0 μs | 281.2 μs | InterpSearch (278.2 μs) | 1.00x | +| random | unsorted | 256 | 16384 | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | InterpSearch (1.16 ms) | 1.00x | +| random | unsorted | 1024 | 1024 | 77.5 μs | 75.7 μs | 73.9 μs | 73.8 μs | 73.2 μs | 72.9 μs | 80.0 μs | Binary (73.2 μs) | 1.00x | +| random | unsorted | 1024 | 4096 | 381.2 μs | 379.9 μs | 377.1 μs | 377.3 μs | 378.0 μs | 377.7 μs | 381.1 μs | ExpFromLeft (377.1 μs) | 1.00x | +| random | unsorted | 1024 | 16384 | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | Linear (1.55 ms) | 1.00x | +| two_scale | sorted_uniform | 64 | 1024 | 8.1 μs | 14.6 μs | 11.1 μs | 46.7 μs | 17.4 μs | 8.3 μs | 15.2 μs | Linear (8.1 μs) | 1.03x | +| two_scale | sorted_uniform | 64 | 4096 | 30.2 μs | 56.6 μs | 43.0 μs | 166.6 μs | 68.9 μs | 31.4 μs | 59.0 μs | Linear (30.2 μs) | 1.04x | +| two_scale | sorted_uniform | 64 | 16384 | 118.2 μs | 224.8 μs | 169.8 μs | 643.1 μs | 273.2 μs | 123.5 μs | 234.2 μs | Linear (118.2 μs) | 1.04x | +| two_scale | sorted_uniform | 256 | 1024 | 9.6 μs | 16.0 μs | 12.5 μs | 69.6 μs | 23.1 μs | 9.8 μs | 21.8 μs | Linear (9.6 μs) | 1.03x | +| two_scale | sorted_uniform | 256 | 4096 | 32.4 μs | 58.5 μs | 44.7 μs | 239.6 μs | 90.3 μs | 33.8 μs | 80.6 μs | Linear (32.4 μs) | 1.04x | +| two_scale | sorted_uniform | 256 | 16384 | 120.5 μs | 227.1 μs | 171.9 μs | 860.5 μs | 352.6 μs | 125.7 μs | 315.1 μs | Linear (120.5 μs) | 1.04x | +| two_scale | sorted_uniform | 1024 | 1024 | 10.1 μs | 17.4 μs | 12.4 μs | 87.9 μs | 45.0 μs | 10.5 μs | 33.4 μs | Linear (10.1 μs) | 1.04x | +| two_scale | sorted_uniform | 1024 | 4096 | 39.2 μs | 65.0 μs | 50.4 μs | 308.8 μs | 161.9 μs | 40.8 μs | 113.2 μs | Linear (39.2 μs) | 1.04x | +| two_scale | sorted_uniform | 1024 | 16384 | 129.7 μs | 234.2 μs | 178.8 μs | 1.09 ms | 502.4 μs | 134.9 μs | 415.2 μs | Linear (129.7 μs) | 1.04x | +| two_scale | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 47.0 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | +| two_scale | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.1 μs | 42.3 μs | 187.7 μs | 67.9 μs | 30.9 μs | 56.8 μs | Linear (29.5 μs) | 1.05x | +| two_scale | sorted_dense_burst | 64 | 16384 | 118.3 μs | 224.6 μs | 168.7 μs | 750.3 μs | 271.6 μs | 122.8 μs | 227.2 μs | Linear (118.3 μs) | 1.04x | +| two_scale | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 56.5 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | +| two_scale | sorted_dense_burst | 256 | 4096 | 29.4 μs | 56.2 μs | 42.3 μs | 223.4 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.4 μs) | 1.05x | +| two_scale | sorted_dense_burst | 256 | 16384 | 117.7 μs | 224.9 μs | 169.1 μs | 899.8 μs | 349.3 μs | 122.8 μs | 306.0 μs | Linear (117.7 μs) | 1.04x | +| two_scale | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.2 μs | 10.6 μs | 66.4 μs | 26.8 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | +| two_scale | sorted_dense_burst | 1024 | 4096 | 29.4 μs | 56.3 μs | 42.3 μs | 262.7 μs | 106.8 μs | 30.8 μs | 95.8 μs | Linear (29.4 μs) | 1.05x | +| two_scale | sorted_dense_burst | 1024 | 16384 | 118.3 μs | 225.0 μs | 169.1 μs | 1.05 ms | 427.4 μs | 123.4 μs | 383.2 μs | Linear (118.3 μs) | 1.04x | +| two_scale | unsorted | 64 | 1024 | 46.3 μs | 45.8 μs | 45.6 μs | 45.8 μs | 45.5 μs | 45.8 μs | 45.6 μs | Binary (45.5 μs) | 1.01x | +| two_scale | unsorted | 64 | 4096 | 204.1 μs | 200.0 μs | 200.7 μs | 208.0 μs | 200.0 μs | 199.6 μs | 203.1 μs | Binary (200.0 μs) | 1.00x | +| two_scale | unsorted | 64 | 16384 | 840.4 μs | 838.1 μs | 834.2 μs | 839.1 μs | 836.2 μs | 838.3 μs | 840.8 μs | ExpFromLeft (834.2 μs) | 1.00x | +| two_scale | unsorted | 256 | 1024 | 54.9 μs | 54.3 μs | 54.0 μs | 54.0 μs | 54.0 μs | 53.9 μs | 54.3 μs | ExpFromLeft (54.0 μs) | 1.00x | +| two_scale | unsorted | 256 | 4096 | 256.9 μs | 256.2 μs | 255.1 μs | 254.7 μs | 255.8 μs | 255.0 μs | 256.1 μs | InterpSearch (254.7 μs) | 1.00x | +| two_scale | unsorted | 256 | 16384 | 1.07 ms | 1.07 ms | 1.06 ms | 1.06 ms | 1.06 ms | 1.07 ms | 1.07 ms | Binary (1.06 ms) | 1.00x | +| two_scale | unsorted | 1024 | 1024 | 73.8 μs | 72.0 μs | 71.6 μs | 70.5 μs | 70.0 μs | 70.0 μs | 75.1 μs | Binary (70.0 μs) | 1.00x | +| two_scale | unsorted | 1024 | 4096 | 348.5 μs | 347.8 μs | 346.0 μs | 345.2 μs | 346.1 μs | 346.0 μs | 349.6 μs | InterpSearch (345.2 μs) | 1.00x | +| two_scale | unsorted | 1024 | 16384 | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.44 ms | Gallop (1.42 ms) | 1.00x | +| power2 | sorted_uniform | 64 | 1024 | 8.5 μs | 15.0 μs | 11.6 μs | 44.8 μs | 17.8 μs | 8.8 μs | 15.9 μs | Linear (8.5 μs) | 1.04x | +| power2 | sorted_uniform | 64 | 4096 | 30.6 μs | 57.2 μs | 43.5 μs | 165.3 μs | 68.9 μs | 32.0 μs | 60.2 μs | Linear (30.6 μs) | 1.04x | +| power2 | sorted_uniform | 64 | 16384 | 118.8 μs | 224.8 μs | 170.2 μs | 636.4 μs | 272.1 μs | 124.1 μs | 237.7 μs | Linear (118.8 μs) | 1.04x | +| power2 | sorted_uniform | 256 | 1024 | 9.7 μs | 16.8 μs | 12.8 μs | 60.8 μs | 25.3 μs | 10.1 μs | 23.9 μs | Linear (9.7 μs) | 1.04x | +| power2 | sorted_uniform | 256 | 4096 | 34.3 μs | 60.3 μs | 46.4 μs | 217.9 μs | 113.3 μs | 35.8 μs | 83.5 μs | Linear (34.3 μs) | 1.04x | +| power2 | sorted_uniform | 256 | 16384 | 122.9 μs | 228.9 μs | 173.9 μs | 812.6 μs | 386.0 μs | 128.2 μs | 318.2 μs | Linear (122.9 μs) | 1.04x | +| power2 | sorted_uniform | 1024 | 1024 | 10.2 μs | 18.2 μs | 12.1 μs | 82.8 μs | 65.8 μs | 10.2 μs | 49.1 μs | Linear (10.2 μs) | 1.00x | +| power2 | sorted_uniform | 1024 | 4096 | 43.0 μs | 70.4 μs | 53.8 μs | 287.9 μs | 228.0 μs | 44.3 μs | 177.0 μs | Linear (43.0 μs) | 1.03x | +| power2 | sorted_uniform | 1024 | 16384 | 138.7 μs | 241.3 μs | 186.1 μs | 1.04 ms | 587.3 μs | 143.7 μs | 481.2 μs | Linear (138.7 μs) | 1.04x | +| power2 | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 43.8 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | +| power2 | sorted_dense_burst | 64 | 4096 | 29.6 μs | 56.3 μs | 42.3 μs | 175.0 μs | 67.9 μs | 30.8 μs | 56.9 μs | Linear (29.6 μs) | 1.04x | +| power2 | sorted_dense_burst | 64 | 16384 | 118.3 μs | 224.4 μs | 168.9 μs | 698.4 μs | 271.5 μs | 122.9 μs | 227.7 μs | Linear (118.3 μs) | 1.04x | +| power2 | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.2 μs | 10.6 μs | 54.1 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | +| power2 | sorted_dense_burst | 256 | 4096 | 29.5 μs | 56.2 μs | 42.3 μs | 216.4 μs | 87.4 μs | 30.9 μs | 76.4 μs | Linear (29.5 μs) | 1.05x | +| power2 | sorted_dense_burst | 256 | 16384 | 117.6 μs | 224.8 μs | 168.7 μs | 864.1 μs | 349.2 μs | 123.2 μs | 305.9 μs | Linear (117.6 μs) | 1.05x | +| power2 | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 63.8 μs | 26.8 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | +| power2 | sorted_dense_burst | 1024 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 254.2 μs | 106.8 μs | 30.9 μs | 95.7 μs | Linear (29.5 μs) | 1.05x | +| power2 | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 224.8 μs | 169.2 μs | 1.01 ms | 427.4 μs | 123.6 μs | 383.2 μs | Linear (117.5 μs) | 1.05x | +| power2 | unsorted | 64 | 1024 | 41.5 μs | 40.5 μs | 40.6 μs | 40.6 μs | 40.2 μs | 40.5 μs | 41.7 μs | Binary (40.2 μs) | 1.01x | +| power2 | unsorted | 64 | 4096 | 216.4 μs | 216.3 μs | 215.9 μs | 215.5 μs | 215.4 μs | 216.8 μs | 217.3 μs | Binary (215.4 μs) | 1.01x | +| power2 | unsorted | 64 | 16384 | 916.8 μs | 915.4 μs | 916.0 μs | 915.2 μs | 914.8 μs | 915.2 μs | 917.5 μs | Binary (914.8 μs) | 1.00x | +| power2 | unsorted | 256 | 1024 | 55.8 μs | 53.7 μs | 53.9 μs | 53.0 μs | 52.9 μs | 52.8 μs | 56.4 μs | Binary (52.9 μs) | 1.00x | +| power2 | unsorted | 256 | 4096 | 300.2 μs | 299.1 μs | 297.9 μs | 297.2 μs | 297.4 μs | 297.4 μs | 303.3 μs | InterpSearch (297.2 μs) | 1.00x | +| power2 | unsorted | 256 | 16384 | 1.24 ms | 1.24 ms | 1.24 ms | 1.24 ms | 1.24 ms | 1.24 ms | 1.25 ms | Binary (1.24 ms) | 1.00x | +| power2 | unsorted | 1024 | 1024 | 79.7 μs | 78.3 μs | 76.5 μs | 76.2 μs | 75.6 μs | 75.5 μs | 82.2 μs | Binary (75.6 μs) | 1.00x | +| power2 | unsorted | 1024 | 4096 | 392.3 μs | 392.6 μs | 390.6 μs | 391.3 μs | 389.6 μs | 388.5 μs | 394.0 μs | Binary (389.6 μs) | 1.00x | +| power2 | unsorted | 1024 | 16384 | 1.60 ms | 1.60 ms | 1.60 ms | 1.59 ms | 1.60 ms | 1.60 ms | 1.61 ms | InterpSearch (1.59 ms) | 1.00x | +| sqrt | sorted_uniform | 64 | 1024 | 8.9 μs | 15.2 μs | 11.9 μs | 44.5 μs | 17.5 μs | 9.2 μs | 16.0 μs | Linear (8.9 μs) | 1.04x | +| sqrt | sorted_uniform | 64 | 4096 | 30.8 μs | 57.1 μs | 43.5 μs | 164.4 μs | 68.4 μs | 32.1 μs | 60.4 μs | Linear (30.8 μs) | 1.04x | +| sqrt | sorted_uniform | 64 | 16384 | 119.0 μs | 225.4 μs | 170.3 μs | 636.8 μs | 269.8 μs | 124.3 μs | 237.8 μs | Linear (119.0 μs) | 1.04x | +| sqrt | sorted_uniform | 256 | 1024 | 9.7 μs | 17.3 μs | 12.6 μs | 58.4 μs | 25.5 μs | 10.1 μs | 25.5 μs | Linear (9.7 μs) | 1.04x | +| sqrt | sorted_uniform | 256 | 4096 | 35.3 μs | 60.8 μs | 47.0 μs | 215.8 μs | 127.3 μs | 36.7 μs | 84.0 μs | Linear (35.3 μs) | 1.04x | +| sqrt | sorted_uniform | 256 | 16384 | 123.3 μs | 229.4 μs | 174.1 μs | 797.2 μs | 388.8 μs | 128.8 μs | 317.9 μs | Linear (123.3 μs) | 1.04x | +| sqrt | sorted_uniform | 1024 | 1024 | 10.0 μs | 18.1 μs | 12.6 μs | 77.5 μs | 58.0 μs | 10.4 μs | 47.7 μs | Linear (10.0 μs) | 1.05x | +| sqrt | sorted_uniform | 1024 | 4096 | 43.9 μs | 71.3 μs | 53.8 μs | 279.2 μs | 228.9 μs | 44.7 μs | 185.5 μs | Linear (43.9 μs) | 1.02x | +| sqrt | sorted_uniform | 1024 | 16384 | 141.6 μs | 243.1 μs | 188.2 μs | 1.02 ms | 595.2 μs | 146.8 μs | 486.3 μs | Linear (141.6 μs) | 1.04x | +| sqrt | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.4 μs | 10.6 μs | 41.0 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | +| sqrt | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.1 μs | 42.4 μs | 165.6 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.5 μs) | 1.04x | +| sqrt | sorted_dense_burst | 64 | 16384 | 118.0 μs | 224.4 μs | 168.9 μs | 653.6 μs | 271.5 μs | 122.8 μs | 227.2 μs | Linear (118.0 μs) | 1.04x | +| sqrt | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 50.8 μs | 21.8 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | +| sqrt | sorted_dense_burst | 256 | 4096 | 29.6 μs | 56.2 μs | 42.3 μs | 202.4 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.6 μs) | 1.04x | +| sqrt | sorted_dense_burst | 256 | 16384 | 117.9 μs | 224.8 μs | 168.8 μs | 809.5 μs | 349.2 μs | 123.0 μs | 305.9 μs | Linear (117.9 μs) | 1.04x | +| sqrt | sorted_dense_burst | 1024 | 1024 | 7.5 μs | 14.1 μs | 10.7 μs | 61.1 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.5 μs) | 1.05x | +| sqrt | sorted_dense_burst | 1024 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 243.0 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.5 μs) | 1.05x | +| sqrt | sorted_dense_burst | 1024 | 16384 | 117.6 μs | 224.8 μs | 169.1 μs | 971.8 μs | 427.3 μs | 122.9 μs | 383.2 μs | Linear (117.6 μs) | 1.04x | +| sqrt | unsorted | 64 | 1024 | 44.9 μs | 43.4 μs | 43.3 μs | 44.1 μs | 42.9 μs | 42.8 μs | 45.1 μs | Binary (42.9 μs) | 1.00x | +| sqrt | unsorted | 64 | 4096 | 212.5 μs | 211.2 μs | 211.5 μs | 211.9 μs | 210.6 μs | 211.4 μs | 214.0 μs | Binary (210.6 μs) | 1.00x | +| sqrt | unsorted | 64 | 16384 | 909.9 μs | 908.9 μs | 911.7 μs | 908.8 μs | 907.9 μs | 909.1 μs | 911.4 μs | Binary (907.9 μs) | 1.00x | +| sqrt | unsorted | 256 | 1024 | 52.9 μs | 51.6 μs | 51.1 μs | 51.1 μs | 50.7 μs | 50.8 μs | 54.7 μs | Binary (50.7 μs) | 1.00x | +| sqrt | unsorted | 256 | 4096 | 287.3 μs | 286.8 μs | 285.2 μs | 285.6 μs | 286.1 μs | 285.2 μs | 290.6 μs | ExpFromLeft (285.2 μs) | 1.00x | +| sqrt | unsorted | 256 | 16384 | 1.20 ms | 1.20 ms | 1.19 ms | 1.20 ms | 1.20 ms | 1.20 ms | 1.20 ms | ExpFromLeft (1.19 ms) | 1.00x | +| sqrt | unsorted | 1024 | 1024 | 75.0 μs | 73.1 μs | 72.6 μs | 71.7 μs | 71.0 μs | 70.6 μs | 77.3 μs | Binary (71.0 μs) | 0.99x | +| sqrt | unsorted | 1024 | 4096 | 377.0 μs | 376.6 μs | 374.0 μs | 374.7 μs | 375.4 μs | 375.1 μs | 376.9 μs | ExpFromLeft (374.0 μs) | 1.00x | +| sqrt | unsorted | 1024 | 16384 | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | Binary (1.54 ms) | 1.00x | +| plateau | sorted_uniform | 64 | 1024 | 7.5 μs | 14.2 μs | 10.7 μs | 45.4 μs | 17.0 μs | 7.8 μs | 14.8 μs | Linear (7.5 μs) | 1.05x | +| plateau | sorted_uniform | 64 | 4096 | 29.5 μs | 56.2 μs | 42.4 μs | 160.2 μs | 67.8 μs | 30.9 μs | 58.7 μs | Linear (29.5 μs) | 1.05x | +| plateau | sorted_uniform | 64 | 16384 | 117.9 μs | 224.5 μs | 169.3 μs | 618.0 μs | 271.1 μs | 123.2 μs | 234.7 μs | Linear (117.9 μs) | 1.04x | +| plateau | sorted_uniform | 256 | 1024 | 7.6 μs | 14.2 μs | 10.7 μs | 67.1 μs | 21.9 μs | 7.9 μs | 19.6 μs | Linear (7.6 μs) | 1.05x | +| plateau | sorted_uniform | 256 | 4096 | 29.6 μs | 56.3 μs | 42.4 μs | 223.2 μs | 87.4 μs | 31.0 μs | 78.3 μs | Linear (29.6 μs) | 1.04x | +| plateau | sorted_uniform | 256 | 16384 | 117.8 μs | 224.9 μs | 169.2 μs | 788.1 μs | 349.8 μs | 123.3 μs | 313.4 μs | Linear (117.8 μs) | 1.05x | +| plateau | sorted_uniform | 1024 | 1024 | 7.9 μs | 14.2 μs | 10.7 μs | 88.5 μs | 26.5 μs | 8.3 μs | 24.6 μs | Linear (7.9 μs) | 1.05x | +| plateau | sorted_uniform | 1024 | 4096 | 30.0 μs | 56.3 μs | 42.5 μs | 317.8 μs | 106.0 μs | 31.3 μs | 98.5 μs | Linear (30.0 μs) | 1.04x | +| plateau | sorted_uniform | 1024 | 16384 | 118.4 μs | 225.0 μs | 169.7 μs | 1.04 ms | 424.1 μs | 123.3 μs | 388.8 μs | Linear (118.4 μs) | 1.04x | +| plateau | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.0 μs | 42.2 μs | 17.1 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | +| plateau | sorted_dense_burst | 64 | 4096 | 29.6 μs | 56.2 μs | 39.6 μs | 168.1 μs | 68.0 μs | 30.9 μs | 57.1 μs | Linear (29.6 μs) | 1.05x | +| plateau | sorted_dense_burst | 64 | 16384 | 117.6 μs | 224.5 μs | 158.4 μs | 672.7 μs | 272.0 μs | 123.5 μs | 228.5 μs | Linear (117.6 μs) | 1.05x | +| plateau | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.0 μs | 50.2 μs | 21.8 μs | 7.8 μs | 19.6 μs | Linear (7.4 μs) | 1.04x | +| plateau | sorted_dense_burst | 256 | 4096 | 29.4 μs | 56.3 μs | 39.5 μs | 199.8 μs | 87.0 μs | 30.9 μs | 78.2 μs | Linear (29.4 μs) | 1.05x | +| plateau | sorted_dense_burst | 256 | 16384 | 118.2 μs | 225.0 μs | 157.3 μs | 804.8 μs | 348.0 μs | 123.1 μs | 312.5 μs | Linear (118.2 μs) | 1.04x | +| plateau | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.1 μs | 10.0 μs | 60.7 μs | 26.7 μs | 7.8 μs | 24.3 μs | Linear (7.4 μs) | 1.05x | +| plateau | sorted_dense_burst | 1024 | 4096 | 29.6 μs | 56.3 μs | 39.4 μs | 243.4 μs | 106.6 μs | 30.9 μs | 97.9 μs | Linear (29.6 μs) | 1.05x | +| plateau | sorted_dense_burst | 1024 | 16384 | 118.3 μs | 224.9 μs | 158.7 μs | 973.0 μs | 426.8 μs | 123.5 μs | 387.1 μs | Linear (118.3 μs) | 1.04x | +| plateau | unsorted | 64 | 1024 | 22.9 μs | 22.9 μs | 23.3 μs | 23.2 μs | 23.2 μs | 23.1 μs | 22.8 μs | Gallop (22.9 μs) | 1.01x | +| plateau | unsorted | 64 | 4096 | 90.1 μs | 91.9 μs | 90.1 μs | 90.1 μs | 92.0 μs | 90.1 μs | 91.8 μs | Linear (90.1 μs) | 1.00x | +| plateau | unsorted | 64 | 16384 | 369.3 μs | 364.8 μs | 367.9 μs | 361.9 μs | 369.0 μs | 367.8 μs | 361.7 μs | InterpSearch (361.9 μs) | 1.02x | +| plateau | unsorted | 256 | 1024 | 27.4 μs | 27.4 μs | 27.4 μs | 27.3 μs | 27.3 μs | 27.4 μs | 27.4 μs | Binary (27.3 μs) | 1.00x | +| plateau | unsorted | 256 | 4096 | 108.4 μs | 108.4 μs | 108.4 μs | 108.4 μs | 108.2 μs | 108.1 μs | 108.7 μs | Binary (108.2 μs) | 1.00x | +| plateau | unsorted | 256 | 16384 | 435.2 μs | 435.0 μs | 435.4 μs | 434.6 μs | 435.2 μs | 435.3 μs | 435.0 μs | InterpSearch (434.6 μs) | 1.00x | +| plateau | unsorted | 1024 | 1024 | 32.2 μs | 32.4 μs | 32.3 μs | 32.4 μs | 32.4 μs | 32.4 μs | 32.5 μs | Linear (32.2 μs) | 1.01x | +| plateau | unsorted | 1024 | 4096 | 128.8 μs | 129.0 μs | 129.1 μs | 128.8 μs | 128.7 μs | 129.1 μs | 128.4 μs | Binary (128.7 μs) | 1.00x | +| plateau | unsorted | 1024 | 16384 | 516.7 μs | 516.8 μs | 517.0 μs | 516.8 μs | 517.5 μs | 517.0 μs | 517.0 μs | Linear (516.7 μs) | 1.00x | +| bimodal | sorted_uniform | 64 | 1024 | 7.5 μs | 14.5 μs | 10.9 μs | 48.8 μs | 17.1 μs | 7.9 μs | 14.8 μs | Linear (7.5 μs) | 1.05x | +| bimodal | sorted_uniform | 64 | 4096 | 30.4 μs | 57.2 μs | 42.9 μs | 171.8 μs | 68.2 μs | 31.8 μs | 58.1 μs | Linear (30.4 μs) | 1.04x | +| bimodal | sorted_uniform | 64 | 16384 | 118.8 μs | 225.5 μs | 167.7 μs | 660.4 μs | 272.1 μs | 124.0 μs | 229.8 μs | Linear (118.8 μs) | 1.04x | +| bimodal | sorted_uniform | 256 | 1024 | 7.8 μs | 14.7 μs | 10.9 μs | 71.4 μs | 21.9 μs | 8.2 μs | 20.5 μs | Linear (7.8 μs) | 1.05x | +| bimodal | sorted_uniform | 256 | 4096 | 30.6 μs | 59.0 μs | 43.8 μs | 239.6 μs | 88.7 μs | 31.9 μs | 80.5 μs | Linear (30.6 μs) | 1.04x | +| bimodal | sorted_uniform | 256 | 16384 | 122.6 μs | 229.2 μs | 173.0 μs | 849.6 μs | 360.3 μs | 127.8 μs | 312.1 μs | Linear (122.6 μs) | 1.04x | +| bimodal | sorted_uniform | 1024 | 1024 | 9.4 μs | 15.8 μs | 11.8 μs | 91.3 μs | 27.1 μs | 9.8 μs | 25.5 μs | Linear (9.4 μs) | 1.04x | +| bimodal | sorted_uniform | 1024 | 4096 | 31.6 μs | 59.9 μs | 43.8 μs | 324.1 μs | 120.9 μs | 33.6 μs | 110.2 μs | Linear (31.6 μs) | 1.06x | +| bimodal | sorted_uniform | 1024 | 16384 | 128.7 μs | 238.5 μs | 178.3 μs | 1.08 ms | 530.7 μs | 133.8 μs | 452.2 μs | Linear (128.7 μs) | 1.04x | +| bimodal | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.1 μs | 47.4 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | +| bimodal | sorted_dense_burst | 64 | 4096 | 29.2 μs | 56.1 μs | 42.4 μs | 169.1 μs | 67.9 μs | 30.9 μs | 56.8 μs | Linear (29.2 μs) | 1.06x | +| bimodal | sorted_dense_burst | 64 | 16384 | 117.1 μs | 224.3 μs | 169.1 μs | 656.6 μs | 271.5 μs | 122.9 μs | 227.0 μs | Linear (117.1 μs) | 1.05x | +| bimodal | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 69.1 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | +| bimodal | sorted_dense_burst | 256 | 4096 | 29.4 μs | 56.2 μs | 42.3 μs | 228.0 μs | 87.2 μs | 30.8 μs | 76.4 μs | Linear (29.4 μs) | 1.05x | +| bimodal | sorted_dense_burst | 256 | 16384 | 117.5 μs | 224.9 μs | 168.1 μs | 828.1 μs | 349.3 μs | 123.5 μs | 305.9 μs | Linear (117.5 μs) | 1.05x | +| bimodal | sorted_dense_burst | 1024 | 1024 | 7.6 μs | 14.1 μs | 10.5 μs | 91.1 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.6 μs) | 1.03x | +| bimodal | sorted_dense_burst | 1024 | 4096 | 30.2 μs | 56.3 μs | 42.2 μs | 312.9 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (30.2 μs) | 1.02x | +| bimodal | sorted_dense_burst | 1024 | 16384 | 120.5 μs | 249.2 μs | 168.4 μs | 1.04 ms | 427.3 μs | 123.0 μs | 383.1 μs | Linear (120.5 μs) | 1.02x | +| bimodal | unsorted | 64 | 1024 | 21.7 μs | 21.7 μs | 21.7 μs | 22.4 μs | 21.6 μs | 21.7 μs | 21.8 μs | Binary (21.6 μs) | 1.00x | +| bimodal | unsorted | 64 | 4096 | 88.9 μs | 88.8 μs | 89.2 μs | 89.4 μs | 91.8 μs | 91.7 μs | 91.8 μs | Gallop (88.8 μs) | 1.03x | +| bimodal | unsorted | 64 | 16384 | 368.2 μs | 367.6 μs | 368.7 μs | 367.1 μs | 367.7 μs | 367.4 μs | 367.4 μs | InterpSearch (367.1 μs) | 1.00x | +| bimodal | unsorted | 256 | 1024 | 28.8 μs | 28.8 μs | 28.9 μs | 28.8 μs | 28.8 μs | 28.9 μs | 29.0 μs | InterpSearch (28.8 μs) | 1.00x | +| bimodal | unsorted | 256 | 4096 | 119.6 μs | 119.4 μs | 119.5 μs | 119.5 μs | 119.6 μs | 119.5 μs | 119.4 μs | Gallop (119.4 μs) | 1.00x | +| bimodal | unsorted | 256 | 16384 | 489.8 μs | 489.0 μs | 488.8 μs | 489.3 μs | 488.6 μs | 488.0 μs | 493.9 μs | Binary (488.6 μs) | 1.00x | +| bimodal | unsorted | 1024 | 1024 | 34.6 μs | 34.4 μs | 34.3 μs | 34.4 μs | 34.3 μs | 34.5 μs | 34.8 μs | ExpFromLeft (34.3 μs) | 1.01x | +| bimodal | unsorted | 1024 | 4096 | 144.0 μs | 143.1 μs | 142.9 μs | 142.7 μs | 142.5 μs | 142.5 μs | 144.3 μs | Binary (142.5 μs) | 1.00x | +| bimodal | unsorted | 1024 | 16384 | 618.9 μs | 617.9 μs | 615.9 μs | 616.1 μs | 615.6 μs | 614.5 μs | 620.0 μs | Binary (615.6 μs) | 1.00x | +| near_linear | sorted_uniform | 64 | 1024 | 8.8 μs | 15.1 μs | 11.7 μs | 30.9 μs | 18.1 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | +| near_linear | sorted_uniform | 64 | 4096 | 30.8 μs | 57.3 μs | 43.5 μs | 113.9 μs | 68.5 μs | 32.1 μs | 60.2 μs | Linear (30.8 μs) | 1.04x | +| near_linear | sorted_uniform | 64 | 16384 | 119.3 μs | 225.3 μs | 170.6 μs | 444.9 μs | 270.4 μs | 124.1 μs | 237.2 μs | Linear (119.3 μs) | 1.04x | +| near_linear | sorted_uniform | 256 | 1024 | 10.1 μs | 18.1 μs | 13.7 μs | 37.5 μs | 29.1 μs | 10.3 μs | 25.5 μs | Linear (10.1 μs) | 1.02x | +| near_linear | sorted_uniform | 256 | 4096 | 35.0 μs | 60.7 μs | 47.1 μs | 124.1 μs | 131.0 μs | 36.2 μs | 83.9 μs | Linear (35.0 μs) | 1.04x | +| near_linear | sorted_uniform | 256 | 16384 | 123.2 μs | 229.3 μs | 174.1 μs | 455.6 μs | 390.2 μs | 128.5 μs | 317.7 μs | Linear (123.2 μs) | 1.04x | +| near_linear | sorted_uniform | 1024 | 1024 | 10.2 μs | 18.2 μs | 12.6 μs | 39.2 μs | 75.0 μs | 9.9 μs | 58.1 μs | Linear (10.2 μs) | 0.98x | +| near_linear | sorted_uniform | 1024 | 4096 | 47.5 μs | 75.0 μs | 57.6 μs | 152.4 μs | 240.6 μs | 49.0 μs | 191.3 μs | Linear (47.5 μs) | 1.03x | +| near_linear | sorted_uniform | 1024 | 16384 | 141.7 μs | 242.8 μs | 188.1 μs | 495.8 μs | 597.4 μs | 147.3 μs | 487.6 μs | Linear (141.7 μs) | 1.04x | +| near_linear | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.9 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | +| near_linear | sorted_dense_burst | 64 | 4096 | 29.4 μs | 56.3 μs | 42.3 μs | 110.4 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.4 μs) | 1.05x | +| near_linear | sorted_dense_burst | 64 | 16384 | 117.6 μs | 224.6 μs | 168.9 μs | 442.4 μs | 271.6 μs | 123.4 μs | 227.1 μs | Linear (117.6 μs) | 1.05x | +| near_linear | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.7 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | +| near_linear | sorted_dense_burst | 256 | 4096 | 29.3 μs | 56.2 μs | 42.3 μs | 110.3 μs | 87.4 μs | 30.8 μs | 76.4 μs | Linear (29.3 μs) | 1.05x | +| near_linear | sorted_dense_burst | 256 | 16384 | 117.5 μs | 225.0 μs | 168.8 μs | 442.0 μs | 349.2 μs | 122.8 μs | 305.9 μs | Linear (117.5 μs) | 1.05x | +| near_linear | sorted_dense_burst | 1024 | 1024 | 7.5 μs | 14.2 μs | 10.6 μs | 27.6 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.5 μs) | 1.05x | +| near_linear | sorted_dense_burst | 1024 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 110.5 μs | 106.8 μs | 30.8 μs | 95.8 μs | Linear (29.5 μs) | 1.05x | +| near_linear | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 224.9 μs | 168.7 μs | 441.2 μs | 427.4 μs | 123.2 μs | 383.2 μs | Linear (117.5 μs) | 1.05x | +| near_linear | unsorted | 64 | 1024 | 44.3 μs | 43.1 μs | 42.4 μs | 42.3 μs | 43.2 μs | 42.0 μs | 45.2 μs | InterpSearch (42.3 μs) | 0.99x | +| near_linear | unsorted | 64 | 4096 | 233.9 μs | 233.1 μs | 230.5 μs | 230.4 μs | 229.5 μs | 230.1 μs | 233.2 μs | Binary (229.5 μs) | 1.00x | +| near_linear | unsorted | 64 | 16384 | 982.8 μs | 985.4 μs | 982.3 μs | 981.1 μs | 980.8 μs | 982.7 μs | 982.6 μs | Binary (980.8 μs) | 1.00x | +| near_linear | unsorted | 256 | 1024 | 57.2 μs | 55.3 μs | 54.7 μs | 54.1 μs | 53.8 μs | 53.6 μs | 58.5 μs | Binary (53.8 μs) | 1.00x | +| near_linear | unsorted | 256 | 4096 | 315.0 μs | 311.5 μs | 312.0 μs | 311.2 μs | 310.1 μs | 310.9 μs | 314.4 μs | Binary (310.1 μs) | 1.00x | +| near_linear | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.31 ms | 1.30 ms | 1.30 ms | 1.31 ms | 1.31 ms | Binary (1.30 ms) | 1.00x | +| near_linear | unsorted | 1024 | 1024 | 81.6 μs | 79.2 μs | 77.9 μs | 76.7 μs | 76.4 μs | 76.6 μs | 83.5 μs | Binary (76.4 μs) | 1.00x | +| near_linear | unsorted | 1024 | 4096 | 411.4 μs | 408.2 μs | 409.2 μs | 407.7 μs | 406.7 μs | 406.7 μs | 414.4 μs | Binary (406.7 μs) | 1.00x | +| near_linear | unsorted | 1024 | 16384 | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.68 ms | 1.68 ms | Gallop (1.67 ms) | 1.00x | + +**Auto verdict over 270 cells**: 270 within 20% of best, 0 worse than 20% slowdown, 0 effectively-faster-than-best. diff --git a/bench/strategies.jl b/bench/strategies.jl index eb9119b..40d54d3 100644 --- a/bench/strategies.jl +++ b/bench/strategies.jl @@ -3,28 +3,30 @@ Benchmark sweep for the SearchStrategy types in FindFirstFunctions. Run from the repo root: - julia --project=bench bench/strategies.jl - -Or with an existing environment: - - julia --project=. -e 'using Pkg; Pkg.add(["BenchmarkTools", "StableRNGs", "Printf"]); include("bench/strategies.jl")' + julia --project=bench bench/strategies.jl # default fast sweep + MODE=full julia --project=bench bench/strategies.jl # full sweep + MODE=spacing julia --project=bench bench/strategies.jl # focused: spacing variety + MODE=ratio julia --project=bench bench/strategies.jl # focused: n/m crossover + MODE=pattern julia --project=bench bench/strategies.jl # focused: query pattern + MODE=extreme julia --project=bench bench/strategies.jl # focused: very sparse / very dense Sweeps over: - - knot count `n` - - query count `m` - - knot spacing (uniform, log, jittered, geometric-with-outliers) - - query pattern (sorted-uniform, sorted-dense-burst, sorted-clustered-near-start, unsorted, single) - - strategy (LinearScan, BracketGallop, ExpFromLeft, InterpolationSearch, BinaryBracket, Auto) + - knot count `n` (16 .. 1_000_000 in the full sweep) + - query count `m` (1 .. 4n in the full sweep) + - knot spacing (10 spacings, see KNOT_SPACINGS below) + - query pattern (8 patterns, see QUERY_PATTERNS below) + - strategy (LinearScan, BracketGallop, ExpFromLeft, + InterpolationSearch, BinaryBracket, Auto) Emits a Markdown table per sub-sweep so the regimes where each strategy wins -are easy to read off. +are easy to read off, plus a "best/auto" column that flags cells where the +heuristic doesn't land on the actual best strategy. """ using BenchmarkTools using StableRNGs using Printf -import FindFirstFunctions as FFF using FindFirstFunctions: LinearScan, BracketGallop, ExpFromLeft, InterpolationSearch, BinaryBracket, Auto, SearchStrategy, searchsortedlast!, searchsortedfirst! @@ -36,30 +38,67 @@ const RNG = StableRNG(0xfaceb00c) # --------------------------------------------------------------------------- knots_uniform(n) = collect(range(0.0, 10.0; length = n)) -function knots_log(n) - return collect(exp.(range(log(0.1), log(100.0); length = n))) -end +knots_log(n) = collect(exp.(range(log(0.1), log(100.0); length = n))) function knots_jittered(n; rel = 0.3) base = collect(range(0.0, 10.0; length = n)) + n < 2 && return base step = base[2] - base[1] return sort!(base .+ (rand(RNG, n) .- 0.5) .* rel .* step) end -function knots_random(n) - return sort!(rand(RNG, n) .* 10.0) -end -function knots_cluster_then_sparse(n) +knots_random(n) = sort!(rand(RNG, n) .* 10.0) +function knots_two_scale(n) # Half the knots packed near 0..1, half spread over 1..1000 n1 = n ÷ 2 n2 = n - n1 return sort!(vcat(rand(RNG, n1), 1.0 .+ rand(RNG, n2) .* 999.0)) end +# v_i = (i / n)^2 — quadratic spacing; dense near 0, sparse near 1. +knots_power2(n) = collect(((0:(n - 1)) ./ max(1, n - 1)) .^ 2 .* 10.0) +# v_i = sqrt(i / n) — square-root spacing; sparse near 0, dense near 1. +knots_sqrt(n) = collect(sqrt.((0:(n - 1)) ./ max(1, n - 1)) .* 10.0) +# Three flat plateaus and two jumps — many duplicate values. +function knots_plateau(n) + chunk = max(1, n ÷ 3) + v = vcat(fill(1.0, chunk), fill(5.0, chunk), fill(9.0, n - 2 * chunk)) + return v +end +# Bimodal: two dense clusters at 0..1 and 9..10, sparse middle. +function knots_bimodal(n) + n1 = n ÷ 2 + n2 = n - n1 + left = sort!(rand(RNG, n1)) + right = sort!(9.0 .+ rand(RNG, n2)) + return vcat(left, right) +end +# Almost-linear with one tiny offset to defeat simple range checks. +function knots_near_linear(n) + v = collect(range(0.0, 10.0; length = n)) + if n >= 4 + v[end - 1] += 1.0e-9 + end + return v +end + +const ALL_KNOT_SPACINGS = ( + :uniform => knots_uniform, + :log => knots_log, + :jittered => knots_jittered, + :random => knots_random, + :two_scale => knots_two_scale, + :power2 => knots_power2, + :sqrt => knots_sqrt, + :plateau => knots_plateau, + :bimodal => knots_bimodal, + :near_linear => knots_near_linear, +) -const KNOT_SPACINGS = ( +# Fast-sweep subset +const FAST_KNOT_SPACINGS = ( :uniform => knots_uniform, :log => knots_log, :jittered => knots_jittered, :random => knots_random, - :two_scale => knots_cluster_then_sparse, + :two_scale => knots_two_scale, ) # --------------------------------------------------------------------------- @@ -71,27 +110,64 @@ function queries_uniform(t::Vector, m::Integer) return sort!(lo .+ (hi - lo) .* rand(RNG, m)) end +# All queries packed inside a single tiny segment in the middle of t. function queries_dense_burst(t::Vector, m::Integer) - # All queries inside a single tiny window in the middle of t n = length(t) i = max(1, n ÷ 2) lo, hi = t[i], t[min(i + 1, n)] return sort!(lo .+ (hi - lo) .* rand(RNG, m)) end +# 90% of queries clustered in the first 5% of t, 10% spread over the rest. function queries_clustered_near_start(t::Vector, m::Integer) - # 90% of queries in t[1]..t[max(2, n÷20)], 10% spread over the rest n = length(t) cutoff = max(2, n ÷ 20) lo1, hi1 = t[1], t[cutoff] lo2, hi2 = t[cutoff], t[end] n1 = max(1, (9 * m) ÷ 10) n2 = m - n1 - qs = vcat( - lo1 .+ (hi1 - lo1) .* rand(RNG, n1), - lo2 .+ (hi2 - lo2) .* rand(RNG, n2) + return sort!( + vcat( + lo1 .+ (hi1 - lo1) .* rand(RNG, n1), + lo2 .+ (hi2 - lo2) .* rand(RNG, n2) + ) ) - return sort!(qs) +end + +# Arithmetic progression covering the full range of t. +function queries_arithmetic(t::Vector, m::Integer) + return collect(range(first(t), last(t); length = m)) +end + +# Geometric progression — gaps double as we move forward. +function queries_geometric(t::Vector, m::Integer) + m <= 1 && return [first(t)] + lo, hi = first(t), last(t) + span = hi - lo + weights = collect(0:(m - 1)) ./ (m - 1) + geo = exp.(log(1) .+ (log(span + 1) - log(1)) .* weights) .- 1 + return lo .+ geo +end + +# Bimodal: half clustered at one end of t, half at the other. +function queries_bimodal(t::Vector, m::Integer) + lo, hi = first(t), last(t) + n1 = m ÷ 2 + n2 = m - n1 + span = (hi - lo) * 0.1 + return sort!( + vcat( + lo .+ span .* rand(RNG, n1), + hi .- span .* rand(RNG, n2) + ) + ) +end + +# Same value repeated — pathological for any hint-using strategy if `v` +# has duplicates around it. +function queries_repeated(t::Vector, m::Integer) + mid = t[max(1, length(t) ÷ 2)] + return fill(mid, m) end function queries_unsorted(t::Vector, m::Integer) @@ -99,7 +175,18 @@ function queries_unsorted(t::Vector, m::Integer) return lo .+ (hi - lo) .* rand(RNG, m) end -const QUERY_PATTERNS = ( +const ALL_QUERY_PATTERNS = ( + :sorted_uniform => queries_uniform, + :sorted_dense_burst => queries_dense_burst, + :sorted_near_start => queries_clustered_near_start, + :sorted_arithmetic => queries_arithmetic, + :sorted_geometric => queries_geometric, + :sorted_bimodal => queries_bimodal, + :sorted_repeated => queries_repeated, + :unsorted => queries_unsorted, +) + +const FAST_QUERY_PATTERNS = ( :sorted_uniform => queries_uniform, :sorted_dense_burst => queries_dense_burst, :sorted_near_start => queries_clustered_near_start, @@ -120,24 +207,23 @@ const STRATEGIES = ( ) # --------------------------------------------------------------------------- -# Single-batch benchmark +# Benchmark primitives # --------------------------------------------------------------------------- "Returns minimum-time-per-batch (ns) for the given strategy on `(v, q)`." function bench_batch(strategy::SearchStrategy, v::Vector, q::Vector) out = Vector{Int}(undef, length(q)) - b = @benchmark searchsortedlast!($out, $v, $q; strategy = $strategy) samples = 30 evals = 1 + b = @benchmark searchsortedlast!($out, $v, $q; strategy = $strategy) samples = 20 evals = 1 return minimum(b).time # ns end -# Reference: Base.searchsortedlast applied per element function bench_base(v::Vector, q::Vector) out = Vector{Int}(undef, length(q)) b = @benchmark begin @inbounds for k in eachindex($q) $out[k] = searchsortedlast($v, $q[k]) end - end samples = 30 evals = 1 + end samples = 20 evals = 1 return minimum(b).time end @@ -157,13 +243,18 @@ function format_ns(x) end end -function run_sweep(; ns, ms, spacings, query_patterns, strategies) - println("\n## Benchmark sweep\n") - println( - "| spacing | query pattern | n | m | ", - join((s for (s, _) in strategies), " | "), - " | base | best | best/auto |" - ) +function run_sweep(; title, ns, ms, spacings, query_patterns, strategies) + println("\n## $title\n") + header = String[ + "spacing", "query pattern", "n", "m", + ] + for (name, _) in strategies + push!(header, name) + end + push!(header, "base") + push!(header, "best") + push!(header, "best/auto") + println("| ", join(header, " | "), " |") println( "|---|---|---|---|", join(("---" for _ in strategies), "|"), @@ -186,11 +277,9 @@ function run_sweep(; ns, ms, spacings, query_patterns, strategies) results[name] = bench_batch(strat, t, q) end results["base"] = bench_base(t, q) - # Determine best (excluding "Auto" itself) best_name, best_t = "", Inf for (name, t_) in results - name == "Auto" && continue - name == "base" && continue + (name == "Auto" || name == "base") && continue if t_ < best_t best_t = t_ best_name = name @@ -199,7 +288,7 @@ function run_sweep(; ns, ms, spacings, query_patterns, strategies) auto_t = results["Auto"] rel = auto_t / best_t if rel < 0.95 - auto_wins += 1 # shouldn't really happen unless Auto picks correctly + auto_wins += 1 elseif rel > 1.2 auto_losses += 1 else @@ -208,7 +297,8 @@ function run_sweep(; ns, ms, spacings, query_patterns, strategies) rows += 1 cols = String[ - string(sp_name), string(qp_name), string(n), string(m), + string(sp_name), string(qp_name), + string(n), string(m), ] for (name, _) in strategies push!(cols, format_ns(results[name])) @@ -226,37 +316,118 @@ function run_sweep(; ns, ms, spacings, query_patterns, strategies) "\n**Auto verdict over $rows cells**: ", "$auto_within_20pct within 20% of best, ", "$auto_losses worse than 20% slowdown, ", - "$auto_wins effectively-faster-than-best (shouldn't happen)." + "$auto_wins effectively-faster-than-best." ) - return nothing + return (rows, auto_within_20pct, auto_losses, auto_wins) end -# Fast sweep — small enough to run interactively +# --------------------------------------------------------------------------- +# Pre-built sweep definitions +# --------------------------------------------------------------------------- + function fast_sweep() return run_sweep( + title = "Fast sweep", ns = (64, 1024, 65_536), ms = (1, 10, 256, 4096), - spacings = KNOT_SPACINGS, - query_patterns = QUERY_PATTERNS, + spacings = FAST_KNOT_SPACINGS, + query_patterns = FAST_QUERY_PATTERNS, strategies = STRATEGIES, ) end -# Full sweep — slower function full_sweep() return run_sweep( - ns = (16, 64, 256, 1024, 4096, 65_536, 1_000_000), - ms = (1, 10, 100, 1024, 4096), - spacings = KNOT_SPACINGS, - query_patterns = QUERY_PATTERNS, + title = "Full sweep", + ns = (16, 64, 256, 1024, 4096, 65_536, 262_144), + ms = (1, 10, 64, 256, 1024, 4096), + spacings = ALL_KNOT_SPACINGS, + query_patterns = ALL_QUERY_PATTERNS, + strategies = STRATEGIES, + ) +end + +# Focused: vary spacing only, fix n=4096, m=512, pattern=sorted_uniform. +function sweep_spacing() + return run_sweep( + title = "Spacing variety (n=4096, m=512, sorted_uniform)", + ns = (4096,), + ms = (512,), + spacings = ALL_KNOT_SPACINGS, + query_patterns = (:sorted_uniform => queries_uniform,), + strategies = STRATEGIES, + ) +end + +# Focused: vary n and m on uniform data. +function sweep_ratio() + return run_sweep( + title = "n/m crossover (uniform, sorted_uniform)", + ns = (16, 64, 256, 1024, 4096, 16_384, 65_536, 262_144), + ms = (1, 4, 16, 64, 256, 1024, 4096, 16_384), + spacings = (:uniform => knots_uniform,), + query_patterns = (:sorted_uniform => queries_uniform,), + strategies = STRATEGIES, + ) +end + +# Focused: vary query pattern. +function sweep_pattern() + return run_sweep( + title = "Query patterns (n=4096, m=512, uniform)", + ns = (4096,), + ms = (512,), + spacings = (:uniform => knots_uniform,), + query_patterns = ALL_QUERY_PATTERNS, + strategies = STRATEGIES, + ) +end + +# Focused: stress edges — super sparse and super dense. +function sweep_extreme() + # Super sparse: m=1..16 over varied n. + # Super dense: m = 4n. + println("\n### Super-sparse cases (small m on large n)") + res_sparse = run_sweep( + title = "Super sparse", + ns = (1024, 16_384, 262_144), + ms = (1, 4, 16), + spacings = ALL_KNOT_SPACINGS, + query_patterns = ( + :sorted_uniform => queries_uniform, + :unsorted => queries_unsorted, + ), + strategies = STRATEGIES, + ) + + println("\n### Super-dense cases (m ≫ n)") + res_dense = run_sweep( + title = "Super dense", + ns = (64, 256, 1024), + ms = (1024, 4096, 16_384), # m up to 256× n + spacings = ALL_KNOT_SPACINGS, + query_patterns = ( + :sorted_uniform => queries_uniform, + :sorted_dense_burst => queries_dense_burst, + :unsorted => queries_unsorted, + ), strategies = STRATEGIES, ) + return (sparse = res_sparse, dense = res_dense) end if abspath(PROGRAM_FILE) == @__FILE__ mode = get(ENV, "MODE", "fast") if mode == "full" full_sweep() + elseif mode == "spacing" + sweep_spacing() + elseif mode == "ratio" + sweep_ratio() + elseif mode == "pattern" + sweep_pattern() + elseif mode == "extreme" + sweep_extreme() else fast_sweep() end diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index 9077d4a..b53c887 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -285,6 +285,25 @@ that is supplied. """ struct BinaryBracket <: SearchStrategy end +""" + GuesserHint(guesser::Guesser) <: SearchStrategy + +Uses a [`Guesser`](@ref) to produce an integer guess for `x`, then dispatches +to [`BracketGallop`](@ref) from that guess. The `Guesser` already decides +between linear-extrapolation lookup (when `v` looks linear) and using the +previous result as a guess; this strategy plugs that logic into the strategy +dispatch hierarchy, and updates `guesser.idx_prev` on each call. + +This is the strategy backing the existing +`searchsortedfirstcorrelated(v, x, ::Guesser)` and +`searchsortedlastcorrelated(v, x, ::Guesser)` overloads, exposed so it can +be passed to the batched [`searchsortedlast!`](@ref) / [`searchsortedfirst!`](@ref) +APIs. +""" +struct GuesserHint{G} <: SearchStrategy + guesser::G +end + """ Auto <: SearchStrategy @@ -298,23 +317,25 @@ the calling context: - Hint in range, `length(v) > 16` → [`BracketGallop`](@ref). **Batched sorted** (`searchsortedlast!(out, v, queries; strategy = Auto())`), -where the expected average gap between consecutive results is -`avg_gap = length(v) / length(queries)`: - - `avg_gap ≤ 4` → [`LinearScan`](@ref) (most queries land in the same +using the expected average gap between consecutive results. For numeric +data the gap is estimated from the span ratio +`(queries[end] - queries[1]) / (v[end] - v[1])` so that dense-burst queries +clustered inside one segment of `v` are recognized as having gap ≈ 0: + - `gap ≤ 4` → [`LinearScan`](@ref) (most queries land in the same segment or the next; linear-walk overhead is minimal, and `ExpFromLeft` wastes its 5 initial linear probes when the gap is already 0 or 1). - - `avg_gap > 4` → [`ExpFromLeft`](@ref) (linear probes for very small + - `gap > 64`, `length(v) ≥ 1024`, `length(queries) ≥ 2`, and a sampled + linearity probe (5 reads, ~12 ns) accepts → [`InterpolationSearch`](@ref). + On uniformly-spaced data this is ~2× faster than `ExpFromLeft` for + sparse queries; the linearity probe is what keeps `Auto` from picking + `InterpolationSearch` on irregular data where it would lose badly. + - otherwise → [`ExpFromLeft`](@ref) (linear probes for very small jumps, doubling for medium, bounded binary search for far — always moving forward from the previous result, which is what `BracketGallop`'s bidirectional bracketing wastes effort on). **Batched unsorted**: falls back to per-element `Base.searchsortedlast` / `Base.searchsortedfirst` with no hint regardless of strategy. - -[`InterpolationSearch`](@ref) is intentionally not part of the `Auto` choice -because it requires the element type to be subtractable and benefits most -when the user knows the data is roughly linearly spaced. Opt in explicitly -with `strategy = InterpolationSearch()` when that's the case. """ struct Auto <: SearchStrategy end @@ -329,6 +350,39 @@ const _AUTO_LINEAR_THRESHOLD = 16 # sorted queries. const _AUTO_BATCH_LINEAR_GAP = 4 +# For sparse queries (gap large) on long vectors, InterpolationSearch can +# beat ExpFromLeft by ~2× on uniformly-spaced data. The sampled-linearity +# check below is O(1) — 5 fixed probes — so it's cheap enough to run inside +# Auto when there's a real chance of unlocking InterpolationSearch. +const _AUTO_INTERP_MIN_GAP = 64 +const _AUTO_INTERP_MIN_N = 1024 +const _AUTO_INTERP_MIN_M = 2 +const _AUTO_LINEAR_REL_TOLERANCE = 0.05 + +# Sampled linearity check: probes v[1], v[n/4], v[n/2], v[3n/4], v[n] and +# tests whether the interior points sit close to the straight line between +# the endpoints. Cost is ~12 ns regardless of n. Used by Auto to decide +# whether to gamble on InterpolationSearch. +@inline function _sampled_looks_linear(v::AbstractVector{<:Number}) + n = length(v) + n < 5 && return true + @inbounds begin + v1, vn = v[1], v[n] + span = vn - v1 + (iszero(span) || !isfinite(span)) && return false + for k in (n >> 2, n >> 1, (3 * n) >> 2) + kk = max(1, min(n, k)) + expected = v1 + (kk - 1) / (n - 1) * span + rel_err = abs(v[kk] - expected) / abs(span) + rel_err > _AUTO_LINEAR_REL_TOLERANCE && return false + end + end + return true +end + +# Non-numeric eltype: can't sample, never picks InterpolationSearch. +@inline _sampled_looks_linear(::AbstractVector) = false + # Strategy: BinaryBracket — ignore any hint. Base.searchsortedlast( ::BinaryBracket, v::AbstractVector, x; @@ -568,6 +622,10 @@ Base.searchsortedfirst( order::Base.Order.Ordering = Base.Order.Forward ) = searchsortedfirst(BinaryBracket(), v, x; order = order) +# Strategy: GuesserHint — Guesser produces an integer hint, BracketGallop runs +# the search and updates the Guesser's prev-result cache. Methods are defined +# below where Guesser is in scope (search the file for "GuesserHint methods"). + # Strategy: Auto — pick based on hint validity and length(v). @inline function _auto_pick(v::AbstractVector, hint::Integer) return if hint < firstindex(v) || hint > lastindex(v) @@ -795,11 +853,24 @@ function _searchsortedlast_batched!( end gap = _estimate_avg_gap(v, queries, m) # Manually dispatch on the picked strategy so each branch is concrete. - return if gap <= _AUTO_BATCH_LINEAR_GAP - _searchsortedlast_sorted_loop!(idx_out, v, queries, LinearScan(), order) - else - _searchsortedlast_sorted_loop!(idx_out, v, queries, ExpFromLeft(), order) + if gap <= _AUTO_BATCH_LINEAR_GAP + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, LinearScan(), order + ) + end + # Sparse-on-large-linear: InterpolationSearch wins ~2× over ExpFromLeft + # on uniformly-spaced data. Sampled check is ~12 ns. + if gap >= _AUTO_INTERP_MIN_GAP && + length(v) >= _AUTO_INTERP_MIN_N && + m >= _AUTO_INTERP_MIN_M && + _sampled_looks_linear(v) + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, InterpolationSearch(), order + ) end + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, ExpFromLeft(), order + ) end function _searchsortedfirst_batched!( @@ -828,11 +899,22 @@ function _searchsortedfirst_batched!( return _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) end gap = _estimate_avg_gap(v, queries, m) - return if gap <= _AUTO_BATCH_LINEAR_GAP - _searchsortedfirst_sorted_loop!(idx_out, v, queries, LinearScan(), order) - else - _searchsortedfirst_sorted_loop!(idx_out, v, queries, ExpFromLeft(), order) + if gap <= _AUTO_BATCH_LINEAR_GAP + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, LinearScan(), order + ) + end + if gap >= _AUTO_INTERP_MIN_GAP && + length(v) >= _AUTO_INTERP_MIN_N && + m >= _AUTO_INTERP_MIN_M && + _sampled_looks_linear(v) + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, InterpolationSearch(), order + ) end + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, ExpFromLeft(), order + ) end """ @@ -964,6 +1046,39 @@ function searchsortedlastcorrelated( return out end +# GuesserHint methods — strategy dispatch wrapper for the `Guesser`-based +# correlated search. Per-call cost: one `guesser(x)` evaluation + one +# `BracketGallop` call + one `idx_prev[]` write. +function Base.searchsortedlast( + s::GuesserHint, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward + ) + @assert v === s.guesser.v + out = searchsortedlast(BracketGallop(), v, x, s.guesser(x); order = order) + s.guesser.idx_prev[] = out + return out +end + +function Base.searchsortedfirst( + s::GuesserHint, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward + ) + @assert v === s.guesser.v + out = searchsortedfirst(BracketGallop(), v, x, s.guesser(x); order = order) + s.guesser.idx_prev[] = out + return out +end + +# GuesserHint ignores any externally-supplied hint (the Guesser carries its own). +Base.searchsortedlast( + s::GuesserHint, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(s, v, x; order = order) +Base.searchsortedfirst( + s::GuesserHint, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(s, v, x; order = order) + """ searchsortedfirstexp(v, x, lo=firstindex(v), hi=lastindex(v)) From 65ea6c0e5c240a617a100355871487e41c98c6b9 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 17 May 2026 08:15:12 -0400 Subject: [PATCH 04/16] Auto: skew detection + tightened linearity probe, more bench coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two algorithmic refinements driven by the broader benchmark sweep: - **Skew detection in `_estimate_avg_gap`** — the span-based gap estimator now returns `(gap, skewed)` where `skewed` is true when the median query sits more than 20 % of the query span away from the linear midpoint. Gated on `m ≥ 10` so small-batch statistical noise doesn't trip it. For sorted_near_start / sorted_geometric / sorted_bimodal patterns (most queries clustered in part of `v`'s range), the unmodified span heuristic massively underestimated the effective gap and routed Auto to `LinearScan` when `ExpFromLeft` was best (1.8-3.1× slowdown on those cells before). - **`InterpolationSearch` gated on `!skewed`** — even on perfectly uniform `v`, when queries are clustered, `ExpFromLeft` from `prev_idx` beats `InterpolationSearch` because each consecutive query's true index is close to the previous one's. The skew flag now prevents Auto from gambling on InterpSearch in that regime. - **Tightened sampled-linearity probe** from 5 probes / 5 % tolerance to 9 probes (k·n/10 for k = 1..9) / 0.1 % tolerance. This reliably rejects sorted-random data — which still looks linear-ish to a loose probe at large n — without rejecting any genuinely uniform or jittered grid. Probe cost rises from ~12 ns to ~25 ns and now catches the case where Auto used to pick InterpSearch on random data and lose 50-150 %. - **`AbstractRange` short-circuit** — `_sampled_looks_linear(::AbstractRange)` returns true without sampling. Ranges are definitionally uniform. Bench expanded so the heuristic can be vetted in detail: - Five **tuning sub-sweeps** (`MODE=tune`) that locate the actual strategy crossover points empirically — LinearScan↔ExpFromLeft crosses at gap ≈ 5; ExpFromLeft↔InterpSearch crosses around gap 8 *on uniform data*; minimum useful n for InterpSearch is ~2 048; minimum useful m is ~2; InterpSearch's downside on non-linear data bottoms out at 1.5× (random) and tops out at 14× (plateau). - A **3 920-cell validation sweep** (`MODE=validate`) — every combination of 10 spacings × 8 query patterns × 7 `n` × 7 `m`. - Two more knot spacings (`near_linear`, `power2`) and pattern variety (`sorted_arithmetic`, `sorted_geometric`, `sorted_bimodal`, `sorted_repeated`) on top of the v9 set. Bench verdict over **4 692 cells across all sub-sweeps**: | sub-sweep | within 20 % | regression worst case | |--------------------------|-------------|-----------------------| | spacing (10) | 10 / 10 | none | | pattern (8) | 7 / 8 | 1.51× at m=512 | | super-dense (270) | 263 / 270 | 1.21× borderline | | fast (240) | 221 / 240 | 1.59× at m=10 | | super-sparse (180) | 147 / 180 | 2.00× at m=4 | | n/m crossover (64) | 51 / 64 | 1.62× at m=4096 | | **validate (3 920)** | **3 289 / 3 920 (84 %)** | **2.64× (1 cell)** | | **aggregate (4 692)** | **3 988 (85 %)** | **only 1 cell exceeds 2 ×** | Tests: 26 929 / 26 929 still passing. Artifacts: - `bench/strategies.jl` — bench harness with 6 modes - `bench/results.md` — fast sweep - `bench/results_focused.md` — spacing / pattern / ratio / extreme - `bench/results_validate.md` — the 3 920-cell sweep - `bench/results_tune.md` — crossover measurements Co-Authored-By: Chris Rackauckas --- bench/results.md | 489 ++--- bench/results_focused.md | 1068 +++++----- bench/results_tune.md | 103 + bench/results_validate.md | 3927 +++++++++++++++++++++++++++++++++++++ bench/strategies.jl | 185 ++ src/FindFirstFunctions.jl | 93 +- 6 files changed, 5065 insertions(+), 800 deletions(-) create mode 100644 bench/results_tune.md create mode 100644 bench/results_validate.md diff --git a/bench/results.md b/bench/results.md index 8556595..2fb577e 100644 --- a/bench/results.md +++ b/bench/results.md @@ -1,263 +1,266 @@ -# `bench/strategies.jl` results +# `bench/strategies.jl` results — fast sweep -Captured 2026-05-17 on Julia 1.10.11 (`julialauncher +1.10 --project=bench -bench/strategies.jl`). Sweep parameters: `n ∈ {64, 1024, 65536}`, `m ∈ -{1, 10, 256, 4096}`, five knot spacings (`uniform`, `log`, `jittered`, -`random`, `two_scale`), four query patterns (`sorted_uniform`, -`sorted_dense_burst`, `sorted_near_start`, `unsorted`). Each cell: -`BenchmarkTools.@benchmark`, 20 samples, `minimum` time. The `best/auto` -column compares `Auto`'s time to the strategy that won on that cell — values -≤ 1.20 mean `Auto` is within 20% of best. +Captured 2026-05-17 on Julia 1.10.11, run via +`julia --project=bench bench/strategies.jl`. 240 cells, 20 samples each, +`BenchmarkTools.minimum`. -The focused sub-sweeps (`MODE=spacing`, `MODE=ratio`, `MODE=pattern`, -`MODE=extreme`) live in `results_focused.md`. +The companion artifacts are: -To regenerate: `julia --project=bench bench/strategies.jl`. For the slower -full sweep set `MODE=full`. +- `bench/results_focused.md` — spacing/pattern/ratio/extreme sub-sweeps +- `bench/results_validate.md` — large 3920-cell validation sweep +- `bench/results_tune.md` — empirical crossover measurements that drive + the `Auto` thresholds (LinearScan↔ExpFromLeft, ExpFromLeft↔InterpSearch, + min-n / min-m for InterpSearch, and the InterpSearch downside on + non-linear data) + +`Auto` verdict on this sweep: **221 / 240 (92 %) within 20 % of best**. +Aggregate verdict across all sweeps (4 692 cells total): +**3 988 (85 %) within 20 % of best**; **only 1 cell exceeds 2 ×** (and that +one cell is a 180 ns absolute difference at `m = 4`). ## Fast sweep | spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | |---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| uniform | sorted_uniform | 64 | 10 | 170 ns | 230 ns | 230 ns | 310 ns | 240 ns | 270 ns | 180 ns | Linear (170 ns) | 1.59x | -| uniform | sorted_uniform | 64 | 256 | 2.3 μs | 4.2 μs | 3.8 μs | 9.0 μs | 4.4 μs | 2.1 μs | 3.8 μs | Linear (2.3 μs) | 0.95x | -| uniform | sorted_uniform | 64 | 4096 | 32.4 μs | 59.2 μs | 43.4 μs | 115.1 μs | 69.8 μs | 30.8 μs | 60.4 μs | Linear (32.4 μs) | 0.95x | -| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| uniform | sorted_uniform | 1024 | 10 | 1.7 μs | 410 ns | 330 ns | 310 ns | 300 ns | 340 ns | 270 ns | Binary (300 ns) | 1.13x | -| uniform | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.9 μs | 9.1 μs | 7.2 μs | 3.7 μs | 6.9 μs | Linear (3.6 μs) | 1.01x | -| uniform | sorted_uniform | 1024 | 4096 | 55.1 μs | 81.3 μs | 69.3 μs | 152.7 μs | 232.2 μs | 46.7 μs | 221.7 μs | Linear (55.1 μs) | 0.85x | -| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 90 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_uniform | 65536 | 10 | 79.2 μs | 710 ns | 530 ns | 320 ns | 540 ns | 350 ns | 420 ns | InterpSearch (320 ns) | 1.09x | -| uniform | sorted_uniform | 65536 | 256 | 100.1 μs | 12.1 μs | 9.3 μs | 9.2 μs | 13.4 μs | 9.5 μs | 14.5 μs | InterpSearch (9.2 μs) | 1.03x | -| uniform | sorted_uniform | 65536 | 4096 | 193.1 μs | 250.2 μs | 206.4 μs | 166.4 μs | 491.2 μs | 204.0 μs | 482.5 μs | InterpSearch (166.4 μs) | 1.23x | -| uniform | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| uniform | sorted_dense_burst | 64 | 10 | 120 ns | 180 ns | 150 ns | 300 ns | 210 ns | 130 ns | 170 ns | Linear (120 ns) | 1.08x | -| uniform | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 4.3 μs | 1.9 μs | 3.6 μs | Linear (2.0 μs) | 0.97x | -| uniform | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.9 μs | 42.2 μs | 109.9 μs | 67.8 μs | 29.5 μs | 56.9 μs | Linear (30.8 μs) | 0.96x | -| uniform | sorted_dense_burst | 1024 | 1 | 60 ns | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 300 ns | 310 ns | 140 ns | 280 ns | Linear (130 ns) | 1.08x | -| uniform | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 6.7 μs | 1.9 μs | 6.0 μs | Linear (2.0 μs) | 0.96x | -| uniform | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 42.3 μs | 109.6 μs | 106.8 μs | 29.5 μs | 95.7 μs | Linear (30.8 μs) | 0.96x | +| uniform | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| uniform | sorted_uniform | 64 | 10 | 180 ns | 220 ns | 190 ns | 310 ns | 200 ns | 190 ns | 180 ns | Linear (180 ns) | 1.06x | +| uniform | sorted_uniform | 64 | 256 | 2.1 μs | 4.2 μs | 3.0 μs | 9.0 μs | 4.2 μs | 2.2 μs | 4.8 μs | Linear (2.1 μs) | 1.01x | +| uniform | sorted_uniform | 64 | 4096 | 32.2 μs | 56.4 μs | 43.5 μs | 113.3 μs | 68.8 μs | 32.2 μs | 60.3 μs | Linear (32.2 μs) | 1.00x | +| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| uniform | sorted_uniform | 1024 | 10 | 1.7 μs | 410 ns | 330 ns | 320 ns | 290 ns | 370 ns | 270 ns | Binary (290 ns) | 1.28x | +| uniform | sorted_uniform | 1024 | 256 | 3.6 μs | 5.2 μs | 3.8 μs | 9.2 μs | 7.1 μs | 3.8 μs | 7.3 μs | Linear (3.6 μs) | 1.06x | +| uniform | sorted_uniform | 1024 | 4096 | 49.0 μs | 72.7 μs | 57.5 μs | 151.6 μs | 227.8 μs | 48.7 μs | 183.2 μs | Linear (49.0 μs) | 0.99x | +| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | +| uniform | sorted_uniform | 65536 | 10 | 81.6 μs | 750 ns | 500 ns | 310 ns | 430 ns | 379 ns | 410 ns | InterpSearch (310 ns) | 1.22x | +| uniform | sorted_uniform | 65536 | 256 | 100.9 μs | 12.7 μs | 9.1 μs | 9.3 μs | 14.2 μs | 9.7 μs | 17.2 μs | ExpFromLeft (9.1 μs) | 1.07x | +| uniform | sorted_uniform | 65536 | 4096 | 200.1 μs | 251.4 μs | 205.7 μs | 166.2 μs | 489.8 μs | 173.2 μs | 493.1 μs | InterpSearch (166.2 μs) | 1.04x | +| uniform | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Linear (50 ns) | 1.00x | +| uniform | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 310 ns | 200 ns | 140 ns | 170 ns | Linear (130 ns) | 1.08x | +| uniform | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 109.8 μs | 67.9 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| uniform | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 310 ns | 310 ns | 150 ns | 270 ns | Linear (130 ns) | 1.15x | +| uniform | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 109.7 μs | 106.9 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | | uniform | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 300 ns | 450 ns | 160 ns | 410 ns | Linear (150 ns) | 1.07x | -| uniform | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.3 μs | 1.9 μs | 9.6 μs | Linear (2.0 μs) | 0.97x | -| uniform | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.3 μs | 109.5 μs | 164.4 μs | 29.5 μs | 152.4 μs | Linear (30.8 μs) | 0.96x | -| uniform | sorted_near_start | 64 | 1 | 50 ns | 70 ns | 70 ns | 80 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| uniform | sorted_near_start | 64 | 10 | 190 ns | 210 ns | 160 ns | 310 ns | 200 ns | 180 ns | 220 ns | ExpFromLeft (160 ns) | 1.12x | -| uniform | sorted_near_start | 64 | 256 | 2.1 μs | 3.8 μs | 2.8 μs | 7.1 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 0.96x | -| uniform | sorted_near_start | 64 | 4096 | 32.1 μs | 59.3 μs | 43.4 μs | 111.6 μs | 67.4 μs | 30.1 μs | 59.4 μs | Linear (32.1 μs) | 0.94x | -| uniform | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| uniform | sorted_near_start | 1024 | 10 | 1.4 μs | 310 ns | 230 ns | 300 ns | 290 ns | 350 ns | 260 ns | ExpFromLeft (230 ns) | 1.52x | -| uniform | sorted_near_start | 1024 | 256 | 3.7 μs | 4.8 μs | 3.9 μs | 8.7 μs | 6.8 μs | 3.6 μs | 6.3 μs | Linear (3.7 μs) | 0.98x | -| uniform | sorted_near_start | 1024 | 4096 | 34.0 μs | 58.1 μs | 44.4 μs | 116.5 μs | 111.2 μs | 32.4 μs | 104.7 μs | Linear (34.0 μs) | 0.95x | -| uniform | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_near_start | 65536 | 10 | 36.8 μs | 520 ns | 410 ns | 310 ns | 440 ns | 350 ns | 410 ns | InterpSearch (310 ns) | 1.13x | -| uniform | sorted_near_start | 65536 | 256 | 93.5 μs | 7.9 μs | 5.7 μs | 9.0 μs | 11.6 μs | 9.4 μs | 11.5 μs | ExpFromLeft (5.7 μs) | 1.63x | -| uniform | sorted_near_start | 65536 | 4096 | 154.3 μs | 116.5 μs | 94.5 μs | 162.4 μs | 371.4 μs | 90.6 μs | 362.0 μs | ExpFromLeft (94.5 μs) | 0.96x | -| uniform | unsorted | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| uniform | unsorted | 64 | 10 | 180 ns | 180 ns | 180 ns | 180 ns | 200 ns | 200 ns | 169 ns | InterpSearch (180 ns) | 1.11x | -| uniform | unsorted | 64 | 256 | 5.9 μs | 5.7 μs | 5.8 μs | 5.8 μs | 5.8 μs | 5.8 μs | 3.7 μs | Gallop (5.7 μs) | 1.02x | -| uniform | unsorted | 64 | 4096 | 231.8 μs | 228.5 μs | 228.1 μs | 227.7 μs | 225.0 μs | 227.1 μs | 245.0 μs | Binary (225.0 μs) | 1.01x | -| uniform | unsorted | 1024 | 1 | 60 ns | 80 ns | 80 ns | 80 ns | 90 ns | 60 ns | 60 ns | Linear (60 ns) | 1.00x | -| uniform | unsorted | 1024 | 10 | 270 ns | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 270 ns | Linear (270 ns) | 1.07x | -| uniform | unsorted | 1024 | 256 | 8.8 μs | 8.0 μs | 8.0 μs | 7.8 μs | 7.8 μs | 7.9 μs | 6.8 μs | InterpSearch (7.8 μs) | 1.02x | -| uniform | unsorted | 1024 | 4096 | 410.1 μs | 410.5 μs | 411.8 μs | 409.7 μs | 410.8 μs | 411.3 μs | 415.7 μs | InterpSearch (409.7 μs) | 1.00x | +| uniform | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 310 ns | 450 ns | 170 ns | 410 ns | Linear (150 ns) | 1.13x | +| uniform | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.3 μs | 2.1 μs | 9.6 μs | Linear (2.0 μs) | 1.02x | +| uniform | sorted_dense_burst | 65536 | 4096 | 30.9 μs | 55.5 μs | 42.3 μs | 109.6 μs | 164.5 μs | 30.8 μs | 152.4 μs | Linear (30.9 μs) | 1.00x | +| uniform | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| uniform | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 170 ns | 330 ns | 200 ns | 190 ns | 180 ns | ExpFromLeft (170 ns) | 1.12x | +| uniform | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.3 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.06x | +| uniform | sorted_near_start | 64 | 4096 | 31.7 μs | 56.6 μs | 43.4 μs | 111.6 μs | 67.4 μs | 31.8 μs | 60.6 μs | Linear (31.7 μs) | 1.00x | +| uniform | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_near_start | 1024 | 10 | 1.4 μs | 300 ns | 230 ns | 310 ns | 290 ns | 260 ns | 270 ns | ExpFromLeft (230 ns) | 1.13x | +| uniform | sorted_near_start | 1024 | 256 | 3.8 μs | 4.7 μs | 3.5 μs | 8.7 μs | 6.8 μs | 3.7 μs | 7.0 μs | ExpFromLeft (3.5 μs) | 1.05x | +| uniform | sorted_near_start | 1024 | 4096 | 33.6 μs | 58.6 μs | 44.6 μs | 117.5 μs | 111.6 μs | 33.8 μs | 106.3 μs | Linear (33.6 μs) | 1.00x | +| uniform | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_near_start | 65536 | 10 | 36.5 μs | 520 ns | 400 ns | 300 ns | 430 ns | 440 ns | 430 ns | InterpSearch (300 ns) | 1.47x | +| uniform | sorted_near_start | 65536 | 256 | 95.9 μs | 8.0 μs | 5.7 μs | 9.0 μs | 11.9 μs | 5.9 μs | 19.9 μs | ExpFromLeft (5.7 μs) | 1.03x | +| uniform | sorted_near_start | 65536 | 4096 | 157.0 μs | 120.9 μs | 98.0 μs | 162.6 μs | 379.6 μs | 96.9 μs | 301.5 μs | ExpFromLeft (98.0 μs) | 0.99x | +| uniform | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | unsorted | 64 | 10 | 190 ns | 180 ns | 180 ns | 180 ns | 190 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | +| uniform | unsorted | 64 | 256 | 6.1 μs | 6.0 μs | 6.0 μs | 5.9 μs | 6.0 μs | 6.0 μs | 5.8 μs | InterpSearch (5.9 μs) | 1.01x | +| uniform | unsorted | 64 | 4096 | 230.8 μs | 230.3 μs | 229.0 μs | 229.3 μs | 227.0 μs | 226.9 μs | 224.7 μs | Binary (227.0 μs) | 1.00x | +| uniform | unsorted | 1024 | 1 | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| uniform | unsorted | 1024 | 10 | 270 ns | 280 ns | 280 ns | 280 ns | 290 ns | 290 ns | 270 ns | Linear (270 ns) | 1.07x | +| uniform | unsorted | 1024 | 256 | 8.5 μs | 8.1 μs | 8.1 μs | 8.1 μs | 8.0 μs | 8.1 μs | 8.0 μs | Binary (8.0 μs) | 1.00x | +| uniform | unsorted | 1024 | 4096 | 412.4 μs | 410.2 μs | 411.5 μs | 408.8 μs | 410.6 μs | 411.7 μs | 412.4 μs | InterpSearch (408.8 μs) | 1.01x | | uniform | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | unsorted | 65536 | 10 | 420 ns | 430 ns | 430 ns | 420 ns | 430 ns | 430 ns | 420 ns | InterpSearch (420 ns) | 1.02x | -| uniform | unsorted | 65536 | 256 | 14.3 μs | 13.8 μs | 13.8 μs | 13.9 μs | 13.8 μs | 13.7 μs | 15.5 μs | ExpFromLeft (13.8 μs) | 0.99x | -| uniform | unsorted | 65536 | 4096 | 849.7 μs | 847.5 μs | 844.6 μs | 847.6 μs | 847.5 μs | 847.0 μs | 849.5 μs | ExpFromLeft (844.6 μs) | 1.00x | -| log | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_uniform | 64 | 10 | 170 ns | 220 ns | 190 ns | 450 ns | 200 ns | 200 ns | 180 ns | Linear (170 ns) | 1.18x | -| log | sorted_uniform | 64 | 256 | 2.3 μs | 3.9 μs | 3.0 μs | 11.3 μs | 4.5 μs | 2.2 μs | 3.9 μs | Linear (2.3 μs) | 0.97x | -| log | sorted_uniform | 64 | 4096 | 31.7 μs | 55.8 μs | 43.1 μs | 170.5 μs | 69.2 μs | 30.4 μs | 60.7 μs | Linear (31.7 μs) | 0.96x | -| log | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| log | sorted_uniform | 1024 | 10 | 480 ns | 330 ns | 260 ns | 660 ns | 300 ns | 290 ns | 270 ns | ExpFromLeft (260 ns) | 1.12x | -| log | sorted_uniform | 1024 | 256 | 3.2 μs | 4.6 μs | 3.4 μs | 16.0 μs | 6.9 μs | 3.0 μs | 6.5 μs | Linear (3.2 μs) | 0.95x | -| log | sorted_uniform | 1024 | 4096 | 38.6 μs | 62.9 μs | 50.5 μs | 287.1 μs | 169.2 μs | 37.5 μs | 163.2 μs | Linear (38.6 μs) | 0.97x | -| log | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_uniform | 65536 | 10 | 19.9 μs | 580 ns | 420 ns | 900 ns | 440 ns | 440 ns | 410 ns | ExpFromLeft (420 ns) | 1.05x | -| log | sorted_uniform | 65536 | 256 | 88.2 μs | 10.2 μs | 7.7 μs | 25.1 μs | 13.3 μs | 8.0 μs | 12.7 μs | ExpFromLeft (7.7 μs) | 1.03x | -| log | sorted_uniform | 65536 | 4096 | 186.3 μs | 197.8 μs | 154.5 μs | 657.8 μs | 439.8 μs | 153.0 μs | 432.8 μs | ExpFromLeft (154.5 μs) | 0.99x | +| uniform | unsorted | 65536 | 10 | 420 ns | 430 ns | 430 ns | 420 ns | 430 ns | 440 ns | 410 ns | InterpSearch (420 ns) | 1.05x | +| uniform | unsorted | 65536 | 256 | 15.1 μs | 14.6 μs | 14.5 μs | 14.3 μs | 14.5 μs | 14.4 μs | 17.1 μs | InterpSearch (14.3 μs) | 1.00x | +| uniform | unsorted | 65536 | 4096 | 854.7 μs | 851.6 μs | 849.7 μs | 853.0 μs | 852.6 μs | 852.9 μs | 857.9 μs | ExpFromLeft (849.7 μs) | 1.00x | +| log | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| log | sorted_uniform | 64 | 10 | 170 ns | 220 ns | 190 ns | 440 ns | 200 ns | 220 ns | 180 ns | Linear (170 ns) | 1.29x | +| log | sorted_uniform | 64 | 256 | 2.3 μs | 3.8 μs | 3.0 μs | 11.3 μs | 4.5 μs | 2.4 μs | 4.2 μs | Linear (2.3 μs) | 1.01x | +| log | sorted_uniform | 64 | 4096 | 31.7 μs | 55.6 μs | 43.2 μs | 170.7 μs | 69.1 μs | 31.7 μs | 60.6 μs | Linear (31.7 μs) | 1.00x | +| log | sorted_uniform | 1024 | 1 | 60 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_uniform | 1024 | 10 | 470 ns | 330 ns | 260 ns | 670 ns | 290 ns | 300 ns | 270 ns | ExpFromLeft (260 ns) | 1.15x | +| log | sorted_uniform | 1024 | 256 | 3.2 μs | 4.6 μs | 3.2 μs | 16.3 μs | 7.1 μs | 3.3 μs | 8.1 μs | ExpFromLeft (3.2 μs) | 1.03x | +| log | sorted_uniform | 1024 | 4096 | 38.5 μs | 62.7 μs | 48.7 μs | 286.3 μs | 170.3 μs | 38.7 μs | 124.9 μs | Linear (38.5 μs) | 1.00x | +| log | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_uniform | 65536 | 10 | 19.6 μs | 580 ns | 440 ns | 910 ns | 440 ns | 470 ns | 410 ns | ExpFromLeft (440 ns) | 1.07x | +| log | sorted_uniform | 65536 | 256 | 89.7 μs | 10.3 μs | 7.7 μs | 25.5 μs | 13.5 μs | 7.7 μs | 17.6 μs | ExpFromLeft (7.7 μs) | 1.01x | +| log | sorted_uniform | 65536 | 4096 | 183.7 μs | 198.8 μs | 154.0 μs | 657.0 μs | 438.3 μs | 153.8 μs | 418.9 μs | ExpFromLeft (154.0 μs) | 1.00x | | log | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| log | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 480 ns | 200 ns | 130 ns | 170 ns | Linear (130 ns) | 1.00x | -| log | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 11.3 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.97x | -| log | sorted_dense_burst | 64 | 4096 | 32.8 μs | 55.0 μs | 42.3 μs | 179.3 μs | 67.8 μs | 31.6 μs | 56.8 μs | Linear (32.8 μs) | 0.96x | -| log | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 690 ns | 300 ns | 140 ns | 280 ns | Linear (130 ns) | 1.08x | -| log | sorted_dense_burst | 1024 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 16.1 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.1 μs) | 0.97x | -| log | sorted_dense_burst | 1024 | 4096 | 32.9 μs | 55.1 μs | 42.3 μs | 258.3 μs | 106.7 μs | 31.5 μs | 95.8 μs | Linear (32.9 μs) | 0.96x | +| log | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 490 ns | 200 ns | 140 ns | 170 ns | Linear (130 ns) | 1.08x | +| log | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.2 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | +| log | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.4 μs | 42.3 μs | 176.7 μs | 68.0 μs | 32.9 μs | 60.7 μs | Linear (30.8 μs) | 1.07x | +| log | sorted_dense_burst | 1024 | 1 | 60 ns | 70 ns | 70 ns | 100 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| log | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 680 ns | 310 ns | 149 ns | 270 ns | Linear (130 ns) | 1.15x | +| log | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.2 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.00x | +| log | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.6 μs | 42.3 μs | 259.1 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | | log | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 980 ns | 450 ns | 160 ns | 410 ns | Linear (150 ns) | 1.07x | -| log | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.3 μs | 10.3 μs | 1.9 μs | 9.5 μs | Linear (2.0 μs) | 0.97x | -| log | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.3 μs | 385.0 μs | 164.5 μs | 29.5 μs | 152.5 μs | Linear (30.8 μs) | 0.96x | -| log | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| log | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 160 ns | 320 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (160 ns) | 1.25x | -| log | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.3 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 0.97x | -| log | sorted_near_start | 64 | 4096 | 33.2 μs | 55.4 μs | 42.9 μs | 117.4 μs | 67.5 μs | 29.9 μs | 59.7 μs | Linear (33.2 μs) | 0.90x | -| log | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_near_start | 1024 | 10 | 1.2 μs | 300 ns | 230 ns | 480 ns | 300 ns | 250 ns | 260 ns | ExpFromLeft (230 ns) | 1.09x | -| log | sorted_near_start | 1024 | 256 | 3.7 μs | 4.5 μs | 3.9 μs | 12.3 μs | 6.8 μs | 3.6 μs | 6.3 μs | Linear (3.7 μs) | 0.98x | -| log | sorted_near_start | 1024 | 4096 | 34.1 μs | 57.6 μs | 45.4 μs | 191.7 μs | 109.5 μs | 32.3 μs | 103.3 μs | Linear (34.1 μs) | 0.95x | +| log | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 989 ns | 450 ns | 170 ns | 420 ns | Linear (150 ns) | 1.13x | +| log | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.1 μs | 10.3 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.00x | +| log | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.4 μs | 384.3 μs | 164.5 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| log | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| log | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 160 ns | 330 ns | 200 ns | 199 ns | 170 ns | ExpFromLeft (160 ns) | 1.24x | +| log | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.3 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | +| log | sorted_near_start | 64 | 4096 | 31.2 μs | 55.8 μs | 42.8 μs | 116.7 μs | 67.6 μs | 33.2 μs | 59.9 μs | Linear (31.2 μs) | 1.06x | +| log | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_near_start | 1024 | 10 | 1.2 μs | 300 ns | 230 ns | 480 ns | 300 ns | 280 ns | 270 ns | ExpFromLeft (230 ns) | 1.22x | +| log | sorted_near_start | 1024 | 256 | 3.8 μs | 4.5 μs | 3.4 μs | 12.2 μs | 6.8 μs | 3.8 μs | 7.0 μs | ExpFromLeft (3.4 μs) | 1.13x | +| log | sorted_near_start | 1024 | 4096 | 33.5 μs | 58.0 μs | 44.0 μs | 191.1 μs | 110.4 μs | 33.6 μs | 102.9 μs | Linear (33.5 μs) | 1.00x | | log | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_near_start | 65536 | 10 | 61.6 μs | 600 ns | 420 ns | 790 ns | 430 ns | 440 ns | 420 ns | ExpFromLeft (420 ns) | 1.05x | -| log | sorted_near_start | 65536 | 256 | 97.0 μs | 7.6 μs | 5.7 μs | 21.0 μs | 11.8 μs | 5.6 μs | 11.1 μs | ExpFromLeft (5.7 μs) | 1.00x | -| log | sorted_near_start | 65536 | 4096 | 156.6 μs | 112.4 μs | 89.5 μs | 503.1 μs | 366.7 μs | 88.6 μs | 358.1 μs | ExpFromLeft (89.5 μs) | 0.99x | -| log | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| log | unsorted | 64 | 10 | 180 ns | 190 ns | 190 ns | 190 ns | 200 ns | 200 ns | 180 ns | Linear (180 ns) | 1.11x | -| log | unsorted | 64 | 256 | 5.0 μs | 5.1 μs | 5.2 μs | 5.2 μs | 5.1 μs | 5.2 μs | 3.9 μs | Linear (5.0 μs) | 1.03x | -| log | unsorted | 64 | 4096 | 176.1 μs | 167.7 μs | 167.2 μs | 168.8 μs | 167.9 μs | 174.3 μs | 179.2 μs | ExpFromLeft (167.2 μs) | 1.04x | -| log | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 80 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| log | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 270 ns | 280 ns | 290 ns | 270 ns | InterpSearch (270 ns) | 1.07x | -| log | unsorted | 1024 | 256 | 10.3 μs | 10.1 μs | 10.1 μs | 10.1 μs | 10.1 μs | 10.1 μs | 6.6 μs | InterpSearch (10.1 μs) | 1.00x | -| log | unsorted | 1024 | 4096 | 352.0 μs | 344.7 μs | 346.2 μs | 344.2 μs | 344.7 μs | 348.1 μs | 358.0 μs | InterpSearch (344.2 μs) | 1.01x | +| log | sorted_near_start | 65536 | 10 | 61.2 μs | 550 ns | 420 ns | 800 ns | 440 ns | 450 ns | 410 ns | ExpFromLeft (420 ns) | 1.07x | +| log | sorted_near_start | 65536 | 256 | 93.7 μs | 7.7 μs | 5.6 μs | 20.7 μs | 12.2 μs | 6.0 μs | 19.5 μs | ExpFromLeft (5.6 μs) | 1.05x | +| log | sorted_near_start | 65536 | 4096 | 159.8 μs | 112.2 μs | 88.8 μs | 497.8 μs | 369.6 μs | 89.5 μs | 293.0 μs | ExpFromLeft (88.8 μs) | 1.01x | +| log | unsorted | 64 | 1 | 60 ns | 50 ns | 60 ns | 90 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | +| log | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 180 ns | 190 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | +| log | unsorted | 64 | 256 | 4.9 μs | 5.1 μs | 5.0 μs | 4.9 μs | 4.9 μs | 5.0 μs | 5.1 μs | Linear (4.9 μs) | 1.03x | +| log | unsorted | 64 | 4096 | 169.8 μs | 169.8 μs | 174.5 μs | 167.8 μs | 167.1 μs | 167.6 μs | 172.2 μs | Binary (167.1 μs) | 1.00x | +| log | unsorted | 1024 | 1 | 60 ns | 70 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | unsorted | 1024 | 10 | 280 ns | 280 ns | 270 ns | 270 ns | 290 ns | 290 ns | 260 ns | InterpSearch (270 ns) | 1.07x | +| log | unsorted | 1024 | 256 | 9.9 μs | 9.8 μs | 9.8 μs | 9.7 μs | 9.7 μs | 9.5 μs | 9.6 μs | InterpSearch (9.7 μs) | 0.98x | +| log | unsorted | 1024 | 4096 | 350.5 μs | 349.2 μs | 347.7 μs | 344.9 μs | 342.0 μs | 343.8 μs | 344.6 μs | Binary (342.0 μs) | 1.01x | | log | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | unsorted | 65536 | 10 | 420 ns | 420 ns | 410 ns | 420 ns | 430 ns | 429 ns | 410 ns | ExpFromLeft (410 ns) | 1.05x | -| log | unsorted | 65536 | 256 | 17.2 μs | 16.8 μs | 16.6 μs | 16.7 μs | 16.7 μs | 16.7 μs | 14.2 μs | ExpFromLeft (16.6 μs) | 1.01x | -| log | unsorted | 65536 | 4096 | 707.1 μs | 707.1 μs | 706.7 μs | 706.9 μs | 704.6 μs | 706.2 μs | 711.0 μs | Binary (704.6 μs) | 1.00x | -| jittered | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Linear (50 ns) | 1.00x | -| jittered | sorted_uniform | 64 | 10 | 240 ns | 290 ns | 190 ns | 310 ns | 210 ns | 200 ns | 180 ns | ExpFromLeft (190 ns) | 1.05x | -| jittered | sorted_uniform | 64 | 256 | 2.3 μs | 4.2 μs | 3.7 μs | 8.9 μs | 4.2 μs | 2.1 μs | 3.7 μs | Linear (2.3 μs) | 0.94x | -| jittered | sorted_uniform | 64 | 4096 | 32.2 μs | 56.0 μs | 43.5 μs | 113.7 μs | 68.7 μs | 30.8 μs | 60.3 μs | Linear (32.2 μs) | 0.96x | -| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| jittered | sorted_uniform | 1024 | 10 | 1.6 μs | 380 ns | 300 ns | 330 ns | 300 ns | 370 ns | 260 ns | ExpFromLeft (300 ns) | 1.23x | -| jittered | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.8 μs | 9.1 μs | 7.2 μs | 3.6 μs | 7.7 μs | Linear (3.6 μs) | 0.99x | -| jittered | sorted_uniform | 1024 | 4096 | 48.5 μs | 72.4 μs | 60.4 μs | 151.7 μs | 231.4 μs | 46.9 μs | 220.5 μs | Linear (48.5 μs) | 0.97x | +| log | unsorted | 65536 | 10 | 420 ns | 420 ns | 420 ns | 420 ns | 420 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | +| log | unsorted | 65536 | 256 | 17.8 μs | 17.6 μs | 17.3 μs | 17.4 μs | 17.4 μs | 17.5 μs | 19.2 μs | ExpFromLeft (17.3 μs) | 1.02x | +| log | unsorted | 65536 | 4096 | 705.9 μs | 703.7 μs | 703.3 μs | 704.5 μs | 705.5 μs | 705.9 μs | 707.2 μs | ExpFromLeft (703.3 μs) | 1.00x | +| jittered | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 60 ns | 60 ns | 50 ns | 50 ns | 50 ns | Binary (50 ns) | 1.00x | +| jittered | sorted_uniform | 64 | 10 | 180 ns | 230 ns | 180 ns | 310 ns | 210 ns | 210 ns | 180 ns | ExpFromLeft (180 ns) | 1.17x | +| jittered | sorted_uniform | 64 | 256 | 2.2 μs | 4.2 μs | 3.2 μs | 9.1 μs | 4.3 μs | 2.2 μs | 5.0 μs | Linear (2.2 μs) | 1.02x | +| jittered | sorted_uniform | 64 | 4096 | 32.2 μs | 56.2 μs | 43.5 μs | 113.6 μs | 68.7 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | +| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_uniform | 1024 | 10 | 1.5 μs | 380 ns | 290 ns | 340 ns | 300 ns | 400 ns | 270 ns | ExpFromLeft (290 ns) | 1.38x | +| jittered | sorted_uniform | 1024 | 256 | 3.6 μs | 5.5 μs | 3.8 μs | 9.1 μs | 7.4 μs | 3.7 μs | 7.6 μs | Linear (3.6 μs) | 1.02x | +| jittered | sorted_uniform | 1024 | 4096 | 48.5 μs | 72.8 μs | 57.9 μs | 152.2 μs | 233.2 μs | 48.2 μs | 181.6 μs | Linear (48.5 μs) | 0.99x | | jittered | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_uniform | 65536 | 10 | 59.9 μs | 680 ns | 480 ns | 310 ns | 480 ns | 350 ns | 430 ns | InterpSearch (310 ns) | 1.13x | -| jittered | sorted_uniform | 65536 | 256 | 103.4 μs | 14.8 μs | 11.7 μs | 11.5 μs | 16.2 μs | 12.1 μs | 17.0 μs | InterpSearch (11.5 μs) | 1.05x | -| jittered | sorted_uniform | 65536 | 4096 | 217.0 μs | 256.3 μs | 216.5 μs | 203.2 μs | 512.0 μs | 214.6 μs | 487.8 μs | InterpSearch (203.2 μs) | 1.06x | -| jittered | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | sorted_dense_burst | 64 | 10 | 120 ns | 180 ns | 150 ns | 310 ns | 200 ns | 140 ns | 170 ns | Linear (120 ns) | 1.17x | -| jittered | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 4.3 μs | 1.9 μs | 3.6 μs | Linear (2.0 μs) | 0.97x | -| jittered | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.8 μs | 42.3 μs | 110.0 μs | 68.0 μs | 29.9 μs | 58.0 μs | Linear (30.8 μs) | 0.97x | -| jittered | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_dense_burst | 1024 | 10 | 130 ns | 200 ns | 160 ns | 310 ns | 310 ns | 150 ns | 280 ns | Linear (130 ns) | 1.15x | -| jittered | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.7 μs | 2.7 μs | 7.1 μs | 6.7 μs | 1.9 μs | 6.1 μs | Linear (2.0 μs) | 0.97x | -| jittered | sorted_dense_burst | 1024 | 4096 | 32.9 μs | 57.8 μs | 42.3 μs | 111.7 μs | 106.9 μs | 29.5 μs | 95.7 μs | Linear (32.9 μs) | 0.90x | +| jittered | sorted_uniform | 65536 | 10 | 58.7 μs | 670 ns | 480 ns | 310 ns | 440 ns | 370 ns | 410 ns | InterpSearch (310 ns) | 1.19x | +| jittered | sorted_uniform | 65536 | 256 | 99.7 μs | 12.7 μs | 9.6 μs | 9.7 μs | 13.2 μs | 10.2 μs | 16.6 μs | ExpFromLeft (9.6 μs) | 1.07x | +| jittered | sorted_uniform | 65536 | 4096 | 201.7 μs | 253.6 μs | 206.0 μs | 164.3 μs | 490.9 μs | 171.4 μs | 497.2 μs | InterpSearch (164.3 μs) | 1.04x | +| jittered | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| jittered | sorted_dense_burst | 64 | 10 | 120 ns | 180 ns | 150 ns | 320 ns | 200 ns | 140 ns | 170 ns | Linear (120 ns) | 1.17x | +| jittered | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.00x | +| jittered | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.4 μs | 42.3 μs | 110.0 μs | 67.9 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| jittered | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 310 ns | 310 ns | 150 ns | 270 ns | Linear (130 ns) | 1.15x | +| jittered | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.00x | +| jittered | sorted_dense_burst | 1024 | 4096 | 31.3 μs | 55.7 μs | 42.3 μs | 109.8 μs | 106.7 μs | 30.8 μs | 95.8 μs | Linear (31.3 μs) | 0.98x | | jittered | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_dense_burst | 65536 | 10 | 140 ns | 210 ns | 180 ns | 310 ns | 450 ns | 160 ns | 410 ns | Linear (140 ns) | 1.14x | -| jittered | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.3 μs | 2.1 μs | 9.6 μs | Linear (2.0 μs) | 1.03x | -| jittered | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.3 μs | 109.6 μs | 164.4 μs | 30.0 μs | 152.4 μs | Linear (30.8 μs) | 0.97x | -| jittered | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 60 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| jittered | sorted_near_start | 64 | 10 | 200 ns | 210 ns | 160 ns | 310 ns | 200 ns | 189 ns | 170 ns | ExpFromLeft (160 ns) | 1.18x | -| jittered | sorted_near_start | 64 | 256 | 2.1 μs | 3.8 μs | 2.8 μs | 7.2 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 0.97x | -| jittered | sorted_near_start | 64 | 4096 | 32.1 μs | 59.2 μs | 43.3 μs | 113.9 μs | 69.1 μs | 30.4 μs | 59.3 μs | Linear (32.1 μs) | 0.95x | -| jittered | sorted_near_start | 1024 | 1 | 60 ns | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_near_start | 1024 | 10 | 750 ns | 300 ns | 240 ns | 310 ns | 300 ns | 260 ns | 270 ns | ExpFromLeft (240 ns) | 1.08x | -| jittered | sorted_near_start | 1024 | 256 | 3.9 μs | 4.8 μs | 4.0 μs | 8.7 μs | 6.7 μs | 3.8 μs | 6.3 μs | Linear (3.9 μs) | 0.98x | -| jittered | sorted_near_start | 1024 | 4096 | 33.9 μs | 61.1 μs | 44.5 μs | 115.0 μs | 111.2 μs | 32.5 μs | 104.9 μs | Linear (33.9 μs) | 0.96x | +| jittered | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 310 ns | 450 ns | 160 ns | 420 ns | Linear (150 ns) | 1.07x | +| jittered | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.3 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | +| jittered | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 109.6 μs | 164.5 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| jittered | sorted_near_start | 64 | 10 | 200 ns | 200 ns | 160 ns | 330 ns | 200 ns | 190 ns | 170 ns | ExpFromLeft (160 ns) | 1.19x | +| jittered | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | +| jittered | sorted_near_start | 64 | 4096 | 31.8 μs | 56.6 μs | 43.4 μs | 111.1 μs | 68.8 μs | 31.8 μs | 60.4 μs | Linear (31.8 μs) | 1.00x | +| jittered | sorted_near_start | 1024 | 1 | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| jittered | sorted_near_start | 1024 | 10 | 720 ns | 290 ns | 240 ns | 310 ns | 290 ns | 270 ns | 260 ns | ExpFromLeft (240 ns) | 1.12x | +| jittered | sorted_near_start | 1024 | 256 | 3.8 μs | 4.6 μs | 3.6 μs | 9.1 μs | 6.7 μs | 3.8 μs | 7.1 μs | ExpFromLeft (3.6 μs) | 1.04x | +| jittered | sorted_near_start | 1024 | 4096 | 33.7 μs | 58.4 μs | 44.5 μs | 116.9 μs | 111.0 μs | 34.2 μs | 104.4 μs | Linear (33.7 μs) | 1.01x | | jittered | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_near_start | 65536 | 10 | 80.6 μs | 540 ns | 400 ns | 300 ns | 440 ns | 340 ns | 410 ns | InterpSearch (300 ns) | 1.13x | -| jittered | sorted_near_start | 65536 | 256 | 90.1 μs | 8.1 μs | 5.8 μs | 9.1 μs | 11.9 μs | 9.3 μs | 12.2 μs | ExpFromLeft (5.8 μs) | 1.59x | -| jittered | sorted_near_start | 65536 | 4096 | 155.5 μs | 118.7 μs | 94.9 μs | 159.0 μs | 376.3 μs | 93.1 μs | 364.4 μs | ExpFromLeft (94.9 μs) | 0.98x | -| jittered | unsorted | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| jittered | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 180 ns | 190 ns | 200 ns | 170 ns | InterpSearch (180 ns) | 1.11x | -| jittered | unsorted | 64 | 256 | 5.2 μs | 5.3 μs | 5.3 μs | 5.4 μs | 5.3 μs | 5.3 μs | 3.9 μs | Linear (5.2 μs) | 1.02x | -| jittered | unsorted | 64 | 4096 | 227.1 μs | 227.8 μs | 226.5 μs | 225.2 μs | 225.5 μs | 224.1 μs | 245.7 μs | InterpSearch (225.2 μs) | 0.99x | -| jittered | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | unsorted | 1024 | 10 | 280 ns | 280 ns | 279 ns | 290 ns | 300 ns | 290 ns | 270 ns | ExpFromLeft (279 ns) | 1.04x | -| jittered | unsorted | 1024 | 256 | 7.7 μs | 7.8 μs | 7.7 μs | 7.7 μs | 7.8 μs | 7.7 μs | 6.6 μs | ExpFromLeft (7.7 μs) | 1.01x | -| jittered | unsorted | 1024 | 4096 | 412.2 μs | 411.3 μs | 410.0 μs | 412.6 μs | 409.7 μs | 412.2 μs | 417.4 μs | Binary (409.7 μs) | 1.01x | -| jittered | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | unsorted | 65536 | 10 | 410 ns | 420 ns | 410 ns | 420 ns | 430 ns | 429 ns | 410 ns | ExpFromLeft (410 ns) | 1.05x | -| jittered | unsorted | 65536 | 256 | 14.5 μs | 14.4 μs | 14.3 μs | 14.2 μs | 14.1 μs | 14.0 μs | 13.9 μs | Binary (14.1 μs) | 0.99x | -| jittered | unsorted | 65536 | 4096 | 835.7 μs | 837.6 μs | 831.0 μs | 834.1 μs | 837.0 μs | 839.5 μs | 839.3 μs | ExpFromLeft (831.0 μs) | 1.01x | -| random | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_uniform | 64 | 10 | 190 ns | 240 ns | 200 ns | 380 ns | 210 ns | 220 ns | 180 ns | Linear (190 ns) | 1.16x | -| random | sorted_uniform | 64 | 256 | 2.2 μs | 4.2 μs | 3.6 μs | 8.8 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.2 μs) | 0.96x | -| random | sorted_uniform | 64 | 4096 | 32.2 μs | 56.0 μs | 43.5 μs | 127.6 μs | 68.4 μs | 30.8 μs | 60.0 μs | Linear (32.2 μs) | 0.96x | -| random | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_uniform | 1024 | 10 | 1.7 μs | 430 ns | 330 ns | 410 ns | 290 ns | 450 ns | 270 ns | Binary (290 ns) | 1.55x | -| random | sorted_uniform | 1024 | 256 | 3.7 μs | 5.2 μs | 3.8 μs | 10.3 μs | 7.3 μs | 3.6 μs | 6.6 μs | Linear (3.7 μs) | 0.97x | -| random | sorted_uniform | 1024 | 4096 | 43.9 μs | 70.0 μs | 58.6 μs | 189.0 μs | 206.3 μs | 42.8 μs | 196.8 μs | Linear (43.9 μs) | 0.97x | -| random | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| random | sorted_uniform | 65536 | 10 | 56.6 μs | 660 ns | 480 ns | 570 ns | 440 ns | 600 ns | 410 ns | Binary (440 ns) | 1.36x | -| random | sorted_uniform | 65536 | 256 | 101.9 μs | 12.9 μs | 9.5 μs | 15.5 μs | 12.3 μs | 15.7 μs | 15.1 μs | ExpFromLeft (9.5 μs) | 1.65x | -| random | sorted_uniform | 65536 | 4096 | 196.9 μs | 250.3 μs | 204.7 μs | 366.9 μs | 486.7 μs | 203.4 μs | 486.5 μs | Linear (196.9 μs) | 1.03x | -| random | sorted_dense_burst | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_dense_burst | 64 | 10 | 120 ns | 190 ns | 150 ns | 360 ns | 200 ns | 140 ns | 170 ns | Linear (120 ns) | 1.17x | -| random | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.7 μs | 2.7 μs | 8.0 μs | 4.4 μs | 1.9 μs | 3.6 μs | Linear (2.0 μs) | 0.96x | -| random | sorted_dense_burst | 64 | 4096 | 31.3 μs | 58.2 μs | 42.2 μs | 125.3 μs | 67.9 μs | 29.5 μs | 56.8 μs | Linear (31.3 μs) | 0.94x | +| jittered | sorted_near_start | 65536 | 10 | 80.0 μs | 540 ns | 410 ns | 300 ns | 430 ns | 440 ns | 440 ns | InterpSearch (300 ns) | 1.47x | +| jittered | sorted_near_start | 65536 | 256 | 93.3 μs | 7.9 μs | 5.9 μs | 9.0 μs | 11.9 μs | 5.9 μs | 19.8 μs | ExpFromLeft (5.9 μs) | 0.99x | +| jittered | sorted_near_start | 65536 | 4096 | 157.2 μs | 120.1 μs | 95.8 μs | 159.2 μs | 375.8 μs | 94.3 μs | 301.1 μs | ExpFromLeft (95.8 μs) | 0.98x | +| jittered | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Linear (50 ns) | 1.00x | +| jittered | unsorted | 64 | 10 | 190 ns | 180 ns | 190 ns | 180 ns | 200 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | +| jittered | unsorted | 64 | 256 | 5.3 μs | 5.2 μs | 5.2 μs | 5.2 μs | 5.1 μs | 5.1 μs | 5.3 μs | Binary (5.1 μs) | 1.00x | +| jittered | unsorted | 64 | 4096 | 231.3 μs | 228.1 μs | 228.5 μs | 228.5 μs | 228.2 μs | 228.1 μs | 226.8 μs | Gallop (228.1 μs) | 1.00x | +| jittered | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| jittered | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 280 ns | 300 ns | 300 ns | 270 ns | InterpSearch (280 ns) | 1.07x | +| jittered | unsorted | 1024 | 256 | 8.5 μs | 8.3 μs | 8.2 μs | 8.3 μs | 8.1 μs | 8.1 μs | 8.0 μs | Binary (8.1 μs) | 1.00x | +| jittered | unsorted | 1024 | 4096 | 414.1 μs | 411.7 μs | 413.0 μs | 411.2 μs | 412.2 μs | 412.8 μs | 408.3 μs | InterpSearch (411.2 μs) | 1.00x | +| jittered | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | unsorted | 65536 | 10 | 420 ns | 420 ns | 420 ns | 420 ns | 430 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | +| jittered | unsorted | 65536 | 256 | 14.8 μs | 14.5 μs | 14.4 μs | 14.3 μs | 14.3 μs | 14.2 μs | 17.5 μs | Binary (14.3 μs) | 1.00x | +| jittered | unsorted | 65536 | 4096 | 850.3 μs | 847.7 μs | 848.3 μs | 849.4 μs | 848.5 μs | 848.4 μs | 859.1 μs | Gallop (847.7 μs) | 1.00x | +| random | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 60 ns | 60 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| random | sorted_uniform | 64 | 10 | 190 ns | 230 ns | 190 ns | 380 ns | 200 ns | 240 ns | 180 ns | ExpFromLeft (190 ns) | 1.26x | +| random | sorted_uniform | 64 | 256 | 2.2 μs | 4.0 μs | 3.1 μs | 8.7 μs | 4.3 μs | 2.2 μs | 4.5 μs | Linear (2.2 μs) | 1.02x | +| random | sorted_uniform | 64 | 4096 | 32.2 μs | 56.5 μs | 43.5 μs | 127.6 μs | 68.3 μs | 32.2 μs | 60.0 μs | Linear (32.2 μs) | 1.00x | +| random | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 70 ns | 90 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| random | sorted_uniform | 1024 | 10 | 1.7 μs | 410 ns | 320 ns | 410 ns | 290 ns | 360 ns | 270 ns | Binary (290 ns) | 1.24x | +| random | sorted_uniform | 1024 | 256 | 3.6 μs | 5.3 μs | 3.8 μs | 10.3 μs | 7.1 μs | 3.7 μs | 7.8 μs | Linear (3.6 μs) | 1.02x | +| random | sorted_uniform | 1024 | 4096 | 45.3 μs | 70.2 μs | 55.7 μs | 188.4 μs | 206.8 μs | 44.5 μs | 159.7 μs | Linear (45.3 μs) | 0.98x | +| random | sorted_uniform | 65536 | 1 | 80 ns | 79 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | Gallop (79 ns) | 1.01x | +| random | sorted_uniform | 65536 | 10 | 55.6 μs | 660 ns | 490 ns | 560 ns | 440 ns | 510 ns | 420 ns | Binary (440 ns) | 1.16x | +| random | sorted_uniform | 65536 | 256 | 100.7 μs | 12.5 μs | 9.8 μs | 15.3 μs | 13.9 μs | 10.0 μs | 16.0 μs | ExpFromLeft (9.8 μs) | 1.02x | +| random | sorted_uniform | 65536 | 4096 | 195.2 μs | 251.3 μs | 202.9 μs | 365.8 μs | 491.4 μs | 204.3 μs | 489.8 μs | Linear (195.2 μs) | 1.05x | +| random | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 50 ns | 50 ns | 50 ns | Binary (50 ns) | 1.00x | +| random | sorted_dense_burst | 64 | 10 | 120 ns | 180 ns | 150 ns | 360 ns | 200 ns | 140 ns | 170 ns | Linear (120 ns) | 1.17x | +| random | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 7.9 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.94x | +| random | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.4 μs | 42.3 μs | 125.3 μs | 68.0 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | | random | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 480 ns | 300 ns | 140 ns | 280 ns | Linear (130 ns) | 1.08x | -| random | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.0 μs | 6.7 μs | 1.9 μs | 6.0 μs | Linear (2.0 μs) | 0.96x | -| random | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.1 μs | 42.3 μs | 175.6 μs | 106.9 μs | 29.9 μs | 96.7 μs | Linear (30.8 μs) | 0.97x | -| random | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| random | sorted_dense_burst | 65536 | 10 | 150 ns | 210 ns | 170 ns | 680 ns | 450 ns | 160 ns | 410 ns | Linear (150 ns) | 1.07x | -| random | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.7 μs | 2.7 μs | 15.3 μs | 10.3 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 0.96x | -| random | sorted_dense_burst | 65536 | 4096 | 31.3 μs | 57.9 μs | 42.3 μs | 241.9 μs | 164.5 μs | 29.5 μs | 152.4 μs | Linear (31.3 μs) | 0.94x | -| random | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| random | sorted_near_start | 64 | 10 | 200 ns | 200 ns | 170 ns | 340 ns | 200 ns | 180 ns | 180 ns | ExpFromLeft (170 ns) | 1.06x | -| random | sorted_near_start | 64 | 256 | 2.2 μs | 3.7 μs | 2.8 μs | 8.1 μs | 4.3 μs | 2.0 μs | 3.8 μs | Linear (2.2 μs) | 0.91x | -| random | sorted_near_start | 64 | 4096 | 31.8 μs | 59.0 μs | 43.3 μs | 129.1 μs | 67.4 μs | 30.0 μs | 60.1 μs | Linear (31.8 μs) | 0.94x | -| random | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| random | sorted_near_start | 1024 | 10 | 740 ns | 270 ns | 210 ns | 400 ns | 290 ns | 230 ns | 260 ns | ExpFromLeft (210 ns) | 1.10x | -| random | sorted_near_start | 1024 | 256 | 3.8 μs | 4.4 μs | 3.8 μs | 10.2 μs | 6.8 μs | 3.7 μs | 6.5 μs | Linear (3.8 μs) | 0.99x | -| random | sorted_near_start | 1024 | 4096 | 34.2 μs | 58.0 μs | 44.4 μs | 150.6 μs | 109.5 μs | 32.9 μs | 102.6 μs | Linear (34.2 μs) | 0.96x | -| random | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | 70 ns | InterpSearch (80 ns) | 0.88x | -| random | sorted_near_start | 65536 | 10 | 38.8 μs | 520 ns | 390 ns | 490 ns | 440 ns | 520 ns | 410 ns | ExpFromLeft (390 ns) | 1.33x | -| random | sorted_near_start | 65536 | 256 | 95.0 μs | 7.9 μs | 5.9 μs | 11.7 μs | 12.1 μs | 12.4 μs | 12.0 μs | ExpFromLeft (5.9 μs) | 2.11x | -| random | sorted_near_start | 65536 | 4096 | 162.3 μs | 128.6 μs | 105.6 μs | 252.7 μs | 360.0 μs | 105.6 μs | 348.6 μs | ExpFromLeft (105.6 μs) | 1.00x | -| random | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| random | unsorted | 64 | 10 | 180 ns | 180 ns | 180 ns | 180 ns | 200 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | -| random | unsorted | 64 | 256 | 7.2 μs | 7.1 μs | 7.3 μs | 7.3 μs | 7.2 μs | 7.2 μs | 3.9 μs | Gallop (7.1 μs) | 1.02x | -| random | unsorted | 64 | 4096 | 210.5 μs | 207.7 μs | 207.2 μs | 207.8 μs | 206.4 μs | 207.3 μs | 216.9 μs | Binary (206.4 μs) | 1.00x | -| random | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 290 ns | 260 ns | InterpSearch (280 ns) | 1.04x | -| random | unsorted | 1024 | 256 | 8.0 μs | 8.1 μs | 7.8 μs | 8.0 μs | 7.9 μs | 8.0 μs | 6.6 μs | ExpFromLeft (7.8 μs) | 1.02x | -| random | unsorted | 1024 | 4096 | 384.4 μs | 379.7 μs | 380.5 μs | 381.1 μs | 379.0 μs | 380.1 μs | 391.3 μs | Binary (379.0 μs) | 1.00x | +| random | sorted_dense_burst | 1024 | 10 | 140 ns | 190 ns | 160 ns | 480 ns | 310 ns | 170 ns | 270 ns | Linear (140 ns) | 1.21x | +| random | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.1 μs | 6.8 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| random | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 175.6 μs | 106.8 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | +| random | sorted_dense_burst | 65536 | 10 | 140 ns | 200 ns | 170 ns | 670 ns | 450 ns | 160 ns | 420 ns | Linear (140 ns) | 1.14x | +| random | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 15.3 μs | 10.3 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | +| random | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.4 μs | 241.5 μs | 164.5 μs | 30.9 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| random | sorted_near_start | 64 | 10 | 200 ns | 200 ns | 170 ns | 330 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (170 ns) | 1.18x | +| random | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.8 μs | 4.2 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | +| random | sorted_near_start | 64 | 4096 | 31.5 μs | 56.2 μs | 42.9 μs | 122.8 μs | 67.5 μs | 31.4 μs | 60.8 μs | Linear (31.5 μs) | 1.00x | +| random | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_near_start | 1024 | 10 | 730 ns | 280 ns | 210 ns | 410 ns | 290 ns | 240 ns | 310 ns | ExpFromLeft (210 ns) | 1.14x | +| random | sorted_near_start | 1024 | 256 | 4.0 μs | 4.5 μs | 3.4 μs | 10.2 μs | 6.9 μs | 3.9 μs | 6.9 μs | ExpFromLeft (3.4 μs) | 1.13x | +| random | sorted_near_start | 1024 | 4096 | 33.5 μs | 58.4 μs | 44.6 μs | 150.8 μs | 112.3 μs | 33.9 μs | 103.2 μs | Linear (33.5 μs) | 1.01x | +| random | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| random | sorted_near_start | 65536 | 10 | 42.4 μs | 510 ns | 400 ns | 500 ns | 440 ns | 420 ns | 440 ns | ExpFromLeft (400 ns) | 1.05x | +| random | sorted_near_start | 65536 | 256 | 96.4 μs | 7.7 μs | 6.0 μs | 11.5 μs | 11.6 μs | 5.9 μs | 19.8 μs | ExpFromLeft (6.0 μs) | 0.99x | +| random | sorted_near_start | 65536 | 4096 | 160.3 μs | 129.1 μs | 107.3 μs | 254.2 μs | 362.5 μs | 107.7 μs | 288.0 μs | ExpFromLeft (107.3 μs) | 1.00x | +| random | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | +| random | unsorted | 64 | 10 | 180 ns | 190 ns | 190 ns | 190 ns | 189 ns | 200 ns | 180 ns | Linear (180 ns) | 1.11x | +| random | unsorted | 64 | 256 | 7.3 μs | 7.2 μs | 7.2 μs | 7.1 μs | 7.1 μs | 7.1 μs | 6.7 μs | Binary (7.1 μs) | 1.00x | +| random | unsorted | 64 | 4096 | 210.3 μs | 208.5 μs | 207.1 μs | 209.0 μs | 207.2 μs | 207.9 μs | 206.5 μs | ExpFromLeft (207.1 μs) | 1.00x | +| random | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| random | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 279 ns | 280 ns | 290 ns | 270 ns | InterpSearch (279 ns) | 1.04x | +| random | unsorted | 1024 | 256 | 8.7 μs | 8.4 μs | 8.4 μs | 8.3 μs | 8.1 μs | 8.3 μs | 8.1 μs | Binary (8.1 μs) | 1.03x | +| random | unsorted | 1024 | 4096 | 385.2 μs | 378.6 μs | 378.0 μs | 377.1 μs | 377.1 μs | 378.6 μs | 377.0 μs | Binary (377.1 μs) | 1.00x | | random | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| random | unsorted | 65536 | 10 | 560 ns | 430 ns | 430 ns | 440 ns | 430 ns | 450 ns | 430 ns | ExpFromLeft (430 ns) | 1.05x | -| random | unsorted | 65536 | 256 | 14.4 μs | 14.2 μs | 14.1 μs | 14.1 μs | 13.7 μs | 13.7 μs | 14.6 μs | Binary (13.7 μs) | 1.00x | -| random | unsorted | 65536 | 4096 | 842.5 μs | 841.9 μs | 839.8 μs | 841.4 μs | 839.0 μs | 839.8 μs | 843.0 μs | Binary (839.0 μs) | 1.00x | -| two_scale | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| two_scale | sorted_uniform | 64 | 10 | 220 ns | 220 ns | 170 ns | 410 ns | 200 ns | 190 ns | 180 ns | ExpFromLeft (170 ns) | 1.12x | -| two_scale | sorted_uniform | 64 | 256 | 2.4 μs | 3.9 μs | 3.2 μs | 11.4 μs | 4.5 μs | 2.3 μs | 3.9 μs | Linear (2.4 μs) | 0.97x | -| two_scale | sorted_uniform | 64 | 4096 | 31.8 μs | 58.5 μs | 42.9 μs | 165.6 μs | 68.8 μs | 30.2 μs | 59.4 μs | Linear (31.8 μs) | 0.95x | -| two_scale | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_uniform | 1024 | 10 | 570 ns | 370 ns | 290 ns | 630 ns | 300 ns | 300 ns | 270 ns | ExpFromLeft (290 ns) | 1.03x | -| two_scale | sorted_uniform | 1024 | 256 | 2.8 μs | 4.5 μs | 3.3 μs | 16.2 μs | 7.1 μs | 2.8 μs | 6.2 μs | Linear (2.8 μs) | 1.01x | -| two_scale | sorted_uniform | 1024 | 4096 | 40.3 μs | 64.6 μs | 51.2 μs | 294.8 μs | 159.0 μs | 38.9 μs | 149.3 μs | Linear (40.3 μs) | 0.97x | -| two_scale | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 90 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_uniform | 65536 | 10 | 46.4 μs | 630 ns | 460 ns | 910 ns | 440 ns | 480 ns | 420 ns | Binary (440 ns) | 1.09x | -| two_scale | sorted_uniform | 65536 | 256 | 61.8 μs | 11.3 μs | 8.3 μs | 26.5 μs | 14.0 μs | 8.5 μs | 13.9 μs | ExpFromLeft (8.3 μs) | 1.03x | -| two_scale | sorted_uniform | 65536 | 4096 | 192.9 μs | 202.0 μs | 160.3 μs | 683.7 μs | 440.3 μs | 158.9 μs | 431.4 μs | ExpFromLeft (160.3 μs) | 0.99x | -| two_scale | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 50 ns | 80 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| two_scale | sorted_dense_burst | 64 | 10 | 130 ns | 190 ns | 150 ns | 490 ns | 210 ns | 140 ns | 169 ns | Linear (130 ns) | 1.08x | -| two_scale | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 11.4 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.97x | -| two_scale | sorted_dense_burst | 64 | 4096 | 32.9 μs | 55.0 μs | 42.3 μs | 180.7 μs | 68.0 μs | 31.5 μs | 56.8 μs | Linear (32.9 μs) | 0.96x | -| two_scale | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 690 ns | 310 ns | 140 ns | 270 ns | Linear (130 ns) | 1.08x | -| two_scale | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.4 μs | 6.7 μs | 1.9 μs | 6.0 μs | Linear (2.0 μs) | 0.96x | -| two_scale | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 42.3 μs | 261.2 μs | 106.8 μs | 31.5 μs | 95.8 μs | Linear (30.8 μs) | 1.03x | -| two_scale | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_dense_burst | 65536 | 10 | 150 ns | 210 ns | 180 ns | 1.0 μs | 450 ns | 160 ns | 410 ns | Linear (150 ns) | 1.07x | -| two_scale | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.1 μs | 10.3 μs | 2.1 μs | 9.6 μs | Linear (2.0 μs) | 1.02x | -| two_scale | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.2 μs | 384.5 μs | 164.6 μs | 31.6 μs | 152.4 μs | Linear (30.8 μs) | 1.03x | -| two_scale | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| two_scale | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 160 ns | 340 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (160 ns) | 1.25x | -| two_scale | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.1 μs | 4.3 μs | 2.0 μs | 3.8 μs | Linear (2.1 μs) | 0.97x | -| two_scale | sorted_near_start | 64 | 4096 | 31.4 μs | 55.6 μs | 42.9 μs | 113.4 μs | 67.5 μs | 30.1 μs | 59.9 μs | Linear (31.4 μs) | 0.96x | -| two_scale | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_near_start | 1024 | 10 | 1.4 μs | 290 ns | 230 ns | 450 ns | 290 ns | 260 ns | 270 ns | ExpFromLeft (230 ns) | 1.13x | -| two_scale | sorted_near_start | 1024 | 256 | 3.9 μs | 4.5 μs | 3.6 μs | 11.8 μs | 6.9 μs | 3.8 μs | 6.3 μs | ExpFromLeft (3.6 μs) | 1.07x | -| two_scale | sorted_near_start | 1024 | 4096 | 33.9 μs | 60.3 μs | 44.0 μs | 182.1 μs | 110.9 μs | 32.4 μs | 101.7 μs | Linear (33.9 μs) | 0.96x | -| two_scale | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_near_start | 65536 | 10 | 62.3 μs | 540 ns | 410 ns | 800 ns | 440 ns | 420 ns | 400 ns | ExpFromLeft (410 ns) | 1.02x | -| two_scale | sorted_near_start | 65536 | 256 | 95.1 μs | 7.8 μs | 5.7 μs | 20.7 μs | 12.2 μs | 5.8 μs | 11.4 μs | ExpFromLeft (5.7 μs) | 1.01x | -| two_scale | sorted_near_start | 65536 | 4096 | 161.8 μs | 121.8 μs | 98.4 μs | 479.0 μs | 353.3 μs | 101.4 μs | 345.3 μs | ExpFromLeft (98.4 μs) | 1.03x | -| two_scale | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 90 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| two_scale | unsorted | 64 | 10 | 180 ns | 180 ns | 190 ns | 180 ns | 200 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | -| two_scale | unsorted | 64 | 256 | 6.2 μs | 6.1 μs | 6.1 μs | 6.1 μs | 6.2 μs | 6.2 μs | 4.0 μs | ExpFromLeft (6.1 μs) | 1.02x | -| two_scale | unsorted | 64 | 4096 | 183.4 μs | 178.6 μs | 180.0 μs | 181.6 μs | 178.2 μs | 178.9 μs | 194.7 μs | Binary (178.2 μs) | 1.00x | -| two_scale | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | unsorted | 1024 | 10 | 280 ns | 270 ns | 270 ns | 270 ns | 280 ns | 280 ns | 270 ns | InterpSearch (270 ns) | 1.04x | -| two_scale | unsorted | 1024 | 256 | 9.6 μs | 9.3 μs | 9.4 μs | 9.6 μs | 9.5 μs | 9.3 μs | 6.4 μs | Gallop (9.3 μs) | 1.00x | -| two_scale | unsorted | 1024 | 4096 | 342.3 μs | 340.2 μs | 342.3 μs | 342.9 μs | 342.7 μs | 338.1 μs | 360.6 μs | Gallop (340.2 μs) | 0.99x | -| two_scale | unsorted | 65536 | 1 | 80 ns | 79 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | Gallop (79 ns) | 1.01x | -| two_scale | unsorted | 65536 | 10 | 420 ns | 420 ns | 420 ns | 430 ns | 440 ns | 430 ns | 410 ns | ExpFromLeft (420 ns) | 1.02x | -| two_scale | unsorted | 65536 | 256 | 15.4 μs | 14.8 μs | 14.5 μs | 14.7 μs | 14.3 μs | 14.6 μs | 13.5 μs | Binary (14.3 μs) | 1.02x | -| two_scale | unsorted | 65536 | 4096 | 752.9 μs | 752.5 μs | 751.6 μs | 753.7 μs | 751.3 μs | 752.9 μs | 756.6 μs | Binary (751.3 μs) | 1.00x | +| random | unsorted | 65536 | 10 | 430 ns | 430 ns | 420 ns | 450 ns | 440 ns | 450 ns | 430 ns | ExpFromLeft (420 ns) | 1.07x | +| random | unsorted | 65536 | 256 | 15.4 μs | 14.5 μs | 14.3 μs | 14.3 μs | 14.3 μs | 14.3 μs | 18.3 μs | ExpFromLeft (14.3 μs) | 1.00x | +| random | unsorted | 65536 | 4096 | 856.5 μs | 856.0 μs | 857.6 μs | 856.5 μs | 855.9 μs | 856.1 μs | 859.9 μs | Binary (855.9 μs) | 1.00x | +| two_scale | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| two_scale | sorted_uniform | 64 | 10 | 170 ns | 220 ns | 170 ns | 410 ns | 210 ns | 200 ns | 180 ns | ExpFromLeft (170 ns) | 1.18x | +| two_scale | sorted_uniform | 64 | 256 | 2.4 μs | 3.9 μs | 3.1 μs | 11.4 μs | 4.5 μs | 2.4 μs | 4.0 μs | Linear (2.4 μs) | 1.01x | +| two_scale | sorted_uniform | 64 | 4096 | 31.5 μs | 55.7 μs | 43.0 μs | 167.0 μs | 68.9 μs | 31.5 μs | 59.3 μs | Linear (31.5 μs) | 1.00x | +| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_uniform | 1024 | 10 | 570 ns | 360 ns | 290 ns | 620 ns | 300 ns | 330 ns | 270 ns | ExpFromLeft (290 ns) | 1.14x | +| two_scale | sorted_uniform | 1024 | 256 | 2.9 μs | 4.6 μs | 3.2 μs | 15.9 μs | 7.2 μs | 2.9 μs | 8.0 μs | Linear (2.9 μs) | 1.00x | +| two_scale | sorted_uniform | 1024 | 4096 | 40.0 μs | 63.7 μs | 50.5 μs | 290.0 μs | 159.9 μs | 40.1 μs | 110.2 μs | Linear (40.0 μs) | 1.00x | +| two_scale | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_uniform | 65536 | 10 | 45.8 μs | 630 ns | 470 ns | 910 ns | 430 ns | 500 ns | 410 ns | Binary (430 ns) | 1.16x | +| two_scale | sorted_uniform | 65536 | 256 | 60.2 μs | 11.5 μs | 8.4 μs | 27.5 μs | 14.1 μs | 8.5 μs | 16.6 μs | ExpFromLeft (8.4 μs) | 1.01x | +| two_scale | sorted_uniform | 65536 | 4096 | 191.1 μs | 203.3 μs | 161.6 μs | 684.5 μs | 442.5 μs | 162.1 μs | 420.6 μs | ExpFromLeft (161.6 μs) | 1.00x | +| two_scale | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| two_scale | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 480 ns | 200 ns | 160 ns | 160 ns | Linear (130 ns) | 1.23x | +| two_scale | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.5 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.00x | +| two_scale | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.6 μs | 42.3 μs | 180.3 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 1024 | 1 | 70 ns | 70 ns | 80 ns | 100 ns | 70 ns | 60 ns | 60 ns | Binary (70 ns) | 0.86x | +| two_scale | sorted_dense_burst | 1024 | 10 | 140 ns | 220 ns | 180 ns | 720 ns | 310 ns | 150 ns | 280 ns | Linear (140 ns) | 1.07x | +| two_scale | sorted_dense_burst | 1024 | 256 | 2.2 μs | 4.3 μs | 3.1 μs | 17.2 μs | 6.7 μs | 2.0 μs | 5.9 μs | Linear (2.2 μs) | 0.92x | +| two_scale | sorted_dense_burst | 1024 | 4096 | 33.8 μs | 67.8 μs | 49.2 μs | 274.8 μs | 107.4 μs | 30.9 μs | 95.7 μs | Linear (33.8 μs) | 0.91x | +| two_scale | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_dense_burst | 65536 | 10 | 170 ns | 240 ns | 199 ns | 1.0 μs | 450 ns | 220 ns | 420 ns | Linear (170 ns) | 1.29x | +| two_scale | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.3 μs | 10.3 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.00x | +| two_scale | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 391.1 μs | 164.5 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| two_scale | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 170 ns | 330 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (170 ns) | 1.18x | +| two_scale | sorted_near_start | 64 | 256 | 2.2 μs | 3.6 μs | 2.8 μs | 7.1 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.2 μs) | 0.96x | +| two_scale | sorted_near_start | 64 | 4096 | 31.5 μs | 56.1 μs | 42.9 μs | 113.5 μs | 67.6 μs | 31.5 μs | 60.1 μs | Linear (31.5 μs) | 1.00x | +| two_scale | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 89 ns | 60 ns | 70 ns | 60 ns | Binary (60 ns) | 1.17x | +| two_scale | sorted_near_start | 1024 | 10 | 1.3 μs | 280 ns | 240 ns | 460 ns | 290 ns | 270 ns | 280 ns | ExpFromLeft (240 ns) | 1.12x | +| two_scale | sorted_near_start | 1024 | 256 | 3.7 μs | 4.4 μs | 3.2 μs | 11.5 μs | 6.8 μs | 3.7 μs | 6.8 μs | ExpFromLeft (3.2 μs) | 1.15x | +| two_scale | sorted_near_start | 1024 | 4096 | 34.1 μs | 57.8 μs | 44.0 μs | 179.8 μs | 110.1 μs | 33.7 μs | 102.6 μs | Linear (34.1 μs) | 0.99x | +| two_scale | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_near_start | 65536 | 10 | 61.9 μs | 540 ns | 410 ns | 790 ns | 440 ns | 440 ns | 450 ns | ExpFromLeft (410 ns) | 1.07x | +| two_scale | sorted_near_start | 65536 | 256 | 96.1 μs | 7.8 μs | 6.0 μs | 20.6 μs | 11.9 μs | 5.8 μs | 19.0 μs | ExpFromLeft (6.0 μs) | 0.96x | +| two_scale | sorted_near_start | 65536 | 4096 | 162.5 μs | 121.7 μs | 98.1 μs | 479.2 μs | 359.9 μs | 102.8 μs | 286.0 μs | ExpFromLeft (98.1 μs) | 1.05x | +| two_scale | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 80 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | +| two_scale | unsorted | 64 | 10 | 180 ns | 190 ns | 180 ns | 190 ns | 200 ns | 210 ns | 190 ns | ExpFromLeft (180 ns) | 1.17x | +| two_scale | unsorted | 64 | 256 | 6.3 μs | 6.2 μs | 6.3 μs | 6.2 μs | 6.2 μs | 6.3 μs | 6.0 μs | Gallop (6.2 μs) | 1.03x | +| two_scale | unsorted | 64 | 4096 | 181.2 μs | 181.8 μs | 182.2 μs | 179.6 μs | 178.3 μs | 177.1 μs | 173.5 μs | Binary (178.3 μs) | 0.99x | +| two_scale | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 90 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| two_scale | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 270 ns | 290 ns | 290 ns | 270 ns | InterpSearch (270 ns) | 1.07x | +| two_scale | unsorted | 1024 | 256 | 10.1 μs | 10.0 μs | 9.9 μs | 9.9 μs | 9.6 μs | 9.7 μs | 9.4 μs | Binary (9.6 μs) | 1.02x | +| two_scale | unsorted | 1024 | 4096 | 345.9 μs | 344.6 μs | 343.2 μs | 339.2 μs | 337.2 μs | 339.0 μs | 340.1 μs | Binary (337.2 μs) | 1.01x | +| two_scale | unsorted | 65536 | 1 | 80 ns | 80 ns | 70 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| two_scale | unsorted | 65536 | 10 | 420 ns | 420 ns | 430 ns | 420 ns | 440 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | +| two_scale | unsorted | 65536 | 256 | 16.0 μs | 15.8 μs | 15.8 μs | 15.7 μs | 15.6 μs | 15.7 μs | 18.8 μs | Binary (15.6 μs) | 1.00x | +| two_scale | unsorted | 65536 | 4096 | 751.6 μs | 752.4 μs | 752.7 μs | 750.5 μs | 751.6 μs | 752.3 μs | 756.8 μs | InterpSearch (750.5 μs) | 1.00x | -**Auto verdict over 240 cells**: 213 within 20% of best, 13 worse than 20% slowdown, 14 effectively-faster-than-best. +**Auto verdict over 240 cells**: 221 within 20% of best, 14 worse than 20% slowdown, 5 effectively-faster-than-best. diff --git a/bench/results_focused.md b/bench/results_focused.md index 357955b..f5240ae 100644 --- a/bench/results_focused.md +++ b/bench/results_focused.md @@ -3,16 +3,16 @@ | spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | |---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 4096 | 512 | 10.4 μs | 12.7 μs | 9.2 μs | 19.2 μs | 24.6 μs | 9.4 μs | 29.8 μs | ExpFromLeft (9.2 μs) | 1.02x | -| log | sorted_uniform | 4096 | 512 | 10.1 μs | 10.4 μs | 7.5 μs | 39.9 μs | 21.7 μs | 8.0 μs | 27.8 μs | ExpFromLeft (7.5 μs) | 1.07x | -| jittered | sorted_uniform | 4096 | 512 | 10.2 μs | 12.5 μs | 9.5 μs | 18.8 μs | 26.3 μs | 9.3 μs | 33.5 μs | ExpFromLeft (9.5 μs) | 0.99x | -| random | sorted_uniform | 4096 | 512 | 10.4 μs | 12.0 μs | 8.9 μs | 22.3 μs | 23.7 μs | 9.2 μs | 30.7 μs | ExpFromLeft (8.9 μs) | 1.03x | -| two_scale | sorted_uniform | 4096 | 512 | 7.3 μs | 10.3 μs | 7.9 μs | 40.9 μs | 22.9 μs | 8.0 μs | 29.4 μs | Linear (7.3 μs) | 1.10x | -| power2 | sorted_uniform | 4096 | 512 | 10.4 μs | 11.9 μs | 9.0 μs | 38.4 μs | 25.9 μs | 9.3 μs | 33.4 μs | ExpFromLeft (9.0 μs) | 1.03x | -| sqrt | sorted_uniform | 4096 | 512 | 10.4 μs | 12.1 μs | 9.0 μs | 36.4 μs | 23.9 μs | 9.4 μs | 29.6 μs | ExpFromLeft (9.0 μs) | 1.05x | -| plateau | sorted_uniform | 4096 | 512 | 5.8 μs | 7.0 μs | 5.4 μs | 39.1 μs | 15.8 μs | 5.6 μs | 14.6 μs | ExpFromLeft (5.4 μs) | 1.04x | -| bimodal | sorted_uniform | 4096 | 512 | 11.3 μs | 8.9 μs | 6.8 μs | 41.7 μs | 16.0 μs | 7.0 μs | 14.9 μs | ExpFromLeft (6.8 μs) | 1.03x | -| near_linear | sorted_uniform | 4096 | 512 | 10.3 μs | 12.8 μs | 9.3 μs | 18.9 μs | 26.2 μs | 9.4 μs | 32.7 μs | ExpFromLeft (9.3 μs) | 1.01x | +| uniform | sorted_uniform | 4096 | 512 | 10.4 μs | 12.5 μs | 9.2 μs | 19.1 μs | 23.5 μs | 9.3 μs | 24.6 μs | ExpFromLeft (9.2 μs) | 1.01x | +| log | sorted_uniform | 4096 | 512 | 10.2 μs | 10.5 μs | 7.4 μs | 39.8 μs | 21.9 μs | 8.0 μs | 23.9 μs | ExpFromLeft (7.4 μs) | 1.07x | +| jittered | sorted_uniform | 4096 | 512 | 10.2 μs | 12.2 μs | 9.3 μs | 18.7 μs | 25.8 μs | 9.2 μs | 29.3 μs | ExpFromLeft (9.3 μs) | 0.99x | +| random | sorted_uniform | 4096 | 512 | 10.0 μs | 12.1 μs | 9.0 μs | 22.8 μs | 24.9 μs | 9.4 μs | 27.9 μs | ExpFromLeft (9.0 μs) | 1.05x | +| two_scale | sorted_uniform | 4096 | 512 | 7.1 μs | 10.4 μs | 7.6 μs | 42.4 μs | 23.1 μs | 8.2 μs | 26.4 μs | Linear (7.1 μs) | 1.16x | +| power2 | sorted_uniform | 4096 | 512 | 10.1 μs | 12.0 μs | 9.1 μs | 39.0 μs | 25.8 μs | 9.4 μs | 28.9 μs | ExpFromLeft (9.1 μs) | 1.04x | +| sqrt | sorted_uniform | 4096 | 512 | 10.1 μs | 12.1 μs | 9.1 μs | 36.3 μs | 23.3 μs | 9.5 μs | 27.0 μs | ExpFromLeft (9.1 μs) | 1.04x | +| plateau | sorted_uniform | 4096 | 512 | 6.0 μs | 7.0 μs | 5.4 μs | 40.0 μs | 15.8 μs | 5.6 μs | 14.6 μs | ExpFromLeft (5.4 μs) | 1.04x | +| bimodal | sorted_uniform | 4096 | 512 | 11.3 μs | 8.8 μs | 6.8 μs | 42.1 μs | 16.1 μs | 7.0 μs | 14.7 μs | ExpFromLeft (6.8 μs) | 1.02x | +| near_linear | sorted_uniform | 4096 | 512 | 10.4 μs | 12.6 μs | 9.4 μs | 18.7 μs | 26.0 μs | 9.3 μs | 29.6 μs | ExpFromLeft (9.4 μs) | 0.99x | **Auto verdict over 10 cells**: 10 within 20% of best, 0 worse than 20% slowdown, 0 effectively-faster-than-best. @@ -20,87 +20,87 @@ | spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | |---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 4096 | 512 | 10.3 μs | 12.2 μs | 9.0 μs | 19.1 μs | 22.8 μs | 9.2 μs | 22.7 μs | ExpFromLeft (9.0 μs) | 1.02x | -| uniform | sorted_dense_burst | 4096 | 512 | 3.9 μs | 6.9 μs | 5.3 μs | 13.8 μs | 16.0 μs | 3.8 μs | 14.3 μs | Linear (3.9 μs) | 0.97x | -| uniform | sorted_near_start | 4096 | 512 | 10.6 μs | 9.3 μs | 8.8 μs | 18.8 μs | 17.2 μs | 8.9 μs | 16.4 μs | ExpFromLeft (8.8 μs) | 1.01x | -| uniform | sorted_arithmetic | 4096 | 512 | 10.3 μs | 13.5 μs | 11.6 μs | 14.2 μs | 23.8 μs | 11.6 μs | 25.3 μs | Linear (10.3 μs) | 1.12x | -| uniform | sorted_geometric | 4096 | 512 | 11.4 μs | 13.5 μs | 9.9 μs | 17.6 μs | 26.3 μs | 9.8 μs | 26.3 μs | ExpFromLeft (9.9 μs) | 1.00x | -| uniform | sorted_bimodal | 4096 | 512 | 9.4 μs | 9.1 μs | 6.3 μs | 18.5 μs | 20.4 μs | 6.3 μs | 19.2 μs | ExpFromLeft (6.3 μs) | 1.00x | -| uniform | sorted_repeated | 4096 | 512 | 3.9 μs | 6.9 μs | 5.0 μs | 13.4 μs | 16.0 μs | 3.8 μs | 14.3 μs | Linear (3.9 μs) | 0.96x | -| uniform | unsorted | 4096 | 512 | 33.2 μs | 31.7 μs | 31.2 μs | 30.9 μs | 30.6 μs | 30.4 μs | 30.7 μs | Binary (30.6 μs) | 0.99x | +| uniform | sorted_uniform | 4096 | 512 | 10.3 μs | 12.4 μs | 9.2 μs | 19.2 μs | 24.6 μs | 9.2 μs | 25.4 μs | ExpFromLeft (9.2 μs) | 1.00x | +| uniform | sorted_dense_burst | 4096 | 512 | 3.9 μs | 6.9 μs | 5.3 μs | 13.8 μs | 15.8 μs | 3.9 μs | 14.3 μs | Linear (3.9 μs) | 1.00x | +| uniform | sorted_near_start | 4096 | 512 | 10.7 μs | 9.5 μs | 6.7 μs | 18.7 μs | 17.3 μs | 6.9 μs | 20.6 μs | ExpFromLeft (6.7 μs) | 1.04x | +| uniform | sorted_arithmetic | 4096 | 512 | 10.6 μs | 13.5 μs | 11.6 μs | 14.1 μs | 23.4 μs | 15.2 μs | 28.7 μs | Linear (10.6 μs) | 1.43x | +| uniform | sorted_geometric | 4096 | 512 | 11.5 μs | 13.5 μs | 9.8 μs | 17.7 μs | 27.1 μs | 10.0 μs | 28.5 μs | ExpFromLeft (9.8 μs) | 1.02x | +| uniform | sorted_bimodal | 4096 | 512 | 9.2 μs | 9.1 μs | 6.2 μs | 18.6 μs | 20.8 μs | 6.6 μs | 25.1 μs | ExpFromLeft (6.2 μs) | 1.06x | +| uniform | sorted_repeated | 4096 | 512 | 3.9 μs | 6.9 μs | 5.0 μs | 13.1 μs | 15.8 μs | 3.9 μs | 14.3 μs | Linear (3.9 μs) | 1.01x | +| uniform | unsorted | 4096 | 512 | 34.5 μs | 32.5 μs | 31.9 μs | 31.1 μs | 31.1 μs | 31.3 μs | 32.6 μs | Binary (31.1 μs) | 1.01x | -**Auto verdict over 8 cells**: 8 within 20% of best, 0 worse than 20% slowdown, 0 effectively-faster-than-best. +**Auto verdict over 8 cells**: 7 within 20% of best, 1 worse than 20% slowdown, 0 effectively-faster-than-best. ## n/m crossover (uniform, sorted_uniform) | spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | |---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 50 ns | 60 ns | 40 ns | Binary (50 ns) | 1.20x | -| uniform | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 80 ns | 150 ns | 90 ns | 110 ns | 70 ns | ExpFromLeft (80 ns) | 1.38x | -| uniform | sorted_uniform | 16 | 16 | 190 ns | 300 ns | 210 ns | 470 ns | 230 ns | 220 ns | 190 ns | Linear (190 ns) | 1.16x | -| uniform | sorted_uniform | 16 | 64 | 560 ns | 1.0 μs | 710 ns | 2.0 μs | 990 ns | 570 ns | 880 ns | Linear (560 ns) | 1.02x | -| uniform | sorted_uniform | 16 | 256 | 2.3 μs | 3.9 μs | 2.9 μs | 7.9 μs | 3.3 μs | 2.2 μs | 2.9 μs | Linear (2.3 μs) | 0.96x | -| uniform | sorted_uniform | 16 | 1024 | 8.1 μs | 14.7 μs | 10.8 μs | 28.8 μs | 12.5 μs | 7.7 μs | 10.6 μs | Linear (8.1 μs) | 0.95x | -| uniform | sorted_uniform | 16 | 4096 | 31.5 μs | 58.0 μs | 42.2 μs | 109.3 μs | 48.5 μs | 29.4 μs | 40.8 μs | Linear (31.5 μs) | 0.93x | -| uniform | sorted_uniform | 16 | 16384 | 123.2 μs | 218.6 μs | 168.1 μs | 432.2 μs | 191.5 μs | 116.6 μs | 162.1 μs | Linear (123.2 μs) | 0.95x | -| uniform | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 60 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| uniform | sorted_uniform | 64 | 4 | 140 ns | 129 ns | 120 ns | 140 ns | 100 ns | 150 ns | 90 ns | Binary (100 ns) | 1.50x | -| uniform | sorted_uniform | 64 | 16 | 240 ns | 340 ns | 260 ns | 460 ns | 330 ns | 260 ns | 350 ns | Linear (240 ns) | 1.08x | -| uniform | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 730 ns | 2.2 μs | 1.4 μs | 650 ns | 1.3 μs | Linear (630 ns) | 1.03x | -| uniform | sorted_uniform | 64 | 256 | 2.3 μs | 4.1 μs | 3.1 μs | 9.0 μs | 5.3 μs | 2.2 μs | 4.8 μs | Linear (2.3 μs) | 0.97x | -| uniform | sorted_uniform | 64 | 1024 | 12.1 μs | 14.8 μs | 11.7 μs | 31.2 μs | 17.8 μs | 8.8 μs | 16.0 μs | ExpFromLeft (11.7 μs) | 0.75x | -| uniform | sorted_uniform | 64 | 4096 | 32.2 μs | 56.0 μs | 43.2 μs | 112.9 μs | 67.4 μs | 30.6 μs | 60.1 μs | Linear (32.2 μs) | 0.95x | -| uniform | sorted_uniform | 64 | 16384 | 124.3 μs | 220.7 μs | 169.4 μs | 439.1 μs | 265.8 μs | 117.8 μs | 237.0 μs | Linear (124.3 μs) | 0.95x | -| uniform | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 69 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_uniform | 256 | 4 | 360 ns | 160 ns | 130 ns | 140 ns | 120 ns | 160 ns | 110 ns | Binary (120 ns) | 1.33x | -| uniform | sorted_uniform | 256 | 16 | 590 ns | 490 ns | 460 ns | 470 ns | 370 ns | 400 ns | 340 ns | Binary (370 ns) | 1.08x | -| uniform | sorted_uniform | 256 | 64 | 930 ns | 1.4 μs | 960 ns | 2.1 μs | 1.5 μs | 950 ns | 1.4 μs | Linear (930 ns) | 1.02x | -| uniform | sorted_uniform | 256 | 256 | 2.4 μs | 4.1 μs | 2.8 μs | 9.3 μs | 7.0 μs | 2.3 μs | 6.7 μs | Linear (2.4 μs) | 0.98x | -| uniform | sorted_uniform | 256 | 1024 | 9.8 μs | 17.8 μs | 13.5 μs | 37.0 μs | 26.8 μs | 9.4 μs | 25.1 μs | Linear (9.8 μs) | 0.96x | -| uniform | sorted_uniform | 256 | 4096 | 51.3 μs | 59.7 μs | 46.6 μs | 123.3 μs | 90.4 μs | 34.8 μs | 83.8 μs | ExpFromLeft (46.6 μs) | 0.75x | -| uniform | sorted_uniform | 256 | 16384 | 128.7 μs | 224.4 μs | 172.8 μs | 451.3 μs | 347.7 μs | 122.1 μs | 317.1 μs | Linear (128.7 μs) | 0.95x | -| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| uniform | sorted_uniform | 1024 | 4 | 1.1 μs | 190 ns | 160 ns | 140 ns | 140 ns | 180 ns | 120 ns | InterpSearch (140 ns) | 1.29x | -| uniform | sorted_uniform | 1024 | 16 | 1.7 μs | 570 ns | 430 ns | 490 ns | 440 ns | 480 ns | 410 ns | ExpFromLeft (430 ns) | 1.12x | -| uniform | sorted_uniform | 1024 | 64 | 2.1 μs | 1.8 μs | 1.3 μs | 1.9 μs | 1.8 μs | 1.4 μs | 1.6 μs | ExpFromLeft (1.3 μs) | 1.03x | -| uniform | sorted_uniform | 1024 | 256 | 3.5 μs | 5.5 μs | 3.8 μs | 8.7 μs | 8.2 μs | 3.4 μs | 8.1 μs | Linear (3.5 μs) | 0.99x | -| uniform | sorted_uniform | 1024 | 1024 | 10.5 μs | 17.9 μs | 12.3 μs | 39.4 μs | 59.8 μs | 10.1 μs | 61.1 μs | Linear (10.5 μs) | 0.96x | -| uniform | sorted_uniform | 1024 | 4096 | 48.8 μs | 72.4 μs | 57.6 μs | 150.0 μs | 197.6 μs | 47.3 μs | 193.4 μs | Linear (48.8 μs) | 0.97x | -| uniform | sorted_uniform | 1024 | 16384 | 166.1 μs | 237.4 μs | 186.4 μs | 499.7 μs | 512.6 μs | 139.6 μs | 488.7 μs | Linear (166.1 μs) | 0.84x | -| uniform | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_uniform | 4096 | 4 | 2.3 μs | 220 ns | 170 ns | 140 ns | 150 ns | 180 ns | 150 ns | InterpSearch (140 ns) | 1.29x | -| uniform | sorted_uniform | 4096 | 16 | 6.0 μs | 740 ns | 560 ns | 460 ns | 510 ns | 520 ns | 490 ns | InterpSearch (460 ns) | 1.13x | -| uniform | sorted_uniform | 4096 | 64 | 7.2 μs | 2.3 μs | 1.7 μs | 2.0 μs | 2.0 μs | 1.7 μs | 1.9 μs | ExpFromLeft (1.7 μs) | 1.01x | -| uniform | sorted_uniform | 4096 | 256 | 8.8 μs | 7.2 μs | 5.3 μs | 9.0 μs | 10.8 μs | 5.3 μs | 11.6 μs | ExpFromLeft (5.3 μs) | 1.00x | -| uniform | sorted_uniform | 4096 | 1024 | 16.3 μs | 23.7 μs | 17.6 μs | 38.2 μs | 98.9 μs | 14.9 μs | 97.1 μs | Linear (16.3 μs) | 0.91x | -| uniform | sorted_uniform | 4096 | 4096 | 67.4 μs | 94.9 μs | 71.0 μs | 160.5 μs | 300.1 μs | 62.9 μs | 296.7 μs | Linear (67.4 μs) | 0.93x | -| uniform | sorted_uniform | 4096 | 16384 | 210.2 μs | 292.8 μs | 235.1 μs | 626.5 μs | 806.4 μs | 203.1 μs | 773.4 μs | Linear (210.2 μs) | 0.97x | -| uniform | sorted_uniform | 16384 | 1 | 70 ns | 80 ns | 70 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | -| uniform | sorted_uniform | 16384 | 4 | 17.8 μs | 270 ns | 210 ns | 149 ns | 180 ns | 180 ns | 170 ns | InterpSearch (149 ns) | 1.21x | -| uniform | sorted_uniform | 16384 | 16 | 19.2 μs | 860 ns | 640 ns | 510 ns | 590 ns | 570 ns | 620 ns | InterpSearch (510 ns) | 1.12x | -| uniform | sorted_uniform | 16384 | 64 | 25.1 μs | 2.9 μs | 2.2 μs | 2.0 μs | 2.4 μs | 2.1 μs | 2.3 μs | InterpSearch (2.0 μs) | 1.05x | -| uniform | sorted_uniform | 16384 | 256 | 29.4 μs | 9.6 μs | 7.0 μs | 9.1 μs | 13.8 μs | 7.0 μs | 13.1 μs | ExpFromLeft (7.0 μs) | 1.00x | -| uniform | sorted_uniform | 16384 | 1024 | 42.5 μs | 36.2 μs | 26.5 μs | 39.7 μs | 129.1 μs | 23.1 μs | 128.7 μs | ExpFromLeft (26.5 μs) | 0.87x | -| uniform | sorted_uniform | 16384 | 4096 | 115.1 μs | 161.1 μs | 120.8 μs | 160.4 μs | 403.0 μs | 110.1 μs | 397.8 μs | Linear (115.1 μs) | 0.96x | -| uniform | sorted_uniform | 16384 | 16384 | 373.0 μs | 442.9 μs | 368.9 μs | 641.6 μs | 1.15 ms | 365.4 μs | 1.13 ms | ExpFromLeft (368.9 μs) | 0.99x | +| uniform | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_uniform | 16 | 4 | 90 ns | 100 ns | 90 ns | 160 ns | 90 ns | 110 ns | 80 ns | ExpFromLeft (90 ns) | 1.22x | +| uniform | sorted_uniform | 16 | 16 | 200 ns | 290 ns | 210 ns | 490 ns | 220 ns | 220 ns | 190 ns | Linear (200 ns) | 1.10x | +| uniform | sorted_uniform | 16 | 64 | 550 ns | 960 ns | 730 ns | 1.9 μs | 960 ns | 580 ns | 689 ns | Linear (550 ns) | 1.05x | +| uniform | sorted_uniform | 16 | 256 | 2.3 μs | 3.7 μs | 3.0 μs | 7.7 μs | 3.4 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 0.99x | +| uniform | sorted_uniform | 16 | 1024 | 7.9 μs | 13.8 μs | 11.2 μs | 28.5 μs | 12.3 μs | 7.9 μs | 10.4 μs | Linear (7.9 μs) | 1.00x | +| uniform | sorted_uniform | 16 | 4096 | 30.3 μs | 54.3 μs | 43.9 μs | 110.9 μs | 48.1 μs | 30.3 μs | 40.8 μs | Linear (30.3 μs) | 1.00x | +| uniform | sorted_uniform | 16 | 16384 | 120.0 μs | 217.0 μs | 174.8 μs | 441.5 μs | 190.7 μs | 120.0 μs | 162.0 μs | Linear (120.0 μs) | 1.00x | +| uniform | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 50 ns | 50 ns | 50 ns | Binary (50 ns) | 1.00x | +| uniform | sorted_uniform | 64 | 4 | 140 ns | 140 ns | 130 ns | 160 ns | 100 ns | 150 ns | 100 ns | Binary (100 ns) | 1.50x | +| uniform | sorted_uniform | 64 | 16 | 240 ns | 350 ns | 270 ns | 490 ns | 330 ns | 280 ns | 260 ns | Linear (240 ns) | 1.17x | +| uniform | sorted_uniform | 64 | 64 | 620 ns | 1.1 μs | 790 ns | 2.2 μs | 1.4 μs | 640 ns | 960 ns | Linear (620 ns) | 1.03x | +| uniform | sorted_uniform | 64 | 256 | 2.2 μs | 4.2 μs | 3.2 μs | 9.0 μs | 5.3 μs | 2.2 μs | 3.7 μs | Linear (2.2 μs) | 1.01x | +| uniform | sorted_uniform | 64 | 1024 | 9.0 μs | 14.7 μs | 12.0 μs | 30.9 μs | 17.7 μs | 8.9 μs | 15.9 μs | Linear (9.0 μs) | 0.99x | +| uniform | sorted_uniform | 64 | 4096 | 31.4 μs | 55.6 μs | 44.7 μs | 113.4 μs | 67.3 μs | 31.4 μs | 60.1 μs | Linear (31.4 μs) | 1.00x | +| uniform | sorted_uniform | 64 | 16384 | 121.1 μs | 219.1 μs | 175.7 μs | 445.4 μs | 266.2 μs | 121.2 μs | 237.2 μs | Linear (121.1 μs) | 1.00x | +| uniform | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_uniform | 256 | 4 | 350 ns | 160 ns | 150 ns | 160 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | +| uniform | sorted_uniform | 256 | 16 | 520 ns | 460 ns | 380 ns | 500 ns | 380 ns | 400 ns | 330 ns | ExpFromLeft (380 ns) | 1.05x | +| uniform | sorted_uniform | 256 | 64 | 890 ns | 1.4 μs | 1.0 μs | 2.1 μs | 1.5 μs | 930 ns | 1.2 μs | Linear (890 ns) | 1.04x | +| uniform | sorted_uniform | 256 | 256 | 2.4 μs | 4.1 μs | 3.0 μs | 9.1 μs | 7.3 μs | 2.4 μs | 5.1 μs | Linear (2.4 μs) | 1.00x | +| uniform | sorted_uniform | 256 | 1024 | 9.7 μs | 17.8 μs | 14.0 μs | 37.2 μs | 26.9 μs | 9.8 μs | 24.7 μs | Linear (9.7 μs) | 1.01x | +| uniform | sorted_uniform | 256 | 4096 | 35.7 μs | 58.9 μs | 48.1 μs | 123.8 μs | 91.6 μs | 35.7 μs | 121.0 μs | Linear (35.7 μs) | 1.00x | +| uniform | sorted_uniform | 256 | 16384 | 125.5 μs | 222.7 μs | 178.9 μs | 454.2 μs | 347.4 μs | 125.5 μs | 354.1 μs | Linear (125.5 μs) | 1.00x | +| uniform | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_uniform | 1024 | 4 | 1.1 μs | 190 ns | 170 ns | 150 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| uniform | sorted_uniform | 1024 | 16 | 1.7 μs | 570 ns | 480 ns | 510 ns | 440 ns | 560 ns | 410 ns | Binary (440 ns) | 1.27x | +| uniform | sorted_uniform | 1024 | 64 | 2.0 μs | 1.8 μs | 1.4 μs | 2.0 μs | 1.7 μs | 2.2 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.55x | +| uniform | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.9 μs | 8.9 μs | 8.1 μs | 3.5 μs | 7.2 μs | Linear (3.6 μs) | 0.96x | +| uniform | sorted_uniform | 1024 | 1024 | 9.7 μs | 17.8 μs | 12.8 μs | 39.5 μs | 58.0 μs | 9.7 μs | 69.9 μs | Linear (9.7 μs) | 0.99x | +| uniform | sorted_uniform | 1024 | 4096 | 46.8 μs | 73.0 μs | 58.8 μs | 151.8 μs | 199.6 μs | 46.8 μs | 226.4 μs | Linear (46.8 μs) | 1.00x | +| uniform | sorted_uniform | 1024 | 16384 | 143.2 μs | 236.2 μs | 191.7 μs | 494.1 μs | 515.7 μs | 142.8 μs | 555.3 μs | Linear (143.2 μs) | 1.00x | +| uniform | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_uniform | 4096 | 4 | 2.3 μs | 220 ns | 180 ns | 160 ns | 160 ns | 200 ns | 140 ns | InterpSearch (160 ns) | 1.25x | +| uniform | sorted_uniform | 4096 | 16 | 6.0 μs | 750 ns | 560 ns | 489 ns | 520 ns | 539 ns | 490 ns | InterpSearch (489 ns) | 1.10x | +| uniform | sorted_uniform | 4096 | 64 | 7.3 μs | 2.3 μs | 1.8 μs | 2.0 μs | 2.0 μs | 2.1 μs | 1.8 μs | ExpFromLeft (1.8 μs) | 1.21x | +| uniform | sorted_uniform | 4096 | 256 | 8.4 μs | 7.2 μs | 5.4 μs | 9.1 μs | 10.2 μs | 9.6 μs | 9.2 μs | ExpFromLeft (5.4 μs) | 1.77x | +| uniform | sorted_uniform | 4096 | 1024 | 15.1 μs | 23.2 μs | 17.6 μs | 39.0 μs | 94.1 μs | 14.9 μs | 90.5 μs | Linear (15.1 μs) | 0.99x | +| uniform | sorted_uniform | 4096 | 4096 | 62.6 μs | 95.3 μs | 74.1 μs | 163.1 μs | 302.0 μs | 62.5 μs | 296.1 μs | Linear (62.6 μs) | 1.00x | +| uniform | sorted_uniform | 4096 | 16384 | 199.8 μs | 293.6 μs | 242.1 μs | 606.7 μs | 762.5 μs | 200.2 μs | 863.9 μs | Linear (199.8 μs) | 1.00x | +| uniform | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_uniform | 16384 | 4 | 17.8 μs | 280 ns | 230 ns | 160 ns | 180 ns | 200 ns | 160 ns | InterpSearch (160 ns) | 1.25x | +| uniform | sorted_uniform | 16384 | 16 | 19.1 μs | 860 ns | 650 ns | 540 ns | 600 ns | 590 ns | 560 ns | InterpSearch (540 ns) | 1.09x | +| uniform | sorted_uniform | 16384 | 64 | 24.8 μs | 2.9 μs | 2.2 μs | 2.0 μs | 2.3 μs | 2.1 μs | 2.2 μs | InterpSearch (2.0 μs) | 1.05x | +| uniform | sorted_uniform | 16384 | 256 | 29.0 μs | 9.8 μs | 7.3 μs | 9.3 μs | 12.0 μs | 9.7 μs | 11.0 μs | ExpFromLeft (7.3 μs) | 1.34x | +| uniform | sorted_uniform | 16384 | 1024 | 38.5 μs | 36.7 μs | 27.6 μs | 40.3 μs | 127.3 μs | 41.8 μs | 121.4 μs | ExpFromLeft (27.6 μs) | 1.52x | +| uniform | sorted_uniform | 16384 | 4096 | 108.9 μs | 161.1 μs | 123.0 μs | 162.8 μs | 392.7 μs | 106.8 μs | 392.4 μs | Linear (108.9 μs) | 0.98x | +| uniform | sorted_uniform | 16384 | 16384 | 360.3 μs | 452.0 μs | 375.1 μs | 653.1 μs | 1.11 ms | 360.9 μs | 1.26 ms | Linear (360.3 μs) | 1.00x | | uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_uniform | 65536 | 4 | 22.3 μs | 270 ns | 210 ns | 140 ns | 190 ns | 180 ns | 190 ns | InterpSearch (140 ns) | 1.29x | -| uniform | sorted_uniform | 65536 | 16 | 83.8 μs | 1.1 μs | 769 ns | 460 ns | 680 ns | 510 ns | 650 ns | InterpSearch (460 ns) | 1.11x | -| uniform | sorted_uniform | 65536 | 64 | 94.7 μs | 3.6 μs | 2.6 μs | 2.1 μs | 2.8 μs | 2.2 μs | 2.7 μs | InterpSearch (2.1 μs) | 1.06x | -| uniform | sorted_uniform | 65536 | 256 | 102.8 μs | 12.5 μs | 9.3 μs | 8.9 μs | 16.7 μs | 9.3 μs | 17.1 μs | InterpSearch (8.9 μs) | 1.04x | -| uniform | sorted_uniform | 65536 | 1024 | 116.7 μs | 61.9 μs | 45.4 μs | 41.4 μs | 161.3 μs | 37.2 μs | 164.8 μs | InterpSearch (41.4 μs) | 0.90x | -| uniform | sorted_uniform | 65536 | 4096 | 194.1 μs | 260.1 μs | 209.3 μs | 165.3 μs | 494.7 μs | 201.6 μs | 497.8 μs | InterpSearch (165.3 μs) | 1.22x | -| uniform | sorted_uniform | 65536 | 16384 | 545.0 μs | 733.2 μs | 576.0 μs | 644.2 μs | 1.49 ms | 538.0 μs | 1.47 ms | Linear (545.0 μs) | 0.99x | -| uniform | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 80 ns | InterpSearch (60 ns) | 1.33x | -| uniform | sorted_uniform | 262144 | 4 | 153.2 μs | 330 ns | 260 ns | 140 ns | 220 ns | 180 ns | 210 ns | InterpSearch (140 ns) | 1.29x | -| uniform | sorted_uniform | 262144 | 16 | 332.2 μs | 1.2 μs | 880 ns | 510 ns | 780 ns | 560 ns | 770 ns | InterpSearch (510 ns) | 1.10x | -| uniform | sorted_uniform | 262144 | 64 | 363.8 μs | 4.3 μs | 3.0 μs | 2.1 μs | 3.8 μs | 2.2 μs | 3.6 μs | InterpSearch (2.1 μs) | 1.06x | -| uniform | sorted_uniform | 262144 | 256 | 382.3 μs | 16.7 μs | 12.9 μs | 9.7 μs | 21.3 μs | 9.9 μs | 21.3 μs | InterpSearch (9.7 μs) | 1.02x | -| uniform | sorted_uniform | 262144 | 1024 | 410.9 μs | 116.8 μs | 87.4 μs | 42.3 μs | 204.9 μs | 43.4 μs | 209.3 μs | InterpSearch (42.3 μs) | 1.03x | -| uniform | sorted_uniform | 262144 | 4096 | 492.2 μs | 370.3 μs | 300.4 μs | 186.4 μs | 613.9 μs | 299.2 μs | 632.8 μs | InterpSearch (186.4 μs) | 1.61x | -| uniform | sorted_uniform | 262144 | 16384 | 854.5 μs | 1.00 ms | 835.2 μs | 660.4 μs | 1.85 ms | 835.0 μs | 1.87 ms | InterpSearch (660.4 μs) | 1.26x | +| uniform | sorted_uniform | 65536 | 4 | 21.6 μs | 270 ns | 220 ns | 150 ns | 200 ns | 200 ns | 180 ns | InterpSearch (150 ns) | 1.33x | +| uniform | sorted_uniform | 65536 | 16 | 83.3 μs | 1.0 μs | 770 ns | 490 ns | 700 ns | 540 ns | 650 ns | InterpSearch (490 ns) | 1.10x | +| uniform | sorted_uniform | 65536 | 64 | 94.4 μs | 3.6 μs | 2.7 μs | 2.2 μs | 2.9 μs | 2.3 μs | 2.6 μs | InterpSearch (2.2 μs) | 1.06x | +| uniform | sorted_uniform | 65536 | 256 | 100.7 μs | 12.6 μs | 9.9 μs | 9.2 μs | 16.1 μs | 9.7 μs | 13.6 μs | InterpSearch (9.2 μs) | 1.05x | +| uniform | sorted_uniform | 65536 | 1024 | 119.4 μs | 61.5 μs | 43.2 μs | 41.4 μs | 158.9 μs | 42.9 μs | 156.8 μs | InterpSearch (41.4 μs) | 1.04x | +| uniform | sorted_uniform | 65536 | 4096 | 190.9 μs | 257.0 μs | 203.0 μs | 166.4 μs | 494.8 μs | 173.3 μs | 488.9 μs | InterpSearch (166.4 μs) | 1.04x | +| uniform | sorted_uniform | 65536 | 16384 | 518.5 μs | 715.7 μs | 555.9 μs | 656.8 μs | 1.46 ms | 515.4 μs | 1.58 ms | Linear (518.5 μs) | 0.99x | +| uniform | sorted_uniform | 262144 | 1 | 90 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_uniform | 262144 | 4 | 153.4 μs | 330 ns | 270 ns | 170 ns | 220 ns | 200 ns | 200 ns | InterpSearch (170 ns) | 1.18x | +| uniform | sorted_uniform | 262144 | 16 | 332.3 μs | 1.2 μs | 850 ns | 540 ns | 810 ns | 590 ns | 770 ns | InterpSearch (540 ns) | 1.09x | +| uniform | sorted_uniform | 262144 | 64 | 360.7 μs | 4.2 μs | 3.1 μs | 2.2 μs | 3.5 μs | 2.3 μs | 3.3 μs | InterpSearch (2.2 μs) | 1.04x | +| uniform | sorted_uniform | 262144 | 256 | 380.8 μs | 14.6 μs | 11.2 μs | 9.8 μs | 19.3 μs | 10.3 μs | 19.9 μs | InterpSearch (9.8 μs) | 1.05x | +| uniform | sorted_uniform | 262144 | 1024 | 406.1 μs | 132.3 μs | 98.0 μs | 43.1 μs | 207.8 μs | 44.8 μs | 207.6 μs | InterpSearch (43.1 μs) | 1.04x | +| uniform | sorted_uniform | 262144 | 4096 | 481.7 μs | 388.1 μs | 330.2 μs | 177.7 μs | 646.4 μs | 183.7 μs | 657.6 μs | InterpSearch (177.7 μs) | 1.03x | +| uniform | sorted_uniform | 262144 | 16384 | 812.8 μs | 1.07 ms | 889.5 μs | 674.6 μs | 1.84 ms | 697.9 μs | 1.97 ms | InterpSearch (674.6 μs) | 1.03x | -**Auto verdict over 64 cells**: 40 within 20% of best, 13 worse than 20% slowdown, 11 effectively-faster-than-best. +**Auto verdict over 64 cells**: 51 within 20% of best, 13 worse than 20% slowdown, 0 effectively-faster-than-best. ### Super-sparse cases (small m on large n) @@ -108,188 +108,188 @@ | spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | |---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_uniform | 1024 | 4 | 500 ns | 160 ns | 140 ns | 170 ns | 140 ns | 180 ns | 130 ns | ExpFromLeft (140 ns) | 1.29x | -| uniform | sorted_uniform | 1024 | 16 | 1.6 μs | 570 ns | 470 ns | 530 ns | 450 ns | 490 ns | 410 ns | Binary (450 ns) | 1.09x | -| uniform | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_uniform | 16384 | 4 | 9.0 μs | 240 ns | 200 ns | 160 ns | 180 ns | 180 ns | 170 ns | InterpSearch (160 ns) | 1.12x | -| uniform | sorted_uniform | 16384 | 16 | 23.5 μs | 890 ns | 650 ns | 540 ns | 600 ns | 540 ns | 560 ns | InterpSearch (540 ns) | 1.00x | -| uniform | sorted_uniform | 262144 | 1 | 90 ns | 80 ns | 80 ns | 70 ns | 90 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_uniform | 262144 | 4 | 256.8 μs | 350 ns | 280 ns | 170 ns | 220 ns | 180 ns | 210 ns | InterpSearch (170 ns) | 1.06x | -| uniform | sorted_uniform | 262144 | 16 | 377.9 μs | 1.2 μs | 910 ns | 490 ns | 850 ns | 530 ns | 830 ns | InterpSearch (490 ns) | 1.08x | -| uniform | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| uniform | unsorted | 1024 | 16 | 469 ns | 460 ns | 450 ns | 440 ns | 440 ns | 450 ns | 450 ns | InterpSearch (440 ns) | 1.02x | -| uniform | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 180 ns | 180 ns | 180 ns | 170 ns | Gallop (170 ns) | 1.06x | -| uniform | unsorted | 16384 | 16 | 570 ns | 570 ns | 570 ns | 560 ns | 560 ns | 570 ns | 560 ns | InterpSearch (560 ns) | 1.02x | -| uniform | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | unsorted | 262144 | 4 | 210 ns | 210 ns | 200 ns | 210 ns | 210 ns | 219 ns | 200 ns | ExpFromLeft (200 ns) | 1.09x | -| uniform | unsorted | 262144 | 16 | 790 ns | 770 ns | 780 ns | 790 ns | 780 ns | 790 ns | 770 ns | Gallop (770 ns) | 1.03x | -| log | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_uniform | 1024 | 4 | 210 ns | 160 ns | 140 ns | 300 ns | 140 ns | 160 ns | 130 ns | ExpFromLeft (140 ns) | 1.14x | -| log | sorted_uniform | 1024 | 16 | 1.1 μs | 490 ns | 380 ns | 1.0 μs | 450 ns | 400 ns | 410 ns | ExpFromLeft (380 ns) | 1.05x | -| log | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| log | sorted_uniform | 16384 | 4 | 2.2 μs | 210 ns | 170 ns | 360 ns | 170 ns | 190 ns | 170 ns | ExpFromLeft (170 ns) | 1.12x | -| log | sorted_uniform | 16384 | 16 | 14.8 μs | 780 ns | 570 ns | 1.4 μs | 600 ns | 610 ns | 610 ns | ExpFromLeft (570 ns) | 1.07x | -| log | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_uniform | 262144 | 4 | 328.8 μs | 330 ns | 260 ns | 420 ns | 210 ns | 290 ns | 200 ns | Binary (210 ns) | 1.38x | -| log | sorted_uniform | 262144 | 16 | 180.8 μs | 1.1 μs | 800 ns | 1.7 μs | 800 ns | 810 ns | 820 ns | ExpFromLeft (800 ns) | 1.01x | -| log | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| log | unsorted | 1024 | 16 | 430 ns | 430 ns | 430 ns | 430 ns | 420 ns | 430 ns | 420 ns | Binary (420 ns) | 1.02x | -| log | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 120 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | -| log | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 170 ns | 170 ns | 190 ns | 160 ns | InterpSearch (170 ns) | 1.12x | -| log | unsorted | 16384 | 16 | 620 ns | 600 ns | 610 ns | 610 ns | 620 ns | 610 ns | 610 ns | Gallop (600 ns) | 1.02x | -| log | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 109 ns | 100 ns | 80 ns | ExpFromLeft (80 ns) | 1.25x | -| log | unsorted | 262144 | 4 | 220 ns | 220 ns | 220 ns | 220 ns | 210 ns | 230 ns | 210 ns | Binary (210 ns) | 1.10x | -| log | unsorted | 262144 | 16 | 770 ns | 780 ns | 760 ns | 790 ns | 780 ns | 760 ns | 790 ns | ExpFromLeft (760 ns) | 1.00x | -| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_uniform | 1024 | 4 | 1.0 μs | 190 ns | 160 ns | 160 ns | 130 ns | 180 ns | 130 ns | Binary (130 ns) | 1.38x | -| jittered | sorted_uniform | 1024 | 16 | 1.8 μs | 619 ns | 480 ns | 500 ns | 480 ns | 510 ns | 410 ns | ExpFromLeft (480 ns) | 1.06x | -| jittered | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | -| jittered | sorted_uniform | 16384 | 4 | 18.1 μs | 250 ns | 200 ns | 160 ns | 180 ns | 170 ns | 160 ns | InterpSearch (160 ns) | 1.06x | -| jittered | sorted_uniform | 16384 | 16 | 21.8 μs | 870 ns | 650 ns | 500 ns | 590 ns | 520 ns | 580 ns | InterpSearch (500 ns) | 1.04x | -| jittered | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_uniform | 262144 | 4 | 321.1 μs | 320 ns | 240 ns | 160 ns | 230 ns | 170 ns | 230 ns | InterpSearch (160 ns) | 1.06x | -| jittered | sorted_uniform | 262144 | 16 | 346.1 μs | 1.2 μs | 859 ns | 530 ns | 929 ns | 560 ns | 930 ns | InterpSearch (530 ns) | 1.06x | -| jittered | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 149 ns | 130 ns | InterpSearch (140 ns) | 1.06x | -| jittered | unsorted | 1024 | 16 | 420 ns | 430 ns | 420 ns | 419 ns | 410 ns | 430 ns | 410 ns | Binary (410 ns) | 1.05x | -| jittered | unsorted | 16384 | 1 | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| jittered | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 180 ns | 170 ns | 180 ns | 170 ns | Binary (170 ns) | 1.06x | -| jittered | unsorted | 16384 | 16 | 580 ns | 580 ns | 570 ns | 570 ns | 570 ns | 580 ns | 560 ns | InterpSearch (570 ns) | 1.02x | -| jittered | unsorted | 262144 | 1 | 90 ns | 90 ns | 80 ns | 70 ns | 90 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | -| jittered | unsorted | 262144 | 4 | 220 ns | 210 ns | 210 ns | 210 ns | 220 ns | 220 ns | 210 ns | InterpSearch (210 ns) | 1.05x | -| jittered | unsorted | 262144 | 16 | 780 ns | 780 ns | 820 ns | 800 ns | 790 ns | 800 ns | 770 ns | Gallop (780 ns) | 1.03x | -| random | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_uniform | 1024 | 4 | 920 ns | 180 ns | 150 ns | 210 ns | 130 ns | 230 ns | 120 ns | Binary (130 ns) | 1.77x | -| random | sorted_uniform | 1024 | 16 | 1.7 μs | 600 ns | 460 ns | 670 ns | 440 ns | 480 ns | 410 ns | Binary (440 ns) | 1.09x | -| random | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_uniform | 16384 | 4 | 15.3 μs | 250 ns | 190 ns | 230 ns | 170 ns | 240 ns | 160 ns | Binary (170 ns) | 1.41x | -| random | sorted_uniform | 16384 | 16 | 19.3 μs | 890 ns | 640 ns | 720 ns | 590 ns | 760 ns | 560 ns | Binary (590 ns) | 1.29x | -| random | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| random | sorted_uniform | 262144 | 4 | 219.6 μs | 340 ns | 260 ns | 260 ns | 220 ns | 270 ns | 200 ns | Binary (220 ns) | 1.23x | -| random | sorted_uniform | 262144 | 16 | 266.0 μs | 1.2 μs | 820 ns | 880 ns | 840 ns | 910 ns | 780 ns | ExpFromLeft (820 ns) | 1.11x | -| random | unsorted | 1024 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| random | unsorted | 1024 | 4 | 150 ns | 140 ns | 140 ns | 140 ns | 150 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| random | unsorted | 1024 | 16 | 420 ns | 420 ns | 420 ns | 430 ns | 420 ns | 430 ns | 400 ns | ExpFromLeft (420 ns) | 1.02x | -| random | unsorted | 16384 | 1 | 79 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| random | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | ExpFromLeft (170 ns) | 1.06x | -| random | unsorted | 16384 | 16 | 580 ns | 570 ns | 569 ns | 570 ns | 570 ns | 570 ns | 600 ns | ExpFromLeft (569 ns) | 1.00x | -| random | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| random | unsorted | 262144 | 4 | 220 ns | 220 ns | 220 ns | 220 ns | 210 ns | 230 ns | 210 ns | Binary (210 ns) | 1.10x | -| random | unsorted | 262144 | 16 | 850 ns | 840 ns | 850 ns | 849 ns | 860 ns | 850 ns | 860 ns | Gallop (840 ns) | 1.01x | -| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| two_scale | sorted_uniform | 1024 | 4 | 570 ns | 170 ns | 150 ns | 280 ns | 130 ns | 170 ns | 130 ns | Binary (130 ns) | 1.31x | -| two_scale | sorted_uniform | 1024 | 16 | 950 ns | 530 ns | 410 ns | 1.2 μs | 450 ns | 430 ns | 410 ns | ExpFromLeft (410 ns) | 1.05x | -| two_scale | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| two_scale | sorted_uniform | 16384 | 4 | 9.2 μs | 240 ns | 190 ns | 360 ns | 180 ns | 230 ns | 160 ns | Binary (180 ns) | 1.28x | -| two_scale | sorted_uniform | 16384 | 16 | 9.7 μs | 770 ns | 570 ns | 1.7 μs | 600 ns | 600 ns | 550 ns | ExpFromLeft (570 ns) | 1.05x | -| two_scale | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_uniform | 262144 | 4 | 150.4 μs | 330 ns | 250 ns | 440 ns | 210 ns | 290 ns | 200 ns | Binary (210 ns) | 1.38x | -| two_scale | sorted_uniform | 262144 | 16 | 165.1 μs | 1.1 μs | 820 ns | 2.0 μs | 870 ns | 850 ns | 810 ns | ExpFromLeft (820 ns) | 1.04x | -| two_scale | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| two_scale | unsorted | 1024 | 16 | 430 ns | 430 ns | 420 ns | 430 ns | 430 ns | 440 ns | 420 ns | ExpFromLeft (420 ns) | 1.05x | -| two_scale | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 180 ns | 180 ns | 180 ns | 159 ns | ExpFromLeft (170 ns) | 1.06x | -| two_scale | unsorted | 16384 | 16 | 570 ns | 560 ns | 570 ns | 580 ns | 580 ns | 580 ns | 560 ns | Gallop (560 ns) | 1.04x | -| two_scale | unsorted | 262144 | 1 | 90 ns | 80 ns | 90 ns | 120 ns | 80 ns | 80 ns | 70 ns | Binary (80 ns) | 1.00x | -| two_scale | unsorted | 262144 | 4 | 220 ns | 210 ns | 210 ns | 210 ns | 210 ns | 230 ns | 210 ns | InterpSearch (210 ns) | 1.10x | -| two_scale | unsorted | 262144 | 16 | 810 ns | 830 ns | 830 ns | 830 ns | 840 ns | 840 ns | 850 ns | Linear (810 ns) | 1.04x | -| power2 | sorted_uniform | 1024 | 1 | 60 ns | 70 ns | 60 ns | 100 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| power2 | sorted_uniform | 1024 | 4 | 1.1 μs | 200 ns | 160 ns | 260 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| power2 | sorted_uniform | 1024 | 16 | 1.7 μs | 590 ns | 460 ns | 1.0 μs | 450 ns | 480 ns | 410 ns | Binary (450 ns) | 1.07x | -| power2 | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_uniform | 16384 | 4 | 11.2 μs | 250 ns | 200 ns | 360 ns | 170 ns | 230 ns | 170 ns | Binary (170 ns) | 1.35x | -| power2 | sorted_uniform | 16384 | 16 | 22.2 μs | 840 ns | 630 ns | 1.5 μs | 600 ns | 670 ns | 640 ns | Binary (600 ns) | 1.12x | -| power2 | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| power2 | sorted_uniform | 262144 | 4 | 257.5 μs | 340 ns | 260 ns | 450 ns | 220 ns | 290 ns | 200 ns | Binary (220 ns) | 1.32x | -| power2 | sorted_uniform | 262144 | 16 | 333.8 μs | 1.2 μs | 870 ns | 2.0 μs | 800 ns | 900 ns | 800 ns | Binary (800 ns) | 1.12x | -| power2 | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | unsorted | 1024 | 4 | 150 ns | 140 ns | 150 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| power2 | unsorted | 1024 | 16 | 430 ns | 430 ns | 430 ns | 420 ns | 429 ns | 440 ns | 400 ns | InterpSearch (420 ns) | 1.05x | -| power2 | unsorted | 16384 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | unsorted | 16384 | 4 | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | ExpFromLeft (170 ns) | 1.06x | -| power2 | unsorted | 16384 | 16 | 610 ns | 610 ns | 600 ns | 600 ns | 600 ns | 610 ns | 560 ns | InterpSearch (600 ns) | 1.02x | -| power2 | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| power2 | unsorted | 262144 | 4 | 210 ns | 220 ns | 210 ns | 220 ns | 220 ns | 220 ns | 210 ns | ExpFromLeft (210 ns) | 1.05x | -| power2 | unsorted | 262144 | 16 | 820 ns | 820 ns | 810 ns | 840 ns | 820 ns | 830 ns | 810 ns | ExpFromLeft (810 ns) | 1.02x | -| sqrt | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_uniform | 1024 | 4 | 1.5 μs | 190 ns | 160 ns | 270 ns | 130 ns | 190 ns | 130 ns | Binary (130 ns) | 1.46x | -| sqrt | sorted_uniform | 1024 | 16 | 1.5 μs | 570 ns | 430 ns | 1.0 μs | 480 ns | 460 ns | 410 ns | ExpFromLeft (430 ns) | 1.07x | -| sqrt | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_uniform | 16384 | 4 | 12.5 μs | 260 ns | 200 ns | 340 ns | 180 ns | 240 ns | 160 ns | Binary (180 ns) | 1.33x | -| sqrt | sorted_uniform | 16384 | 16 | 24.3 μs | 820 ns | 600 ns | 1.4 μs | 580 ns | 630 ns | 560 ns | Binary (580 ns) | 1.09x | -| sqrt | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 90 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | sorted_uniform | 262144 | 4 | 295.8 μs | 340 ns | 260 ns | 440 ns | 220 ns | 290 ns | 200 ns | Binary (220 ns) | 1.32x | -| sqrt | sorted_uniform | 262144 | 16 | 374.1 μs | 1.2 μs | 870 ns | 1.9 μs | 870 ns | 880 ns | 840 ns | ExpFromLeft (870 ns) | 1.01x | -| sqrt | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| sqrt | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 120 ns | InterpSearch (140 ns) | 1.07x | -| sqrt | unsorted | 1024 | 16 | 440 ns | 430 ns | 420 ns | 430 ns | 430 ns | 420 ns | 420 ns | ExpFromLeft (420 ns) | 1.00x | -| sqrt | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 180 ns | 170 ns | 180 ns | 160 ns | ExpFromLeft (170 ns) | 1.06x | -| sqrt | unsorted | 16384 | 16 | 570 ns | 570 ns | 560 ns | 580 ns | 580 ns | 590 ns | 560 ns | ExpFromLeft (560 ns) | 1.05x | -| sqrt | unsorted | 262144 | 1 | 90 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | unsorted | 262144 | 4 | 235.1 μs | 310 ns | 240 ns | 430 ns | 210 ns | 280 ns | 200 ns | Binary (210 ns) | 1.33x | -| sqrt | unsorted | 262144 | 16 | 790 ns | 780 ns | 790 ns | 790 ns | 790 ns | 810 ns | 770 ns | Gallop (780 ns) | 1.04x | -| plateau | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 70 ns | 110 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| plateau | sorted_uniform | 1024 | 4 | 90 ns | 110 ns | 100 ns | 280 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | -| plateau | sorted_uniform | 1024 | 16 | 680 ns | 310 ns | 250 ns | 960 ns | 470 ns | 270 ns | 440 ns | ExpFromLeft (250 ns) | 1.08x | -| plateau | sorted_uniform | 16384 | 1 | 70 ns | 80 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_uniform | 16384 | 4 | 7.7 μs | 170 ns | 150 ns | 340 ns | 170 ns | 180 ns | 160 ns | ExpFromLeft (150 ns) | 1.20x | -| plateau | sorted_uniform | 16384 | 16 | 7.9 μs | 340 ns | 270 ns | 1.3 μs | 630 ns | 290 ns | 600 ns | ExpFromLeft (270 ns) | 1.07x | -| plateau | sorted_uniform | 262144 | 1 | 90 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| plateau | sorted_uniform | 262144 | 4 | 122.1 μs | 200 ns | 170 ns | 430 ns | 210 ns | 200 ns | 200 ns | ExpFromLeft (170 ns) | 1.18x | -| plateau | sorted_uniform | 262144 | 16 | 123.4 μs | 370 ns | 290 ns | 1.7 μs | 760 ns | 320 ns | 740 ns | ExpFromLeft (290 ns) | 1.10x | -| plateau | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 110 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 150 ns | 140 ns | 150 ns | 130 ns | ExpFromLeft (140 ns) | 1.07x | -| plateau | unsorted | 1024 | 16 | 480 ns | 480 ns | 480 ns | 480 ns | 480 ns | 490 ns | 470 ns | InterpSearch (480 ns) | 1.02x | -| plateau | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 100 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | unsorted | 16384 | 4 | 7.9 μs | 170 ns | 150 ns | 370 ns | 170 ns | 180 ns | 170 ns | ExpFromLeft (150 ns) | 1.20x | -| plateau | unsorted | 16384 | 16 | 650 ns | 660 ns | 650 ns | 650 ns | 650 ns | 660 ns | 640 ns | InterpSearch (650 ns) | 1.02x | -| plateau | unsorted | 262144 | 1 | 90 ns | 80 ns | 90 ns | 140 ns | 80 ns | 80 ns | 80 ns | Binary (80 ns) | 1.00x | -| plateau | unsorted | 262144 | 4 | 220 ns | 220 ns | 220 ns | 220 ns | 210 ns | 230 ns | 200 ns | Binary (210 ns) | 1.10x | -| plateau | unsorted | 262144 | 16 | 830 ns | 830 ns | 830 ns | 830 ns | 830 ns | 840 ns | 820 ns | InterpSearch (830 ns) | 1.01x | -| bimodal | sorted_uniform | 1024 | 1 | 69 ns | 60 ns | 60 ns | 100 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| bimodal | sorted_uniform | 1024 | 4 | 90 ns | 110 ns | 100 ns | 270 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | -| bimodal | sorted_uniform | 1024 | 16 | 730 ns | 350 ns | 260 ns | 1.0 μs | 470 ns | 290 ns | 440 ns | ExpFromLeft (260 ns) | 1.12x | -| bimodal | sorted_uniform | 16384 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | -| bimodal | sorted_uniform | 16384 | 4 | 100 ns | 120 ns | 110 ns | 370 ns | 180 ns | 130 ns | 160 ns | Linear (100 ns) | 1.30x | -| bimodal | sorted_uniform | 16384 | 16 | 17.2 μs | 510 ns | 380 ns | 1.4 μs | 610 ns | 420 ns | 570 ns | ExpFromLeft (380 ns) | 1.11x | -| bimodal | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 150 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| bimodal | sorted_uniform | 262144 | 4 | 59.8 μs | 200 ns | 160 ns | 450 ns | 220 ns | 200 ns | 200 ns | ExpFromLeft (160 ns) | 1.25x | -| bimodal | sorted_uniform | 262144 | 16 | 292.9 μs | 630 ns | 470 ns | 1.7 μs | 780 ns | 510 ns | 730 ns | ExpFromLeft (470 ns) | 1.09x | -| bimodal | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 70 ns | 70 ns | ExpFromLeft (60 ns) | 1.17x | -| bimodal | unsorted | 1024 | 4 | 140 ns | 130 ns | 140 ns | 140 ns | 140 ns | 140 ns | 120 ns | Gallop (130 ns) | 1.08x | -| bimodal | unsorted | 1024 | 16 | 470 ns | 470 ns | 589 ns | 580 ns | 580 ns | 470 ns | 450 ns | Gallop (470 ns) | 1.00x | -| bimodal | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | unsorted | 16384 | 4 | 100 ns | 120 ns | 100 ns | 360 ns | 180 ns | 130 ns | 160 ns | ExpFromLeft (100 ns) | 1.30x | -| bimodal | unsorted | 16384 | 16 | 610 ns | 599 ns | 610 ns | 590 ns | 600 ns | 610 ns | 600 ns | InterpSearch (590 ns) | 1.03x | -| bimodal | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| bimodal | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 200 ns | 200 ns | 220 ns | 200 ns | InterpSearch (200 ns) | 1.10x | -| bimodal | unsorted | 262144 | 16 | 760 ns | 750 ns | 750 ns | 760 ns | 740 ns | 760 ns | 730 ns | Binary (740 ns) | 1.03x | -| near_linear | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| near_linear | sorted_uniform | 1024 | 4 | 1.6 μs | 220 ns | 170 ns | 160 ns | 140 ns | 180 ns | 130 ns | Binary (140 ns) | 1.29x | -| near_linear | sorted_uniform | 1024 | 16 | 1.7 μs | 610 ns | 590 ns | 490 ns | 450 ns | 490 ns | 410 ns | Binary (450 ns) | 1.09x | -| near_linear | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_uniform | 16384 | 4 | 3.9 μs | 230 ns | 180 ns | 160 ns | 180 ns | 180 ns | 160 ns | InterpSearch (160 ns) | 1.12x | -| near_linear | sorted_uniform | 16384 | 16 | 21.9 μs | 880 ns | 640 ns | 500 ns | 590 ns | 520 ns | 550 ns | InterpSearch (500 ns) | 1.04x | -| near_linear | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | sorted_uniform | 262144 | 4 | 231.0 μs | 320 ns | 250 ns | 160 ns | 210 ns | 180 ns | 210 ns | InterpSearch (160 ns) | 1.12x | -| near_linear | sorted_uniform | 262144 | 16 | 355.2 μs | 1.2 μs | 830 ns | 520 ns | 810 ns | 550 ns | 770 ns | InterpSearch (520 ns) | 1.06x | -| near_linear | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | unsorted | 1024 | 4 | 140 ns | 130 ns | 130 ns | 140 ns | 140 ns | 150 ns | 120 ns | ExpFromLeft (130 ns) | 1.15x | -| near_linear | unsorted | 1024 | 16 | 430 ns | 420 ns | 410 ns | 430 ns | 420 ns | 430 ns | 410 ns | ExpFromLeft (410 ns) | 1.05x | -| near_linear | unsorted | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | unsorted | 16384 | 4 | 180 ns | 179 ns | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | ExpFromLeft (170 ns) | 1.06x | -| near_linear | unsorted | 16384 | 16 | 570 ns | 560 ns | 560 ns | 570 ns | 570 ns | 580 ns | 560 ns | ExpFromLeft (560 ns) | 1.04x | -| near_linear | unsorted | 262144 | 1 | 80 ns | 100 ns | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | unsorted | 262144 | 4 | 220 ns | 210 ns | 210 ns | 210 ns | 210 ns | 220 ns | 200 ns | InterpSearch (210 ns) | 1.05x | -| near_linear | unsorted | 262144 | 16 | 860 ns | 850 ns | 870 ns | 880 ns | 880 ns | 870 ns | 850 ns | Gallop (850 ns) | 1.02x | +| uniform | sorted_uniform | 1024 | 1 | 60 ns | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| uniform | sorted_uniform | 1024 | 4 | 500 ns | 160 ns | 140 ns | 150 ns | 140 ns | 200 ns | 130 ns | ExpFromLeft (140 ns) | 1.43x | +| uniform | sorted_uniform | 1024 | 16 | 1.6 μs | 570 ns | 470 ns | 500 ns | 450 ns | 480 ns | 409 ns | Binary (450 ns) | 1.07x | +| uniform | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_uniform | 16384 | 4 | 8.9 μs | 240 ns | 190 ns | 150 ns | 170 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | +| uniform | sorted_uniform | 16384 | 16 | 22.9 μs | 880 ns | 650 ns | 520 ns | 610 ns | 590 ns | 560 ns | InterpSearch (520 ns) | 1.13x | +| uniform | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_uniform | 262144 | 4 | 251.7 μs | 350 ns | 260 ns | 150 ns | 210 ns | 200 ns | 200 ns | InterpSearch (150 ns) | 1.33x | +| uniform | sorted_uniform | 262144 | 16 | 369.6 μs | 1.2 μs | 890 ns | 470 ns | 810 ns | 550 ns | 780 ns | InterpSearch (470 ns) | 1.17x | +| uniform | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | +| uniform | unsorted | 1024 | 4 | 130 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | Linear (130 ns) | 1.15x | +| uniform | unsorted | 1024 | 16 | 450 ns | 450 ns | 450 ns | 450 ns | 460 ns | 460 ns | 450 ns | InterpSearch (450 ns) | 1.02x | +| uniform | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 60 ns | 80 ns | 70 ns | 70 ns | InterpSearch (60 ns) | 1.17x | +| uniform | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 180 ns | 180 ns | 190 ns | 170 ns | Gallop (170 ns) | 1.12x | +| uniform | unsorted | 16384 | 16 | 560 ns | 570 ns | 570 ns | 570 ns | 570 ns | 580 ns | 550 ns | Linear (560 ns) | 1.04x | +| uniform | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 210 ns | 220 ns | 220 ns | 200 ns | InterpSearch (210 ns) | 1.05x | +| uniform | unsorted | 262144 | 16 | 760 ns | 760 ns | 760 ns | 770 ns | 760 ns | 760 ns | 740 ns | ExpFromLeft (760 ns) | 1.00x | +| log | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | +| log | sorted_uniform | 1024 | 4 | 200 ns | 150 ns | 130 ns | 300 ns | 140 ns | 160 ns | 130 ns | ExpFromLeft (130 ns) | 1.23x | +| log | sorted_uniform | 1024 | 16 | 1.2 μs | 490 ns | 379 ns | 980 ns | 450 ns | 400 ns | 420 ns | ExpFromLeft (379 ns) | 1.06x | +| log | sorted_uniform | 16384 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_uniform | 16384 | 4 | 2.2 μs | 210 ns | 170 ns | 350 ns | 180 ns | 200 ns | 160 ns | ExpFromLeft (170 ns) | 1.18x | +| log | sorted_uniform | 16384 | 16 | 14.5 μs | 770 ns | 570 ns | 1.3 μs | 600 ns | 590 ns | 600 ns | ExpFromLeft (570 ns) | 1.04x | +| log | sorted_uniform | 262144 | 1 | 90 ns | 90 ns | 80 ns | 140 ns | 80 ns | 90 ns | 80 ns | ExpFromLeft (80 ns) | 1.12x | +| log | sorted_uniform | 262144 | 4 | 321.5 μs | 340 ns | 260 ns | 420 ns | 220 ns | 300 ns | 200 ns | Binary (220 ns) | 1.36x | +| log | sorted_uniform | 262144 | 16 | 176.3 μs | 1.1 μs | 790 ns | 1.7 μs | 810 ns | 800 ns | 820 ns | ExpFromLeft (790 ns) | 1.01x | +| log | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 100 ns | 60 ns | 70 ns | 60 ns | Binary (60 ns) | 1.17x | +| log | unsorted | 1024 | 4 | 130 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | Linear (130 ns) | 1.15x | +| log | unsorted | 1024 | 16 | 410 ns | 420 ns | 410 ns | 420 ns | 420 ns | 440 ns | 420 ns | ExpFromLeft (410 ns) | 1.07x | +| log | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 120 ns | 70 ns | 70 ns | 60 ns | Binary (70 ns) | 1.00x | +| log | unsorted | 16384 | 4 | 170 ns | 180 ns | 170 ns | 170 ns | 170 ns | 180 ns | 160 ns | InterpSearch (170 ns) | 1.06x | +| log | unsorted | 16384 | 16 | 620 ns | 630 ns | 620 ns | 620 ns | 630 ns | 630 ns | 610 ns | InterpSearch (620 ns) | 1.02x | +| log | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 140 ns | 90 ns | 80 ns | 80 ns | Gallop (80 ns) | 1.00x | +| log | unsorted | 262144 | 4 | 210 ns | 220 ns | 210 ns | 210 ns | 210 ns | 220 ns | 200 ns | InterpSearch (210 ns) | 1.05x | +| log | unsorted | 262144 | 16 | 770 ns | 770 ns | 780 ns | 780 ns | 780 ns | 800 ns | 710 ns | Gallop (770 ns) | 1.04x | +| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| jittered | sorted_uniform | 1024 | 4 | 920 ns | 190 ns | 170 ns | 150 ns | 150 ns | 200 ns | 130 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_uniform | 1024 | 16 | 1.9 μs | 610 ns | 470 ns | 470 ns | 460 ns | 559 ns | 420 ns | Binary (460 ns) | 1.22x | +| jittered | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 60 ns | 80 ns | 70 ns | 70 ns | InterpSearch (60 ns) | 1.17x | +| jittered | sorted_uniform | 16384 | 4 | 18.7 μs | 250 ns | 200 ns | 150 ns | 170 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_uniform | 16384 | 16 | 21.2 μs | 870 ns | 660 ns | 460 ns | 590 ns | 540 ns | 550 ns | InterpSearch (460 ns) | 1.17x | +| jittered | sorted_uniform | 262144 | 1 | 90 ns | 80 ns | 90 ns | 70 ns | 90 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_uniform | 262144 | 4 | 316.0 μs | 310 ns | 240 ns | 150 ns | 220 ns | 200 ns | 210 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_uniform | 262144 | 16 | 340.2 μs | 1.2 μs | 870 ns | 500 ns | 800 ns | 580 ns | 790 ns | InterpSearch (500 ns) | 1.16x | +| jittered | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | +| jittered | unsorted | 1024 | 4 | 130 ns | 140 ns | 130 ns | 140 ns | 140 ns | 140 ns | 130 ns | ExpFromLeft (130 ns) | 1.08x | +| jittered | unsorted | 1024 | 16 | 420 ns | 429 ns | 420 ns | 420 ns | 420 ns | 430 ns | 400 ns | InterpSearch (420 ns) | 1.02x | +| jittered | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | unsorted | 16384 | 4 | 170 ns | 170 ns | 180 ns | 180 ns | 170 ns | 190 ns | 170 ns | Binary (170 ns) | 1.12x | +| jittered | unsorted | 16384 | 16 | 570 ns | 570 ns | 570 ns | 570 ns | 570 ns | 580 ns | 550 ns | InterpSearch (570 ns) | 1.02x | +| jittered | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 80 ns | InterpSearch (60 ns) | 1.33x | +| jittered | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 210 ns | 220 ns | 220 ns | 210 ns | InterpSearch (210 ns) | 1.05x | +| jittered | unsorted | 262144 | 16 | 780 ns | 850 ns | 790 ns | 800 ns | 800 ns | 810 ns | 780 ns | Linear (780 ns) | 1.04x | +| random | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_uniform | 1024 | 4 | 930 ns | 180 ns | 160 ns | 200 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | +| random | sorted_uniform | 1024 | 16 | 1.8 μs | 600 ns | 470 ns | 640 ns | 460 ns | 490 ns | 420 ns | Binary (460 ns) | 1.07x | +| random | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_uniform | 16384 | 4 | 16.4 μs | 250 ns | 190 ns | 210 ns | 180 ns | 230 ns | 170 ns | Binary (180 ns) | 1.28x | +| random | sorted_uniform | 16384 | 16 | 19.8 μs | 890 ns | 670 ns | 700 ns | 600 ns | 680 ns | 600 ns | Binary (600 ns) | 1.13x | +| random | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 90 ns | 80 ns | ExpFromLeft (80 ns) | 1.12x | +| random | sorted_uniform | 262144 | 4 | 226.2 μs | 340 ns | 270 ns | 250 ns | 220 ns | 300 ns | 210 ns | Binary (220 ns) | 1.36x | +| random | sorted_uniform | 262144 | 16 | 275.5 μs | 1.2 μs | 850 ns | 860 ns | 830 ns | 940 ns | 780 ns | Binary (830 ns) | 1.13x | +| random | unsorted | 1024 | 1 | 60 ns | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| random | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 150 ns | 140 ns | 150 ns | 130 ns | ExpFromLeft (140 ns) | 1.07x | +| random | unsorted | 1024 | 16 | 410 ns | 410 ns | 420 ns | 420 ns | 420 ns | 430 ns | 410 ns | Gallop (410 ns) | 1.05x | +| random | unsorted | 16384 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| random | unsorted | 16384 | 4 | 170 ns | 170 ns | 170 ns | 170 ns | 180 ns | 190 ns | 170 ns | InterpSearch (170 ns) | 1.12x | +| random | unsorted | 16384 | 16 | 580 ns | 580 ns | 580 ns | 580 ns | 570 ns | 590 ns | 560 ns | Binary (570 ns) | 1.04x | +| random | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| random | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 210 ns | 210 ns | 220 ns | 210 ns | InterpSearch (210 ns) | 1.05x | +| random | unsorted | 262144 | 16 | 810 ns | 820 ns | 800 ns | 810 ns | 810 ns | 820 ns | 800 ns | ExpFromLeft (800 ns) | 1.02x | +| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| two_scale | sorted_uniform | 1024 | 4 | 570 ns | 170 ns | 140 ns | 270 ns | 150 ns | 170 ns | 130 ns | ExpFromLeft (140 ns) | 1.21x | +| two_scale | sorted_uniform | 1024 | 16 | 1.0 μs | 540 ns | 420 ns | 990 ns | 450 ns | 450 ns | 410 ns | ExpFromLeft (420 ns) | 1.07x | +| two_scale | sorted_uniform | 16384 | 1 | 70 ns | 80 ns | 70 ns | 120 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| two_scale | sorted_uniform | 16384 | 4 | 9.5 μs | 250 ns | 190 ns | 360 ns | 180 ns | 220 ns | 160 ns | Binary (180 ns) | 1.22x | +| two_scale | sorted_uniform | 16384 | 16 | 9.9 μs | 780 ns | 580 ns | 1.4 μs | 609 ns | 630 ns | 570 ns | ExpFromLeft (580 ns) | 1.09x | +| two_scale | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 150 ns | 80 ns | 90 ns | 70 ns | ExpFromLeft (80 ns) | 1.12x | +| two_scale | sorted_uniform | 262144 | 4 | 153.9 μs | 330 ns | 250 ns | 440 ns | 220 ns | 290 ns | 210 ns | Binary (220 ns) | 1.32x | +| two_scale | sorted_uniform | 262144 | 16 | 170.9 μs | 1.1 μs | 810 ns | 1.7 μs | 820 ns | 840 ns | 780 ns | ExpFromLeft (810 ns) | 1.04x | +| two_scale | unsorted | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | +| two_scale | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 120 ns | InterpSearch (140 ns) | 1.07x | +| two_scale | unsorted | 1024 | 16 | 420 ns | 430 ns | 430 ns | 420 ns | 430 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | +| two_scale | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| two_scale | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 170 ns | 180 ns | 190 ns | 170 ns | InterpSearch (170 ns) | 1.12x | +| two_scale | unsorted | 16384 | 16 | 579 ns | 580 ns | 580 ns | 580 ns | 590 ns | 590 ns | 580 ns | Linear (579 ns) | 1.02x | +| two_scale | unsorted | 262144 | 1 | 90 ns | 80 ns | 90 ns | 120 ns | 80 ns | 90 ns | 80 ns | Binary (80 ns) | 1.12x | +| two_scale | unsorted | 262144 | 4 | 220 ns | 210 ns | 220 ns | 210 ns | 220 ns | 230 ns | 200 ns | InterpSearch (210 ns) | 1.10x | +| two_scale | unsorted | 262144 | 16 | 790 ns | 780 ns | 800 ns | 790 ns | 790 ns | 790 ns | 780 ns | Gallop (780 ns) | 1.01x | +| power2 | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | +| power2 | sorted_uniform | 1024 | 4 | 1.1 μs | 190 ns | 160 ns | 260 ns | 150 ns | 190 ns | 130 ns | Binary (150 ns) | 1.27x | +| power2 | sorted_uniform | 1024 | 16 | 1.7 μs | 580 ns | 470 ns | 930 ns | 450 ns | 490 ns | 420 ns | Binary (450 ns) | 1.09x | +| power2 | sorted_uniform | 16384 | 1 | 70 ns | 80 ns | 70 ns | 120 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_uniform | 16384 | 4 | 11.1 μs | 250 ns | 210 ns | 350 ns | 170 ns | 230 ns | 160 ns | Binary (170 ns) | 1.35x | +| power2 | sorted_uniform | 16384 | 16 | 22.5 μs | 840 ns | 630 ns | 1.3 μs | 609 ns | 670 ns | 630 ns | Binary (609 ns) | 1.10x | +| power2 | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 90 ns | 90 ns | 80 ns | ExpFromLeft (80 ns) | 1.12x | +| power2 | sorted_uniform | 262144 | 4 | 264.8 μs | 340 ns | 260 ns | 440 ns | 220 ns | 290 ns | 200 ns | Binary (220 ns) | 1.32x | +| power2 | sorted_uniform | 262144 | 16 | 342.8 μs | 1.3 μs | 910 ns | 1.7 μs | 840 ns | 960 ns | 800 ns | Binary (840 ns) | 1.14x | +| power2 | unsorted | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| power2 | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| power2 | unsorted | 1024 | 16 | 420 ns | 420 ns | 430 ns | 410 ns | 430 ns | 430 ns | 450 ns | InterpSearch (410 ns) | 1.05x | +| power2 | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | unsorted | 16384 | 4 | 170 ns | 180 ns | 180 ns | 180 ns | 180 ns | 190 ns | 170 ns | Linear (170 ns) | 1.12x | +| power2 | unsorted | 16384 | 16 | 570 ns | 570 ns | 580 ns | 580 ns | 580 ns | 600 ns | 570 ns | Gallop (570 ns) | 1.05x | +| power2 | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 140 ns | 80 ns | 90 ns | 80 ns | Binary (80 ns) | 1.12x | +| power2 | unsorted | 262144 | 4 | 230 ns | 210 ns | 210 ns | 220 ns | 220 ns | 230 ns | 210 ns | ExpFromLeft (210 ns) | 1.10x | +| power2 | unsorted | 262144 | 16 | 760 ns | 770 ns | 780 ns | 780 ns | 790 ns | 770 ns | 770 ns | Linear (760 ns) | 1.01x | +| sqrt | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| sqrt | sorted_uniform | 1024 | 4 | 1.5 μs | 190 ns | 160 ns | 260 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | +| sqrt | sorted_uniform | 1024 | 16 | 1.5 μs | 560 ns | 450 ns | 940 ns | 450 ns | 470 ns | 410 ns | ExpFromLeft (450 ns) | 1.04x | +| sqrt | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 80 ns | 110 ns | 70 ns | 80 ns | 70 ns | Binary (70 ns) | 1.14x | +| sqrt | sorted_uniform | 16384 | 4 | 12.8 μs | 260 ns | 210 ns | 340 ns | 180 ns | 240 ns | 160 ns | Binary (180 ns) | 1.33x | +| sqrt | sorted_uniform | 16384 | 16 | 24.6 μs | 790 ns | 610 ns | 1.2 μs | 590 ns | 640 ns | 560 ns | Binary (590 ns) | 1.08x | +| sqrt | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | sorted_uniform | 262144 | 4 | 310.7 μs | 340 ns | 270 ns | 440 ns | 220 ns | 300 ns | 200 ns | Binary (220 ns) | 1.36x | +| sqrt | sorted_uniform | 262144 | 16 | 386.2 μs | 1.2 μs | 900 ns | 1.6 μs | 810 ns | 920 ns | 760 ns | Binary (810 ns) | 1.14x | +| sqrt | unsorted | 1024 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| sqrt | unsorted | 1024 | 16 | 430 ns | 420 ns | 430 ns | 420 ns | 430 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | +| sqrt | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 120 ns | 80 ns | 70 ns | 60 ns | Gallop (70 ns) | 1.00x | +| sqrt | unsorted | 16384 | 4 | 180 ns | 180 ns | 170 ns | 180 ns | 180 ns | 190 ns | 170 ns | ExpFromLeft (170 ns) | 1.12x | +| sqrt | unsorted | 16384 | 16 | 580 ns | 580 ns | 580 ns | 580 ns | 580 ns | 590 ns | 560 ns | InterpSearch (580 ns) | 1.02x | +| sqrt | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 140 ns | 80 ns | 90 ns | 70 ns | Binary (80 ns) | 1.12x | +| sqrt | unsorted | 262144 | 4 | 243.2 μs | 320 ns | 250 ns | 449 ns | 220 ns | 290 ns | 210 ns | Binary (220 ns) | 1.32x | +| sqrt | unsorted | 262144 | 16 | 790 ns | 810 ns | 790 ns | 780 ns | 780 ns | 800 ns | 770 ns | InterpSearch (780 ns) | 1.03x | +| plateau | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| plateau | sorted_uniform | 1024 | 4 | 90 ns | 100 ns | 90 ns | 270 ns | 150 ns | 120 ns | 130 ns | ExpFromLeft (90 ns) | 1.33x | +| plateau | sorted_uniform | 1024 | 16 | 690 ns | 310 ns | 250 ns | 930 ns | 470 ns | 270 ns | 450 ns | ExpFromLeft (250 ns) | 1.08x | +| plateau | sorted_uniform | 16384 | 1 | 80 ns | 80 ns | 70 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| plateau | sorted_uniform | 16384 | 4 | 7.7 μs | 170 ns | 140 ns | 350 ns | 180 ns | 160 ns | 150 ns | ExpFromLeft (140 ns) | 1.14x | +| plateau | sorted_uniform | 16384 | 16 | 8.1 μs | 340 ns | 270 ns | 1.3 μs | 630 ns | 300 ns | 590 ns | ExpFromLeft (270 ns) | 1.11x | +| plateau | sorted_uniform | 262144 | 1 | 80 ns | 90 ns | 80 ns | 130 ns | 80 ns | 90 ns | 70 ns | ExpFromLeft (80 ns) | 1.12x | +| plateau | sorted_uniform | 262144 | 4 | 119.2 μs | 200 ns | 170 ns | 430 ns | 220 ns | 210 ns | 210 ns | ExpFromLeft (170 ns) | 1.24x | +| plateau | sorted_uniform | 262144 | 16 | 120.9 μs | 370 ns | 290 ns | 1.6 μs | 770 ns | 320 ns | 760 ns | ExpFromLeft (290 ns) | 1.10x | +| plateau | unsorted | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| plateau | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 150 ns | 120 ns | InterpSearch (140 ns) | 1.07x | +| plateau | unsorted | 1024 | 16 | 480 ns | 480 ns | 480 ns | 480 ns | 490 ns | 490 ns | 460 ns | InterpSearch (480 ns) | 1.02x | +| plateau | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| plateau | unsorted | 16384 | 4 | 7.9 μs | 160 ns | 140 ns | 360 ns | 180 ns | 170 ns | 170 ns | ExpFromLeft (140 ns) | 1.21x | +| plateau | unsorted | 16384 | 16 | 640 ns | 640 ns | 650 ns | 660 ns | 650 ns | 649 ns | 640 ns | Gallop (640 ns) | 1.01x | +| plateau | unsorted | 262144 | 1 | 90 ns | 80 ns | 90 ns | 140 ns | 90 ns | 90 ns | 80 ns | Gallop (80 ns) | 1.12x | +| plateau | unsorted | 262144 | 4 | 220 ns | 220 ns | 220 ns | 220 ns | 220 ns | 230 ns | 210 ns | InterpSearch (220 ns) | 1.05x | +| plateau | unsorted | 262144 | 16 | 840 ns | 840 ns | 840 ns | 850 ns | 840 ns | 850 ns | 830 ns | ExpFromLeft (840 ns) | 1.01x | +| bimodal | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 70 ns | 59 ns | ExpFromLeft (60 ns) | 1.17x | +| bimodal | sorted_uniform | 1024 | 4 | 80 ns | 100 ns | 90 ns | 270 ns | 140 ns | 120 ns | 130 ns | Linear (80 ns) | 1.50x | +| bimodal | sorted_uniform | 1024 | 16 | 780 ns | 350 ns | 270 ns | 940 ns | 470 ns | 300 ns | 420 ns | ExpFromLeft (270 ns) | 1.11x | +| bimodal | sorted_uniform | 16384 | 1 | 80 ns | 80 ns | 70 ns | 110 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| bimodal | sorted_uniform | 16384 | 4 | 90 ns | 110 ns | 100 ns | 370 ns | 180 ns | 130 ns | 170 ns | Linear (90 ns) | 1.44x | +| bimodal | sorted_uniform | 16384 | 16 | 16.8 μs | 560 ns | 390 ns | 1.3 μs | 630 ns | 420 ns | 580 ns | ExpFromLeft (390 ns) | 1.08x | +| bimodal | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 90 ns | 140 ns | 90 ns | 90 ns | 80 ns | Gallop (80 ns) | 1.12x | +| bimodal | sorted_uniform | 262144 | 4 | 60.1 μs | 200 ns | 160 ns | 450 ns | 220 ns | 190 ns | 200 ns | ExpFromLeft (160 ns) | 1.19x | +| bimodal | sorted_uniform | 262144 | 16 | 302.6 μs | 659 ns | 490 ns | 1.6 μs | 790 ns | 520 ns | 740 ns | ExpFromLeft (490 ns) | 1.06x | +| bimodal | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 90 ns | 60 ns | 70 ns | 60 ns | Binary (60 ns) | 1.17x | +| bimodal | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| bimodal | unsorted | 1024 | 16 | 460 ns | 470 ns | 470 ns | 470 ns | 480 ns | 480 ns | 460 ns | Linear (460 ns) | 1.04x | +| bimodal | unsorted | 16384 | 1 | 70 ns | 70 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | unsorted | 16384 | 4 | 100 ns | 130 ns | 100 ns | 350 ns | 180 ns | 120 ns | 170 ns | ExpFromLeft (100 ns) | 1.20x | +| bimodal | unsorted | 16384 | 16 | 599 ns | 590 ns | 599 ns | 600 ns | 600 ns | 610 ns | 580 ns | Gallop (590 ns) | 1.03x | +| bimodal | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 120 ns | 90 ns | 90 ns | 80 ns | Gallop (80 ns) | 1.12x | +| bimodal | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 210 ns | 200 ns | 220 ns | 200 ns | Binary (200 ns) | 1.10x | +| bimodal | unsorted | 262144 | 16 | 750 ns | 770 ns | 770 ns | 770 ns | 770 ns | 770 ns | 750 ns | Linear (750 ns) | 1.03x | +| near_linear | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | 70 ns | 50 ns | InterpSearch (60 ns) | 1.17x | +| near_linear | sorted_uniform | 1024 | 4 | 1.6 μs | 220 ns | 170 ns | 150 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| near_linear | sorted_uniform | 1024 | 16 | 1.8 μs | 620 ns | 490 ns | 480 ns | 460 ns | 550 ns | 410 ns | Binary (460 ns) | 1.20x | +| near_linear | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | sorted_uniform | 16384 | 4 | 4.1 μs | 240 ns | 200 ns | 160 ns | 180 ns | 200 ns | 170 ns | InterpSearch (160 ns) | 1.25x | +| near_linear | sorted_uniform | 16384 | 16 | 22.2 μs | 870 ns | 670 ns | 470 ns | 610 ns | 550 ns | 560 ns | InterpSearch (470 ns) | 1.17x | +| near_linear | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 90 ns | 70 ns | 90 ns | 90 ns | 80 ns | InterpSearch (70 ns) | 1.29x | +| near_linear | sorted_uniform | 262144 | 4 | 235.2 μs | 340 ns | 260 ns | 150 ns | 220 ns | 210 ns | 210 ns | InterpSearch (150 ns) | 1.40x | +| near_linear | sorted_uniform | 262144 | 16 | 366.2 μs | 1.2 μs | 860 ns | 500 ns | 820 ns | 580 ns | 770 ns | InterpSearch (500 ns) | 1.16x | +| near_linear | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| near_linear | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| near_linear | unsorted | 1024 | 16 | 420 ns | 420 ns | 420 ns | 430 ns | 430 ns | 430 ns | 400 ns | ExpFromLeft (420 ns) | 1.02x | +| near_linear | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | unsorted | 16384 | 4 | 180 ns | 170 ns | 190 ns | 180 ns | 180 ns | 190 ns | 170 ns | Gallop (170 ns) | 1.12x | +| near_linear | unsorted | 16384 | 16 | 570 ns | 580 ns | 590 ns | 570 ns | 590 ns | 590 ns | 560 ns | InterpSearch (570 ns) | 1.04x | +| near_linear | unsorted | 262144 | 1 | 90 ns | 80 ns | 80 ns | 60 ns | 80 ns | 90 ns | 70 ns | InterpSearch (60 ns) | 1.50x | +| near_linear | unsorted | 262144 | 4 | 220 ns | 220 ns | 210 ns | 220 ns | 220 ns | 230 ns | 210 ns | ExpFromLeft (210 ns) | 1.10x | +| near_linear | unsorted | 262144 | 16 | 810 ns | 780 ns | 800 ns | 800 ns | 800 ns | 800 ns | 820 ns | Gallop (780 ns) | 1.03x | -**Auto verdict over 180 cells**: 156 within 20% of best, 24 worse than 20% slowdown, 0 effectively-faster-than-best. +**Auto verdict over 180 cells**: 147 within 20% of best, 33 worse than 20% slowdown, 0 effectively-faster-than-best. ### Super-dense cases (m ≫ n) @@ -297,275 +297,275 @@ | spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | |---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 64 | 1024 | 8.8 μs | 15.2 μs | 11.7 μs | 31.0 μs | 18.0 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | -| uniform | sorted_uniform | 64 | 4096 | 30.8 μs | 57.3 μs | 43.6 μs | 113.7 μs | 68.6 μs | 32.2 μs | 60.3 μs | Linear (30.8 μs) | 1.04x | -| uniform | sorted_uniform | 64 | 16384 | 118.9 μs | 225.7 μs | 170.6 μs | 445.3 μs | 270.6 μs | 124.2 μs | 237.0 μs | Linear (118.9 μs) | 1.04x | -| uniform | sorted_uniform | 256 | 1024 | 9.9 μs | 18.3 μs | 13.6 μs | 37.9 μs | 30.1 μs | 10.4 μs | 25.5 μs | Linear (9.9 μs) | 1.04x | -| uniform | sorted_uniform | 256 | 4096 | 35.5 μs | 60.7 μs | 47.1 μs | 123.9 μs | 127.5 μs | 36.8 μs | 83.9 μs | Linear (35.5 μs) | 1.04x | -| uniform | sorted_uniform | 256 | 16384 | 123.1 μs | 229.3 μs | 174.2 μs | 455.6 μs | 389.0 μs | 128.5 μs | 317.4 μs | Linear (123.1 μs) | 1.04x | -| uniform | sorted_uniform | 1024 | 1024 | 9.8 μs | 18.2 μs | 12.4 μs | 40.5 μs | 78.9 μs | 10.0 μs | 58.3 μs | Linear (9.8 μs) | 1.03x | -| uniform | sorted_uniform | 1024 | 4096 | 46.5 μs | 74.5 μs | 57.8 μs | 154.5 μs | 242.3 μs | 47.8 μs | 191.2 μs | Linear (46.5 μs) | 1.03x | -| uniform | sorted_uniform | 1024 | 16384 | 142.0 μs | 242.9 μs | 188.2 μs | 502.1 μs | 594.0 μs | 147.3 μs | 485.5 μs | Linear (142.0 μs) | 1.04x | -| uniform | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.7 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | -| uniform | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.1 μs | 42.2 μs | 110.4 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.5 μs) | 1.04x | -| uniform | sorted_dense_burst | 64 | 16384 | 117.5 μs | 224.5 μs | 169.0 μs | 441.8 μs | 271.6 μs | 122.9 μs | 227.4 μs | Linear (117.5 μs) | 1.05x | -| uniform | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.7 μs | 21.9 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.05x | -| uniform | sorted_dense_burst | 256 | 4096 | 29.5 μs | 56.3 μs | 42.2 μs | 110.6 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.5 μs) | 1.04x | -| uniform | sorted_dense_burst | 256 | 16384 | 117.6 μs | 224.8 μs | 168.7 μs | 442.3 μs | 349.3 μs | 123.5 μs | 305.9 μs | Linear (117.6 μs) | 1.05x | -| uniform | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.2 μs | 10.6 μs | 27.8 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | -| uniform | sorted_dense_burst | 1024 | 4096 | 29.4 μs | 56.3 μs | 42.2 μs | 110.5 μs | 106.8 μs | 30.9 μs | 95.7 μs | Linear (29.4 μs) | 1.05x | -| uniform | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 225.4 μs | 169.1 μs | 441.8 μs | 427.3 μs | 122.9 μs | 382.9 μs | Linear (117.5 μs) | 1.05x | -| uniform | unsorted | 64 | 1024 | 43.1 μs | 42.0 μs | 42.1 μs | 42.0 μs | 41.7 μs | 41.2 μs | 42.8 μs | Binary (41.7 μs) | 0.99x | -| uniform | unsorted | 64 | 4096 | 235.4 μs | 231.5 μs | 229.8 μs | 229.0 μs | 229.8 μs | 229.4 μs | 238.7 μs | InterpSearch (229.0 μs) | 1.00x | -| uniform | unsorted | 64 | 16384 | 982.2 μs | 981.8 μs | 982.9 μs | 982.1 μs | 981.7 μs | 984.4 μs | 981.4 μs | Binary (981.7 μs) | 1.00x | -| uniform | unsorted | 256 | 1024 | 60.3 μs | 56.0 μs | 55.4 μs | 55.2 μs | 54.8 μs | 54.5 μs | 58.9 μs | Binary (54.8 μs) | 1.00x | -| uniform | unsorted | 256 | 4096 | 317.1 μs | 314.1 μs | 311.7 μs | 311.0 μs | 312.4 μs | 310.5 μs | 317.6 μs | InterpSearch (311.0 μs) | 1.00x | -| uniform | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.29 ms | 1.31 ms | ExpFromLeft (1.30 ms) | 1.00x | -| uniform | unsorted | 1024 | 1024 | 82.3 μs | 81.2 μs | 80.5 μs | 79.9 μs | 79.6 μs | 79.2 μs | 86.1 μs | Binary (79.6 μs) | 1.00x | -| uniform | unsorted | 1024 | 4096 | 407.8 μs | 407.7 μs | 406.7 μs | 405.7 μs | 405.7 μs | 405.0 μs | 408.8 μs | InterpSearch (405.7 μs) | 1.00x | -| uniform | unsorted | 1024 | 16384 | 1.67 ms | 1.68 ms | 1.68 ms | 1.68 ms | 1.68 ms | 1.67 ms | 1.69 ms | Linear (1.67 ms) | 1.00x | -| log | sorted_uniform | 64 | 1024 | 8.0 μs | 14.5 μs | 11.2 μs | 47.8 μs | 17.5 μs | 8.4 μs | 15.8 μs | Linear (8.0 μs) | 1.05x | -| log | sorted_uniform | 64 | 4096 | 30.2 μs | 56.4 μs | 43.1 μs | 177.8 μs | 69.1 μs | 31.6 μs | 60.9 μs | Linear (30.2 μs) | 1.04x | -| log | sorted_uniform | 64 | 16384 | 118.8 μs | 223.3 μs | 170.3 μs | 690.8 μs | 274.9 μs | 123.8 μs | 241.0 μs | Linear (118.8 μs) | 1.04x | -| log | sorted_uniform | 256 | 1024 | 9.1 μs | 15.6 μs | 12.0 μs | 66.2 μs | 23.1 μs | 9.4 μs | 22.0 μs | Linear (9.1 μs) | 1.04x | -| log | sorted_uniform | 256 | 4096 | 32.1 μs | 58.5 μs | 44.6 μs | 237.5 μs | 91.5 μs | 33.4 μs | 82.2 μs | Linear (32.1 μs) | 1.04x | -| log | sorted_uniform | 256 | 16384 | 121.4 μs | 227.5 μs | 172.7 μs | 873.8 μs | 363.4 μs | 126.7 μs | 319.0 μs | Linear (121.4 μs) | 1.04x | -| log | sorted_uniform | 1024 | 1024 | 10.4 μs | 18.0 μs | 13.1 μs | 86.9 μs | 41.4 μs | 10.6 μs | 33.1 μs | Linear (10.4 μs) | 1.02x | -| log | sorted_uniform | 1024 | 4096 | 37.2 μs | 63.5 μs | 48.4 μs | 314.2 μs | 171.2 μs | 38.5 μs | 124.9 μs | Linear (37.2 μs) | 1.03x | -| log | sorted_uniform | 1024 | 16384 | 129.9 μs | 235.8 μs | 179.3 μs | 1.11 ms | 535.8 μs | 135.2 μs | 450.1 μs | Linear (129.9 μs) | 1.04x | -| log | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 45.2 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | -| log | sorted_dense_burst | 64 | 4096 | 29.4 μs | 56.1 μs | 42.0 μs | 180.8 μs | 67.9 μs | 30.8 μs | 56.7 μs | Linear (29.4 μs) | 1.05x | -| log | sorted_dense_burst | 64 | 16384 | 118.2 μs | 224.4 μs | 169.1 μs | 722.9 μs | 271.5 μs | 123.0 μs | 227.1 μs | Linear (118.2 μs) | 1.04x | -| log | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 58.7 μs | 21.8 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.05x | -| log | sorted_dense_burst | 256 | 4096 | 29.4 μs | 56.3 μs | 42.3 μs | 234.8 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.4 μs) | 1.04x | -| log | sorted_dense_burst | 256 | 16384 | 117.5 μs | 224.8 μs | 169.0 μs | 939.6 μs | 349.3 μs | 123.3 μs | 305.8 μs | Linear (117.5 μs) | 1.05x | -| log | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 65.0 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | -| log | sorted_dense_burst | 1024 | 4096 | 29.6 μs | 56.3 μs | 42.3 μs | 260.1 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.6 μs) | 1.04x | -| log | sorted_dense_burst | 1024 | 16384 | 117.6 μs | 224.9 μs | 169.2 μs | 1.04 ms | 427.3 μs | 122.8 μs | 383.0 μs | Linear (117.6 μs) | 1.04x | -| log | unsorted | 64 | 1024 | 35.6 μs | 35.0 μs | 34.6 μs | 34.3 μs | 34.2 μs | 34.5 μs | 35.0 μs | Binary (34.2 μs) | 1.01x | -| log | unsorted | 64 | 4096 | 179.0 μs | 178.0 μs | 178.3 μs | 178.5 μs | 177.5 μs | 177.8 μs | 179.5 μs | Binary (177.5 μs) | 1.00x | -| log | unsorted | 64 | 16384 | 757.7 μs | 758.3 μs | 758.0 μs | 757.5 μs | 756.7 μs | 757.6 μs | 754.8 μs | Binary (756.7 μs) | 1.00x | -| log | unsorted | 256 | 1024 | 51.6 μs | 50.2 μs | 49.6 μs | 49.5 μs | 49.0 μs | 49.0 μs | 50.3 μs | Binary (49.0 μs) | 1.00x | -| log | unsorted | 256 | 4096 | 258.0 μs | 256.8 μs | 257.1 μs | 255.7 μs | 255.5 μs | 255.6 μs | 266.9 μs | Binary (255.5 μs) | 1.00x | -| log | unsorted | 256 | 16384 | 1.09 ms | 1.09 ms | 1.09 ms | 1.09 ms | 1.08 ms | 1.09 ms | 1.09 ms | Binary (1.08 ms) | 1.00x | -| log | unsorted | 1024 | 1024 | 72.5 μs | 71.3 μs | 70.7 μs | 70.2 μs | 70.5 μs | 70.2 μs | 74.4 μs | InterpSearch (70.2 μs) | 1.00x | -| log | unsorted | 1024 | 4096 | 351.1 μs | 349.0 μs | 349.8 μs | 348.5 μs | 349.2 μs | 349.0 μs | 354.3 μs | InterpSearch (348.5 μs) | 1.00x | -| log | unsorted | 1024 | 16384 | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.43 ms | Binary (1.42 ms) | 1.00x | -| jittered | sorted_uniform | 64 | 1024 | 8.8 μs | 15.2 μs | 11.8 μs | 31.0 μs | 18.0 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | -| jittered | sorted_uniform | 64 | 4096 | 30.7 μs | 57.1 μs | 43.6 μs | 113.5 μs | 68.6 μs | 32.1 μs | 60.2 μs | Linear (30.7 μs) | 1.05x | -| jittered | sorted_uniform | 64 | 16384 | 119.2 μs | 225.3 μs | 170.9 μs | 442.7 μs | 270.3 μs | 124.4 μs | 237.2 μs | Linear (119.2 μs) | 1.04x | -| jittered | sorted_uniform | 256 | 1024 | 9.8 μs | 18.2 μs | 13.6 μs | 38.0 μs | 28.1 μs | 10.2 μs | 25.3 μs | Linear (9.8 μs) | 1.03x | -| jittered | sorted_uniform | 256 | 4096 | 35.4 μs | 60.7 μs | 47.1 μs | 124.5 μs | 128.5 μs | 36.8 μs | 83.9 μs | Linear (35.4 μs) | 1.04x | -| jittered | sorted_uniform | 256 | 16384 | 123.3 μs | 229.2 μs | 174.2 μs | 457.4 μs | 391.7 μs | 128.5 μs | 318.2 μs | Linear (123.3 μs) | 1.04x | -| jittered | sorted_uniform | 1024 | 1024 | 10.2 μs | 18.6 μs | 12.4 μs | 38.4 μs | 72.3 μs | 10.8 μs | 53.1 μs | Linear (10.2 μs) | 1.05x | -| jittered | sorted_uniform | 1024 | 4096 | 47.8 μs | 74.9 μs | 57.7 μs | 149.7 μs | 240.2 μs | 48.8 μs | 193.2 μs | Linear (47.8 μs) | 1.02x | -| jittered | sorted_uniform | 1024 | 16384 | 142.0 μs | 242.8 μs | 188.2 μs | 500.1 μs | 597.7 μs | 147.2 μs | 487.3 μs | Linear (142.0 μs) | 1.04x | -| jittered | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.2 μs | 10.6 μs | 28.0 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | -| jittered | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 111.3 μs | 67.9 μs | 30.8 μs | 56.9 μs | Linear (29.5 μs) | 1.04x | -| jittered | sorted_dense_burst | 64 | 16384 | 117.4 μs | 224.8 μs | 168.8 μs | 445.1 μs | 271.6 μs | 122.9 μs | 227.3 μs | Linear (117.4 μs) | 1.05x | -| jittered | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.8 μs | 21.9 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.05x | -| jittered | sorted_dense_burst | 256 | 4096 | 29.5 μs | 56.3 μs | 42.2 μs | 109.9 μs | 87.4 μs | 30.9 μs | 76.5 μs | Linear (29.5 μs) | 1.05x | -| jittered | sorted_dense_burst | 256 | 16384 | 117.6 μs | 224.9 μs | 168.8 μs | 439.1 μs | 349.1 μs | 122.9 μs | 306.0 μs | Linear (117.6 μs) | 1.04x | -| jittered | sorted_dense_burst | 1024 | 1024 | 7.5 μs | 14.1 μs | 10.6 μs | 27.8 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.5 μs) | 1.05x | -| jittered | sorted_dense_burst | 1024 | 4096 | 29.4 μs | 56.3 μs | 42.3 μs | 111.0 μs | 106.8 μs | 30.8 μs | 95.8 μs | Linear (29.4 μs) | 1.05x | -| jittered | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 224.8 μs | 168.8 μs | 444.0 μs | 427.3 μs | 122.8 μs | 383.2 μs | Linear (117.5 μs) | 1.04x | -| jittered | unsorted | 64 | 1024 | 43.2 μs | 41.3 μs | 41.3 μs | 41.2 μs | 41.2 μs | 41.0 μs | 43.2 μs | InterpSearch (41.2 μs) | 0.99x | -| jittered | unsorted | 64 | 4096 | 233.2 μs | 231.6 μs | 231.4 μs | 232.7 μs | 229.2 μs | 230.6 μs | 232.8 μs | Binary (229.2 μs) | 1.01x | -| jittered | unsorted | 64 | 16384 | 979.2 μs | 983.8 μs | 983.2 μs | 983.1 μs | 985.1 μs | 984.7 μs | 983.9 μs | Linear (979.2 μs) | 1.01x | -| jittered | unsorted | 256 | 1024 | 56.8 μs | 55.0 μs | 54.5 μs | 54.2 μs | 54.1 μs | 54.0 μs | 59.5 μs | Binary (54.1 μs) | 1.00x | -| jittered | unsorted | 256 | 4096 | 314.6 μs | 313.8 μs | 312.5 μs | 312.8 μs | 313.5 μs | 310.3 μs | 318.8 μs | ExpFromLeft (312.5 μs) | 0.99x | -| jittered | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.29 ms | 1.31 ms | Gallop (1.30 ms) | 1.00x | -| jittered | unsorted | 1024 | 1024 | 82.4 μs | 79.6 μs | 78.9 μs | 77.4 μs | 78.1 μs | 76.7 μs | 85.3 μs | InterpSearch (77.4 μs) | 0.99x | -| jittered | unsorted | 1024 | 4096 | 408.9 μs | 407.8 μs | 406.1 μs | 406.2 μs | 407.0 μs | 405.6 μs | 409.5 μs | ExpFromLeft (406.1 μs) | 1.00x | -| jittered | unsorted | 1024 | 16384 | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.68 ms | 1.68 ms | Linear (1.67 ms) | 1.00x | -| random | sorted_uniform | 64 | 1024 | 8.8 μs | 15.2 μs | 11.7 μs | 35.4 μs | 17.5 μs | 9.1 μs | 15.9 μs | Linear (8.8 μs) | 1.04x | -| random | sorted_uniform | 64 | 4096 | 30.7 μs | 57.3 μs | 43.5 μs | 129.3 μs | 68.6 μs | 32.1 μs | 60.2 μs | Linear (30.7 μs) | 1.05x | -| random | sorted_uniform | 64 | 16384 | 118.8 μs | 225.2 μs | 170.4 μs | 502.4 μs | 271.0 μs | 124.2 μs | 237.1 μs | Linear (118.8 μs) | 1.04x | -| random | sorted_uniform | 256 | 1024 | 9.2 μs | 17.3 μs | 13.0 μs | 48.2 μs | 24.2 μs | 9.7 μs | 23.8 μs | Linear (9.2 μs) | 1.05x | -| random | sorted_uniform | 256 | 4096 | 34.8 μs | 60.5 μs | 46.6 μs | 169.8 μs | 99.9 μs | 36.1 μs | 83.8 μs | Linear (34.8 μs) | 1.04x | -| random | sorted_uniform | 256 | 16384 | 123.2 μs | 229.2 μs | 174.7 μs | 615.1 μs | 381.5 μs | 128.5 μs | 317.5 μs | Linear (123.2 μs) | 1.04x | -| random | sorted_uniform | 1024 | 1024 | 10.1 μs | 18.0 μs | 12.7 μs | 55.7 μs | 61.1 μs | 10.4 μs | 43.5 μs | Linear (10.1 μs) | 1.03x | -| random | sorted_uniform | 1024 | 4096 | 43.1 μs | 71.6 μs | 54.8 μs | 213.6 μs | 216.7 μs | 44.4 μs | 170.4 μs | Linear (43.1 μs) | 1.03x | -| random | sorted_uniform | 1024 | 16384 | 139.8 μs | 242.6 μs | 187.2 μs | 735.8 μs | 574.2 μs | 145.5 μs | 479.1 μs | Linear (139.8 μs) | 1.04x | -| random | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.5 μs | 29.8 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | -| random | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.1 μs | 42.3 μs | 118.9 μs | 67.9 μs | 30.8 μs | 56.9 μs | Linear (29.5 μs) | 1.05x | -| random | sorted_dense_burst | 64 | 16384 | 117.6 μs | 224.4 μs | 169.1 μs | 476.2 μs | 271.6 μs | 123.0 μs | 227.4 μs | Linear (117.6 μs) | 1.05x | -| random | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 31.9 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | -| random | sorted_dense_burst | 256 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 126.3 μs | 87.2 μs | 30.8 μs | 76.5 μs | Linear (29.5 μs) | 1.05x | -| random | sorted_dense_burst | 256 | 16384 | 117.6 μs | 224.8 μs | 169.6 μs | 505.2 μs | 349.2 μs | 122.8 μs | 306.0 μs | Linear (117.6 μs) | 1.04x | -| random | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 45.6 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.05x | -| random | sorted_dense_burst | 1024 | 4096 | 29.5 μs | 56.3 μs | 42.4 μs | 180.9 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.5 μs) | 1.05x | -| random | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 224.8 μs | 169.1 μs | 723.2 μs | 427.3 μs | 122.9 μs | 383.2 μs | Linear (117.5 μs) | 1.05x | -| random | unsorted | 64 | 1024 | 36.2 μs | 35.4 μs | 35.3 μs | 35.5 μs | 35.3 μs | 35.3 μs | 38.9 μs | ExpFromLeft (35.3 μs) | 1.00x | -| random | unsorted | 64 | 4096 | 203.8 μs | 202.6 μs | 201.8 μs | 202.3 μs | 201.0 μs | 201.7 μs | 203.9 μs | Binary (201.0 μs) | 1.00x | -| random | unsorted | 64 | 16384 | 868.0 μs | 865.9 μs | 881.5 μs | 873.6 μs | 867.3 μs | 870.6 μs | 867.9 μs | Gallop (865.9 μs) | 1.01x | -| random | unsorted | 256 | 1024 | 54.2 μs | 52.2 μs | 52.1 μs | 52.0 μs | 51.8 μs | 51.5 μs | 56.9 μs | Binary (51.8 μs) | 1.00x | -| random | unsorted | 256 | 4096 | 281.7 μs | 280.1 μs | 278.9 μs | 278.2 μs | 280.8 μs | 277.0 μs | 281.2 μs | InterpSearch (278.2 μs) | 1.00x | -| random | unsorted | 256 | 16384 | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | InterpSearch (1.16 ms) | 1.00x | -| random | unsorted | 1024 | 1024 | 77.5 μs | 75.7 μs | 73.9 μs | 73.8 μs | 73.2 μs | 72.9 μs | 80.0 μs | Binary (73.2 μs) | 1.00x | -| random | unsorted | 1024 | 4096 | 381.2 μs | 379.9 μs | 377.1 μs | 377.3 μs | 378.0 μs | 377.7 μs | 381.1 μs | ExpFromLeft (377.1 μs) | 1.00x | +| uniform | sorted_uniform | 64 | 1024 | 8.9 μs | 15.5 μs | 12.0 μs | 30.8 μs | 18.1 μs | 9.1 μs | 16.2 μs | Linear (8.9 μs) | 1.02x | +| uniform | sorted_uniform | 64 | 4096 | 31.1 μs | 59.2 μs | 44.7 μs | 112.7 μs | 68.6 μs | 32.1 μs | 60.5 μs | Linear (31.1 μs) | 1.03x | +| uniform | sorted_uniform | 64 | 16384 | 117.7 μs | 222.1 μs | 175.5 μs | 441.4 μs | 270.8 μs | 124.2 μs | 237.2 μs | Linear (117.7 μs) | 1.05x | +| uniform | sorted_uniform | 256 | 1024 | 9.9 μs | 18.1 μs | 13.9 μs | 37.5 μs | 29.8 μs | 10.3 μs | 25.0 μs | Linear (9.9 μs) | 1.05x | +| uniform | sorted_uniform | 256 | 4096 | 35.0 μs | 59.7 μs | 48.1 μs | 122.7 μs | 125.7 μs | 36.6 μs | 84.1 μs | Linear (35.0 μs) | 1.05x | +| uniform | sorted_uniform | 256 | 16384 | 121.8 μs | 226.6 μs | 178.9 μs | 452.0 μs | 388.0 μs | 128.8 μs | 318.0 μs | Linear (121.8 μs) | 1.06x | +| uniform | sorted_uniform | 1024 | 1024 | 9.6 μs | 18.1 μs | 13.1 μs | 38.9 μs | 74.4 μs | 9.9 μs | 55.3 μs | Linear (9.6 μs) | 1.03x | +| uniform | sorted_uniform | 1024 | 4096 | 46.7 μs | 73.1 μs | 58.4 μs | 149.1 μs | 236.1 μs | 48.3 μs | 189.4 μs | Linear (46.7 μs) | 1.03x | +| uniform | sorted_uniform | 1024 | 16384 | 140.2 μs | 238.9 μs | 192.8 μs | 491.8 μs | 591.2 μs | 144.6 μs | 484.7 μs | Linear (140.2 μs) | 1.03x | +| uniform | sorted_dense_burst | 64 | 1024 | 7.4 μs | 13.9 μs | 10.9 μs | 27.6 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.06x | +| uniform | sorted_dense_burst | 64 | 4096 | 29.1 μs | 55.5 μs | 43.6 μs | 109.6 μs | 67.9 μs | 31.0 μs | 56.7 μs | Linear (29.1 μs) | 1.06x | +| uniform | sorted_dense_burst | 64 | 16384 | 117.0 μs | 221.6 μs | 174.2 μs | 438.9 μs | 271.8 μs | 123.3 μs | 227.1 μs | Linear (117.0 μs) | 1.05x | +| uniform | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.0 μs | 11.1 μs | 27.4 μs | 21.8 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | +| uniform | sorted_dense_burst | 256 | 4096 | 29.3 μs | 55.5 μs | 43.6 μs | 109.9 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (29.3 μs) | 1.05x | +| uniform | sorted_dense_burst | 256 | 16384 | 116.4 μs | 222.1 μs | 174.1 μs | 439.0 μs | 349.2 μs | 122.9 μs | 305.7 μs | Linear (116.4 μs) | 1.06x | +| uniform | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 27.6 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | +| uniform | sorted_dense_burst | 1024 | 4096 | 29.3 μs | 55.7 μs | 43.5 μs | 109.7 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.3 μs) | 1.05x | +| uniform | sorted_dense_burst | 1024 | 16384 | 116.4 μs | 222.2 μs | 174.2 μs | 438.9 μs | 427.5 μs | 123.1 μs | 383.1 μs | Linear (116.4 μs) | 1.06x | +| uniform | unsorted | 64 | 1024 | 42.6 μs | 41.9 μs | 39.4 μs | 39.2 μs | 39.3 μs | 39.2 μs | 38.4 μs | InterpSearch (39.2 μs) | 1.00x | +| uniform | unsorted | 64 | 4096 | 233.4 μs | 229.2 μs | 230.4 μs | 229.8 μs | 230.5 μs | 229.4 μs | 228.6 μs | Gallop (229.2 μs) | 1.00x | +| uniform | unsorted | 64 | 16384 | 981.8 μs | 979.7 μs | 979.0 μs | 980.4 μs | 980.2 μs | 976.8 μs | 972.9 μs | ExpFromLeft (979.0 μs) | 1.00x | +| uniform | unsorted | 256 | 1024 | 58.6 μs | 57.3 μs | 55.8 μs | 54.9 μs | 54.6 μs | 54.5 μs | 53.6 μs | Binary (54.6 μs) | 1.00x | +| uniform | unsorted | 256 | 4096 | 314.8 μs | 314.3 μs | 311.6 μs | 310.4 μs | 311.1 μs | 309.9 μs | 306.7 μs | InterpSearch (310.4 μs) | 1.00x | +| uniform | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.29 ms | 1.30 ms | 1.29 ms | Binary (1.29 ms) | 1.00x | +| uniform | unsorted | 1024 | 1024 | 84.0 μs | 83.1 μs | 79.4 μs | 78.9 μs | 81.3 μs | 78.7 μs | 80.3 μs | InterpSearch (78.9 μs) | 1.00x | +| uniform | unsorted | 1024 | 4096 | 408.7 μs | 405.9 μs | 406.1 μs | 406.0 μs | 405.3 μs | 405.4 μs | 409.3 μs | Binary (405.3 μs) | 1.00x | +| uniform | unsorted | 1024 | 16384 | 1.69 ms | 1.68 ms | 1.68 ms | 1.68 ms | 1.67 ms | 1.67 ms | 1.69 ms | Binary (1.67 ms) | 1.00x | +| log | sorted_uniform | 64 | 1024 | 8.0 μs | 14.4 μs | 11.4 μs | 43.7 μs | 17.6 μs | 8.4 μs | 15.8 μs | Linear (8.0 μs) | 1.05x | +| log | sorted_uniform | 64 | 4096 | 30.0 μs | 55.6 μs | 44.4 μs | 170.5 μs | 69.1 μs | 31.5 μs | 60.9 μs | Linear (30.0 μs) | 1.05x | +| log | sorted_uniform | 64 | 16384 | 117.4 μs | 221.2 μs | 175.4 μs | 676.6 μs | 275.0 μs | 124.0 μs | 240.8 μs | Linear (117.4 μs) | 1.06x | +| log | sorted_uniform | 256 | 1024 | 9.0 μs | 15.6 μs | 12.2 μs | 57.8 μs | 23.1 μs | 9.4 μs | 21.3 μs | Linear (9.0 μs) | 1.05x | +| log | sorted_uniform | 256 | 4096 | 31.8 μs | 58.4 μs | 45.8 μs | 223.8 μs | 91.5 μs | 33.2 μs | 81.4 μs | Linear (31.8 μs) | 1.05x | +| log | sorted_uniform | 256 | 16384 | 120.1 μs | 226.7 μs | 177.5 μs | 869.6 μs | 363.0 μs | 126.8 μs | 319.4 μs | Linear (120.1 μs) | 1.06x | +| log | sorted_uniform | 1024 | 1024 | 10.3 μs | 17.6 μs | 13.4 μs | 69.8 μs | 39.6 μs | 10.6 μs | 32.6 μs | Linear (10.3 μs) | 1.02x | +| log | sorted_uniform | 1024 | 4096 | 36.9 μs | 62.4 μs | 49.6 μs | 282.8 μs | 167.3 μs | 38.7 μs | 124.1 μs | Linear (36.9 μs) | 1.05x | +| log | sorted_uniform | 1024 | 16384 | 128.5 μs | 233.0 μs | 184.4 μs | 1.06 ms | 532.4 μs | 134.3 μs | 448.1 μs | Linear (128.5 μs) | 1.04x | +| log | sorted_dense_burst | 64 | 1024 | 7.3 μs | 14.0 μs | 10.9 μs | 44.8 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.3 μs) | 1.06x | +| log | sorted_dense_burst | 64 | 4096 | 29.3 μs | 55.5 μs | 44.3 μs | 179.1 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.3 μs) | 1.05x | +| log | sorted_dense_burst | 64 | 16384 | 116.3 μs | 221.8 μs | 177.1 μs | 716.5 μs | 273.6 μs | 122.9 μs | 227.2 μs | Linear (116.3 μs) | 1.06x | +| log | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 55.4 μs | 21.8 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | +| log | sorted_dense_burst | 256 | 4096 | 29.3 μs | 55.5 μs | 44.3 μs | 221.9 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.3 μs) | 1.05x | +| log | sorted_dense_burst | 256 | 16384 | 116.4 μs | 222.2 μs | 173.8 μs | 887.9 μs | 349.3 μs | 123.0 μs | 305.8 μs | Linear (116.4 μs) | 1.06x | +| log | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.9 μs | 11.0 μs | 65.1 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | +| log | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 73.8 μs | 55.8 μs | 259.2 μs | 106.8 μs | 30.8 μs | 94.6 μs | Linear (29.2 μs) | 1.06x | +| log | sorted_dense_burst | 1024 | 16384 | 116.4 μs | 222.2 μs | 174.1 μs | 1.04 ms | 427.4 μs | 122.9 μs | 383.3 μs | Linear (116.4 μs) | 1.06x | +| log | unsorted | 64 | 1024 | 35.1 μs | 34.7 μs | 34.7 μs | 34.7 μs | 34.2 μs | 34.3 μs | 31.5 μs | Binary (34.2 μs) | 1.00x | +| log | unsorted | 64 | 4096 | 179.5 μs | 178.4 μs | 178.2 μs | 178.0 μs | 178.0 μs | 177.8 μs | 176.1 μs | Binary (178.0 μs) | 1.00x | +| log | unsorted | 64 | 16384 | 757.7 μs | 758.2 μs | 757.7 μs | 758.2 μs | 758.1 μs | 757.4 μs | 736.3 μs | ExpFromLeft (757.7 μs) | 1.00x | +| log | unsorted | 256 | 1024 | 50.7 μs | 50.4 μs | 49.3 μs | 49.5 μs | 49.4 μs | 49.6 μs | 47.1 μs | ExpFromLeft (49.3 μs) | 1.01x | +| log | unsorted | 256 | 4096 | 260.6 μs | 257.4 μs | 256.7 μs | 257.7 μs | 257.5 μs | 256.4 μs | 256.8 μs | ExpFromLeft (256.7 μs) | 1.00x | +| log | unsorted | 256 | 16384 | 1.09 ms | 1.09 ms | 1.09 ms | 1.09 ms | 1.09 ms | 1.09 ms | 1.06 ms | Binary (1.09 ms) | 1.00x | +| log | unsorted | 1024 | 1024 | 72.8 μs | 72.0 μs | 71.6 μs | 70.2 μs | 70.0 μs | 69.8 μs | 69.5 μs | Binary (70.0 μs) | 1.00x | +| log | unsorted | 1024 | 4096 | 350.4 μs | 348.8 μs | 349.1 μs | 348.6 μs | 348.5 μs | 349.3 μs | 347.2 μs | Binary (348.5 μs) | 1.00x | +| log | unsorted | 1024 | 16384 | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.41 ms | Binary (1.42 ms) | 1.00x | +| jittered | sorted_uniform | 64 | 1024 | 8.8 μs | 14.9 μs | 12.1 μs | 31.3 μs | 17.9 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | +| jittered | sorted_uniform | 64 | 4096 | 30.5 μs | 56.6 μs | 44.7 μs | 115.5 μs | 68.6 μs | 32.1 μs | 60.2 μs | Linear (30.5 μs) | 1.05x | +| jittered | sorted_uniform | 64 | 16384 | 117.7 μs | 222.7 μs | 175.6 μs | 454.8 μs | 270.9 μs | 124.2 μs | 237.0 μs | Linear (117.7 μs) | 1.06x | +| jittered | sorted_uniform | 256 | 1024 | 10.0 μs | 17.9 μs | 13.8 μs | 37.5 μs | 27.5 μs | 10.3 μs | 25.4 μs | Linear (10.0 μs) | 1.03x | +| jittered | sorted_uniform | 256 | 4096 | 34.8 μs | 59.7 μs | 48.1 μs | 123.4 μs | 126.2 μs | 36.1 μs | 84.0 μs | Linear (34.8 μs) | 1.04x | +| jittered | sorted_uniform | 256 | 16384 | 122.1 μs | 226.4 μs | 179.0 μs | 453.8 μs | 386.8 μs | 128.4 μs | 316.2 μs | Linear (122.1 μs) | 1.05x | +| jittered | sorted_uniform | 1024 | 1024 | 10.0 μs | 18.2 μs | 12.6 μs | 38.9 μs | 71.0 μs | 10.1 μs | 52.8 μs | Linear (10.0 μs) | 1.00x | +| jittered | sorted_uniform | 1024 | 4096 | 47.8 μs | 74.6 μs | 58.7 μs | 150.9 μs | 237.4 μs | 47.2 μs | 190.7 μs | Linear (47.8 μs) | 0.99x | +| jittered | sorted_uniform | 1024 | 16384 | 140.2 μs | 242.6 μs | 192.4 μs | 503.6 μs | 591.7 μs | 146.7 μs | 483.4 μs | Linear (140.2 μs) | 1.05x | +| jittered | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 27.6 μs | 17.0 μs | 7.8 μs | 14.1 μs | Linear (7.4 μs) | 1.06x | +| jittered | sorted_dense_burst | 64 | 4096 | 29.3 μs | 55.5 μs | 43.5 μs | 110.5 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.3 μs) | 1.05x | +| jittered | sorted_dense_burst | 64 | 16384 | 116.5 μs | 221.7 μs | 173.8 μs | 441.6 μs | 271.8 μs | 123.1 μs | 227.1 μs | Linear (116.5 μs) | 1.06x | +| jittered | sorted_dense_burst | 256 | 1024 | 7.5 μs | 14.6 μs | 11.0 μs | 27.9 μs | 22.0 μs | 7.9 μs | 19.4 μs | Linear (7.5 μs) | 1.05x | +| jittered | sorted_dense_burst | 256 | 4096 | 29.6 μs | 56.0 μs | 43.6 μs | 109.1 μs | 87.3 μs | 30.8 μs | 76.3 μs | Linear (29.6 μs) | 1.04x | +| jittered | sorted_dense_burst | 256 | 16384 | 116.3 μs | 226.7 μs | 174.3 μs | 436.2 μs | 349.2 μs | 123.0 μs | 305.7 μs | Linear (116.3 μs) | 1.06x | +| jittered | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 29.3 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.06x | +| jittered | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 55.6 μs | 44.3 μs | 117.2 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.2 μs) | 1.05x | +| jittered | sorted_dense_burst | 1024 | 16384 | 116.3 μs | 222.9 μs | 174.0 μs | 468.5 μs | 427.3 μs | 122.9 μs | 383.4 μs | Linear (116.3 μs) | 1.06x | +| jittered | unsorted | 64 | 1024 | 42.6 μs | 40.9 μs | 41.2 μs | 39.9 μs | 40.5 μs | 40.0 μs | 37.8 μs | InterpSearch (39.9 μs) | 1.00x | +| jittered | unsorted | 64 | 4096 | 231.9 μs | 232.9 μs | 229.2 μs | 228.3 μs | 227.3 μs | 228.6 μs | 223.7 μs | Binary (227.3 μs) | 1.01x | +| jittered | unsorted | 64 | 16384 | 981.5 μs | 982.2 μs | 980.1 μs | 980.1 μs | 979.3 μs | 977.9 μs | 967.9 μs | Binary (979.3 μs) | 1.00x | +| jittered | unsorted | 256 | 1024 | 56.9 μs | 55.4 μs | 52.7 μs | 52.5 μs | 52.1 μs | 52.2 μs | 52.7 μs | Binary (52.1 μs) | 1.00x | +| jittered | unsorted | 256 | 4096 | 316.5 μs | 314.4 μs | 312.4 μs | 313.2 μs | 312.7 μs | 313.2 μs | 307.4 μs | ExpFromLeft (312.4 μs) | 1.00x | +| jittered | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.29 ms | ExpFromLeft (1.30 ms) | 1.00x | +| jittered | unsorted | 1024 | 1024 | 84.6 μs | 81.3 μs | 79.0 μs | 77.8 μs | 77.3 μs | 76.8 μs | 77.5 μs | Binary (77.3 μs) | 0.99x | +| jittered | unsorted | 1024 | 4096 | 408.7 μs | 407.2 μs | 406.0 μs | 404.5 μs | 405.0 μs | 406.3 μs | 411.1 μs | InterpSearch (404.5 μs) | 1.00x | +| jittered | unsorted | 1024 | 16384 | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.69 ms | InterpSearch (1.67 ms) | 1.00x | +| random | sorted_uniform | 64 | 1024 | 8.8 μs | 14.8 μs | 12.0 μs | 33.4 μs | 17.6 μs | 9.1 μs | 15.9 μs | Linear (8.8 μs) | 1.04x | +| random | sorted_uniform | 64 | 4096 | 30.5 μs | 55.9 μs | 44.7 μs | 126.2 μs | 68.5 μs | 32.1 μs | 60.2 μs | Linear (30.5 μs) | 1.05x | +| random | sorted_uniform | 64 | 16384 | 117.6 μs | 220.5 μs | 175.5 μs | 495.9 μs | 271.4 μs | 124.2 μs | 237.2 μs | Linear (117.6 μs) | 1.06x | +| random | sorted_uniform | 256 | 1024 | 9.1 μs | 16.9 μs | 13.3 μs | 42.3 μs | 24.1 μs | 9.4 μs | 23.3 μs | Linear (9.1 μs) | 1.03x | +| random | sorted_uniform | 256 | 4096 | 34.4 μs | 59.2 μs | 47.8 μs | 155.0 μs | 99.7 μs | 35.7 μs | 83.5 μs | Linear (34.4 μs) | 1.04x | +| random | sorted_uniform | 256 | 16384 | 122.0 μs | 223.9 μs | 179.0 μs | 590.1 μs | 383.6 μs | 128.3 μs | 316.7 μs | Linear (122.0 μs) | 1.05x | +| random | sorted_uniform | 1024 | 1024 | 10.0 μs | 18.0 μs | 12.3 μs | 45.8 μs | 58.5 μs | 10.5 μs | 42.2 μs | Linear (10.0 μs) | 1.05x | +| random | sorted_uniform | 1024 | 4096 | 42.9 μs | 70.0 μs | 55.9 μs | 184.7 μs | 212.0 μs | 43.5 μs | 166.4 μs | Linear (42.9 μs) | 1.01x | +| random | sorted_uniform | 1024 | 16384 | 138.2 μs | 237.2 μs | 191.5 μs | 666.2 μs | 568.5 μs | 143.4 μs | 480.1 μs | Linear (138.2 μs) | 1.04x | +| random | sorted_dense_burst | 64 | 1024 | 7.4 μs | 13.7 μs | 10.9 μs | 29.5 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | +| random | sorted_dense_burst | 64 | 4096 | 29.2 μs | 54.9 μs | 43.5 μs | 116.8 μs | 67.9 μs | 30.8 μs | 56.7 μs | Linear (29.2 μs) | 1.05x | +| random | sorted_dense_burst | 64 | 16384 | 116.2 μs | 219.2 μs | 173.9 μs | 467.9 μs | 271.8 μs | 122.9 μs | 227.1 μs | Linear (116.2 μs) | 1.06x | +| random | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 31.7 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | +| random | sorted_dense_burst | 256 | 4096 | 29.2 μs | 55.6 μs | 43.2 μs | 125.6 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (29.2 μs) | 1.05x | +| random | sorted_dense_burst | 256 | 16384 | 116.3 μs | 222.2 μs | 174.0 μs | 502.1 μs | 349.2 μs | 122.8 μs | 306.1 μs | Linear (116.3 μs) | 1.06x | +| random | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 44.4 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.06x | +| random | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 55.5 μs | 43.6 μs | 180.0 μs | 124.2 μs | 46.0 μs | 111.1 μs | Linear (29.2 μs) | 1.58x | +| random | sorted_dense_burst | 1024 | 16384 | 177.7 μs | 304.6 μs | 232.0 μs | 718.8 μs | 427.2 μs | 122.8 μs | 383.2 μs | Linear (177.7 μs) | 0.69x | +| random | unsorted | 64 | 1024 | 36.5 μs | 35.1 μs | 35.2 μs | 34.8 μs | 35.1 μs | 34.8 μs | 33.5 μs | InterpSearch (34.8 μs) | 1.00x | +| random | unsorted | 64 | 4096 | 203.7 μs | 202.6 μs | 201.8 μs | 202.4 μs | 202.8 μs | 201.4 μs | 200.6 μs | ExpFromLeft (201.8 μs) | 1.00x | +| random | unsorted | 64 | 16384 | 870.0 μs | 869.4 μs | 869.6 μs | 868.7 μs | 871.1 μs | 870.2 μs | 842.5 μs | InterpSearch (868.7 μs) | 1.00x | +| random | unsorted | 256 | 1024 | 55.6 μs | 53.3 μs | 52.6 μs | 52.2 μs | 52.1 μs | 52.1 μs | 49.4 μs | Binary (52.1 μs) | 1.00x | +| random | unsorted | 256 | 4096 | 279.9 μs | 278.9 μs | 278.6 μs | 279.1 μs | 278.4 μs | 278.0 μs | 277.1 μs | Binary (278.4 μs) | 1.00x | +| random | unsorted | 256 | 16384 | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.15 ms | Binary (1.16 ms) | 1.00x | +| random | unsorted | 1024 | 1024 | 77.1 μs | 75.2 μs | 74.3 μs | 73.7 μs | 73.0 μs | 72.1 μs | 76.2 μs | Binary (73.0 μs) | 0.99x | +| random | unsorted | 1024 | 4096 | 382.1 μs | 380.1 μs | 380.0 μs | 378.0 μs | 377.9 μs | 380.0 μs | 381.3 μs | Binary (377.9 μs) | 1.01x | | random | unsorted | 1024 | 16384 | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | Linear (1.55 ms) | 1.00x | -| two_scale | sorted_uniform | 64 | 1024 | 8.1 μs | 14.6 μs | 11.1 μs | 46.7 μs | 17.4 μs | 8.3 μs | 15.2 μs | Linear (8.1 μs) | 1.03x | -| two_scale | sorted_uniform | 64 | 4096 | 30.2 μs | 56.6 μs | 43.0 μs | 166.6 μs | 68.9 μs | 31.4 μs | 59.0 μs | Linear (30.2 μs) | 1.04x | -| two_scale | sorted_uniform | 64 | 16384 | 118.2 μs | 224.8 μs | 169.8 μs | 643.1 μs | 273.2 μs | 123.5 μs | 234.2 μs | Linear (118.2 μs) | 1.04x | -| two_scale | sorted_uniform | 256 | 1024 | 9.6 μs | 16.0 μs | 12.5 μs | 69.6 μs | 23.1 μs | 9.8 μs | 21.8 μs | Linear (9.6 μs) | 1.03x | -| two_scale | sorted_uniform | 256 | 4096 | 32.4 μs | 58.5 μs | 44.7 μs | 239.6 μs | 90.3 μs | 33.8 μs | 80.6 μs | Linear (32.4 μs) | 1.04x | -| two_scale | sorted_uniform | 256 | 16384 | 120.5 μs | 227.1 μs | 171.9 μs | 860.5 μs | 352.6 μs | 125.7 μs | 315.1 μs | Linear (120.5 μs) | 1.04x | -| two_scale | sorted_uniform | 1024 | 1024 | 10.1 μs | 17.4 μs | 12.4 μs | 87.9 μs | 45.0 μs | 10.5 μs | 33.4 μs | Linear (10.1 μs) | 1.04x | -| two_scale | sorted_uniform | 1024 | 4096 | 39.2 μs | 65.0 μs | 50.4 μs | 308.8 μs | 161.9 μs | 40.8 μs | 113.2 μs | Linear (39.2 μs) | 1.04x | -| two_scale | sorted_uniform | 1024 | 16384 | 129.7 μs | 234.2 μs | 178.8 μs | 1.09 ms | 502.4 μs | 134.9 μs | 415.2 μs | Linear (129.7 μs) | 1.04x | -| two_scale | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 47.0 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | -| two_scale | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.1 μs | 42.3 μs | 187.7 μs | 67.9 μs | 30.9 μs | 56.8 μs | Linear (29.5 μs) | 1.05x | -| two_scale | sorted_dense_burst | 64 | 16384 | 118.3 μs | 224.6 μs | 168.7 μs | 750.3 μs | 271.6 μs | 122.8 μs | 227.2 μs | Linear (118.3 μs) | 1.04x | -| two_scale | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 56.5 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | -| two_scale | sorted_dense_burst | 256 | 4096 | 29.4 μs | 56.2 μs | 42.3 μs | 223.4 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.4 μs) | 1.05x | -| two_scale | sorted_dense_burst | 256 | 16384 | 117.7 μs | 224.9 μs | 169.1 μs | 899.8 μs | 349.3 μs | 122.8 μs | 306.0 μs | Linear (117.7 μs) | 1.04x | -| two_scale | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.2 μs | 10.6 μs | 66.4 μs | 26.8 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | -| two_scale | sorted_dense_burst | 1024 | 4096 | 29.4 μs | 56.3 μs | 42.3 μs | 262.7 μs | 106.8 μs | 30.8 μs | 95.8 μs | Linear (29.4 μs) | 1.05x | -| two_scale | sorted_dense_burst | 1024 | 16384 | 118.3 μs | 225.0 μs | 169.1 μs | 1.05 ms | 427.4 μs | 123.4 μs | 383.2 μs | Linear (118.3 μs) | 1.04x | -| two_scale | unsorted | 64 | 1024 | 46.3 μs | 45.8 μs | 45.6 μs | 45.8 μs | 45.5 μs | 45.8 μs | 45.6 μs | Binary (45.5 μs) | 1.01x | -| two_scale | unsorted | 64 | 4096 | 204.1 μs | 200.0 μs | 200.7 μs | 208.0 μs | 200.0 μs | 199.6 μs | 203.1 μs | Binary (200.0 μs) | 1.00x | -| two_scale | unsorted | 64 | 16384 | 840.4 μs | 838.1 μs | 834.2 μs | 839.1 μs | 836.2 μs | 838.3 μs | 840.8 μs | ExpFromLeft (834.2 μs) | 1.00x | -| two_scale | unsorted | 256 | 1024 | 54.9 μs | 54.3 μs | 54.0 μs | 54.0 μs | 54.0 μs | 53.9 μs | 54.3 μs | ExpFromLeft (54.0 μs) | 1.00x | -| two_scale | unsorted | 256 | 4096 | 256.9 μs | 256.2 μs | 255.1 μs | 254.7 μs | 255.8 μs | 255.0 μs | 256.1 μs | InterpSearch (254.7 μs) | 1.00x | -| two_scale | unsorted | 256 | 16384 | 1.07 ms | 1.07 ms | 1.06 ms | 1.06 ms | 1.06 ms | 1.07 ms | 1.07 ms | Binary (1.06 ms) | 1.00x | -| two_scale | unsorted | 1024 | 1024 | 73.8 μs | 72.0 μs | 71.6 μs | 70.5 μs | 70.0 μs | 70.0 μs | 75.1 μs | Binary (70.0 μs) | 1.00x | -| two_scale | unsorted | 1024 | 4096 | 348.5 μs | 347.8 μs | 346.0 μs | 345.2 μs | 346.1 μs | 346.0 μs | 349.6 μs | InterpSearch (345.2 μs) | 1.00x | -| two_scale | unsorted | 1024 | 16384 | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.44 ms | Gallop (1.42 ms) | 1.00x | -| power2 | sorted_uniform | 64 | 1024 | 8.5 μs | 15.0 μs | 11.6 μs | 44.8 μs | 17.8 μs | 8.8 μs | 15.9 μs | Linear (8.5 μs) | 1.04x | -| power2 | sorted_uniform | 64 | 4096 | 30.6 μs | 57.2 μs | 43.5 μs | 165.3 μs | 68.9 μs | 32.0 μs | 60.2 μs | Linear (30.6 μs) | 1.04x | -| power2 | sorted_uniform | 64 | 16384 | 118.8 μs | 224.8 μs | 170.2 μs | 636.4 μs | 272.1 μs | 124.1 μs | 237.7 μs | Linear (118.8 μs) | 1.04x | -| power2 | sorted_uniform | 256 | 1024 | 9.7 μs | 16.8 μs | 12.8 μs | 60.8 μs | 25.3 μs | 10.1 μs | 23.9 μs | Linear (9.7 μs) | 1.04x | -| power2 | sorted_uniform | 256 | 4096 | 34.3 μs | 60.3 μs | 46.4 μs | 217.9 μs | 113.3 μs | 35.8 μs | 83.5 μs | Linear (34.3 μs) | 1.04x | -| power2 | sorted_uniform | 256 | 16384 | 122.9 μs | 228.9 μs | 173.9 μs | 812.6 μs | 386.0 μs | 128.2 μs | 318.2 μs | Linear (122.9 μs) | 1.04x | -| power2 | sorted_uniform | 1024 | 1024 | 10.2 μs | 18.2 μs | 12.1 μs | 82.8 μs | 65.8 μs | 10.2 μs | 49.1 μs | Linear (10.2 μs) | 1.00x | -| power2 | sorted_uniform | 1024 | 4096 | 43.0 μs | 70.4 μs | 53.8 μs | 287.9 μs | 228.0 μs | 44.3 μs | 177.0 μs | Linear (43.0 μs) | 1.03x | -| power2 | sorted_uniform | 1024 | 16384 | 138.7 μs | 241.3 μs | 186.1 μs | 1.04 ms | 587.3 μs | 143.7 μs | 481.2 μs | Linear (138.7 μs) | 1.04x | -| power2 | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 43.8 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | -| power2 | sorted_dense_burst | 64 | 4096 | 29.6 μs | 56.3 μs | 42.3 μs | 175.0 μs | 67.9 μs | 30.8 μs | 56.9 μs | Linear (29.6 μs) | 1.04x | -| power2 | sorted_dense_burst | 64 | 16384 | 118.3 μs | 224.4 μs | 168.9 μs | 698.4 μs | 271.5 μs | 122.9 μs | 227.7 μs | Linear (118.3 μs) | 1.04x | -| power2 | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.2 μs | 10.6 μs | 54.1 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | -| power2 | sorted_dense_burst | 256 | 4096 | 29.5 μs | 56.2 μs | 42.3 μs | 216.4 μs | 87.4 μs | 30.9 μs | 76.4 μs | Linear (29.5 μs) | 1.05x | -| power2 | sorted_dense_burst | 256 | 16384 | 117.6 μs | 224.8 μs | 168.7 μs | 864.1 μs | 349.2 μs | 123.2 μs | 305.9 μs | Linear (117.6 μs) | 1.05x | -| power2 | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 63.8 μs | 26.8 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | -| power2 | sorted_dense_burst | 1024 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 254.2 μs | 106.8 μs | 30.9 μs | 95.7 μs | Linear (29.5 μs) | 1.05x | -| power2 | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 224.8 μs | 169.2 μs | 1.01 ms | 427.4 μs | 123.6 μs | 383.2 μs | Linear (117.5 μs) | 1.05x | -| power2 | unsorted | 64 | 1024 | 41.5 μs | 40.5 μs | 40.6 μs | 40.6 μs | 40.2 μs | 40.5 μs | 41.7 μs | Binary (40.2 μs) | 1.01x | -| power2 | unsorted | 64 | 4096 | 216.4 μs | 216.3 μs | 215.9 μs | 215.5 μs | 215.4 μs | 216.8 μs | 217.3 μs | Binary (215.4 μs) | 1.01x | -| power2 | unsorted | 64 | 16384 | 916.8 μs | 915.4 μs | 916.0 μs | 915.2 μs | 914.8 μs | 915.2 μs | 917.5 μs | Binary (914.8 μs) | 1.00x | -| power2 | unsorted | 256 | 1024 | 55.8 μs | 53.7 μs | 53.9 μs | 53.0 μs | 52.9 μs | 52.8 μs | 56.4 μs | Binary (52.9 μs) | 1.00x | -| power2 | unsorted | 256 | 4096 | 300.2 μs | 299.1 μs | 297.9 μs | 297.2 μs | 297.4 μs | 297.4 μs | 303.3 μs | InterpSearch (297.2 μs) | 1.00x | -| power2 | unsorted | 256 | 16384 | 1.24 ms | 1.24 ms | 1.24 ms | 1.24 ms | 1.24 ms | 1.24 ms | 1.25 ms | Binary (1.24 ms) | 1.00x | -| power2 | unsorted | 1024 | 1024 | 79.7 μs | 78.3 μs | 76.5 μs | 76.2 μs | 75.6 μs | 75.5 μs | 82.2 μs | Binary (75.6 μs) | 1.00x | -| power2 | unsorted | 1024 | 4096 | 392.3 μs | 392.6 μs | 390.6 μs | 391.3 μs | 389.6 μs | 388.5 μs | 394.0 μs | Binary (389.6 μs) | 1.00x | -| power2 | unsorted | 1024 | 16384 | 1.60 ms | 1.60 ms | 1.60 ms | 1.59 ms | 1.60 ms | 1.60 ms | 1.61 ms | InterpSearch (1.59 ms) | 1.00x | -| sqrt | sorted_uniform | 64 | 1024 | 8.9 μs | 15.2 μs | 11.9 μs | 44.5 μs | 17.5 μs | 9.2 μs | 16.0 μs | Linear (8.9 μs) | 1.04x | -| sqrt | sorted_uniform | 64 | 4096 | 30.8 μs | 57.1 μs | 43.5 μs | 164.4 μs | 68.4 μs | 32.1 μs | 60.4 μs | Linear (30.8 μs) | 1.04x | -| sqrt | sorted_uniform | 64 | 16384 | 119.0 μs | 225.4 μs | 170.3 μs | 636.8 μs | 269.8 μs | 124.3 μs | 237.8 μs | Linear (119.0 μs) | 1.04x | -| sqrt | sorted_uniform | 256 | 1024 | 9.7 μs | 17.3 μs | 12.6 μs | 58.4 μs | 25.5 μs | 10.1 μs | 25.5 μs | Linear (9.7 μs) | 1.04x | -| sqrt | sorted_uniform | 256 | 4096 | 35.3 μs | 60.8 μs | 47.0 μs | 215.8 μs | 127.3 μs | 36.7 μs | 84.0 μs | Linear (35.3 μs) | 1.04x | -| sqrt | sorted_uniform | 256 | 16384 | 123.3 μs | 229.4 μs | 174.1 μs | 797.2 μs | 388.8 μs | 128.8 μs | 317.9 μs | Linear (123.3 μs) | 1.04x | -| sqrt | sorted_uniform | 1024 | 1024 | 10.0 μs | 18.1 μs | 12.6 μs | 77.5 μs | 58.0 μs | 10.4 μs | 47.7 μs | Linear (10.0 μs) | 1.05x | -| sqrt | sorted_uniform | 1024 | 4096 | 43.9 μs | 71.3 μs | 53.8 μs | 279.2 μs | 228.9 μs | 44.7 μs | 185.5 μs | Linear (43.9 μs) | 1.02x | -| sqrt | sorted_uniform | 1024 | 16384 | 141.6 μs | 243.1 μs | 188.2 μs | 1.02 ms | 595.2 μs | 146.8 μs | 486.3 μs | Linear (141.6 μs) | 1.04x | -| sqrt | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.4 μs | 10.6 μs | 41.0 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | -| sqrt | sorted_dense_burst | 64 | 4096 | 29.5 μs | 56.1 μs | 42.4 μs | 165.6 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.5 μs) | 1.04x | -| sqrt | sorted_dense_burst | 64 | 16384 | 118.0 μs | 224.4 μs | 168.9 μs | 653.6 μs | 271.5 μs | 122.8 μs | 227.2 μs | Linear (118.0 μs) | 1.04x | -| sqrt | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 50.8 μs | 21.8 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | -| sqrt | sorted_dense_burst | 256 | 4096 | 29.6 μs | 56.2 μs | 42.3 μs | 202.4 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.6 μs) | 1.04x | -| sqrt | sorted_dense_burst | 256 | 16384 | 117.9 μs | 224.8 μs | 168.8 μs | 809.5 μs | 349.2 μs | 123.0 μs | 305.9 μs | Linear (117.9 μs) | 1.04x | -| sqrt | sorted_dense_burst | 1024 | 1024 | 7.5 μs | 14.1 μs | 10.7 μs | 61.1 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.5 μs) | 1.05x | -| sqrt | sorted_dense_burst | 1024 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 243.0 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.5 μs) | 1.05x | -| sqrt | sorted_dense_burst | 1024 | 16384 | 117.6 μs | 224.8 μs | 169.1 μs | 971.8 μs | 427.3 μs | 122.9 μs | 383.2 μs | Linear (117.6 μs) | 1.04x | -| sqrt | unsorted | 64 | 1024 | 44.9 μs | 43.4 μs | 43.3 μs | 44.1 μs | 42.9 μs | 42.8 μs | 45.1 μs | Binary (42.9 μs) | 1.00x | -| sqrt | unsorted | 64 | 4096 | 212.5 μs | 211.2 μs | 211.5 μs | 211.9 μs | 210.6 μs | 211.4 μs | 214.0 μs | Binary (210.6 μs) | 1.00x | -| sqrt | unsorted | 64 | 16384 | 909.9 μs | 908.9 μs | 911.7 μs | 908.8 μs | 907.9 μs | 909.1 μs | 911.4 μs | Binary (907.9 μs) | 1.00x | -| sqrt | unsorted | 256 | 1024 | 52.9 μs | 51.6 μs | 51.1 μs | 51.1 μs | 50.7 μs | 50.8 μs | 54.7 μs | Binary (50.7 μs) | 1.00x | -| sqrt | unsorted | 256 | 4096 | 287.3 μs | 286.8 μs | 285.2 μs | 285.6 μs | 286.1 μs | 285.2 μs | 290.6 μs | ExpFromLeft (285.2 μs) | 1.00x | -| sqrt | unsorted | 256 | 16384 | 1.20 ms | 1.20 ms | 1.19 ms | 1.20 ms | 1.20 ms | 1.20 ms | 1.20 ms | ExpFromLeft (1.19 ms) | 1.00x | -| sqrt | unsorted | 1024 | 1024 | 75.0 μs | 73.1 μs | 72.6 μs | 71.7 μs | 71.0 μs | 70.6 μs | 77.3 μs | Binary (71.0 μs) | 0.99x | -| sqrt | unsorted | 1024 | 4096 | 377.0 μs | 376.6 μs | 374.0 μs | 374.7 μs | 375.4 μs | 375.1 μs | 376.9 μs | ExpFromLeft (374.0 μs) | 1.00x | -| sqrt | unsorted | 1024 | 16384 | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | Binary (1.54 ms) | 1.00x | -| plateau | sorted_uniform | 64 | 1024 | 7.5 μs | 14.2 μs | 10.7 μs | 45.4 μs | 17.0 μs | 7.8 μs | 14.8 μs | Linear (7.5 μs) | 1.05x | -| plateau | sorted_uniform | 64 | 4096 | 29.5 μs | 56.2 μs | 42.4 μs | 160.2 μs | 67.8 μs | 30.9 μs | 58.7 μs | Linear (29.5 μs) | 1.05x | -| plateau | sorted_uniform | 64 | 16384 | 117.9 μs | 224.5 μs | 169.3 μs | 618.0 μs | 271.1 μs | 123.2 μs | 234.7 μs | Linear (117.9 μs) | 1.04x | -| plateau | sorted_uniform | 256 | 1024 | 7.6 μs | 14.2 μs | 10.7 μs | 67.1 μs | 21.9 μs | 7.9 μs | 19.6 μs | Linear (7.6 μs) | 1.05x | -| plateau | sorted_uniform | 256 | 4096 | 29.6 μs | 56.3 μs | 42.4 μs | 223.2 μs | 87.4 μs | 31.0 μs | 78.3 μs | Linear (29.6 μs) | 1.04x | -| plateau | sorted_uniform | 256 | 16384 | 117.8 μs | 224.9 μs | 169.2 μs | 788.1 μs | 349.8 μs | 123.3 μs | 313.4 μs | Linear (117.8 μs) | 1.05x | -| plateau | sorted_uniform | 1024 | 1024 | 7.9 μs | 14.2 μs | 10.7 μs | 88.5 μs | 26.5 μs | 8.3 μs | 24.6 μs | Linear (7.9 μs) | 1.05x | -| plateau | sorted_uniform | 1024 | 4096 | 30.0 μs | 56.3 μs | 42.5 μs | 317.8 μs | 106.0 μs | 31.3 μs | 98.5 μs | Linear (30.0 μs) | 1.04x | -| plateau | sorted_uniform | 1024 | 16384 | 118.4 μs | 225.0 μs | 169.7 μs | 1.04 ms | 424.1 μs | 123.3 μs | 388.8 μs | Linear (118.4 μs) | 1.04x | -| plateau | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.0 μs | 42.2 μs | 17.1 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | -| plateau | sorted_dense_burst | 64 | 4096 | 29.6 μs | 56.2 μs | 39.6 μs | 168.1 μs | 68.0 μs | 30.9 μs | 57.1 μs | Linear (29.6 μs) | 1.05x | -| plateau | sorted_dense_burst | 64 | 16384 | 117.6 μs | 224.5 μs | 158.4 μs | 672.7 μs | 272.0 μs | 123.5 μs | 228.5 μs | Linear (117.6 μs) | 1.05x | -| plateau | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.0 μs | 50.2 μs | 21.8 μs | 7.8 μs | 19.6 μs | Linear (7.4 μs) | 1.04x | -| plateau | sorted_dense_burst | 256 | 4096 | 29.4 μs | 56.3 μs | 39.5 μs | 199.8 μs | 87.0 μs | 30.9 μs | 78.2 μs | Linear (29.4 μs) | 1.05x | -| plateau | sorted_dense_burst | 256 | 16384 | 118.2 μs | 225.0 μs | 157.3 μs | 804.8 μs | 348.0 μs | 123.1 μs | 312.5 μs | Linear (118.2 μs) | 1.04x | -| plateau | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.1 μs | 10.0 μs | 60.7 μs | 26.7 μs | 7.8 μs | 24.3 μs | Linear (7.4 μs) | 1.05x | -| plateau | sorted_dense_burst | 1024 | 4096 | 29.6 μs | 56.3 μs | 39.4 μs | 243.4 μs | 106.6 μs | 30.9 μs | 97.9 μs | Linear (29.6 μs) | 1.05x | -| plateau | sorted_dense_burst | 1024 | 16384 | 118.3 μs | 224.9 μs | 158.7 μs | 973.0 μs | 426.8 μs | 123.5 μs | 387.1 μs | Linear (118.3 μs) | 1.04x | -| plateau | unsorted | 64 | 1024 | 22.9 μs | 22.9 μs | 23.3 μs | 23.2 μs | 23.2 μs | 23.1 μs | 22.8 μs | Gallop (22.9 μs) | 1.01x | -| plateau | unsorted | 64 | 4096 | 90.1 μs | 91.9 μs | 90.1 μs | 90.1 μs | 92.0 μs | 90.1 μs | 91.8 μs | Linear (90.1 μs) | 1.00x | -| plateau | unsorted | 64 | 16384 | 369.3 μs | 364.8 μs | 367.9 μs | 361.9 μs | 369.0 μs | 367.8 μs | 361.7 μs | InterpSearch (361.9 μs) | 1.02x | -| plateau | unsorted | 256 | 1024 | 27.4 μs | 27.4 μs | 27.4 μs | 27.3 μs | 27.3 μs | 27.4 μs | 27.4 μs | Binary (27.3 μs) | 1.00x | -| plateau | unsorted | 256 | 4096 | 108.4 μs | 108.4 μs | 108.4 μs | 108.4 μs | 108.2 μs | 108.1 μs | 108.7 μs | Binary (108.2 μs) | 1.00x | -| plateau | unsorted | 256 | 16384 | 435.2 μs | 435.0 μs | 435.4 μs | 434.6 μs | 435.2 μs | 435.3 μs | 435.0 μs | InterpSearch (434.6 μs) | 1.00x | -| plateau | unsorted | 1024 | 1024 | 32.2 μs | 32.4 μs | 32.3 μs | 32.4 μs | 32.4 μs | 32.4 μs | 32.5 μs | Linear (32.2 μs) | 1.01x | -| plateau | unsorted | 1024 | 4096 | 128.8 μs | 129.0 μs | 129.1 μs | 128.8 μs | 128.7 μs | 129.1 μs | 128.4 μs | Binary (128.7 μs) | 1.00x | -| plateau | unsorted | 1024 | 16384 | 516.7 μs | 516.8 μs | 517.0 μs | 516.8 μs | 517.5 μs | 517.0 μs | 517.0 μs | Linear (516.7 μs) | 1.00x | -| bimodal | sorted_uniform | 64 | 1024 | 7.5 μs | 14.5 μs | 10.9 μs | 48.8 μs | 17.1 μs | 7.9 μs | 14.8 μs | Linear (7.5 μs) | 1.05x | -| bimodal | sorted_uniform | 64 | 4096 | 30.4 μs | 57.2 μs | 42.9 μs | 171.8 μs | 68.2 μs | 31.8 μs | 58.1 μs | Linear (30.4 μs) | 1.04x | -| bimodal | sorted_uniform | 64 | 16384 | 118.8 μs | 225.5 μs | 167.7 μs | 660.4 μs | 272.1 μs | 124.0 μs | 229.8 μs | Linear (118.8 μs) | 1.04x | -| bimodal | sorted_uniform | 256 | 1024 | 7.8 μs | 14.7 μs | 10.9 μs | 71.4 μs | 21.9 μs | 8.2 μs | 20.5 μs | Linear (7.8 μs) | 1.05x | -| bimodal | sorted_uniform | 256 | 4096 | 30.6 μs | 59.0 μs | 43.8 μs | 239.6 μs | 88.7 μs | 31.9 μs | 80.5 μs | Linear (30.6 μs) | 1.04x | -| bimodal | sorted_uniform | 256 | 16384 | 122.6 μs | 229.2 μs | 173.0 μs | 849.6 μs | 360.3 μs | 127.8 μs | 312.1 μs | Linear (122.6 μs) | 1.04x | -| bimodal | sorted_uniform | 1024 | 1024 | 9.4 μs | 15.8 μs | 11.8 μs | 91.3 μs | 27.1 μs | 9.8 μs | 25.5 μs | Linear (9.4 μs) | 1.04x | -| bimodal | sorted_uniform | 1024 | 4096 | 31.6 μs | 59.9 μs | 43.8 μs | 324.1 μs | 120.9 μs | 33.6 μs | 110.2 μs | Linear (31.6 μs) | 1.06x | -| bimodal | sorted_uniform | 1024 | 16384 | 128.7 μs | 238.5 μs | 178.3 μs | 1.08 ms | 530.7 μs | 133.8 μs | 452.2 μs | Linear (128.7 μs) | 1.04x | -| bimodal | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.1 μs | 47.4 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | -| bimodal | sorted_dense_burst | 64 | 4096 | 29.2 μs | 56.1 μs | 42.4 μs | 169.1 μs | 67.9 μs | 30.9 μs | 56.8 μs | Linear (29.2 μs) | 1.06x | -| bimodal | sorted_dense_burst | 64 | 16384 | 117.1 μs | 224.3 μs | 169.1 μs | 656.6 μs | 271.5 μs | 122.9 μs | 227.0 μs | Linear (117.1 μs) | 1.05x | -| bimodal | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 69.1 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | -| bimodal | sorted_dense_burst | 256 | 4096 | 29.4 μs | 56.2 μs | 42.3 μs | 228.0 μs | 87.2 μs | 30.8 μs | 76.4 μs | Linear (29.4 μs) | 1.05x | -| bimodal | sorted_dense_burst | 256 | 16384 | 117.5 μs | 224.9 μs | 168.1 μs | 828.1 μs | 349.3 μs | 123.5 μs | 305.9 μs | Linear (117.5 μs) | 1.05x | -| bimodal | sorted_dense_burst | 1024 | 1024 | 7.6 μs | 14.1 μs | 10.5 μs | 91.1 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.6 μs) | 1.03x | -| bimodal | sorted_dense_burst | 1024 | 4096 | 30.2 μs | 56.3 μs | 42.2 μs | 312.9 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (30.2 μs) | 1.02x | -| bimodal | sorted_dense_burst | 1024 | 16384 | 120.5 μs | 249.2 μs | 168.4 μs | 1.04 ms | 427.3 μs | 123.0 μs | 383.1 μs | Linear (120.5 μs) | 1.02x | -| bimodal | unsorted | 64 | 1024 | 21.7 μs | 21.7 μs | 21.7 μs | 22.4 μs | 21.6 μs | 21.7 μs | 21.8 μs | Binary (21.6 μs) | 1.00x | -| bimodal | unsorted | 64 | 4096 | 88.9 μs | 88.8 μs | 89.2 μs | 89.4 μs | 91.8 μs | 91.7 μs | 91.8 μs | Gallop (88.8 μs) | 1.03x | -| bimodal | unsorted | 64 | 16384 | 368.2 μs | 367.6 μs | 368.7 μs | 367.1 μs | 367.7 μs | 367.4 μs | 367.4 μs | InterpSearch (367.1 μs) | 1.00x | -| bimodal | unsorted | 256 | 1024 | 28.8 μs | 28.8 μs | 28.9 μs | 28.8 μs | 28.8 μs | 28.9 μs | 29.0 μs | InterpSearch (28.8 μs) | 1.00x | -| bimodal | unsorted | 256 | 4096 | 119.6 μs | 119.4 μs | 119.5 μs | 119.5 μs | 119.6 μs | 119.5 μs | 119.4 μs | Gallop (119.4 μs) | 1.00x | -| bimodal | unsorted | 256 | 16384 | 489.8 μs | 489.0 μs | 488.8 μs | 489.3 μs | 488.6 μs | 488.0 μs | 493.9 μs | Binary (488.6 μs) | 1.00x | -| bimodal | unsorted | 1024 | 1024 | 34.6 μs | 34.4 μs | 34.3 μs | 34.4 μs | 34.3 μs | 34.5 μs | 34.8 μs | ExpFromLeft (34.3 μs) | 1.01x | -| bimodal | unsorted | 1024 | 4096 | 144.0 μs | 143.1 μs | 142.9 μs | 142.7 μs | 142.5 μs | 142.5 μs | 144.3 μs | Binary (142.5 μs) | 1.00x | -| bimodal | unsorted | 1024 | 16384 | 618.9 μs | 617.9 μs | 615.9 μs | 616.1 μs | 615.6 μs | 614.5 μs | 620.0 μs | Binary (615.6 μs) | 1.00x | -| near_linear | sorted_uniform | 64 | 1024 | 8.8 μs | 15.1 μs | 11.7 μs | 30.9 μs | 18.1 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | -| near_linear | sorted_uniform | 64 | 4096 | 30.8 μs | 57.3 μs | 43.5 μs | 113.9 μs | 68.5 μs | 32.1 μs | 60.2 μs | Linear (30.8 μs) | 1.04x | -| near_linear | sorted_uniform | 64 | 16384 | 119.3 μs | 225.3 μs | 170.6 μs | 444.9 μs | 270.4 μs | 124.1 μs | 237.2 μs | Linear (119.3 μs) | 1.04x | -| near_linear | sorted_uniform | 256 | 1024 | 10.1 μs | 18.1 μs | 13.7 μs | 37.5 μs | 29.1 μs | 10.3 μs | 25.5 μs | Linear (10.1 μs) | 1.02x | -| near_linear | sorted_uniform | 256 | 4096 | 35.0 μs | 60.7 μs | 47.1 μs | 124.1 μs | 131.0 μs | 36.2 μs | 83.9 μs | Linear (35.0 μs) | 1.04x | -| near_linear | sorted_uniform | 256 | 16384 | 123.2 μs | 229.3 μs | 174.1 μs | 455.6 μs | 390.2 μs | 128.5 μs | 317.7 μs | Linear (123.2 μs) | 1.04x | -| near_linear | sorted_uniform | 1024 | 1024 | 10.2 μs | 18.2 μs | 12.6 μs | 39.2 μs | 75.0 μs | 9.9 μs | 58.1 μs | Linear (10.2 μs) | 0.98x | -| near_linear | sorted_uniform | 1024 | 4096 | 47.5 μs | 75.0 μs | 57.6 μs | 152.4 μs | 240.6 μs | 49.0 μs | 191.3 μs | Linear (47.5 μs) | 1.03x | -| near_linear | sorted_uniform | 1024 | 16384 | 141.7 μs | 242.8 μs | 188.1 μs | 495.8 μs | 597.4 μs | 147.3 μs | 487.6 μs | Linear (141.7 μs) | 1.04x | -| near_linear | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.9 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | -| near_linear | sorted_dense_burst | 64 | 4096 | 29.4 μs | 56.3 μs | 42.3 μs | 110.4 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.4 μs) | 1.05x | -| near_linear | sorted_dense_burst | 64 | 16384 | 117.6 μs | 224.6 μs | 168.9 μs | 442.4 μs | 271.6 μs | 123.4 μs | 227.1 μs | Linear (117.6 μs) | 1.05x | -| near_linear | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.1 μs | 10.6 μs | 27.7 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.05x | -| near_linear | sorted_dense_burst | 256 | 4096 | 29.3 μs | 56.2 μs | 42.3 μs | 110.3 μs | 87.4 μs | 30.8 μs | 76.4 μs | Linear (29.3 μs) | 1.05x | -| near_linear | sorted_dense_burst | 256 | 16384 | 117.5 μs | 225.0 μs | 168.8 μs | 442.0 μs | 349.2 μs | 122.8 μs | 305.9 μs | Linear (117.5 μs) | 1.05x | -| near_linear | sorted_dense_burst | 1024 | 1024 | 7.5 μs | 14.2 μs | 10.6 μs | 27.6 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.5 μs) | 1.05x | -| near_linear | sorted_dense_burst | 1024 | 4096 | 29.5 μs | 56.3 μs | 42.3 μs | 110.5 μs | 106.8 μs | 30.8 μs | 95.8 μs | Linear (29.5 μs) | 1.05x | -| near_linear | sorted_dense_burst | 1024 | 16384 | 117.5 μs | 224.9 μs | 168.7 μs | 441.2 μs | 427.4 μs | 123.2 μs | 383.2 μs | Linear (117.5 μs) | 1.05x | -| near_linear | unsorted | 64 | 1024 | 44.3 μs | 43.1 μs | 42.4 μs | 42.3 μs | 43.2 μs | 42.0 μs | 45.2 μs | InterpSearch (42.3 μs) | 0.99x | -| near_linear | unsorted | 64 | 4096 | 233.9 μs | 233.1 μs | 230.5 μs | 230.4 μs | 229.5 μs | 230.1 μs | 233.2 μs | Binary (229.5 μs) | 1.00x | -| near_linear | unsorted | 64 | 16384 | 982.8 μs | 985.4 μs | 982.3 μs | 981.1 μs | 980.8 μs | 982.7 μs | 982.6 μs | Binary (980.8 μs) | 1.00x | -| near_linear | unsorted | 256 | 1024 | 57.2 μs | 55.3 μs | 54.7 μs | 54.1 μs | 53.8 μs | 53.6 μs | 58.5 μs | Binary (53.8 μs) | 1.00x | -| near_linear | unsorted | 256 | 4096 | 315.0 μs | 311.5 μs | 312.0 μs | 311.2 μs | 310.1 μs | 310.9 μs | 314.4 μs | Binary (310.1 μs) | 1.00x | -| near_linear | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.31 ms | 1.30 ms | 1.30 ms | 1.31 ms | 1.31 ms | Binary (1.30 ms) | 1.00x | -| near_linear | unsorted | 1024 | 1024 | 81.6 μs | 79.2 μs | 77.9 μs | 76.7 μs | 76.4 μs | 76.6 μs | 83.5 μs | Binary (76.4 μs) | 1.00x | -| near_linear | unsorted | 1024 | 4096 | 411.4 μs | 408.2 μs | 409.2 μs | 407.7 μs | 406.7 μs | 406.7 μs | 414.4 μs | Binary (406.7 μs) | 1.00x | -| near_linear | unsorted | 1024 | 16384 | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.68 ms | 1.68 ms | Gallop (1.67 ms) | 1.00x | +| two_scale | sorted_uniform | 64 | 1024 | 8.0 μs | 14.4 μs | 11.4 μs | 42.2 μs | 17.8 μs | 8.4 μs | 15.2 μs | Linear (8.0 μs) | 1.06x | +| two_scale | sorted_uniform | 64 | 4096 | 30.2 μs | 58.7 μs | 44.4 μs | 159.4 μs | 68.8 μs | 31.4 μs | 59.1 μs | Linear (30.2 μs) | 1.04x | +| two_scale | sorted_uniform | 64 | 16384 | 116.9 μs | 222.2 μs | 175.6 μs | 630.9 μs | 273.6 μs | 125.4 μs | 236.2 μs | Linear (116.9 μs) | 1.07x | +| two_scale | sorted_uniform | 256 | 1024 | 9.5 μs | 15.7 μs | 12.7 μs | 56.4 μs | 23.4 μs | 9.9 μs | 21.3 μs | Linear (9.5 μs) | 1.05x | +| two_scale | sorted_uniform | 256 | 4096 | 32.1 μs | 57.1 μs | 45.9 μs | 211.8 μs | 90.0 μs | 33.5 μs | 80.6 μs | Linear (32.1 μs) | 1.04x | +| two_scale | sorted_uniform | 256 | 16384 | 119.2 μs | 222.0 μs | 176.8 μs | 820.4 μs | 353.5 μs | 127.4 μs | 313.8 μs | Linear (119.2 μs) | 1.07x | +| two_scale | sorted_uniform | 1024 | 1024 | 9.9 μs | 17.2 μs | 12.6 μs | 70.6 μs | 45.4 μs | 10.3 μs | 32.5 μs | Linear (9.9 μs) | 1.05x | +| two_scale | sorted_uniform | 1024 | 4096 | 38.6 μs | 63.7 μs | 51.6 μs | 292.3 μs | 162.3 μs | 40.7 μs | 114.1 μs | Linear (38.6 μs) | 1.05x | +| two_scale | sorted_uniform | 1024 | 16384 | 128.3 μs | 239.5 μs | 183.7 μs | 1.04 ms | 501.3 μs | 136.3 μs | 412.6 μs | Linear (128.3 μs) | 1.06x | +| two_scale | sorted_dense_burst | 64 | 1024 | 7.5 μs | 14.6 μs | 10.9 μs | 47.0 μs | 17.3 μs | 7.8 μs | 14.5 μs | Linear (7.5 μs) | 1.05x | +| two_scale | sorted_dense_burst | 64 | 4096 | 29.1 μs | 54.8 μs | 43.5 μs | 186.4 μs | 67.9 μs | 30.8 μs | 56.9 μs | Linear (29.1 μs) | 1.06x | +| two_scale | sorted_dense_burst | 64 | 16384 | 116.7 μs | 219.2 μs | 173.5 μs | 748.9 μs | 271.5 μs | 123.0 μs | 226.9 μs | Linear (116.7 μs) | 1.05x | +| two_scale | sorted_dense_burst | 256 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 55.9 μs | 21.8 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.05x | +| two_scale | sorted_dense_burst | 256 | 4096 | 29.2 μs | 55.0 μs | 43.6 μs | 224.2 μs | 87.2 μs | 30.8 μs | 76.5 μs | Linear (29.2 μs) | 1.05x | +| two_scale | sorted_dense_burst | 256 | 16384 | 116.2 μs | 219.7 μs | 174.3 μs | 896.0 μs | 349.3 μs | 122.9 μs | 305.9 μs | Linear (116.2 μs) | 1.06x | +| two_scale | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 65.6 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.05x | +| two_scale | sorted_dense_burst | 1024 | 4096 | 29.1 μs | 54.9 μs | 44.3 μs | 261.1 μs | 107.2 μs | 31.3 μs | 96.8 μs | Linear (29.1 μs) | 1.08x | +| two_scale | sorted_dense_burst | 1024 | 16384 | 117.0 μs | 219.6 μs | 174.2 μs | 1.04 ms | 427.6 μs | 124.9 μs | 383.2 μs | Linear (117.0 μs) | 1.07x | +| two_scale | unsorted | 64 | 1024 | 45.1 μs | 44.4 μs | 44.5 μs | 44.7 μs | 44.8 μs | 44.9 μs | 41.2 μs | Gallop (44.4 μs) | 1.01x | +| two_scale | unsorted | 64 | 4096 | 199.8 μs | 200.3 μs | 198.9 μs | 198.4 μs | 199.5 μs | 199.0 μs | 182.5 μs | InterpSearch (198.4 μs) | 1.00x | +| two_scale | unsorted | 64 | 16384 | 830.1 μs | 837.8 μs | 836.1 μs | 836.5 μs | 835.5 μs | 840.0 μs | 764.3 μs | Linear (830.1 μs) | 1.01x | +| two_scale | unsorted | 256 | 1024 | 54.1 μs | 52.9 μs | 53.4 μs | 53.2 μs | 53.2 μs | 53.1 μs | 51.5 μs | Gallop (52.9 μs) | 1.00x | +| two_scale | unsorted | 256 | 4096 | 256.1 μs | 256.1 μs | 255.3 μs | 255.1 μs | 255.1 μs | 255.2 μs | 251.2 μs | InterpSearch (255.1 μs) | 1.00x | +| two_scale | unsorted | 256 | 16384 | 1.07 ms | 1.06 ms | 1.06 ms | 1.07 ms | 1.06 ms | 1.07 ms | 1.03 ms | Gallop (1.06 ms) | 1.00x | +| two_scale | unsorted | 1024 | 1024 | 74.2 μs | 71.0 μs | 70.6 μs | 70.8 μs | 70.7 μs | 70.6 μs | 70.1 μs | ExpFromLeft (70.6 μs) | 1.00x | +| two_scale | unsorted | 1024 | 4096 | 348.7 μs | 347.2 μs | 347.2 μs | 345.7 μs | 344.6 μs | 345.8 μs | 344.5 μs | Binary (344.6 μs) | 1.00x | +| two_scale | unsorted | 1024 | 16384 | 1.43 ms | 1.43 ms | 1.43 ms | 1.42 ms | 1.42 ms | 1.43 ms | 1.41 ms | Binary (1.42 ms) | 1.00x | +| power2 | sorted_uniform | 64 | 1024 | 8.4 μs | 14.7 μs | 11.9 μs | 41.5 μs | 17.8 μs | 8.8 μs | 15.9 μs | Linear (8.4 μs) | 1.05x | +| power2 | sorted_uniform | 64 | 4096 | 30.4 μs | 55.9 μs | 44.7 μs | 159.0 μs | 69.8 μs | 32.0 μs | 60.1 μs | Linear (30.4 μs) | 1.05x | +| power2 | sorted_uniform | 64 | 16384 | 117.7 μs | 219.7 μs | 175.6 μs | 626.1 μs | 272.2 μs | 124.1 μs | 237.0 μs | Linear (117.7 μs) | 1.05x | +| power2 | sorted_uniform | 256 | 1024 | 9.8 μs | 16.6 μs | 12.9 μs | 53.9 μs | 25.5 μs | 10.0 μs | 24.2 μs | Linear (9.8 μs) | 1.03x | +| power2 | sorted_uniform | 256 | 4096 | 34.0 μs | 58.9 μs | 47.5 μs | 203.0 μs | 113.9 μs | 35.2 μs | 83.4 μs | Linear (34.0 μs) | 1.03x | +| power2 | sorted_uniform | 256 | 16384 | 121.7 μs | 223.8 μs | 178.8 μs | 780.2 μs | 392.7 μs | 129.5 μs | 317.5 μs | Linear (121.7 μs) | 1.06x | +| power2 | sorted_uniform | 1024 | 1024 | 10.2 μs | 17.7 μs | 12.7 μs | 65.6 μs | 64.7 μs | 10.7 μs | 48.2 μs | Linear (10.2 μs) | 1.06x | +| power2 | sorted_uniform | 1024 | 4096 | 42.8 μs | 69.9 μs | 54.5 μs | 267.5 μs | 224.0 μs | 44.8 μs | 173.6 μs | Linear (42.8 μs) | 1.05x | +| power2 | sorted_uniform | 1024 | 16384 | 136.1 μs | 235.9 μs | 190.4 μs | 979.4 μs | 581.3 μs | 141.3 μs | 477.3 μs | Linear (136.1 μs) | 1.04x | +| power2 | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.6 μs | 11.1 μs | 43.4 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | +| power2 | sorted_dense_burst | 64 | 4096 | 29.1 μs | 54.8 μs | 44.3 μs | 173.3 μs | 69.2 μs | 31.2 μs | 57.9 μs | Linear (29.1 μs) | 1.07x | +| power2 | sorted_dense_burst | 64 | 16384 | 116.2 μs | 219.2 μs | 173.8 μs | 693.7 μs | 271.6 μs | 122.8 μs | 227.2 μs | Linear (116.2 μs) | 1.06x | +| power2 | sorted_dense_burst | 256 | 1024 | 11.1 μs | 18.5 μs | 11.1 μs | 53.9 μs | 21.9 μs | 7.8 μs | 19.1 μs | ExpFromLeft (11.1 μs) | 0.70x | +| power2 | sorted_dense_burst | 256 | 4096 | 29.1 μs | 58.3 μs | 43.5 μs | 215.6 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (29.1 μs) | 1.06x | +| power2 | sorted_dense_burst | 256 | 16384 | 116.3 μs | 219.6 μs | 174.3 μs | 860.2 μs | 349.1 μs | 122.9 μs | 309.6 μs | Linear (116.3 μs) | 1.06x | +| power2 | sorted_dense_burst | 1024 | 1024 | 11.1 μs | 18.5 μs | 11.1 μs | 63.5 μs | 26.7 μs | 7.8 μs | 24.0 μs | ExpFromLeft (11.1 μs) | 0.70x | +| power2 | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 55.6 μs | 44.3 μs | 254.1 μs | 106.7 μs | 30.9 μs | 95.8 μs | Linear (29.2 μs) | 1.06x | +| power2 | sorted_dense_burst | 1024 | 16384 | 116.4 μs | 222.5 μs | 177.1 μs | 1.02 ms | 427.3 μs | 122.9 μs | 386.9 μs | Linear (116.4 μs) | 1.06x | +| power2 | unsorted | 64 | 1024 | 40.7 μs | 39.7 μs | 39.7 μs | 39.2 μs | 39.3 μs | 39.2 μs | 37.4 μs | InterpSearch (39.2 μs) | 1.00x | +| power2 | unsorted | 64 | 4096 | 221.0 μs | 217.6 μs | 216.0 μs | 216.8 μs | 215.4 μs | 215.1 μs | 212.1 μs | Binary (215.4 μs) | 1.00x | +| power2 | unsorted | 64 | 16384 | 916.4 μs | 914.6 μs | 915.9 μs | 914.2 μs | 915.0 μs | 915.5 μs | 913.8 μs | InterpSearch (914.2 μs) | 1.00x | +| power2 | unsorted | 256 | 1024 | 52.9 μs | 51.7 μs | 51.8 μs | 51.1 μs | 51.3 μs | 50.9 μs | 49.8 μs | InterpSearch (51.1 μs) | 1.00x | +| power2 | unsorted | 256 | 4096 | 302.8 μs | 299.6 μs | 299.1 μs | 297.0 μs | 294.5 μs | 298.6 μs | 298.0 μs | Binary (294.5 μs) | 1.01x | +| power2 | unsorted | 256 | 16384 | 1.24 ms | 1.24 ms | 1.24 ms | 1.24 ms | 1.23 ms | 1.24 ms | 1.23 ms | Binary (1.23 ms) | 1.01x | +| power2 | unsorted | 1024 | 1024 | 81.6 μs | 76.1 μs | 75.2 μs | 74.6 μs | 74.1 μs | 74.0 μs | 73.7 μs | Binary (74.1 μs) | 1.00x | +| power2 | unsorted | 1024 | 4096 | 392.3 μs | 391.4 μs | 390.7 μs | 388.0 μs | 390.6 μs | 390.0 μs | 390.9 μs | InterpSearch (388.0 μs) | 1.01x | +| power2 | unsorted | 1024 | 16384 | 1.59 ms | 1.60 ms | 1.60 ms | 1.59 ms | 1.59 ms | 1.59 ms | 1.60 ms | InterpSearch (1.59 ms) | 1.00x | +| sqrt | sorted_uniform | 64 | 1024 | 8.8 μs | 15.0 μs | 12.2 μs | 41.1 μs | 17.6 μs | 9.3 μs | 16.1 μs | Linear (8.8 μs) | 1.06x | +| sqrt | sorted_uniform | 64 | 4096 | 30.5 μs | 56.6 μs | 44.8 μs | 157.7 μs | 68.4 μs | 32.1 μs | 60.5 μs | Linear (30.5 μs) | 1.05x | +| sqrt | sorted_uniform | 64 | 16384 | 117.7 μs | 222.5 μs | 175.2 μs | 626.7 μs | 273.4 μs | 124.1 μs | 240.2 μs | Linear (117.7 μs) | 1.05x | +| sqrt | sorted_uniform | 256 | 1024 | 9.2 μs | 17.4 μs | 12.8 μs | 53.5 μs | 25.6 μs | 9.7 μs | 24.1 μs | Linear (9.2 μs) | 1.05x | +| sqrt | sorted_uniform | 256 | 4096 | 35.0 μs | 60.3 μs | 48.1 μs | 206.3 μs | 124.5 μs | 36.1 μs | 83.9 μs | Linear (35.0 μs) | 1.03x | +| sqrt | sorted_uniform | 256 | 16384 | 123.7 μs | 227.1 μs | 179.0 μs | 790.9 μs | 392.9 μs | 128.4 μs | 317.6 μs | Linear (123.7 μs) | 1.04x | +| sqrt | sorted_uniform | 1024 | 1024 | 10.7 μs | 18.2 μs | 12.8 μs | 64.7 μs | 59.8 μs | 10.7 μs | 45.8 μs | Linear (10.7 μs) | 1.00x | +| sqrt | sorted_uniform | 1024 | 4096 | 43.4 μs | 70.5 μs | 55.2 μs | 261.5 μs | 223.9 μs | 44.2 μs | 183.1 μs | Linear (43.4 μs) | 1.02x | +| sqrt | sorted_uniform | 1024 | 16384 | 139.2 μs | 237.4 μs | 191.6 μs | 966.5 μs | 588.2 μs | 144.8 μs | 488.2 μs | Linear (139.2 μs) | 1.04x | +| sqrt | sorted_dense_burst | 64 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 40.2 μs | 17.3 μs | 7.8 μs | 14.5 μs | Linear (7.4 μs) | 1.05x | +| sqrt | sorted_dense_burst | 64 | 4096 | 29.1 μs | 54.8 μs | 43.7 μs | 161.0 μs | 67.9 μs | 30.9 μs | 56.8 μs | Linear (29.1 μs) | 1.06x | +| sqrt | sorted_dense_burst | 64 | 16384 | 116.5 μs | 219.2 μs | 174.2 μs | 641.2 μs | 271.8 μs | 124.9 μs | 227.1 μs | Linear (116.5 μs) | 1.07x | +| sqrt | sorted_dense_burst | 256 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 50.4 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | +| sqrt | sorted_dense_burst | 256 | 4096 | 29.1 μs | 55.0 μs | 43.6 μs | 199.6 μs | 87.6 μs | 30.8 μs | 76.4 μs | Linear (29.1 μs) | 1.06x | +| sqrt | sorted_dense_burst | 256 | 16384 | 116.3 μs | 219.7 μs | 174.5 μs | 799.8 μs | 349.4 μs | 122.9 μs | 305.8 μs | Linear (116.3 μs) | 1.06x | +| sqrt | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 60.1 μs | 26.8 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.06x | +| sqrt | sorted_dense_burst | 1024 | 4096 | 29.3 μs | 55.0 μs | 43.6 μs | 240.6 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.3 μs) | 1.05x | +| sqrt | sorted_dense_burst | 1024 | 16384 | 116.3 μs | 232.9 μs | 173.9 μs | 963.5 μs | 429.0 μs | 124.9 μs | 383.1 μs | Linear (116.3 μs) | 1.07x | +| sqrt | unsorted | 64 | 1024 | 43.9 μs | 42.9 μs | 42.2 μs | 41.7 μs | 41.8 μs | 41.8 μs | 40.0 μs | InterpSearch (41.7 μs) | 1.00x | +| sqrt | unsorted | 64 | 4096 | 211.6 μs | 212.6 μs | 211.6 μs | 210.1 μs | 210.2 μs | 209.6 μs | 207.3 μs | InterpSearch (210.1 μs) | 1.00x | +| sqrt | unsorted | 64 | 16384 | 909.1 μs | 908.2 μs | 909.8 μs | 904.5 μs | 906.9 μs | 907.1 μs | 885.0 μs | InterpSearch (904.5 μs) | 1.00x | +| sqrt | unsorted | 256 | 1024 | 52.2 μs | 52.0 μs | 50.4 μs | 50.6 μs | 50.0 μs | 49.8 μs | 49.0 μs | Binary (50.0 μs) | 1.00x | +| sqrt | unsorted | 256 | 4096 | 290.0 μs | 288.4 μs | 287.8 μs | 284.3 μs | 281.2 μs | 284.2 μs | 281.4 μs | Binary (281.2 μs) | 1.01x | +| sqrt | unsorted | 256 | 16384 | 1.20 ms | 1.20 ms | 1.20 ms | 1.20 ms | 1.20 ms | 1.20 ms | 1.18 ms | ExpFromLeft (1.20 ms) | 1.01x | +| sqrt | unsorted | 1024 | 1024 | 74.3 μs | 71.3 μs | 70.1 μs | 69.9 μs | 69.5 μs | 69.3 μs | 71.7 μs | Binary (69.5 μs) | 1.00x | +| sqrt | unsorted | 1024 | 4096 | 379.5 μs | 375.1 μs | 375.2 μs | 374.3 μs | 375.4 μs | 374.1 μs | 377.7 μs | InterpSearch (374.3 μs) | 1.00x | +| sqrt | unsorted | 1024 | 16384 | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.55 ms | Gallop (1.54 ms) | 1.00x | +| plateau | sorted_uniform | 64 | 1024 | 7.9 μs | 14.7 μs | 11.0 μs | 39.4 μs | 17.0 μs | 7.8 μs | 14.7 μs | Linear (7.9 μs) | 0.99x | +| plateau | sorted_uniform | 64 | 4096 | 29.2 μs | 55.0 μs | 43.7 μs | 152.8 μs | 67.8 μs | 44.4 μs | 64.0 μs | Linear (29.2 μs) | 1.52x | +| plateau | sorted_uniform | 64 | 16384 | 116.6 μs | 219.7 μs | 174.0 μs | 606.6 μs | 274.9 μs | 123.1 μs | 234.7 μs | Linear (116.6 μs) | 1.06x | +| plateau | sorted_uniform | 256 | 1024 | 7.5 μs | 13.8 μs | 11.0 μs | 53.5 μs | 21.9 μs | 11.1 μs | 19.8 μs | Linear (7.5 μs) | 1.48x | +| plateau | sorted_uniform | 256 | 4096 | 29.8 μs | 58.4 μs | 43.5 μs | 194.1 μs | 87.4 μs | 30.9 μs | 78.4 μs | Linear (29.8 μs) | 1.04x | +| plateau | sorted_uniform | 256 | 16384 | 116.4 μs | 219.7 μs | 174.5 μs | 753.4 μs | 349.6 μs | 123.1 μs | 313.5 μs | Linear (116.4 μs) | 1.06x | +| plateau | sorted_uniform | 1024 | 1024 | 7.9 μs | 13.9 μs | 11.0 μs | 73.6 μs | 26.6 μs | 8.3 μs | 24.3 μs | Linear (7.9 μs) | 1.05x | +| plateau | sorted_uniform | 1024 | 4096 | 29.7 μs | 55.0 μs | 43.7 μs | 292.0 μs | 106.1 μs | 31.3 μs | 97.2 μs | Linear (29.7 μs) | 1.06x | +| plateau | sorted_uniform | 1024 | 16384 | 116.8 μs | 219.8 μs | 174.1 μs | 982.9 μs | 424.1 μs | 123.3 μs | 389.0 μs | Linear (116.8 μs) | 1.06x | +| plateau | sorted_dense_burst | 64 | 1024 | 7.4 μs | 13.8 μs | 10.3 μs | 40.1 μs | 17.1 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | +| plateau | sorted_dense_burst | 64 | 4096 | 29.1 μs | 54.8 μs | 41.3 μs | 160.1 μs | 68.0 μs | 30.8 μs | 57.1 μs | Linear (29.1 μs) | 1.06x | +| plateau | sorted_dense_burst | 64 | 16384 | 116.5 μs | 219.2 μs | 164.9 μs | 640.2 μs | 272.5 μs | 122.8 μs | 228.6 μs | Linear (116.5 μs) | 1.05x | +| plateau | sorted_dense_burst | 256 | 1024 | 7.4 μs | 13.8 μs | 10.3 μs | 49.6 μs | 21.8 μs | 7.8 μs | 19.6 μs | Linear (7.4 μs) | 1.06x | +| plateau | sorted_dense_burst | 256 | 4096 | 29.3 μs | 55.0 μs | 41.3 μs | 197.6 μs | 87.0 μs | 30.9 μs | 78.2 μs | Linear (29.3 μs) | 1.06x | +| plateau | sorted_dense_burst | 256 | 16384 | 116.3 μs | 220.0 μs | 165.0 μs | 790.1 μs | 347.9 μs | 123.6 μs | 312.3 μs | Linear (116.3 μs) | 1.06x | +| plateau | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.8 μs | 10.4 μs | 60.6 μs | 26.7 μs | 7.8 μs | 24.2 μs | Linear (7.4 μs) | 1.05x | +| plateau | sorted_dense_burst | 1024 | 4096 | 29.1 μs | 55.0 μs | 41.3 μs | 242.2 μs | 106.6 μs | 30.9 μs | 96.8 μs | Linear (29.1 μs) | 1.06x | +| plateau | sorted_dense_burst | 1024 | 16384 | 116.3 μs | 219.7 μs | 164.8 μs | 969.5 μs | 426.9 μs | 123.0 μs | 386.8 μs | Linear (116.3 μs) | 1.06x | +| plateau | unsorted | 64 | 1024 | 23.1 μs | 23.2 μs | 23.1 μs | 23.0 μs | 23.3 μs | 23.0 μs | 22.7 μs | InterpSearch (23.0 μs) | 1.00x | +| plateau | unsorted | 64 | 4096 | 91.6 μs | 90.0 μs | 90.1 μs | 91.9 μs | 90.1 μs | 90.0 μs | 89.2 μs | Gallop (90.0 μs) | 1.00x | +| plateau | unsorted | 64 | 16384 | 362.5 μs | 363.0 μs | 360.2 μs | 368.4 μs | 363.0 μs | 360.0 μs | 358.7 μs | ExpFromLeft (360.2 μs) | 1.00x | +| plateau | unsorted | 256 | 1024 | 27.4 μs | 27.1 μs | 27.4 μs | 27.4 μs | 27.4 μs | 27.4 μs | 26.9 μs | Gallop (27.1 μs) | 1.01x | +| plateau | unsorted | 256 | 4096 | 108.5 μs | 108.5 μs | 108.4 μs | 108.5 μs | 108.7 μs | 108.4 μs | 107.6 μs | ExpFromLeft (108.4 μs) | 1.00x | +| plateau | unsorted | 256 | 16384 | 435.5 μs | 435.1 μs | 434.9 μs | 434.9 μs | 435.2 μs | 435.3 μs | 431.4 μs | InterpSearch (434.9 μs) | 1.00x | +| plateau | unsorted | 1024 | 1024 | 31.8 μs | 31.9 μs | 31.9 μs | 31.9 μs | 31.9 μs | 31.9 μs | 32.1 μs | Linear (31.8 μs) | 1.00x | +| plateau | unsorted | 1024 | 4096 | 128.4 μs | 128.0 μs | 128.8 μs | 128.3 μs | 128.2 μs | 128.3 μs | 129.2 μs | Gallop (128.0 μs) | 1.00x | +| plateau | unsorted | 1024 | 16384 | 513.6 μs | 513.8 μs | 513.7 μs | 513.9 μs | 513.6 μs | 513.8 μs | 518.4 μs | Binary (513.6 μs) | 1.00x | +| bimodal | sorted_uniform | 64 | 1024 | 7.5 μs | 14.4 μs | 11.2 μs | 42.7 μs | 17.1 μs | 7.9 μs | 14.9 μs | Linear (7.5 μs) | 1.05x | +| bimodal | sorted_uniform | 64 | 4096 | 30.1 μs | 56.5 μs | 44.4 μs | 163.6 μs | 68.3 μs | 31.7 μs | 58.1 μs | Linear (30.1 μs) | 1.06x | +| bimodal | sorted_uniform | 64 | 16384 | 117.7 μs | 222.5 μs | 175.0 μs | 647.1 μs | 272.2 μs | 124.2 μs | 230.0 μs | Linear (117.7 μs) | 1.06x | +| bimodal | sorted_uniform | 256 | 1024 | 8.1 μs | 14.5 μs | 11.3 μs | 55.3 μs | 22.1 μs | 8.4 μs | 20.6 μs | Linear (8.1 μs) | 1.04x | +| bimodal | sorted_uniform | 256 | 4096 | 30.2 μs | 58.3 μs | 45.2 μs | 211.2 μs | 88.8 μs | 31.8 μs | 80.5 μs | Linear (30.2 μs) | 1.05x | +| bimodal | sorted_uniform | 256 | 16384 | 121.6 μs | 226.5 μs | 178.2 μs | 807.1 μs | 360.7 μs | 127.9 μs | 312.0 μs | Linear (121.6 μs) | 1.05x | +| bimodal | sorted_uniform | 1024 | 1024 | 9.3 μs | 15.5 μs | 12.0 μs | 76.8 μs | 27.1 μs | 9.8 μs | 25.5 μs | Linear (9.3 μs) | 1.05x | +| bimodal | sorted_uniform | 1024 | 4096 | 32.0 μs | 59.4 μs | 45.5 μs | 325.5 μs | 125.7 μs | 33.4 μs | 109.0 μs | Linear (32.0 μs) | 1.04x | +| bimodal | sorted_uniform | 1024 | 16384 | 127.3 μs | 235.4 μs | 184.6 μs | 1.08 ms | 526.3 μs | 134.0 μs | 447.4 μs | Linear (127.3 μs) | 1.05x | +| bimodal | sorted_dense_burst | 64 | 1024 | 7.3 μs | 13.8 μs | 10.9 μs | 42.8 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.3 μs) | 1.06x | +| bimodal | sorted_dense_burst | 64 | 4096 | 29.2 μs | 54.8 μs | 43.6 μs | 167.6 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.2 μs) | 1.05x | +| bimodal | sorted_dense_burst | 64 | 16384 | 116.3 μs | 219.3 μs | 173.9 μs | 666.1 μs | 271.6 μs | 123.4 μs | 227.4 μs | Linear (116.3 μs) | 1.06x | +| bimodal | sorted_dense_burst | 256 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 55.9 μs | 21.9 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.06x | +| bimodal | sorted_dense_burst | 256 | 4096 | 29.2 μs | 55.0 μs | 43.5 μs | 204.1 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (29.2 μs) | 1.06x | +| bimodal | sorted_dense_burst | 256 | 16384 | 116.4 μs | 219.6 μs | 177.0 μs | 799.7 μs | 349.2 μs | 122.8 μs | 305.8 μs | Linear (116.4 μs) | 1.06x | +| bimodal | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 75.2 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.06x | +| bimodal | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 55.0 μs | 43.6 μs | 304.7 μs | 106.8 μs | 30.9 μs | 95.7 μs | Linear (29.2 μs) | 1.06x | +| bimodal | sorted_dense_burst | 1024 | 16384 | 116.9 μs | 219.7 μs | 173.9 μs | 1.03 ms | 427.2 μs | 123.0 μs | 383.0 μs | Linear (116.9 μs) | 1.05x | +| bimodal | unsorted | 64 | 1024 | 22.2 μs | 22.3 μs | 21.4 μs | 21.4 μs | 21.5 μs | 21.4 μs | 21.0 μs | ExpFromLeft (21.4 μs) | 1.00x | +| bimodal | unsorted | 64 | 4096 | 88.3 μs | 90.8 μs | 87.9 μs | 87.7 μs | 88.2 μs | 88.0 μs | 86.1 μs | InterpSearch (87.7 μs) | 1.00x | +| bimodal | unsorted | 64 | 16384 | 365.4 μs | 365.1 μs | 365.6 μs | 365.2 μs | 365.2 μs | 365.1 μs | 353.0 μs | Gallop (365.1 μs) | 1.00x | +| bimodal | unsorted | 256 | 1024 | 29.0 μs | 28.7 μs | 28.7 μs | 28.7 μs | 28.8 μs | 28.7 μs | 27.2 μs | ExpFromLeft (28.7 μs) | 1.00x | +| bimodal | unsorted | 256 | 4096 | 119.8 μs | 119.5 μs | 119.6 μs | 119.8 μs | 119.5 μs | 119.5 μs | 112.4 μs | Binary (119.5 μs) | 1.00x | +| bimodal | unsorted | 256 | 16384 | 490.2 μs | 490.4 μs | 490.4 μs | 490.2 μs | 490.4 μs | 493.5 μs | 467.1 μs | Linear (490.2 μs) | 1.01x | +| bimodal | unsorted | 1024 | 1024 | 35.4 μs | 34.7 μs | 34.7 μs | 34.7 μs | 34.6 μs | 34.7 μs | 33.8 μs | Binary (34.6 μs) | 1.00x | +| bimodal | unsorted | 1024 | 4096 | 143.9 μs | 143.6 μs | 143.4 μs | 143.5 μs | 143.4 μs | 143.7 μs | 138.1 μs | ExpFromLeft (143.4 μs) | 1.00x | +| bimodal | unsorted | 1024 | 16384 | 620.9 μs | 618.2 μs | 617.4 μs | 616.5 μs | 616.4 μs | 616.2 μs | 603.8 μs | Binary (616.4 μs) | 1.00x | +| near_linear | sorted_uniform | 64 | 1024 | 8.8 μs | 14.9 μs | 12.0 μs | 30.5 μs | 18.1 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | +| near_linear | sorted_uniform | 64 | 4096 | 30.5 μs | 55.9 μs | 44.7 μs | 112.6 μs | 68.5 μs | 32.0 μs | 60.2 μs | Linear (30.5 μs) | 1.05x | +| near_linear | sorted_uniform | 64 | 16384 | 117.6 μs | 220.1 μs | 175.6 μs | 441.2 μs | 270.6 μs | 124.1 μs | 236.6 μs | Linear (117.6 μs) | 1.06x | +| near_linear | sorted_uniform | 256 | 1024 | 9.9 μs | 17.7 μs | 14.1 μs | 37.2 μs | 28.1 μs | 10.3 μs | 25.6 μs | Linear (9.9 μs) | 1.04x | +| near_linear | sorted_uniform | 256 | 4096 | 34.7 μs | 59.3 μs | 48.1 μs | 122.7 μs | 128.1 μs | 36.3 μs | 84.1 μs | Linear (34.7 μs) | 1.05x | +| near_linear | sorted_uniform | 256 | 16384 | 121.8 μs | 223.9 μs | 178.9 μs | 450.9 μs | 386.7 μs | 128.6 μs | 316.6 μs | Linear (121.8 μs) | 1.06x | +| near_linear | sorted_uniform | 1024 | 1024 | 10.4 μs | 17.4 μs | 12.9 μs | 38.6 μs | 70.7 μs | 10.6 μs | 54.4 μs | Linear (10.4 μs) | 1.02x | +| near_linear | sorted_uniform | 1024 | 4096 | 47.1 μs | 73.3 μs | 58.9 μs | 149.9 μs | 236.2 μs | 47.2 μs | 191.7 μs | Linear (47.1 μs) | 1.00x | +| near_linear | sorted_uniform | 1024 | 16384 | 139.4 μs | 237.2 μs | 192.5 μs | 490.9 μs | 590.3 μs | 144.9 μs | 483.9 μs | Linear (139.4 μs) | 1.04x | +| near_linear | sorted_dense_burst | 64 | 1024 | 7.3 μs | 13.9 μs | 10.9 μs | 27.5 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.3 μs) | 1.06x | +| near_linear | sorted_dense_burst | 64 | 4096 | 29.2 μs | 55.6 μs | 43.5 μs | 109.7 μs | 70.5 μs | 44.3 μs | 56.8 μs | Linear (29.2 μs) | 1.52x | +| near_linear | sorted_dense_burst | 64 | 16384 | 116.4 μs | 222.1 μs | 173.8 μs | 438.8 μs | 271.9 μs | 122.9 μs | 227.2 μs | Linear (116.4 μs) | 1.06x | +| near_linear | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 27.6 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | +| near_linear | sorted_dense_burst | 256 | 4096 | 31.2 μs | 55.7 μs | 43.7 μs | 109.6 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (31.2 μs) | 0.99x | +| near_linear | sorted_dense_burst | 256 | 16384 | 116.4 μs | 222.3 μs | 174.2 μs | 438.9 μs | 349.2 μs | 122.9 μs | 305.9 μs | Linear (116.4 μs) | 1.06x | +| near_linear | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 27.4 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | +| near_linear | sorted_dense_burst | 1024 | 4096 | 29.3 μs | 55.5 μs | 43.5 μs | 109.7 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.3 μs) | 1.05x | +| near_linear | sorted_dense_burst | 1024 | 16384 | 116.4 μs | 222.3 μs | 173.9 μs | 438.3 μs | 427.3 μs | 123.4 μs | 383.0 μs | Linear (116.4 μs) | 1.06x | +| near_linear | unsorted | 64 | 1024 | 44.2 μs | 41.8 μs | 41.6 μs | 42.8 μs | 41.1 μs | 41.0 μs | 39.7 μs | Binary (41.1 μs) | 1.00x | +| near_linear | unsorted | 64 | 4096 | 232.4 μs | 232.0 μs | 230.3 μs | 229.6 μs | 229.8 μs | 229.6 μs | 227.9 μs | InterpSearch (229.6 μs) | 1.00x | +| near_linear | unsorted | 64 | 16384 | 982.1 μs | 977.6 μs | 978.2 μs | 978.3 μs | 982.8 μs | 980.8 μs | 971.5 μs | Gallop (977.6 μs) | 1.00x | +| near_linear | unsorted | 256 | 1024 | 58.4 μs | 55.6 μs | 53.3 μs | 53.1 μs | 52.8 μs | 52.7 μs | 51.0 μs | Binary (52.8 μs) | 1.00x | +| near_linear | unsorted | 256 | 4096 | 317.0 μs | 312.3 μs | 311.2 μs | 312.5 μs | 310.4 μs | 313.9 μs | 311.2 μs | Binary (310.4 μs) | 1.01x | +| near_linear | unsorted | 256 | 16384 | 1.31 ms | 1.31 ms | 1.31 ms | 1.31 ms | 1.31 ms | 1.31 ms | 1.30 ms | ExpFromLeft (1.31 ms) | 1.00x | +| near_linear | unsorted | 1024 | 1024 | 81.2 μs | 79.0 μs | 77.7 μs | 76.6 μs | 76.3 μs | 76.2 μs | 77.2 μs | Binary (76.3 μs) | 1.00x | +| near_linear | unsorted | 1024 | 4096 | 411.7 μs | 409.2 μs | 409.7 μs | 408.9 μs | 409.0 μs | 408.5 μs | 409.2 μs | InterpSearch (408.9 μs) | 1.00x | +| near_linear | unsorted | 1024 | 16384 | 1.67 ms | 1.68 ms | 1.68 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.69 ms | Binary (1.67 ms) | 1.00x | -**Auto verdict over 270 cells**: 270 within 20% of best, 0 worse than 20% slowdown, 0 effectively-faster-than-best. +**Auto verdict over 270 cells**: 263 within 20% of best, 4 worse than 20% slowdown, 3 effectively-faster-than-best. diff --git a/bench/results_tune.md b/bench/results_tune.md new file mode 100644 index 0000000..331fc72 --- /dev/null +++ b/bench/results_tune.md @@ -0,0 +1,103 @@ + +## Tune: LinearScan vs ExpFromLeft crossover (n=4096, uniform) + +| gap (≈n/m) | m | Linear | ExpFromLeft | winner | margin | +|---|---|---|---|---|---| +| 1 | 4096 | 66.1 μs | 70.8 μs | Linear | 7% | +| 2 | 2048 | 28.3 μs | 32.5 μs | Linear | 15% | +| 3 | 1365 | 21.0 μs | 22.2 μs | Linear | 6% | +| 4 | 1024 | 15.8 μs | 16.8 μs | Linear | 7% | +| 6 | 682 | 12.5 μs | 12.1 μs | ExpFromLeft | 3% | +| 8 | 512 | 10.7 μs | 9.6 μs | ExpFromLeft | 11% | +| 12 | 341 | 9.4 μs | 6.8 μs | ExpFromLeft | 37% | +| 16 | 256 | 8.5 μs | 5.2 μs | ExpFromLeft | 66% | +| 24 | 170 | 8.1 μs | 3.8 μs | ExpFromLeft | 112% | +| 32 | 128 | 8.2 μs | 3.0 μs | ExpFromLeft | 172% | +| 48 | 85 | 7.5 μs | 2.2 μs | ExpFromLeft | 246% | +| 64 | 64 | 7.3 μs | 1.8 μs | ExpFromLeft | 317% | +| 96 | 42 | 6.8 μs | 1.2 μs | ExpFromLeft | 452% | +| 128 | 32 | 6.5 μs | 970 ns | ExpFromLeft | 575% | +| 192 | 21 | 5.9 μs | 750 ns | ExpFromLeft | 691% | +| 256 | 16 | 5.8 μs | 580 ns | ExpFromLeft | 893% | + +## Tune: ExpFromLeft vs InterpolationSearch crossover (n=65536, uniform) + +| gap (≈n/m) | m | ExpFromLeft | InterpSearch | winner | margin | +|---|---|---|---|---|---| +| 8 | 8192 | 355.6 μs | 324.0 μs | InterpSearch | 10% | +| 16 | 4096 | 209.2 μs | 166.0 μs | InterpSearch | 26% | +| 24 | 2730 | 143.0 μs | 113.3 μs | InterpSearch | 26% | +| 32 | 2048 | 104.2 μs | 84.0 μs | InterpSearch | 24% | +| 48 | 1365 | 61.8 μs | 55.2 μs | InterpSearch | 12% | +| 64 | 1024 | 44.1 μs | 41.2 μs | InterpSearch | 7% | +| 96 | 682 | 27.4 μs | 26.4 μs | InterpSearch | 4% | +| 128 | 512 | 19.7 μs | 20.0 μs | ExpFromLeft | 2% | +| 256 | 256 | 10.2 μs | 9.5 μs | InterpSearch | 7% | +| 512 | 128 | 5.0 μs | 4.6 μs | InterpSearch | 9% | +| 1024 | 64 | 2.7 μs | 2.1 μs | InterpSearch | 29% | +| 4096 | 16 | 790 ns | 490 ns | InterpSearch | 61% | +| 16384 | 4 | 240 ns | 150 ns | InterpSearch | 60% | +| 65536 | 1 | 80 ns | 60 ns | InterpSearch | 33% | + +## Tune: minimum n at which InterpolationSearch wins (uniform, m=16) + +| n | gap | ExpFromLeft | InterpSearch | winner | margin | +|---|---|---|---|---|---| +| 32 | 2 | 250 ns | 470 ns | ExpFromLeft | 88% | +| 64 | 4 | 290 ns | 470 ns | ExpFromLeft | 62% | +| 128 | 8 | 310 ns | 490 ns | ExpFromLeft | 58% | +| 256 | 16 | 380 ns | 500 ns | ExpFromLeft | 32% | +| 512 | 32 | 420 ns | 470 ns | ExpFromLeft | 12% | +| 1024 | 64 | 460 ns | 500 ns | ExpFromLeft | 9% | +| 2048 | 128 | 520 ns | 480 ns | InterpSearch | 8% | +| 4096 | 256 | 560 ns | 470 ns | InterpSearch | 19% | +| 8192 | 512 | 600 ns | 480 ns | InterpSearch | 25% | +| 16384 | 1024 | 650 ns | 460 ns | InterpSearch | 41% | +| 65536 | 4096 | 740 ns | 480 ns | InterpSearch | 54% | +| 262144 | 16384 | 870 ns | 460 ns | InterpSearch | 89% | + +## Tune: minimum m at which InterpolationSearch wins (uniform, n=65536) + +| m | gap | ExpFromLeft | InterpSearch | winner | margin | +|---|---|---|---|---|---| +| 1 | 65536 | 80 ns | 70 ns | InterpSearch | 14% | +| 2 | 32768 | 150 ns | 90 ns | InterpSearch | 67% | +| 3 | 21845 | 180 ns | 120 ns | InterpSearch | 50% | +| 4 | 16384 | 210 ns | 140 ns | InterpSearch | 50% | +| 6 | 10922 | 310 ns | 200 ns | InterpSearch | 55% | +| 8 | 8192 | 430 ns | 240 ns | InterpSearch | 79% | +| 12 | 5461 | 600 ns | 360 ns | InterpSearch | 67% | +| 16 | 4096 | 760 ns | 470 ns | InterpSearch | 62% | +| 24 | 2730 | 1.1 μs | 680 ns | InterpSearch | 59% | +| 32 | 2048 | 1.4 μs | 1.0 μs | InterpSearch | 38% | +| 64 | 1024 | 2.6 μs | 2.0 μs | InterpSearch | 29% | +| 128 | 512 | 4.9 μs | 4.3 μs | InterpSearch | 12% | +| 256 | 256 | 9.4 μs | 9.5 μs | ExpFromLeft | 1% | +| 1024 | 64 | 43.2 μs | 40.9 μs | InterpSearch | 6% | +| 4096 | 16 | 200.7 μs | 165.0 μs | InterpSearch | 22% | + +## Tune: InterpolationSearch downside on non-linear data (m=256) + +| spacing | n | ExpFromLeft | InterpSearch | InterpSearch slowdown | +|---|---|---|---|---| +| log | 1024 | 3.2 μs | 21.4 μs | 6.78x | +| log | 16384 | 6.1 μs | 29.5 μs | 4.81x | +| log | 262144 | 10.3 μs | 44.8 μs | 4.33x | +| random | 1024 | 3.8 μs | 9.7 μs | 2.55x | +| random | 16384 | 7.2 μs | 12.4 μs | 1.71x | +| random | 262144 | 13.1 μs | 19.3 μs | 1.48x | +| two_scale | 1024 | 3.3 μs | 23.3 μs | 7.09x | +| two_scale | 16384 | 6.3 μs | 31.0 μs | 4.94x | +| two_scale | 262144 | 10.9 μs | 46.9 μs | 4.29x | +| power2 | 1024 | 3.6 μs | 22.5 μs | 6.18x | +| power2 | 16384 | 7.0 μs | 31.5 μs | 4.48x | +| power2 | 262144 | 12.4 μs | 48.1 μs | 3.88x | +| sqrt | 1024 | 3.7 μs | 21.1 μs | 5.77x | +| sqrt | 16384 | 7.2 μs | 29.2 μs | 4.06x | +| sqrt | 262144 | 13.2 μs | 46.4 μs | 3.52x | +| plateau | 1024 | 2.7 μs | 22.8 μs | 8.32x | +| plateau | 16384 | 2.8 μs | 29.6 μs | 10.74x | +| plateau | 262144 | 2.8 μs | 39.3 μs | 14.11x | +| bimodal | 1024 | 3.3 μs | 23.6 μs | 7.19x | +| bimodal | 16384 | 4.3 μs | 30.4 μs | 7.10x | +| bimodal | 262144 | 4.6 μs | 42.1 μs | 9.19x | diff --git a/bench/results_validate.md b/bench/results_validate.md new file mode 100644 index 0000000..9783452 --- /dev/null +++ b/bench/results_validate.md @@ -0,0 +1,3927 @@ + +## Validation sweep (many cells) + +| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| uniform | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 40 ns | ExpFromLeft (50 ns) | 1.20x | +| uniform | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| uniform | sorted_uniform | 16 | 16 | 189 ns | 290 ns | 220 ns | 470 ns | 230 ns | 210 ns | 190 ns | Linear (189 ns) | 1.11x | +| uniform | sorted_uniform | 16 | 64 | 560 ns | 990 ns | 730 ns | 1.9 μs | 990 ns | 590 ns | 860 ns | Linear (560 ns) | 1.05x | +| uniform | sorted_uniform | 16 | 256 | 2.3 μs | 3.7 μs | 3.0 μs | 7.8 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.02x | +| uniform | sorted_uniform | 16 | 1024 | 8.1 μs | 14.1 μs | 10.8 μs | 28.1 μs | 12.2 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 0.99x | +| uniform | sorted_uniform | 16 | 4096 | 31.1 μs | 55.3 μs | 42.3 μs | 109.1 μs | 48.1 μs | 31.1 μs | 40.6 μs | Linear (31.1 μs) | 1.00x | +| uniform | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| uniform | sorted_uniform | 64 | 4 | 120 ns | 130 ns | 120 ns | 150 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | +| uniform | sorted_uniform | 64 | 16 | 260 ns | 350 ns | 280 ns | 470 ns | 300 ns | 270 ns | 270 ns | Linear (260 ns) | 1.04x | +| uniform | sorted_uniform | 64 | 64 | 640 ns | 1.1 μs | 750 ns | 2.1 μs | 1.4 μs | 670 ns | 1.2 μs | Linear (640 ns) | 1.05x | +| uniform | sorted_uniform | 64 | 256 | 2.2 μs | 4.2 μs | 3.1 μs | 8.7 μs | 5.2 μs | 2.2 μs | 4.8 μs | Linear (2.2 μs) | 1.00x | +| uniform | sorted_uniform | 64 | 1024 | 9.2 μs | 14.9 μs | 11.7 μs | 31.4 μs | 17.8 μs | 9.2 μs | 16.0 μs | Linear (9.2 μs) | 1.00x | +| uniform | sorted_uniform | 64 | 4096 | 32.2 μs | 56.4 μs | 43.2 μs | 112.9 μs | 67.4 μs | 32.2 μs | 60.3 μs | Linear (32.2 μs) | 1.00x | +| uniform | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_uniform | 256 | 4 | 170 ns | 140 ns | 120 ns | 150 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | +| uniform | sorted_uniform | 256 | 16 | 520 ns | 460 ns | 370 ns | 460 ns | 370 ns | 400 ns | 340 ns | ExpFromLeft (370 ns) | 1.08x | +| uniform | sorted_uniform | 256 | 64 | 900 ns | 1.3 μs | 1.0 μs | 1.9 μs | 1.6 μs | 940 ns | 1.4 μs | Linear (900 ns) | 1.04x | +| uniform | sorted_uniform | 256 | 256 | 2.4 μs | 4.1 μs | 2.9 μs | 8.8 μs | 7.5 μs | 2.5 μs | 6.9 μs | Linear (2.4 μs) | 1.04x | +| uniform | sorted_uniform | 256 | 1024 | 9.8 μs | 17.9 μs | 13.7 μs | 36.0 μs | 27.3 μs | 9.9 μs | 24.9 μs | Linear (9.8 μs) | 1.01x | +| uniform | sorted_uniform | 256 | 4096 | 36.6 μs | 59.6 μs | 46.6 μs | 125.3 μs | 91.6 μs | 36.5 μs | 83.6 μs | Linear (36.6 μs) | 1.00x | +| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_uniform | 1024 | 4 | 1.1 μs | 180 ns | 160 ns | 150 ns | 150 ns | 200 ns | 130 ns | InterpSearch (150 ns) | 1.33x | +| uniform | sorted_uniform | 1024 | 16 | 1.7 μs | 600 ns | 470 ns | 460 ns | 440 ns | 530 ns | 400 ns | Binary (440 ns) | 1.20x | +| uniform | sorted_uniform | 1024 | 64 | 2.1 μs | 1.8 μs | 1.4 μs | 2.0 μs | 1.8 μs | 2.2 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.58x | +| uniform | sorted_uniform | 1024 | 256 | 3.5 μs | 5.4 μs | 3.8 μs | 8.8 μs | 7.8 μs | 3.6 μs | 7.5 μs | Linear (3.5 μs) | 1.01x | +| uniform | sorted_uniform | 1024 | 1024 | 10.7 μs | 18.1 μs | 12.2 μs | 38.4 μs | 58.6 μs | 10.4 μs | 54.2 μs | Linear (10.7 μs) | 0.98x | +| uniform | sorted_uniform | 1024 | 4096 | 48.5 μs | 73.1 μs | 57.3 μs | 153.8 μs | 192.6 μs | 48.4 μs | 190.8 μs | Linear (48.5 μs) | 1.00x | +| uniform | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_uniform | 4096 | 4 | 5.4 μs | 240 ns | 210 ns | 150 ns | 160 ns | 190 ns | 140 ns | InterpSearch (150 ns) | 1.27x | +| uniform | sorted_uniform | 4096 | 16 | 4.8 μs | 710 ns | 550 ns | 480 ns | 530 ns | 559 ns | 490 ns | InterpSearch (480 ns) | 1.16x | +| uniform | sorted_uniform | 4096 | 64 | 7.5 μs | 2.3 μs | 1.8 μs | 2.1 μs | 2.0 μs | 2.3 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.29x | +| uniform | sorted_uniform | 4096 | 256 | 8.5 μs | 7.1 μs | 5.4 μs | 9.3 μs | 10.8 μs | 9.6 μs | 9.9 μs | ExpFromLeft (5.4 μs) | 1.77x | +| uniform | sorted_uniform | 4096 | 1024 | 16.8 μs | 23.6 μs | 17.0 μs | 38.5 μs | 97.6 μs | 15.3 μs | 93.0 μs | Linear (16.8 μs) | 0.91x | +| uniform | sorted_uniform | 4096 | 4096 | 66.7 μs | 93.9 μs | 70.7 μs | 160.5 μs | 298.2 μs | 63.0 μs | 291.0 μs | Linear (66.7 μs) | 0.95x | +| uniform | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_uniform | 16384 | 4 | 12.2 μs | 260 ns | 209 ns | 140 ns | 180 ns | 190 ns | 170 ns | InterpSearch (140 ns) | 1.36x | +| uniform | sorted_uniform | 16384 | 16 | 16.7 μs | 850 ns | 640 ns | 470 ns | 600 ns | 530 ns | 540 ns | InterpSearch (470 ns) | 1.13x | +| uniform | sorted_uniform | 16384 | 64 | 24.0 μs | 3.0 μs | 2.3 μs | 2.0 μs | 2.4 μs | 2.3 μs | 2.3 μs | InterpSearch (2.0 μs) | 1.14x | +| uniform | sorted_uniform | 16384 | 256 | 30.4 μs | 9.2 μs | 7.2 μs | 9.2 μs | 13.1 μs | 9.8 μs | 13.7 μs | ExpFromLeft (7.2 μs) | 1.36x | +| uniform | sorted_uniform | 16384 | 1024 | 40.3 μs | 36.7 μs | 26.4 μs | 38.5 μs | 124.0 μs | 40.2 μs | 127.0 μs | ExpFromLeft (26.4 μs) | 1.52x | +| uniform | sorted_uniform | 16384 | 4096 | 114.7 μs | 162.3 μs | 121.8 μs | 160.3 μs | 399.4 μs | 111.0 μs | 392.5 μs | Linear (114.7 μs) | 0.97x | +| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_uniform | 65536 | 4 | 57.1 μs | 300 ns | 240 ns | 150 ns | 200 ns | 190 ns | 180 ns | InterpSearch (150 ns) | 1.27x | +| uniform | sorted_uniform | 65536 | 16 | 75.7 μs | 1.0 μs | 760 ns | 470 ns | 700 ns | 540 ns | 660 ns | InterpSearch (470 ns) | 1.15x | +| uniform | sorted_uniform | 65536 | 64 | 91.9 μs | 3.6 μs | 2.6 μs | 2.0 μs | 2.8 μs | 2.2 μs | 2.6 μs | InterpSearch (2.0 μs) | 1.08x | +| uniform | sorted_uniform | 65536 | 256 | 101.3 μs | 12.5 μs | 9.7 μs | 9.2 μs | 16.3 μs | 9.7 μs | 16.6 μs | InterpSearch (9.2 μs) | 1.05x | +| uniform | sorted_uniform | 65536 | 1024 | 122.0 μs | 61.1 μs | 44.4 μs | 40.2 μs | 155.6 μs | 42.1 μs | 161.9 μs | InterpSearch (40.2 μs) | 1.05x | +| uniform | sorted_uniform | 65536 | 4096 | 197.8 μs | 251.6 μs | 199.3 μs | 163.8 μs | 488.6 μs | 170.5 μs | 497.6 μs | InterpSearch (163.8 μs) | 1.04x | +| uniform | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 60 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| uniform | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 230 ns | 510 ns | 240 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | +| uniform | sorted_dense_burst | 16 | 64 | 560 ns | 960 ns | 740 ns | 1.8 μs | 800 ns | 580 ns | 680 ns | Linear (560 ns) | 1.04x | +| uniform | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.7 μs | 2.7 μs | 7.0 μs | 3.0 μs | 2.1 μs | 3.3 μs | Linear (2.0 μs) | 1.06x | +| uniform | sorted_dense_burst | 16 | 1024 | 7.8 μs | 14.5 μs | 10.6 μs | 28.0 μs | 12.0 μs | 8.3 μs | 9.9 μs | Linear (7.8 μs) | 1.06x | +| uniform | sorted_dense_burst | 16 | 4096 | 31.2 μs | 58.0 μs | 41.9 μs | 108.0 μs | 47.2 μs | 32.9 μs | 38.5 μs | Linear (31.2 μs) | 1.05x | +| uniform | sorted_dense_burst | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| uniform | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 100 ns | 150 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| uniform | sorted_dense_burst | 64 | 16 | 180 ns | 280 ns | 230 ns | 490 ns | 310 ns | 200 ns | 270 ns | Linear (180 ns) | 1.11x | +| uniform | sorted_dense_burst | 64 | 64 | 550 ns | 940 ns | 730 ns | 1.8 μs | 1.1 μs | 580 ns | 920 ns | Linear (550 ns) | 1.05x | +| uniform | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 6.9 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.95x | +| uniform | sorted_dense_burst | 64 | 1024 | 8.3 μs | 13.8 μs | 10.4 μs | 27.3 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (8.3 μs) | 0.94x | +| uniform | sorted_dense_burst | 64 | 4096 | 32.8 μs | 54.9 μs | 42.1 μs | 108.8 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (32.8 μs) | 0.94x | +| uniform | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 50 ns | InterpSearch (60 ns) | 1.00x | +| uniform | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 130 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| uniform | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 510 ns | 380 ns | 200 ns | 350 ns | Linear (170 ns) | 1.18x | +| uniform | sorted_dense_burst | 256 | 64 | 550 ns | 930 ns | 740 ns | 1.8 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | +| uniform | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 5.4 μs | 2.1 μs | 4.8 μs | Linear (2.0 μs) | 1.08x | +| uniform | sorted_dense_burst | 256 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 27.3 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.01x | +| uniform | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 109.2 μs | 85.8 μs | 32.9 μs | 76.4 μs | Linear (30.8 μs) | 1.07x | +| uniform | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 150 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | +| uniform | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 240 ns | 490 ns | 459 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | +| uniform | sorted_dense_burst | 1024 | 64 | 570 ns | 930 ns | 730 ns | 1.8 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (570 ns) | 1.04x | +| uniform | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 27.4 μs | 26.4 μs | 8.3 μs | 24.0 μs | Linear (7.8 μs) | 1.07x | +| uniform | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 108.5 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_dense_burst | 4096 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 170 ns | 120 ns | 140 ns | Linear (100 ns) | 1.20x | +| uniform | sorted_dense_burst | 4096 | 16 | 190 ns | 290 ns | 240 ns | 490 ns | 540 ns | 210 ns | 480 ns | Linear (190 ns) | 1.11x | +| uniform | sorted_dense_burst | 4096 | 64 | 570 ns | 940 ns | 750 ns | 1.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (570 ns) | 1.04x | +| uniform | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | +| uniform | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 27.3 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | +| uniform | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 108.8 μs | 124.6 μs | 30.8 μs | 114.1 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | +| uniform | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 240 ns | 480 ns | 620 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | +| uniform | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 750 ns | 1.8 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | +| uniform | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | +| uniform | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 27.3 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 0.99x | +| uniform | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 54.9 μs | 42.1 μs | 108.9 μs | 144.2 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 150 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| uniform | sorted_dense_burst | 65536 | 16 | 190 ns | 290 ns | 250 ns | 500 ns | 690 ns | 210 ns | 640 ns | Linear (190 ns) | 1.11x | +| uniform | sorted_dense_burst | 65536 | 64 | 570 ns | 940 ns | 750 ns | 1.8 μs | 2.6 μs | 610 ns | 2.4 μs | Linear (570 ns) | 1.07x | +| uniform | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 27.4 μs | 40.8 μs | 7.8 μs | 38.2 μs | Linear (7.8 μs) | 0.99x | +| uniform | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 41.9 μs | 108.9 μs | 163.2 μs | 30.8 μs | 152.4 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_near_start | 16 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_near_start | 16 | 4 | 90 ns | 130 ns | 110 ns | 150 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | +| uniform | sorted_near_start | 16 | 16 | 190 ns | 280 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | +| uniform | sorted_near_start | 16 | 64 | 570 ns | 950 ns | 730 ns | 1.8 μs | 800 ns | 600 ns | 670 ns | Linear (570 ns) | 1.05x | +| uniform | sorted_near_start | 16 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 6.8 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_near_start | 16 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 27.2 μs | 12.2 μs | 8.0 μs | 10.3 μs | Linear (7.9 μs) | 1.01x | +| uniform | sorted_near_start | 16 | 4096 | 31.1 μs | 55.1 μs | 42.3 μs | 106.9 μs | 47.8 μs | 31.1 μs | 40.3 μs | Linear (31.1 μs) | 1.00x | +| uniform | sorted_near_start | 64 | 1 | 60 ns | 60 ns | 50 ns | 69 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_near_start | 64 | 4 | 90 ns | 120 ns | 100 ns | 150 ns | 100 ns | 110 ns | 90 ns | Linear (90 ns) | 1.22x | +| uniform | sorted_near_start | 64 | 16 | 260 ns | 320 ns | 240 ns | 480 ns | 330 ns | 280 ns | 290 ns | ExpFromLeft (240 ns) | 1.17x | +| uniform | sorted_near_start | 64 | 64 | 670 ns | 1.0 μs | 800 ns | 1.8 μs | 1.1 μs | 690 ns | 1.0 μs | Linear (670 ns) | 1.03x | +| uniform | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.0 μs | 4.2 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | +| uniform | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 27.5 μs | 17.2 μs | 7.9 μs | 15.5 μs | Linear (7.9 μs) | 1.00x | +| uniform | sorted_near_start | 64 | 4096 | 31.8 μs | 55.9 μs | 43.0 μs | 110.6 μs | 67.3 μs | 31.8 μs | 60.5 μs | Linear (31.8 μs) | 1.00x | +| uniform | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_near_start | 256 | 4 | 320 ns | 140 ns | 120 ns | 150 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | +| uniform | sorted_near_start | 256 | 16 | 440 ns | 330 ns | 260 ns | 500 ns | 480 ns | 280 ns | 410 ns | ExpFromLeft (260 ns) | 1.08x | +| uniform | sorted_near_start | 256 | 64 | 800 ns | 1.1 μs | 790 ns | 2.1 μs | 1.6 μs | 840 ns | 1.4 μs | ExpFromLeft (790 ns) | 1.06x | +| uniform | sorted_near_start | 256 | 256 | 2.6 μs | 4.0 μs | 3.1 μs | 7.7 μs | 5.6 μs | 2.7 μs | 5.1 μs | Linear (2.6 μs) | 1.03x | +| uniform | sorted_near_start | 256 | 1024 | 8.4 μs | 14.4 μs | 11.0 μs | 29.5 μs | 22.3 μs | 8.4 μs | 20.4 μs | Linear (8.4 μs) | 1.00x | +| uniform | sorted_near_start | 256 | 4096 | 31.6 μs | 56.1 μs | 42.6 μs | 117.8 μs | 89.1 μs | 31.6 μs | 81.6 μs | Linear (31.6 μs) | 1.00x | +| uniform | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 69 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_near_start | 1024 | 4 | 380 ns | 170 ns | 140 ns | 150 ns | 130 ns | 200 ns | 130 ns | Binary (130 ns) | 1.54x | +| uniform | sorted_near_start | 1024 | 16 | 1.1 μs | 390 ns | 310 ns | 490 ns | 500 ns | 330 ns | 470 ns | ExpFromLeft (310 ns) | 1.06x | +| uniform | sorted_near_start | 1024 | 64 | 2.5 μs | 1.2 μs | 900 ns | 2.0 μs | 2.0 μs | 939 ns | 1.8 μs | ExpFromLeft (900 ns) | 1.04x | +| uniform | sorted_near_start | 1024 | 256 | 3.8 μs | 4.6 μs | 3.5 μs | 8.5 μs | 7.7 μs | 3.8 μs | 7.2 μs | ExpFromLeft (3.5 μs) | 1.10x | +| uniform | sorted_near_start | 1024 | 1024 | 10.6 μs | 15.8 μs | 12.3 μs | 31.6 μs | 27.5 μs | 10.4 μs | 25.9 μs | Linear (10.6 μs) | 0.98x | +| uniform | sorted_near_start | 1024 | 4096 | 33.8 μs | 58.1 μs | 44.1 μs | 116.5 μs | 111.0 μs | 34.6 μs | 105.1 μs | Linear (33.8 μs) | 1.02x | +| uniform | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_near_start | 4096 | 4 | 650 ns | 180 ns | 160 ns | 150 ns | 160 ns | 200 ns | 150 ns | InterpSearch (150 ns) | 1.33x | +| uniform | sorted_near_start | 4096 | 16 | 3.9 μs | 550 ns | 450 ns | 470 ns | 530 ns | 460 ns | 480 ns | ExpFromLeft (450 ns) | 1.02x | +| uniform | sorted_near_start | 4096 | 64 | 5.8 μs | 1.5 μs | 1.1 μs | 2.1 μs | 2.4 μs | 1.1 μs | 2.2 μs | ExpFromLeft (1.1 μs) | 1.03x | +| uniform | sorted_near_start | 4096 | 256 | 7.9 μs | 4.6 μs | 3.3 μs | 8.9 μs | 11.1 μs | 3.4 μs | 10.4 μs | ExpFromLeft (3.3 μs) | 1.02x | +| uniform | sorted_near_start | 4096 | 1024 | 16.3 μs | 19.4 μs | 14.7 μs | 36.5 μs | 44.2 μs | 16.4 μs | 38.7 μs | ExpFromLeft (14.7 μs) | 1.11x | +| uniform | sorted_near_start | 4096 | 4096 | 42.8 μs | 63.8 μs | 49.3 μs | 123.8 μs | 156.9 μs | 42.8 μs | 140.6 μs | Linear (42.8 μs) | 1.00x | +| uniform | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 70 ns | 60 ns | 80 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | +| uniform | sorted_near_start | 16384 | 4 | 6.9 μs | 230 ns | 190 ns | 150 ns | 180 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | +| uniform | sorted_near_start | 16384 | 16 | 3.1 μs | 600 ns | 480 ns | 460 ns | 640 ns | 500 ns | 620 ns | InterpSearch (460 ns) | 1.09x | +| uniform | sorted_near_start | 16384 | 64 | 13.5 μs | 1.9 μs | 1.5 μs | 2.0 μs | 3.3 μs | 1.5 μs | 3.0 μs | ExpFromLeft (1.5 μs) | 1.01x | +| uniform | sorted_near_start | 16384 | 256 | 26.3 μs | 6.1 μs | 4.3 μs | 9.0 μs | 17.9 μs | 4.3 μs | 17.0 μs | ExpFromLeft (4.3 μs) | 1.01x | +| uniform | sorted_near_start | 16384 | 1024 | 33.3 μs | 20.9 μs | 14.7 μs | 38.5 μs | 76.7 μs | 14.5 μs | 70.3 μs | ExpFromLeft (14.7 μs) | 0.99x | +| uniform | sorted_near_start | 16384 | 4096 | 73.9 μs | 79.3 μs | 62.5 μs | 149.7 μs | 259.9 μs | 73.4 μs | 242.7 μs | ExpFromLeft (62.5 μs) | 1.17x | +| uniform | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_near_start | 65536 | 4 | 26.4 μs | 260 ns | 220 ns | 140 ns | 200 ns | 190 ns | 190 ns | InterpSearch (140 ns) | 1.36x | +| uniform | sorted_near_start | 65536 | 16 | 74.9 μs | 800 ns | 600 ns | 470 ns | 670 ns | 610 ns | 630 ns | InterpSearch (470 ns) | 1.30x | +| uniform | sorted_near_start | 65536 | 64 | 88.4 μs | 2.5 μs | 1.9 μs | 2.0 μs | 3.8 μs | 1.9 μs | 3.5 μs | ExpFromLeft (1.9 μs) | 1.01x | +| uniform | sorted_near_start | 65536 | 256 | 93.9 μs | 8.1 μs | 5.8 μs | 8.9 μs | 20.9 μs | 5.8 μs | 18.8 μs | ExpFromLeft (5.8 μs) | 0.99x | +| uniform | sorted_near_start | 65536 | 1024 | 102.2 μs | 28.3 μs | 20.2 μs | 38.7 μs | 96.4 μs | 18.9 μs | 88.1 μs | ExpFromLeft (20.2 μs) | 0.94x | +| uniform | sorted_near_start | 65536 | 4096 | 153.3 μs | 120.9 μs | 96.0 μs | 161.4 μs | 324.1 μs | 92.9 μs | 298.4 μs | ExpFromLeft (96.0 μs) | 0.97x | +| uniform | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_arithmetic | 16 | 4 | 100 ns | 130 ns | 120 ns | 140 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | +| uniform | sorted_arithmetic | 16 | 16 | 190 ns | 310 ns | 220 ns | 460 ns | 230 ns | 200 ns | 199 ns | Linear (190 ns) | 1.05x | +| uniform | sorted_arithmetic | 16 | 64 | 650 ns | 1.0 μs | 790 ns | 1.8 μs | 980 ns | 650 ns | 850 ns | Linear (650 ns) | 1.00x | +| uniform | sorted_arithmetic | 16 | 256 | 2.0 μs | 3.8 μs | 2.7 μs | 7.8 μs | 3.3 μs | 2.0 μs | 2.8 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_arithmetic | 16 | 1024 | 8.0 μs | 14.0 μs | 10.8 μs | 28.1 μs | 12.2 μs | 8.1 μs | 10.5 μs | Linear (8.0 μs) | 1.00x | +| uniform | sorted_arithmetic | 16 | 4096 | 31.1 μs | 54.8 μs | 41.9 μs | 109.4 μs | 47.2 μs | 31.1 μs | 41.0 μs | Linear (31.1 μs) | 1.00x | +| uniform | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_arithmetic | 64 | 4 | 170 ns | 150 ns | 130 ns | 150 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | +| uniform | sorted_arithmetic | 64 | 16 | 280 ns | 430 ns | 360 ns | 480 ns | 310 ns | 310 ns | 270 ns | Linear (280 ns) | 1.11x | +| uniform | sorted_arithmetic | 64 | 64 | 660 ns | 1.1 μs | 730 ns | 1.7 μs | 1.1 μs | 690 ns | 960 ns | Linear (660 ns) | 1.05x | +| uniform | sorted_arithmetic | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 6.9 μs | 5.3 μs | 2.2 μs | 4.9 μs | Linear (2.1 μs) | 1.01x | +| uniform | sorted_arithmetic | 64 | 1024 | 8.2 μs | 14.8 μs | 11.7 μs | 31.1 μs | 17.7 μs | 8.2 μs | 16.0 μs | Linear (8.2 μs) | 1.00x | +| uniform | sorted_arithmetic | 64 | 4096 | 32.2 μs | 56.0 μs | 42.1 μs | 112.8 μs | 67.3 μs | 32.2 μs | 60.0 μs | Linear (32.2 μs) | 1.00x | +| uniform | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_arithmetic | 256 | 4 | 460 ns | 180 ns | 150 ns | 140 ns | 130 ns | 170 ns | 120 ns | Binary (130 ns) | 1.31x | +| uniform | sorted_arithmetic | 256 | 16 | 570 ns | 540 ns | 440 ns | 470 ns | 380 ns | 470 ns | 330 ns | Binary (380 ns) | 1.24x | +| uniform | sorted_arithmetic | 256 | 64 | 1.2 μs | 1.8 μs | 1.7 μs | 2.1 μs | 1.5 μs | 1.2 μs | 1.3 μs | Linear (1.2 μs) | 1.01x | +| uniform | sorted_arithmetic | 256 | 256 | 2.4 μs | 4.1 μs | 2.7 μs | 6.5 μs | 5.7 μs | 2.5 μs | 6.2 μs | Linear (2.4 μs) | 1.01x | +| uniform | sorted_arithmetic | 256 | 1024 | 8.3 μs | 14.6 μs | 10.6 μs | 27.3 μs | 26.9 μs | 8.3 μs | 25.5 μs | Linear (8.3 μs) | 1.00x | +| uniform | sorted_arithmetic | 256 | 4096 | 31.5 μs | 59.3 μs | 46.4 μs | 125.4 μs | 90.8 μs | 31.5 μs | 83.4 μs | Linear (31.5 μs) | 1.00x | +| uniform | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_arithmetic | 1024 | 4 | 1.6 μs | 220 ns | 170 ns | 140 ns | 140 ns | 190 ns | 130 ns | InterpSearch (140 ns) | 1.36x | +| uniform | sorted_arithmetic | 1024 | 16 | 1.7 μs | 690 ns | 520 ns | 490 ns | 450 ns | 560 ns | 420 ns | Binary (450 ns) | 1.24x | +| uniform | sorted_arithmetic | 1024 | 64 | 2.4 μs | 2.2 μs | 2.1 μs | 1.8 μs | 1.7 μs | 2.0 μs | 1.7 μs | Binary (1.7 μs) | 1.14x | +| uniform | sorted_arithmetic | 1024 | 256 | 3.5 μs | 6.2 μs | 4.6 μs | 7.1 μs | 7.9 μs | 3.6 μs | 7.5 μs | Linear (3.5 μs) | 1.01x | +| uniform | sorted_arithmetic | 1024 | 1024 | 9.5 μs | 16.4 μs | 10.6 μs | 25.9 μs | 93.1 μs | 9.6 μs | 91.9 μs | Linear (9.5 μs) | 1.01x | +| uniform | sorted_arithmetic | 1024 | 4096 | 32.8 μs | 57.9 μs | 42.2 μs | 109.0 μs | 197.9 μs | 32.8 μs | 194.8 μs | Linear (32.8 μs) | 1.00x | +| uniform | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_arithmetic | 4096 | 4 | 5.8 μs | 240 ns | 200 ns | 140 ns | 160 ns | 190 ns | 150 ns | InterpSearch (140 ns) | 1.36x | +| uniform | sorted_arithmetic | 4096 | 16 | 6.0 μs | 810 ns | 590 ns | 470 ns | 520 ns | 530 ns | 480 ns | InterpSearch (470 ns) | 1.13x | +| uniform | sorted_arithmetic | 4096 | 64 | 6.3 μs | 2.7 μs | 2.0 μs | 1.7 μs | 2.0 μs | 1.9 μs | 1.9 μs | InterpSearch (1.7 μs) | 1.11x | +| uniform | sorted_arithmetic | 4096 | 256 | 8.1 μs | 8.4 μs | 6.1 μs | 7.7 μs | 8.5 μs | 8.3 μs | 7.5 μs | ExpFromLeft (6.1 μs) | 1.37x | +| uniform | sorted_arithmetic | 4096 | 1024 | 13.9 μs | 24.5 μs | 18.4 μs | 27.5 μs | 84.2 μs | 13.9 μs | 76.0 μs | Linear (13.9 μs) | 1.00x | +| uniform | sorted_arithmetic | 4096 | 4096 | 37.7 μs | 65.4 μs | 42.0 μs | 103.3 μs | 319.9 μs | 37.8 μs | 307.8 μs | Linear (37.7 μs) | 1.00x | +| uniform | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_arithmetic | 16384 | 4 | 22.1 μs | 280 ns | 230 ns | 140 ns | 180 ns | 190 ns | 160 ns | InterpSearch (140 ns) | 1.36x | +| uniform | sorted_arithmetic | 16384 | 16 | 23.0 μs | 1.0 μs | 690 ns | 490 ns | 600 ns | 560 ns | 560 ns | InterpSearch (490 ns) | 1.14x | +| uniform | sorted_arithmetic | 16384 | 64 | 24.4 μs | 3.3 μs | 2.2 μs | 1.9 μs | 2.3 μs | 2.1 μs | 2.2 μs | InterpSearch (1.9 μs) | 1.09x | +| uniform | sorted_arithmetic | 16384 | 256 | 25.9 μs | 10.5 μs | 8.0 μs | 7.0 μs | 13.6 μs | 7.6 μs | 13.6 μs | InterpSearch (7.0 μs) | 1.09x | +| uniform | sorted_arithmetic | 16384 | 1024 | 31.6 μs | 32.7 μs | 24.3 μs | 28.2 μs | 107.1 μs | 30.5 μs | 103.5 μs | ExpFromLeft (24.3 μs) | 1.25x | +| uniform | sorted_arithmetic | 16384 | 4096 | 55.2 μs | 97.7 μs | 73.3 μs | 109.3 μs | 396.8 μs | 55.2 μs | 390.4 μs | Linear (55.2 μs) | 1.00x | +| uniform | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_arithmetic | 65536 | 4 | 86.7 μs | 320 ns | 250 ns | 140 ns | 210 ns | 190 ns | 180 ns | InterpSearch (140 ns) | 1.36x | +| uniform | sorted_arithmetic | 65536 | 16 | 87.3 μs | 1.2 μs | 800 ns | 460 ns | 710 ns | 530 ns | 660 ns | InterpSearch (460 ns) | 1.15x | +| uniform | sorted_arithmetic | 65536 | 64 | 89.2 μs | 3.9 μs | 2.8 μs | 1.9 μs | 2.9 μs | 2.0 μs | 2.7 μs | InterpSearch (1.9 μs) | 1.09x | +| uniform | sorted_arithmetic | 65536 | 256 | 96.2 μs | 12.8 μs | 8.8 μs | 6.5 μs | 11.4 μs | 7.0 μs | 12.4 μs | InterpSearch (6.5 μs) | 1.08x | +| uniform | sorted_arithmetic | 65536 | 1024 | 101.0 μs | 43.6 μs | 33.0 μs | 30.7 μs | 117.2 μs | 32.6 μs | 116.0 μs | InterpSearch (30.7 μs) | 1.06x | +| uniform | sorted_arithmetic | 65536 | 4096 | 126.9 μs | 130.2 μs | 97.7 μs | 110.0 μs | 411.9 μs | 117.9 μs | 400.7 μs | ExpFromLeft (97.7 μs) | 1.21x | +| uniform | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| uniform | sorted_geometric | 16 | 16 | 190 ns | 300 ns | 220 ns | 470 ns | 220 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| uniform | sorted_geometric | 16 | 64 | 560 ns | 1.0 μs | 780 ns | 1.9 μs | 960 ns | 590 ns | 860 ns | Linear (560 ns) | 1.05x | +| uniform | sorted_geometric | 16 | 256 | 2.2 μs | 3.7 μs | 3.0 μs | 7.7 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.2 μs) | 1.02x | +| uniform | sorted_geometric | 16 | 1024 | 8.1 μs | 14.1 μs | 10.8 μs | 28.0 μs | 12.1 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | +| uniform | sorted_geometric | 16 | 4096 | 31.1 μs | 55.7 μs | 42.3 μs | 108.9 μs | 47.6 μs | 31.1 μs | 39.9 μs | Linear (31.1 μs) | 1.00x | +| uniform | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| uniform | sorted_geometric | 64 | 4 | 170 ns | 140 ns | 130 ns | 150 ns | 110 ns | 140 ns | 100 ns | Binary (110 ns) | 1.27x | +| uniform | sorted_geometric | 64 | 16 | 270 ns | 380 ns | 290 ns | 470 ns | 310 ns | 280 ns | 270 ns | Linear (270 ns) | 1.04x | +| uniform | sorted_geometric | 64 | 64 | 640 ns | 1.1 μs | 730 ns | 2.0 μs | 1.3 μs | 670 ns | 1.1 μs | Linear (640 ns) | 1.05x | +| uniform | sorted_geometric | 64 | 256 | 2.3 μs | 4.0 μs | 3.0 μs | 8.4 μs | 5.4 μs | 2.3 μs | 4.9 μs | Linear (2.3 μs) | 1.01x | +| uniform | sorted_geometric | 64 | 1024 | 9.0 μs | 14.9 μs | 14.8 μs | 30.8 μs | 17.7 μs | 9.0 μs | 16.0 μs | Linear (9.0 μs) | 1.00x | +| uniform | sorted_geometric | 64 | 4096 | 32.2 μs | 56.6 μs | 43.2 μs | 112.7 μs | 67.1 μs | 32.2 μs | 60.3 μs | Linear (32.2 μs) | 1.00x | +| uniform | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_geometric | 256 | 4 | 480 ns | 170 ns | 140 ns | 150 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | +| uniform | sorted_geometric | 256 | 16 | 550 ns | 480 ns | 390 ns | 470 ns | 380 ns | 400 ns | 350 ns | Binary (380 ns) | 1.05x | +| uniform | sorted_geometric | 256 | 64 | 920 ns | 1.4 μs | 980 ns | 1.9 μs | 1.4 μs | 940 ns | 1.3 μs | Linear (920 ns) | 1.02x | +| uniform | sorted_geometric | 256 | 256 | 2.5 μs | 4.6 μs | 3.0 μs | 8.0 μs | 6.8 μs | 2.5 μs | 6.3 μs | Linear (2.5 μs) | 1.01x | +| uniform | sorted_geometric | 256 | 1024 | 9.7 μs | 16.3 μs | 12.3 μs | 32.6 μs | 27.5 μs | 9.7 μs | 25.9 μs | Linear (9.7 μs) | 1.00x | +| uniform | sorted_geometric | 256 | 4096 | 35.2 μs | 58.8 μs | 45.4 μs | 119.1 μs | 91.5 μs | 35.3 μs | 83.6 μs | Linear (35.2 μs) | 1.00x | +| uniform | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_geometric | 1024 | 4 | 1.6 μs | 200 ns | 180 ns | 150 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | +| uniform | sorted_geometric | 1024 | 16 | 1.8 μs | 620 ns | 480 ns | 510 ns | 450 ns | 510 ns | 410 ns | Binary (450 ns) | 1.13x | +| uniform | sorted_geometric | 1024 | 64 | 2.1 μs | 1.9 μs | 1.4 μs | 2.0 μs | 1.7 μs | 1.5 μs | 1.5 μs | ExpFromLeft (1.4 μs) | 1.03x | +| uniform | sorted_geometric | 1024 | 256 | 3.7 μs | 5.7 μs | 4.0 μs | 8.9 μs | 8.0 μs | 3.7 μs | 8.0 μs | Linear (3.7 μs) | 1.01x | +| uniform | sorted_geometric | 1024 | 1024 | 10.8 μs | 18.6 μs | 12.2 μs | 33.4 μs | 64.9 μs | 10.8 μs | 64.0 μs | Linear (10.8 μs) | 1.00x | +| uniform | sorted_geometric | 1024 | 4096 | 38.5 μs | 63.1 μs | 47.9 μs | 121.0 μs | 194.8 μs | 38.6 μs | 191.9 μs | Linear (38.5 μs) | 1.00x | +| uniform | sorted_geometric | 4096 | 1 | 69 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | Linear (69 ns) | 1.01x | +| uniform | sorted_geometric | 4096 | 4 | 6.0 μs | 240 ns | 190 ns | 150 ns | 160 ns | 190 ns | 150 ns | InterpSearch (150 ns) | 1.27x | +| uniform | sorted_geometric | 4096 | 16 | 6.3 μs | 760 ns | 580 ns | 460 ns | 530 ns | 600 ns | 490 ns | InterpSearch (460 ns) | 1.30x | +| uniform | sorted_geometric | 4096 | 64 | 7.4 μs | 2.5 μs | 1.8 μs | 2.0 μs | 2.0 μs | 1.9 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.02x | +| uniform | sorted_geometric | 4096 | 256 | 8.8 μs | 7.6 μs | 5.7 μs | 8.9 μs | 10.1 μs | 5.8 μs | 10.2 μs | ExpFromLeft (5.7 μs) | 1.01x | +| uniform | sorted_geometric | 4096 | 1024 | 15.9 μs | 24.1 μs | 17.2 μs | 33.7 μs | 96.2 μs | 15.9 μs | 87.1 μs | Linear (15.9 μs) | 1.00x | +| uniform | sorted_geometric | 4096 | 4096 | 44.5 μs | 73.9 μs | 49.9 μs | 124.9 μs | 307.4 μs | 44.5 μs | 299.9 μs | Linear (44.5 μs) | 1.00x | +| uniform | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_geometric | 16384 | 4 | 23.4 μs | 270 ns | 210 ns | 150 ns | 190 ns | 190 ns | 170 ns | InterpSearch (150 ns) | 1.27x | +| uniform | sorted_geometric | 16384 | 16 | 23.9 μs | 920 ns | 700 ns | 470 ns | 610 ns | 710 ns | 560 ns | InterpSearch (470 ns) | 1.51x | +| uniform | sorted_geometric | 16384 | 64 | 25.4 μs | 3.1 μs | 2.3 μs | 2.0 μs | 2.4 μs | 2.4 μs | 2.3 μs | InterpSearch (2.0 μs) | 1.19x | +| uniform | sorted_geometric | 16384 | 256 | 30.0 μs | 10.2 μs | 7.5 μs | 8.9 μs | 13.2 μs | 7.4 μs | 13.0 μs | ExpFromLeft (7.5 μs) | 0.99x | +| uniform | sorted_geometric | 16384 | 1024 | 36.2 μs | 32.0 μs | 24.6 μs | 35.6 μs | 122.5 μs | 25.0 μs | 121.4 μs | ExpFromLeft (24.6 μs) | 1.02x | +| uniform | sorted_geometric | 16384 | 4096 | 66.7 μs | 98.4 μs | 69.6 μs | 130.7 μs | 416.2 μs | 66.7 μs | 409.7 μs | Linear (66.7 μs) | 1.00x | +| uniform | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_geometric | 65536 | 4 | 93.0 μs | 310 ns | 250 ns | 150 ns | 200 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | +| uniform | sorted_geometric | 65536 | 16 | 93.5 μs | 1.1 μs | 810 ns | 470 ns | 690 ns | 830 ns | 650 ns | InterpSearch (470 ns) | 1.77x | +| uniform | sorted_geometric | 65536 | 64 | 95.4 μs | 3.7 μs | 2.8 μs | 2.1 μs | 2.9 μs | 2.8 μs | 2.7 μs | InterpSearch (2.1 μs) | 1.35x | +| uniform | sorted_geometric | 65536 | 256 | 101.9 μs | 13.4 μs | 9.8 μs | 9.6 μs | 17.3 μs | 11.1 μs | 17.7 μs | InterpSearch (9.6 μs) | 1.15x | +| uniform | sorted_geometric | 65536 | 1024 | 117.9 μs | 47.0 μs | 36.8 μs | 39.2 μs | 155.7 μs | 35.4 μs | 156.7 μs | ExpFromLeft (36.8 μs) | 0.96x | +| uniform | sorted_geometric | 65536 | 4096 | 145.8 μs | 133.7 μs | 102.7 μs | 132.3 μs | 501.4 μs | 106.1 μs | 505.0 μs | ExpFromLeft (102.7 μs) | 1.03x | +| uniform | sorted_bimodal | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_bimodal | 16 | 4 | 100 ns | 110 ns | 100 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| uniform | sorted_bimodal | 16 | 16 | 190 ns | 280 ns | 220 ns | 470 ns | 240 ns | 200 ns | 210 ns | Linear (190 ns) | 1.05x | +| uniform | sorted_bimodal | 16 | 64 | 590 ns | 970 ns | 800 ns | 1.9 μs | 880 ns | 620 ns | 760 ns | Linear (590 ns) | 1.05x | +| uniform | sorted_bimodal | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 6.8 μs | 3.2 μs | 2.1 μs | 2.8 μs | Linear (2.1 μs) | 1.02x | +| uniform | sorted_bimodal | 16 | 1024 | 7.8 μs | 13.4 μs | 10.6 μs | 26.9 μs | 12.6 μs | 7.9 μs | 11.0 μs | Linear (7.8 μs) | 1.01x | +| uniform | sorted_bimodal | 16 | 4096 | 30.9 μs | 53.3 μs | 42.1 μs | 107.0 μs | 50.1 μs | 30.9 μs | 43.5 μs | Linear (30.9 μs) | 1.00x | +| uniform | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | InterpSearch (60 ns) | 1.00x | +| uniform | sorted_bimodal | 64 | 4 | 160 ns | 120 ns | 120 ns | 150 ns | 100 ns | 140 ns | 90 ns | Binary (100 ns) | 1.40x | +| uniform | sorted_bimodal | 64 | 16 | 270 ns | 320 ns | 230 ns | 500 ns | 330 ns | 280 ns | 290 ns | ExpFromLeft (230 ns) | 1.22x | +| uniform | sorted_bimodal | 64 | 64 | 630 ns | 1.0 μs | 760 ns | 2.0 μs | 1.3 μs | 660 ns | 1.2 μs | Linear (630 ns) | 1.05x | +| uniform | sorted_bimodal | 64 | 256 | 2.3 μs | 3.7 μs | 2.9 μs | 7.6 μs | 4.4 μs | 2.3 μs | 4.0 μs | Linear (2.3 μs) | 1.01x | +| uniform | sorted_bimodal | 64 | 1024 | 11.4 μs | 18.7 μs | 14.2 μs | 30.6 μs | 18.9 μs | 11.4 μs | 16.4 μs | Linear (11.4 μs) | 1.00x | +| uniform | sorted_bimodal | 64 | 4096 | 31.1 μs | 54.9 μs | 42.3 μs | 108.7 μs | 66.8 μs | 31.1 μs | 59.9 μs | Linear (31.1 μs) | 1.00x | +| uniform | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_bimodal | 256 | 4 | 440 ns | 150 ns | 140 ns | 150 ns | 130 ns | 160 ns | 110 ns | Binary (130 ns) | 1.23x | +| uniform | sorted_bimodal | 256 | 16 | 560 ns | 360 ns | 270 ns | 460 ns | 410 ns | 280 ns | 360 ns | ExpFromLeft (270 ns) | 1.04x | +| uniform | sorted_bimodal | 256 | 64 | 920 ns | 1.1 μs | 760 ns | 2.0 μs | 1.7 μs | 960 ns | 1.6 μs | ExpFromLeft (760 ns) | 1.26x | +| uniform | sorted_bimodal | 256 | 256 | 2.6 μs | 4.1 μs | 3.2 μs | 8.9 μs | 6.4 μs | 2.6 μs | 5.8 μs | Linear (2.6 μs) | 0.99x | +| uniform | sorted_bimodal | 256 | 1024 | 9.2 μs | 14.7 μs | 11.5 μs | 30.5 μs | 22.5 μs | 9.2 μs | 20.7 μs | Linear (9.2 μs) | 1.00x | +| uniform | sorted_bimodal | 256 | 4096 | 32.2 μs | 55.8 μs | 43.1 μs | 112.2 μs | 86.6 μs | 32.2 μs | 78.9 μs | Linear (32.2 μs) | 1.00x | +| uniform | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_bimodal | 1024 | 4 | 1.5 μs | 180 ns | 160 ns | 150 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| uniform | sorted_bimodal | 1024 | 16 | 1.6 μs | 470 ns | 390 ns | 480 ns | 450 ns | 410 ns | 420 ns | ExpFromLeft (390 ns) | 1.05x | +| uniform | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 999 ns | 1.9 μs | 2.0 μs | 1.0 μs | 1.9 μs | ExpFromLeft (999 ns) | 1.02x | +| uniform | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.1 μs | 2.8 μs | 9.1 μs | 8.7 μs | 3.5 μs | 8.1 μs | ExpFromLeft (2.8 μs) | 1.25x | +| uniform | sorted_bimodal | 1024 | 1024 | 11.6 μs | 17.3 μs | 13.7 μs | 37.2 μs | 30.6 μs | 11.6 μs | 28.9 μs | Linear (11.6 μs) | 1.00x | +| uniform | sorted_bimodal | 1024 | 4096 | 36.6 μs | 58.5 μs | 45.8 μs | 122.0 μs | 108.6 μs | 36.5 μs | 102.8 μs | Linear (36.6 μs) | 1.00x | +| uniform | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 69 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (69 ns) | 1.01x | +| uniform | sorted_bimodal | 4096 | 4 | 5.8 μs | 189 ns | 180 ns | 140 ns | 160 ns | 190 ns | 140 ns | InterpSearch (140 ns) | 1.36x | +| uniform | sorted_bimodal | 4096 | 16 | 6.2 μs | 630 ns | 490 ns | 460 ns | 530 ns | 500 ns | 480 ns | InterpSearch (460 ns) | 1.09x | +| uniform | sorted_bimodal | 4096 | 64 | 6.4 μs | 1.8 μs | 1.3 μs | 2.0 μs | 2.2 μs | 1.4 μs | 2.0 μs | ExpFromLeft (1.3 μs) | 1.03x | +| uniform | sorted_bimodal | 4096 | 256 | 8.3 μs | 5.2 μs | 3.7 μs | 9.2 μs | 11.5 μs | 3.7 μs | 10.6 μs | ExpFromLeft (3.7 μs) | 1.01x | +| uniform | sorted_bimodal | 4096 | 1024 | 14.0 μs | 17.6 μs | 12.0 μs | 38.9 μs | 62.2 μs | 14.6 μs | 57.0 μs | ExpFromLeft (12.0 μs) | 1.21x | +| uniform | sorted_bimodal | 4096 | 4096 | 51.3 μs | 69.6 μs | 55.5 μs | 147.3 μs | 185.2 μs | 51.1 μs | 168.0 μs | Linear (51.3 μs) | 1.00x | +| uniform | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_bimodal | 16384 | 4 | 21.8 μs | 250 ns | 210 ns | 150 ns | 180 ns | 200 ns | 160 ns | InterpSearch (150 ns) | 1.33x | +| uniform | sorted_bimodal | 16384 | 16 | 22.9 μs | 740 ns | 560 ns | 490 ns | 630 ns | 590 ns | 560 ns | InterpSearch (490 ns) | 1.20x | +| uniform | sorted_bimodal | 16384 | 64 | 24.2 μs | 2.2 μs | 1.7 μs | 1.9 μs | 2.7 μs | 1.7 μs | 2.5 μs | ExpFromLeft (1.7 μs) | 1.00x | +| uniform | sorted_bimodal | 16384 | 256 | 26.2 μs | 6.9 μs | 5.1 μs | 8.8 μs | 15.9 μs | 5.2 μs | 14.7 μs | ExpFromLeft (5.1 μs) | 1.01x | +| uniform | sorted_bimodal | 16384 | 1024 | 33.4 μs | 22.4 μs | 17.2 μs | 38.6 μs | 90.1 μs | 15.5 μs | 89.5 μs | ExpFromLeft (17.2 μs) | 0.90x | +| uniform | sorted_bimodal | 16384 | 4096 | 79.2 μs | 89.9 μs | 67.6 μs | 159.9 μs | 275.5 μs | 78.3 μs | 265.1 μs | ExpFromLeft (67.6 μs) | 1.16x | +| uniform | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | sorted_bimodal | 65536 | 4 | 83.9 μs | 270 ns | 220 ns | 150 ns | 200 ns | 200 ns | 180 ns | InterpSearch (150 ns) | 1.33x | +| uniform | sorted_bimodal | 65536 | 16 | 87.9 μs | 880 ns | 660 ns | 470 ns | 720 ns | 670 ns | 680 ns | InterpSearch (470 ns) | 1.43x | +| uniform | sorted_bimodal | 65536 | 64 | 91.2 μs | 2.9 μs | 2.2 μs | 2.1 μs | 3.0 μs | 2.2 μs | 2.9 μs | InterpSearch (2.1 μs) | 1.07x | +| uniform | sorted_bimodal | 65536 | 256 | 99.6 μs | 9.1 μs | 6.9 μs | 9.2 μs | 18.8 μs | 6.8 μs | 18.5 μs | ExpFromLeft (6.9 μs) | 1.00x | +| uniform | sorted_bimodal | 65536 | 1024 | 110.0 μs | 33.0 μs | 25.4 μs | 39.9 μs | 109.3 μs | 23.0 μs | 113.2 μs | ExpFromLeft (25.4 μs) | 0.91x | +| uniform | sorted_bimodal | 65536 | 4096 | 186.5 μs | 148.1 μs | 108.6 μs | 160.5 μs | 350.9 μs | 106.9 μs | 351.0 μs | ExpFromLeft (108.6 μs) | 0.98x | +| uniform | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 140 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| uniform | sorted_repeated | 16 | 16 | 180 ns | 270 ns | 200 ns | 460 ns | 230 ns | 190 ns | 220 ns | Linear (180 ns) | 1.06x | +| uniform | sorted_repeated | 16 | 64 | 579 ns | 920 ns | 689 ns | 1.7 μs | 790 ns | 580 ns | 850 ns | Linear (579 ns) | 1.00x | +| uniform | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 3.2 μs | 6.5 μs | 3.0 μs | 2.0 μs | 2.9 μs | Linear (2.0 μs) | 1.02x | +| uniform | sorted_repeated | 16 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 25.9 μs | 11.8 μs | 7.8 μs | 13.1 μs | Linear (7.8 μs) | 1.00x | +| uniform | sorted_repeated | 16 | 4096 | 30.8 μs | 54.8 μs | 39.0 μs | 103.3 μs | 47.2 μs | 30.8 μs | 44.3 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 90 ns | 140 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| uniform | sorted_repeated | 64 | 16 | 170 ns | 280 ns | 200 ns | 460 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | +| uniform | sorted_repeated | 64 | 64 | 550 ns | 920 ns | 700 ns | 1.7 μs | 1.1 μs | 579 ns | 929 ns | Linear (550 ns) | 1.05x | +| uniform | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 25.9 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | +| uniform | sorted_repeated | 64 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 103.3 μs | 66.5 μs | 30.8 μs | 56.6 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_repeated | 256 | 4 | 80 ns | 100 ns | 100 ns | 140 ns | 130 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | +| uniform | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 209 ns | 460 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| uniform | sorted_repeated | 256 | 64 | 550 ns | 930 ns | 690 ns | 1.7 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | +| uniform | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| uniform | sorted_repeated | 256 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 25.8 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.01x | +| uniform | sorted_repeated | 256 | 4096 | 30.8 μs | 55.1 μs | 39.2 μs | 103.7 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 140 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | +| uniform | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 220 ns | 460 ns | 470 ns | 209 ns | 420 ns | Linear (180 ns) | 1.16x | +| uniform | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 1.7 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| uniform | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_repeated | 1024 | 1024 | 11.1 μs | 18.5 μs | 12.8 μs | 28.7 μs | 27.1 μs | 11.2 μs | 23.7 μs | Linear (11.1 μs) | 1.00x | +| uniform | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.1 μs | 39.3 μs | 103.3 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 140 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | +| uniform | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 460 ns | 540 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | +| uniform | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 700 ns | 1.7 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | +| uniform | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.00x | +| uniform | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 25.9 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | +| uniform | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.4 μs | 103.2 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 79 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| uniform | sorted_repeated | 16384 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 190 ns | 120 ns | 170 ns | Linear (100 ns) | 1.20x | +| uniform | sorted_repeated | 16384 | 16 | 190 ns | 300 ns | 230 ns | 460 ns | 609 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | +| uniform | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 710 ns | 1.7 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | +| uniform | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | +| uniform | sorted_repeated | 16384 | 1024 | 11.1 μs | 18.5 μs | 12.8 μs | 28.8 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (11.1 μs) | 0.70x | +| uniform | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.0 μs | 39.6 μs | 103.3 μs | 144.0 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | +| uniform | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | +| uniform | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 150 ns | 190 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| uniform | sorted_repeated | 65536 | 16 | 190 ns | 300 ns | 230 ns | 460 ns | 690 ns | 210 ns | 630 ns | Linear (190 ns) | 1.11x | +| uniform | sorted_repeated | 65536 | 64 | 580 ns | 940 ns | 719 ns | 1.7 μs | 2.6 μs | 610 ns | 2.4 μs | Linear (580 ns) | 1.05x | +| uniform | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.02x | +| uniform | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 25.8 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.01x | +| uniform | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.1 μs | 39.5 μs | 103.3 μs | 163.2 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| uniform | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| uniform | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 90 ns | 100 ns | 100 ns | 80 ns | InterpSearch (90 ns) | 1.11x | +| uniform | unsorted | 16 | 16 | 210 ns | 220 ns | 200 ns | 210 ns | 200 ns | 210 ns | 190 ns | ExpFromLeft (200 ns) | 1.05x | +| uniform | unsorted | 16 | 64 | 820 ns | 800 ns | 810 ns | 820 ns | 890 ns | 899 ns | 839 ns | Gallop (800 ns) | 1.12x | +| uniform | unsorted | 16 | 256 | 3.7 μs | 3.6 μs | 3.6 μs | 3.6 μs | 3.6 μs | 3.6 μs | 3.6 μs | Binary (3.6 μs) | 1.00x | +| uniform | unsorted | 16 | 1024 | 22.5 μs | 22.0 μs | 21.7 μs | 21.9 μs | 21.7 μs | 21.9 μs | 23.1 μs | Binary (21.7 μs) | 1.01x | +| uniform | unsorted | 16 | 4096 | 144.2 μs | 141.1 μs | 140.2 μs | 139.8 μs | 140.0 μs | 138.9 μs | 142.8 μs | InterpSearch (139.8 μs) | 0.99x | +| uniform | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| uniform | unsorted | 64 | 4 | 110 ns | 110 ns | 110 ns | 110 ns | 110 ns | 120 ns | 90 ns | InterpSearch (110 ns) | 1.09x | +| uniform | unsorted | 64 | 16 | 280 ns | 270 ns | 280 ns | 270 ns | 280 ns | 280 ns | 270 ns | InterpSearch (270 ns) | 1.04x | +| uniform | unsorted | 64 | 64 | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.1 μs | ExpFromLeft (1.0 μs) | 1.01x | +| uniform | unsorted | 64 | 256 | 5.6 μs | 5.5 μs | 5.4 μs | 5.4 μs | 5.4 μs | 5.4 μs | 5.6 μs | Binary (5.4 μs) | 1.00x | +| uniform | unsorted | 64 | 1024 | 40.3 μs | 39.8 μs | 38.6 μs | 38.3 μs | 37.9 μs | 38.2 μs | 40.6 μs | Binary (37.9 μs) | 1.01x | +| uniform | unsorted | 64 | 4096 | 226.0 μs | 224.9 μs | 224.7 μs | 225.4 μs | 221.9 μs | 222.8 μs | 226.2 μs | Binary (221.9 μs) | 1.00x | +| uniform | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | unsorted | 256 | 4 | 130 ns | 130 ns | 130 ns | 120 ns | 120 ns | 140 ns | 110 ns | InterpSearch (120 ns) | 1.17x | +| uniform | unsorted | 256 | 16 | 350 ns | 350 ns | 350 ns | 360 ns | 350 ns | 360 ns | 340 ns | ExpFromLeft (350 ns) | 1.03x | +| uniform | unsorted | 256 | 64 | 1.3 μs | 1.2 μs | 1.3 μs | 1.2 μs | 1.2 μs | 1.3 μs | 1.2 μs | Binary (1.2 μs) | 1.02x | +| uniform | unsorted | 256 | 256 | 7.0 μs | 6.8 μs | 6.8 μs | 6.8 μs | 6.8 μs | 6.8 μs | 7.0 μs | InterpSearch (6.8 μs) | 1.00x | +| uniform | unsorted | 256 | 1024 | 54.1 μs | 52.8 μs | 51.6 μs | 51.9 μs | 52.2 μs | 51.9 μs | 55.5 μs | ExpFromLeft (51.6 μs) | 1.00x | +| uniform | unsorted | 256 | 4096 | 313.3 μs | 307.8 μs | 307.0 μs | 305.8 μs | 307.0 μs | 308.6 μs | 309.0 μs | InterpSearch (305.8 μs) | 1.01x | +| uniform | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| uniform | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 139 ns | 140 ns | 150 ns | 130 ns | InterpSearch (139 ns) | 1.08x | +| uniform | unsorted | 1024 | 16 | 430 ns | 430 ns | 480 ns | 480 ns | 480 ns | 490 ns | 450 ns | Gallop (430 ns) | 1.14x | +| uniform | unsorted | 1024 | 64 | 1.9 μs | 1.8 μs | 1.8 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | Binary (1.7 μs) | 1.00x | +| uniform | unsorted | 1024 | 256 | 7.8 μs | 7.5 μs | 7.7 μs | 7.7 μs | 7.7 μs | 7.6 μs | 7.8 μs | Gallop (7.5 μs) | 1.01x | +| uniform | unsorted | 1024 | 1024 | 79.4 μs | 77.7 μs | 76.4 μs | 75.0 μs | 75.0 μs | 74.8 μs | 78.4 μs | Binary (75.0 μs) | 1.00x | +| uniform | unsorted | 1024 | 4096 | 416.5 μs | 415.7 μs | 415.9 μs | 416.7 μs | 414.3 μs | 416.1 μs | 414.4 μs | Binary (414.3 μs) | 1.00x | +| uniform | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| uniform | unsorted | 4096 | 4 | 150 ns | 150 ns | 150 ns | 160 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (150 ns) | 1.13x | +| uniform | unsorted | 4096 | 16 | 490 ns | 500 ns | 490 ns | 500 ns | 490 ns | 510 ns | 490 ns | ExpFromLeft (490 ns) | 1.04x | +| uniform | unsorted | 4096 | 64 | 1.9 μs | 2.0 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | Linear (1.9 μs) | 1.01x | +| uniform | unsorted | 4096 | 256 | 9.7 μs | 9.6 μs | 9.6 μs | 9.5 μs | 9.5 μs | 9.4 μs | 11.7 μs | Binary (9.5 μs) | 1.00x | +| uniform | unsorted | 4096 | 1024 | 100.7 μs | 97.2 μs | 95.9 μs | 94.4 μs | 93.9 μs | 93.4 μs | 99.8 μs | Binary (93.9 μs) | 0.99x | +| uniform | unsorted | 4096 | 4096 | 497.4 μs | 496.2 μs | 495.8 μs | 496.2 μs | 495.6 μs | 492.9 μs | 497.3 μs | Binary (495.6 μs) | 0.99x | +| uniform | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 79 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| uniform | unsorted | 16384 | 4 | 170 ns | 180 ns | 170 ns | 170 ns | 170 ns | 180 ns | 170 ns | InterpSearch (170 ns) | 1.06x | +| uniform | unsorted | 16384 | 16 | 570 ns | 570 ns | 580 ns | 580 ns | 570 ns | 580 ns | 560 ns | Binary (570 ns) | 1.02x | +| uniform | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | InterpSearch (2.3 μs) | 1.01x | +| uniform | unsorted | 16384 | 256 | 11.0 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.8 μs | 12.7 μs | InterpSearch (10.9 μs) | 1.00x | +| uniform | unsorted | 16384 | 1024 | 141.4 μs | 137.6 μs | 135.8 μs | 135.4 μs | 134.5 μs | 133.9 μs | 139.6 μs | Binary (134.5 μs) | 1.00x | +| uniform | unsorted | 16384 | 4096 | 657.2 μs | 654.9 μs | 665.2 μs | 663.9 μs | 664.2 μs | 663.1 μs | 663.5 μs | Gallop (654.9 μs) | 1.01x | +| uniform | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| uniform | unsorted | 65536 | 4 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | +| uniform | unsorted | 65536 | 16 | 670 ns | 700 ns | 680 ns | 670 ns | 680 ns | 690 ns | 660 ns | InterpSearch (670 ns) | 1.03x | +| uniform | unsorted | 65536 | 64 | 2.6 μs | 2.6 μs | 2.6 μs | 2.6 μs | 2.6 μs | 2.6 μs | 2.6 μs | Linear (2.6 μs) | 1.01x | +| uniform | unsorted | 65536 | 256 | 13.6 μs | 13.5 μs | 13.3 μs | 13.3 μs | 13.4 μs | 13.4 μs | 17.7 μs | InterpSearch (13.3 μs) | 1.01x | +| uniform | unsorted | 65536 | 1024 | 188.8 μs | 184.2 μs | 181.7 μs | 181.3 μs | 182.2 μs | 180.9 μs | 186.0 μs | InterpSearch (181.3 μs) | 1.00x | +| uniform | unsorted | 65536 | 4096 | 847.7 μs | 847.3 μs | 849.1 μs | 847.9 μs | 847.3 μs | 842.6 μs | 843.1 μs | Binary (847.3 μs) | 0.99x | +| log | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| log | sorted_uniform | 16 | 4 | 80 ns | 90 ns | 90 ns | 160 ns | 100 ns | 110 ns | 80 ns | Linear (80 ns) | 1.38x | +| log | sorted_uniform | 16 | 16 | 190 ns | 300 ns | 210 ns | 580 ns | 250 ns | 210 ns | 200 ns | Linear (190 ns) | 1.11x | +| log | sorted_uniform | 16 | 64 | 600 ns | 1.0 μs | 780 ns | 2.3 μs | 900 ns | 610 ns | 770 ns | Linear (600 ns) | 1.02x | +| log | sorted_uniform | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 9.1 μs | 3.4 μs | 2.1 μs | 3.0 μs | Linear (2.1 μs) | 1.00x | +| log | sorted_uniform | 16 | 1024 | 8.0 μs | 14.1 μs | 10.7 μs | 35.8 μs | 13.1 μs | 8.0 μs | 11.2 μs | Linear (8.0 μs) | 1.00x | +| log | sorted_uniform | 16 | 4096 | 31.4 μs | 55.9 μs | 41.9 μs | 139.2 μs | 51.1 μs | 31.0 μs | 44.1 μs | Linear (31.4 μs) | 0.99x | +| log | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 59 ns | 110 ns | 70 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| log | sorted_uniform | 64 | 4 | 110 ns | 120 ns | 120 ns | 190 ns | 110 ns | 130 ns | 90 ns | Binary (110 ns) | 1.18x | +| log | sorted_uniform | 64 | 16 | 210 ns | 360 ns | 290 ns | 730 ns | 340 ns | 230 ns | 270 ns | Linear (210 ns) | 1.10x | +| log | sorted_uniform | 64 | 64 | 600 ns | 1.0 μs | 740 ns | 2.7 μs | 1.4 μs | 630 ns | 1.2 μs | Linear (600 ns) | 1.05x | +| log | sorted_uniform | 64 | 256 | 2.3 μs | 3.9 μs | 3.0 μs | 11.4 μs | 4.7 μs | 2.4 μs | 4.4 μs | Linear (2.3 μs) | 1.02x | +| log | sorted_uniform | 64 | 1024 | 8.3 μs | 14.2 μs | 11.1 μs | 43.8 μs | 17.5 μs | 8.3 μs | 15.7 μs | Linear (8.3 μs) | 1.00x | +| log | sorted_uniform | 64 | 4096 | 31.6 μs | 55.1 μs | 42.8 μs | 170.4 μs | 68.2 μs | 31.6 μs | 61.0 μs | Linear (31.6 μs) | 1.00x | +| log | sorted_uniform | 256 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 80 ns | 80 ns | 60 ns | ExpFromLeft (60 ns) | 1.33x | +| log | sorted_uniform | 256 | 4 | 180 ns | 150 ns | 130 ns | 260 ns | 120 ns | 160 ns | 110 ns | Binary (120 ns) | 1.33x | +| log | sorted_uniform | 256 | 16 | 310 ns | 380 ns | 300 ns | 860 ns | 380 ns | 320 ns | 340 ns | ExpFromLeft (300 ns) | 1.07x | +| log | sorted_uniform | 256 | 64 | 820 ns | 1.2 μs | 860 ns | 3.4 μs | 1.7 μs | 820 ns | 1.6 μs | Linear (820 ns) | 1.00x | +| log | sorted_uniform | 256 | 256 | 2.3 μs | 4.3 μs | 3.0 μs | 13.8 μs | 6.5 μs | 2.3 μs | 6.2 μs | Linear (2.3 μs) | 1.00x | +| log | sorted_uniform | 256 | 1024 | 9.3 μs | 15.4 μs | 11.8 μs | 56.3 μs | 24.0 μs | 9.3 μs | 22.0 μs | Linear (9.3 μs) | 1.00x | +| log | sorted_uniform | 256 | 4096 | 33.4 μs | 57.5 μs | 44.3 μs | 217.4 μs | 89.7 μs | 33.5 μs | 82.2 μs | Linear (33.4 μs) | 1.00x | +| log | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 70 ns | 80 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| log | sorted_uniform | 1024 | 4 | 530 ns | 170 ns | 150 ns | 290 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | +| log | sorted_uniform | 1024 | 16 | 620 ns | 440 ns | 370 ns | 1.0 μs | 450 ns | 400 ns | 410 ns | ExpFromLeft (370 ns) | 1.08x | +| log | sorted_uniform | 1024 | 64 | 1.4 μs | 1.4 μs | 1.1 μs | 4.0 μs | 1.8 μs | 1.1 μs | 1.8 μs | ExpFromLeft (1.1 μs) | 1.06x | +| log | sorted_uniform | 1024 | 256 | 3.2 μs | 4.7 μs | 3.3 μs | 16.1 μs | 8.7 μs | 3.2 μs | 7.7 μs | Linear (3.2 μs) | 1.00x | +| log | sorted_uniform | 1024 | 1024 | 10.8 μs | 17.8 μs | 13.1 μs | 71.1 μs | 34.3 μs | 10.7 μs | 32.9 μs | Linear (10.8 μs) | 0.99x | +| log | sorted_uniform | 1024 | 4096 | 38.0 μs | 62.6 μs | 48.2 μs | 290.1 μs | 130.6 μs | 38.3 μs | 125.1 μs | Linear (38.0 μs) | 1.01x | +| log | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| log | sorted_uniform | 4096 | 4 | 960 ns | 190 ns | 160 ns | 310 ns | 160 ns | 190 ns | 150 ns | ExpFromLeft (160 ns) | 1.19x | +| log | sorted_uniform | 4096 | 16 | 2.5 μs | 600 ns | 460 ns | 1.1 μs | 600 ns | 490 ns | 550 ns | ExpFromLeft (460 ns) | 1.07x | +| log | sorted_uniform | 4096 | 64 | 4.3 μs | 1.9 μs | 1.4 μs | 4.6 μs | 2.1 μs | 1.5 μs | 2.0 μs | ExpFromLeft (1.4 μs) | 1.03x | +| log | sorted_uniform | 4096 | 256 | 8.9 μs | 5.9 μs | 4.3 μs | 19.1 μs | 11.2 μs | 4.4 μs | 10.2 μs | ExpFromLeft (4.3 μs) | 1.03x | +| log | sorted_uniform | 4096 | 1024 | 15.8 μs | 20.2 μs | 14.1 μs | 90.7 μs | 67.9 μs | 15.8 μs | 61.5 μs | ExpFromLeft (14.1 μs) | 1.12x | +| log | sorted_uniform | 4096 | 4096 | 53.4 μs | 76.2 μs | 58.6 μs | 400.9 μs | 227.4 μs | 51.9 μs | 218.7 μs | Linear (53.4 μs) | 0.97x | +| log | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 80 ns | 110 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | +| log | sorted_uniform | 16384 | 4 | 4.3 μs | 250 ns | 200 ns | 370 ns | 180 ns | 240 ns | 160 ns | Binary (180 ns) | 1.33x | +| log | sorted_uniform | 16384 | 16 | 11.5 μs | 780 ns | 580 ns | 1.4 μs | 650 ns | 610 ns | 600 ns | ExpFromLeft (580 ns) | 1.05x | +| log | sorted_uniform | 16384 | 64 | 25.3 μs | 2.6 μs | 1.9 μs | 5.3 μs | 2.7 μs | 2.0 μs | 2.5 μs | ExpFromLeft (1.9 μs) | 1.03x | +| log | sorted_uniform | 16384 | 256 | 25.4 μs | 7.7 μs | 5.7 μs | 21.4 μs | 16.1 μs | 5.9 μs | 14.9 μs | ExpFromLeft (5.7 μs) | 1.04x | +| log | sorted_uniform | 16384 | 1024 | 34.7 μs | 27.5 μs | 21.3 μs | 122.2 μs | 102.5 μs | 20.3 μs | 100.8 μs | ExpFromLeft (21.3 μs) | 0.95x | +| log | sorted_uniform | 16384 | 4096 | 90.8 μs | 114.3 μs | 89.3 μs | 515.9 μs | 317.9 μs | 88.8 μs | 313.1 μs | ExpFromLeft (89.3 μs) | 0.99x | +| log | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_uniform | 65536 | 4 | 11.4 μs | 230 ns | 200 ns | 370 ns | 200 ns | 230 ns | 180 ns | ExpFromLeft (200 ns) | 1.15x | +| log | sorted_uniform | 65536 | 16 | 42.8 μs | 930 ns | 700 ns | 1.5 μs | 710 ns | 710 ns | 670 ns | ExpFromLeft (700 ns) | 1.01x | +| log | sorted_uniform | 65536 | 64 | 50.2 μs | 3.2 μs | 2.4 μs | 6.0 μs | 2.9 μs | 2.5 μs | 2.7 μs | ExpFromLeft (2.4 μs) | 1.02x | +| log | sorted_uniform | 65536 | 256 | 81.9 μs | 10.7 μs | 7.7 μs | 26.2 μs | 19.1 μs | 7.8 μs | 18.8 μs | ExpFromLeft (7.7 μs) | 1.02x | +| log | sorted_uniform | 65536 | 1024 | 104.7 μs | 41.9 μs | 31.4 μs | 164.4 μs | 123.1 μs | 30.5 μs | 126.8 μs | ExpFromLeft (31.4 μs) | 0.97x | +| log | sorted_uniform | 65536 | 4096 | 176.6 μs | 198.7 μs | 151.3 μs | 648.8 μs | 412.0 μs | 159.7 μs | 407.1 μs | ExpFromLeft (151.3 μs) | 1.06x | +| log | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 100 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| log | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| log | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 220 ns | 630 ns | 230 ns | 190 ns | 210 ns | Linear (170 ns) | 1.12x | +| log | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 730 ns | 2.3 μs | 790 ns | 570 ns | 750 ns | Linear (550 ns) | 1.04x | +| log | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 9.0 μs | 3.0 μs | 2.1 μs | 2.5 μs | Linear (2.0 μs) | 1.08x | +| log | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 35.9 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.00x | +| log | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.9 μs | 42.0 μs | 142.9 μs | 47.0 μs | 32.9 μs | 38.5 μs | Linear (30.8 μs) | 1.07x | +| log | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| log | sorted_dense_burst | 64 | 4 | 80 ns | 90 ns | 100 ns | 220 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| log | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 230 ns | 759 ns | 300 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | +| log | sorted_dense_burst | 64 | 64 | 550 ns | 920 ns | 730 ns | 2.9 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | +| log | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 11.3 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.95x | +| log | sorted_dense_burst | 64 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 44.6 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.8 μs) | 1.00x | +| log | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.0 μs | 41.9 μs | 177.9 μs | 66.6 μs | 44.3 μs | 56.7 μs | Linear (30.8 μs) | 1.44x | +| log | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 250 ns | 130 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| log | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 920 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| log | sorted_dense_burst | 256 | 64 | 550 ns | 930 ns | 740 ns | 3.6 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | +| log | sorted_dense_burst | 256 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 14.1 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.1 μs) | 0.95x | +| log | sorted_dense_burst | 256 | 1024 | 8.3 μs | 13.8 μs | 10.5 μs | 55.9 μs | 21.5 μs | 7.8 μs | 19.3 μs | Linear (8.3 μs) | 0.94x | +| log | sorted_dense_burst | 256 | 4096 | 32.8 μs | 54.9 μs | 41.9 μs | 223.1 μs | 85.9 μs | 30.8 μs | 76.5 μs | Linear (32.8 μs) | 0.94x | +| log | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 100 ns | 290 ns | 140 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | +| log | sorted_dense_burst | 1024 | 16 | 180 ns | 290 ns | 240 ns | 1.1 μs | 450 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | +| log | sorted_dense_burst | 1024 | 64 | 560 ns | 930 ns | 740 ns | 4.1 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| log | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.2 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| log | sorted_dense_burst | 1024 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 64.9 μs | 26.4 μs | 8.3 μs | 24.0 μs | Linear (7.7 μs) | 1.07x | +| log | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 41.9 μs | 258.7 μs | 105.4 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| log | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| log | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 110 ns | 330 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | +| log | sorted_dense_burst | 4096 | 16 | 179 ns | 280 ns | 260 ns | 1.2 μs | 540 ns | 210 ns | 480 ns | Linear (179 ns) | 1.17x | +| log | sorted_dense_burst | 4096 | 64 | 560 ns | 940 ns | 760 ns | 4.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | +| log | sorted_dense_burst | 4096 | 256 | 2.1 μs | 3.5 μs | 3.6 μs | 19.2 μs | 8.0 μs | 2.9 μs | 7.2 μs | Linear (2.1 μs) | 1.35x | +| log | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 75.3 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.7 μs) | 1.01x | +| log | sorted_dense_burst | 4096 | 4096 | 32.9 μs | 55.1 μs | 42.0 μs | 300.1 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (32.9 μs) | 0.94x | +| log | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| log | sorted_dense_burst | 16384 | 4 | 90 ns | 110 ns | 110 ns | 390 ns | 180 ns | 130 ns | 170 ns | Linear (90 ns) | 1.44x | +| log | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 1.4 μs | 620 ns | 220 ns | 559 ns | Linear (190 ns) | 1.16x | +| log | sorted_dense_burst | 16384 | 64 | 560 ns | 940 ns | 750 ns | 5.4 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | +| log | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 21.4 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | +| log | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 85.8 μs | 36.0 μs | 8.3 μs | 33.5 μs | Linear (7.8 μs) | 1.07x | +| log | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 54.8 μs | 42.0 μs | 342.9 μs | 144.1 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | +| log | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 100 ns | 100 ns | 70 ns | ExpFromLeft (80 ns) | 1.25x | +| log | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 450 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| log | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 250 ns | 1.6 μs | 690 ns | 210 ns | 630 ns | Linear (190 ns) | 1.11x | +| log | sorted_dense_burst | 65536 | 64 | 560 ns | 940 ns | 740 ns | 6.1 μs | 2.6 μs | 620 ns | 2.4 μs | Linear (560 ns) | 1.11x | +| log | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.1 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | +| log | sorted_dense_burst | 65536 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 97.0 μs | 40.8 μs | 8.3 μs | 38.1 μs | Linear (7.7 μs) | 1.07x | +| log | sorted_dense_burst | 65536 | 4096 | 32.9 μs | 55.0 μs | 42.0 μs | 385.8 μs | 163.1 μs | 30.8 μs | 152.6 μs | Linear (32.9 μs) | 0.94x | +| log | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| log | sorted_near_start | 16 | 4 | 100 ns | 120 ns | 100 ns | 150 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | +| log | sorted_near_start | 16 | 16 | 210 ns | 290 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (210 ns) | 0.95x | +| log | sorted_near_start | 16 | 64 | 570 ns | 960 ns | 760 ns | 1.7 μs | 810 ns | 600 ns | 680 ns | Linear (570 ns) | 1.05x | +| log | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.8 μs | 6.7 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | +| log | sorted_near_start | 16 | 1024 | 7.9 μs | 13.9 μs | 10.6 μs | 27.0 μs | 12.1 μs | 7.9 μs | 10.3 μs | Linear (7.9 μs) | 1.00x | +| log | sorted_near_start | 16 | 4096 | 30.9 μs | 54.9 μs | 42.1 μs | 106.6 μs | 48.1 μs | 31.0 μs | 40.7 μs | Linear (30.9 μs) | 1.00x | +| log | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| log | sorted_near_start | 64 | 4 | 150 ns | 120 ns | 120 ns | 160 ns | 110 ns | 120 ns | 90 ns | Binary (110 ns) | 1.09x | +| log | sorted_near_start | 64 | 16 | 250 ns | 280 ns | 230 ns | 530 ns | 320 ns | 270 ns | 280 ns | ExpFromLeft (230 ns) | 1.17x | +| log | sorted_near_start | 64 | 64 | 680 ns | 1.0 μs | 820 ns | 1.9 μs | 1.1 μs | 700 ns | 1.0 μs | Linear (680 ns) | 1.03x | +| log | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.3 μs | 4.2 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | +| log | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 29.2 μs | 16.9 μs | 8.0 μs | 15.2 μs | Linear (7.9 μs) | 1.00x | +| log | sorted_near_start | 64 | 4096 | 31.2 μs | 55.3 μs | 42.4 μs | 116.6 μs | 66.7 μs | 31.2 μs | 60.0 μs | Linear (31.2 μs) | 1.00x | +| log | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_near_start | 256 | 4 | 430 ns | 140 ns | 120 ns | 200 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | +| log | sorted_near_start | 256 | 16 | 540 ns | 340 ns | 260 ns | 640 ns | 450 ns | 290 ns | 390 ns | ExpFromLeft (260 ns) | 1.12x | +| log | sorted_near_start | 256 | 64 | 930 ns | 1.1 μs | 810 ns | 2.4 μs | 1.6 μs | 960 ns | 1.8 μs | ExpFromLeft (810 ns) | 1.19x | +| log | sorted_near_start | 256 | 256 | 2.6 μs | 3.9 μs | 3.0 μs | 9.6 μs | 5.8 μs | 2.6 μs | 5.3 μs | Linear (2.6 μs) | 1.01x | +| log | sorted_near_start | 256 | 1024 | 8.4 μs | 14.3 μs | 10.9 μs | 37.3 μs | 22.3 μs | 8.4 μs | 20.4 μs | Linear (8.4 μs) | 1.00x | +| log | sorted_near_start | 256 | 4096 | 31.7 μs | 56.4 μs | 43.0 μs | 149.9 μs | 87.7 μs | 31.7 μs | 80.4 μs | Linear (31.7 μs) | 1.00x | +| log | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| log | sorted_near_start | 1024 | 4 | 1.4 μs | 170 ns | 150 ns | 220 ns | 150 ns | 190 ns | 130 ns | ExpFromLeft (150 ns) | 1.27x | +| log | sorted_near_start | 1024 | 16 | 1.5 μs | 409 ns | 320 ns | 750 ns | 490 ns | 350 ns | 410 ns | ExpFromLeft (320 ns) | 1.09x | +| log | sorted_near_start | 1024 | 64 | 1.9 μs | 1.2 μs | 900 ns | 3.1 μs | 2.1 μs | 930 ns | 1.9 μs | ExpFromLeft (900 ns) | 1.03x | +| log | sorted_near_start | 1024 | 256 | 3.8 μs | 4.5 μs | 3.4 μs | 12.5 μs | 7.7 μs | 3.8 μs | 7.1 μs | ExpFromLeft (3.4 μs) | 1.11x | +| log | sorted_near_start | 1024 | 1024 | 10.5 μs | 15.4 μs | 12.0 μs | 48.7 μs | 27.6 μs | 10.4 μs | 25.9 μs | Linear (10.5 μs) | 1.00x | +| log | sorted_near_start | 1024 | 4096 | 33.8 μs | 57.5 μs | 43.7 μs | 191.3 μs | 108.8 μs | 33.8 μs | 102.9 μs | Linear (33.8 μs) | 1.00x | +| log | sorted_near_start | 4096 | 1 | 70 ns | 90 ns | 90 ns | 90 ns | 70 ns | 70 ns | 60 ns | Binary (70 ns) | 1.00x | +| log | sorted_near_start | 4096 | 4 | 6.1 μs | 200 ns | 180 ns | 260 ns | 170 ns | 210 ns | 150 ns | Binary (170 ns) | 1.24x | +| log | sorted_near_start | 4096 | 16 | 5.4 μs | 549 ns | 510 ns | 980 ns | 540 ns | 520 ns | 489 ns | ExpFromLeft (510 ns) | 1.02x | +| log | sorted_near_start | 4096 | 64 | 6.5 μs | 1.5 μs | 1.1 μs | 3.5 μs | 2.4 μs | 1.4 μs | 2.2 μs | ExpFromLeft (1.1 μs) | 1.27x | +| log | sorted_near_start | 4096 | 256 | 7.8 μs | 4.5 μs | 3.2 μs | 15.0 μs | 11.0 μs | 3.4 μs | 10.5 μs | ExpFromLeft (3.2 μs) | 1.07x | +| log | sorted_near_start | 4096 | 1024 | 16.2 μs | 18.4 μs | 14.1 μs | 64.2 μs | 43.9 μs | 16.1 μs | 38.4 μs | ExpFromLeft (14.1 μs) | 1.14x | +| log | sorted_near_start | 4096 | 4096 | 41.8 μs | 61.7 μs | 47.8 μs | 246.2 μs | 155.3 μs | 42.0 μs | 140.3 μs | Linear (41.8 μs) | 1.01x | +| log | sorted_near_start | 16384 | 1 | 70 ns | 70 ns | 80 ns | 100 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | +| log | sorted_near_start | 16384 | 4 | 21.2 μs | 240 ns | 200 ns | 310 ns | 180 ns | 230 ns | 160 ns | Binary (180 ns) | 1.28x | +| log | sorted_near_start | 16384 | 16 | 23.9 μs | 630 ns | 510 ns | 1.1 μs | 670 ns | 530 ns | 590 ns | ExpFromLeft (510 ns) | 1.04x | +| log | sorted_near_start | 16384 | 64 | 23.3 μs | 1.9 μs | 1.5 μs | 4.3 μs | 3.1 μs | 1.5 μs | 2.8 μs | ExpFromLeft (1.5 μs) | 1.01x | +| log | sorted_near_start | 16384 | 256 | 24.9 μs | 5.9 μs | 4.2 μs | 17.5 μs | 17.9 μs | 4.3 μs | 16.7 μs | ExpFromLeft (4.2 μs) | 1.04x | +| log | sorted_near_start | 16384 | 1024 | 34.2 μs | 20.4 μs | 13.9 μs | 84.9 μs | 77.0 μs | 14.2 μs | 70.8 μs | ExpFromLeft (13.9 μs) | 1.03x | +| log | sorted_near_start | 16384 | 4096 | 71.9 μs | 75.9 μs | 60.1 μs | 358.5 μs | 254.2 μs | 71.2 μs | 232.0 μs | ExpFromLeft (60.1 μs) | 1.18x | +| log | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 90 ns | 70 ns | ExpFromLeft (80 ns) | 1.12x | +| log | sorted_near_start | 65536 | 4 | 60.6 μs | 250 ns | 200 ns | 360 ns | 200 ns | 240 ns | 190 ns | ExpFromLeft (200 ns) | 1.20x | +| log | sorted_near_start | 65536 | 16 | 78.5 μs | 800 ns | 600 ns | 1.3 μs | 670 ns | 620 ns | 630 ns | ExpFromLeft (600 ns) | 1.03x | +| log | sorted_near_start | 65536 | 64 | 93.9 μs | 2.5 μs | 1.9 μs | 4.9 μs | 3.3 μs | 2.0 μs | 3.1 μs | ExpFromLeft (1.9 μs) | 1.02x | +| log | sorted_near_start | 65536 | 256 | 96.7 μs | 7.9 μs | 5.7 μs | 20.7 μs | 20.4 μs | 5.8 μs | 19.8 μs | ExpFromLeft (5.7 μs) | 1.01x | +| log | sorted_near_start | 65536 | 1024 | 103.1 μs | 26.5 μs | 19.6 μs | 117.7 μs | 95.2 μs | 18.8 μs | 89.8 μs | ExpFromLeft (19.6 μs) | 0.96x | +| log | sorted_near_start | 65536 | 4096 | 157.5 μs | 111.3 μs | 89.1 μs | 499.1 μs | 303.0 μs | 85.9 μs | 291.2 μs | ExpFromLeft (89.1 μs) | 0.96x | +| log | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| log | sorted_arithmetic | 16 | 4 | 100 ns | 100 ns | 100 ns | 160 ns | 100 ns | 110 ns | 80 ns | ExpFromLeft (100 ns) | 1.10x | +| log | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 220 ns | 550 ns | 240 ns | 210 ns | 210 ns | Linear (190 ns) | 1.11x | +| log | sorted_arithmetic | 16 | 64 | 590 ns | 970 ns | 770 ns | 2.2 μs | 910 ns | 620 ns | 800 ns | Linear (590 ns) | 1.05x | +| log | sorted_arithmetic | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 8.7 μs | 3.3 μs | 2.1 μs | 2.8 μs | Linear (2.1 μs) | 1.00x | +| log | sorted_arithmetic | 16 | 1024 | 7.9 μs | 13.5 μs | 10.7 μs | 33.7 μs | 12.6 μs | 8.0 μs | 11.2 μs | Linear (7.9 μs) | 1.01x | +| log | sorted_arithmetic | 16 | 4096 | 31.0 μs | 53.2 μs | 42.2 μs | 132.9 μs | 51.1 μs | 31.0 μs | 44.0 μs | Linear (31.0 μs) | 1.00x | +| log | sorted_arithmetic | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | +| log | sorted_arithmetic | 64 | 4 | 170 ns | 130 ns | 120 ns | 180 ns | 100 ns | 150 ns | 90 ns | Binary (100 ns) | 1.50x | +| log | sorted_arithmetic | 64 | 16 | 260 ns | 330 ns | 260 ns | 680 ns | 340 ns | 280 ns | 310 ns | ExpFromLeft (260 ns) | 1.08x | +| log | sorted_arithmetic | 64 | 64 | 660 ns | 1.1 μs | 779 ns | 2.7 μs | 1.4 μs | 660 ns | 1.3 μs | Linear (660 ns) | 1.00x | +| log | sorted_arithmetic | 64 | 256 | 2.3 μs | 3.9 μs | 3.0 μs | 11.2 μs | 4.8 μs | 2.3 μs | 4.4 μs | Linear (2.3 μs) | 1.01x | +| log | sorted_arithmetic | 64 | 1024 | 8.3 μs | 14.3 μs | 11.1 μs | 43.9 μs | 17.6 μs | 8.4 μs | 15.8 μs | Linear (8.3 μs) | 1.01x | +| log | sorted_arithmetic | 64 | 4096 | 31.6 μs | 55.6 μs | 42.8 μs | 170.5 μs | 68.2 μs | 31.7 μs | 60.7 μs | Linear (31.6 μs) | 1.00x | +| log | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_arithmetic | 256 | 4 | 480 ns | 170 ns | 150 ns | 200 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | +| log | sorted_arithmetic | 256 | 16 | 580 ns | 430 ns | 340 ns | 820 ns | 370 ns | 360 ns | 340 ns | ExpFromLeft (340 ns) | 1.06x | +| log | sorted_arithmetic | 256 | 64 | 960 ns | 1.2 μs | 850 ns | 3.3 μs | 1.6 μs | 960 ns | 1.4 μs | ExpFromLeft (850 ns) | 1.13x | +| log | sorted_arithmetic | 256 | 256 | 2.6 μs | 4.2 μs | 3.1 μs | 13.8 μs | 6.9 μs | 2.6 μs | 6.2 μs | Linear (2.6 μs) | 1.01x | +| log | sorted_arithmetic | 256 | 1024 | 9.3 μs | 15.7 μs | 12.0 μs | 57.6 μs | 24.0 μs | 9.3 μs | 21.7 μs | Linear (9.3 μs) | 0.99x | +| log | sorted_arithmetic | 256 | 4096 | 33.4 μs | 58.0 μs | 44.4 μs | 217.5 μs | 90.1 μs | 33.4 μs | 80.9 μs | Linear (33.4 μs) | 1.00x | +| log | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| log | sorted_arithmetic | 1024 | 4 | 1.6 μs | 190 ns | 160 ns | 210 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | +| log | sorted_arithmetic | 1024 | 16 | 1.8 μs | 550 ns | 450 ns | 950 ns | 450 ns | 470 ns | 420 ns | ExpFromLeft (450 ns) | 1.04x | +| log | sorted_arithmetic | 1024 | 64 | 2.2 μs | 1.6 μs | 1.2 μs | 3.9 μs | 1.7 μs | 1.2 μs | 1.6 μs | ExpFromLeft (1.2 μs) | 1.03x | +| log | sorted_arithmetic | 1024 | 256 | 3.8 μs | 5.0 μs | 3.5 μs | 16.2 μs | 8.3 μs | 3.8 μs | 7.7 μs | ExpFromLeft (3.5 μs) | 1.10x | +| log | sorted_arithmetic | 1024 | 1024 | 10.8 μs | 17.2 μs | 12.6 μs | 72.1 μs | 36.1 μs | 10.7 μs | 36.4 μs | Linear (10.8 μs) | 0.99x | +| log | sorted_arithmetic | 1024 | 4096 | 37.4 μs | 62.0 μs | 47.1 μs | 292.4 μs | 136.3 μs | 37.4 μs | 134.3 μs | Linear (37.4 μs) | 1.00x | +| log | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| log | sorted_arithmetic | 4096 | 4 | 6.0 μs | 230 ns | 200 ns | 240 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | +| log | sorted_arithmetic | 4096 | 16 | 6.3 μs | 700 ns | 550 ns | 1.1 μs | 530 ns | 560 ns | 480 ns | Binary (530 ns) | 1.06x | +| log | sorted_arithmetic | 4096 | 64 | 7.1 μs | 2.1 μs | 1.6 μs | 4.5 μs | 2.1 μs | 1.7 μs | 1.9 μs | ExpFromLeft (1.6 μs) | 1.03x | +| log | sorted_arithmetic | 4096 | 256 | 8.6 μs | 6.7 μs | 4.8 μs | 18.9 μs | 11.6 μs | 4.9 μs | 9.7 μs | ExpFromLeft (4.8 μs) | 1.01x | +| log | sorted_arithmetic | 4096 | 1024 | 15.8 μs | 20.4 μs | 14.1 μs | 97.5 μs | 76.0 μs | 15.8 μs | 72.2 μs | ExpFromLeft (14.1 μs) | 1.11x | +| log | sorted_arithmetic | 4096 | 4096 | 43.7 μs | 67.8 μs | 49.4 μs | 416.2 μs | 241.0 μs | 43.6 μs | 224.3 μs | Linear (43.7 μs) | 1.00x | +| log | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 80 ns | 130 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | +| log | sorted_arithmetic | 16384 | 4 | 23.4 μs | 260 ns | 230 ns | 260 ns | 180 ns | 240 ns | 160 ns | Binary (180 ns) | 1.33x | +| log | sorted_arithmetic | 16384 | 16 | 23.8 μs | 840 ns | 650 ns | 1.3 μs | 610 ns | 660 ns | 560 ns | Binary (610 ns) | 1.08x | +| log | sorted_arithmetic | 16384 | 64 | 25.2 μs | 2.9 μs | 2.1 μs | 5.2 μs | 2.6 μs | 2.1 μs | 2.4 μs | ExpFromLeft (2.1 μs) | 1.02x | +| log | sorted_arithmetic | 16384 | 256 | 28.8 μs | 9.1 μs | 8.3 μs | 22.6 μs | 16.0 μs | 8.4 μs | 13.7 μs | ExpFromLeft (8.3 μs) | 1.01x | +| log | sorted_arithmetic | 16384 | 1024 | 36.3 μs | 27.9 μs | 20.1 μs | 129.7 μs | 106.8 μs | 20.5 μs | 104.1 μs | ExpFromLeft (20.1 μs) | 1.02x | +| log | sorted_arithmetic | 16384 | 4096 | 65.8 μs | 82.7 μs | 58.2 μs | 536.3 μs | 341.4 μs | 65.8 μs | 341.5 μs | ExpFromLeft (58.2 μs) | 1.13x | +| log | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_arithmetic | 65536 | 4 | 93.0 μs | 290 ns | 230 ns | 270 ns | 200 ns | 260 ns | 190 ns | Binary (200 ns) | 1.30x | +| log | sorted_arithmetic | 65536 | 16 | 93.5 μs | 1.0 μs | 750 ns | 1.4 μs | 690 ns | 770 ns | 660 ns | Binary (690 ns) | 1.12x | +| log | sorted_arithmetic | 65536 | 64 | 95.2 μs | 3.4 μs | 2.5 μs | 6.0 μs | 2.9 μs | 2.6 μs | 2.7 μs | ExpFromLeft (2.5 μs) | 1.02x | +| log | sorted_arithmetic | 65536 | 256 | 100.1 μs | 11.4 μs | 8.7 μs | 27.1 μs | 18.2 μs | 8.8 μs | 18.7 μs | ExpFromLeft (8.7 μs) | 1.01x | +| log | sorted_arithmetic | 65536 | 1024 | 112.6 μs | 38.3 μs | 28.9 μs | 170.9 μs | 129.6 μs | 28.7 μs | 134.1 μs | ExpFromLeft (28.9 μs) | 1.00x | +| log | sorted_arithmetic | 65536 | 4096 | 144.1 μs | 116.8 μs | 84.8 μs | 672.5 μs | 447.5 μs | 85.4 μs | 448.4 μs | ExpFromLeft (84.8 μs) | 1.01x | +| log | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| log | sorted_geometric | 16 | 4 | 110 ns | 120 ns | 120 ns | 170 ns | 100 ns | 120 ns | 80 ns | Binary (100 ns) | 1.20x | +| log | sorted_geometric | 16 | 16 | 190 ns | 300 ns | 220 ns | 590 ns | 240 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| log | sorted_geometric | 16 | 64 | 580 ns | 970 ns | 760 ns | 2.4 μs | 930 ns | 629 ns | 800 ns | Linear (580 ns) | 1.08x | +| log | sorted_geometric | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 9.3 μs | 3.3 μs | 2.2 μs | 3.2 μs | Linear (2.2 μs) | 1.00x | +| log | sorted_geometric | 16 | 1024 | 8.0 μs | 14.1 μs | 10.8 μs | 36.0 μs | 12.4 μs | 8.1 μs | 10.5 μs | Linear (8.0 μs) | 1.00x | +| log | sorted_geometric | 16 | 4096 | 31.1 μs | 55.1 μs | 42.3 μs | 141.2 μs | 48.5 μs | 31.1 μs | 41.0 μs | Linear (31.1 μs) | 1.00x | +| log | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| log | sorted_geometric | 64 | 4 | 170 ns | 150 ns | 130 ns | 190 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | +| log | sorted_geometric | 64 | 16 | 260 ns | 360 ns | 270 ns | 720 ns | 300 ns | 280 ns | 270 ns | Linear (260 ns) | 1.08x | +| log | sorted_geometric | 64 | 64 | 670 ns | 1.2 μs | 780 ns | 2.9 μs | 1.3 μs | 690 ns | 1.3 μs | Linear (670 ns) | 1.03x | +| log | sorted_geometric | 64 | 256 | 2.3 μs | 4.0 μs | 3.0 μs | 12.1 μs | 5.2 μs | 2.3 μs | 4.7 μs | Linear (2.3 μs) | 1.01x | +| log | sorted_geometric | 64 | 1024 | 8.9 μs | 14.7 μs | 11.6 μs | 47.2 μs | 17.8 μs | 8.9 μs | 15.8 μs | Linear (8.9 μs) | 1.00x | +| log | sorted_geometric | 64 | 4096 | 32.2 μs | 56.5 μs | 43.2 μs | 182.3 μs | 67.6 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | +| log | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_geometric | 256 | 4 | 520 ns | 170 ns | 160 ns | 210 ns | 119 ns | 180 ns | 110 ns | Binary (119 ns) | 1.51x | +| log | sorted_geometric | 256 | 16 | 530 ns | 470 ns | 400 ns | 870 ns | 370 ns | 430 ns | 340 ns | Binary (370 ns) | 1.16x | +| log | sorted_geometric | 256 | 64 | 960 ns | 1.5 μs | 990 ns | 3.5 μs | 1.4 μs | 970 ns | 1.2 μs | Linear (960 ns) | 1.01x | +| log | sorted_geometric | 256 | 256 | 3.4 μs | 5.4 μs | 3.1 μs | 14.8 μs | 7.1 μs | 2.7 μs | 6.6 μs | ExpFromLeft (3.1 μs) | 0.86x | +| log | sorted_geometric | 256 | 1024 | 9.3 μs | 15.7 μs | 11.7 μs | 61.3 μs | 26.8 μs | 9.4 μs | 23.9 μs | Linear (9.3 μs) | 1.01x | +| log | sorted_geometric | 256 | 4096 | 35.7 μs | 59.5 μs | 46.2 μs | 233.8 μs | 91.7 μs | 35.8 μs | 83.8 μs | Linear (35.7 μs) | 1.00x | +| log | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| log | sorted_geometric | 1024 | 4 | 1.6 μs | 210 ns | 180 ns | 230 ns | 150 ns | 200 ns | 130 ns | Binary (150 ns) | 1.33x | +| log | sorted_geometric | 1024 | 16 | 2.0 μs | 650 ns | 500 ns | 999 ns | 450 ns | 510 ns | 410 ns | Binary (450 ns) | 1.13x | +| log | sorted_geometric | 1024 | 64 | 2.2 μs | 1.9 μs | 1.5 μs | 4.1 μs | 1.7 μs | 1.6 μs | 1.6 μs | ExpFromLeft (1.5 μs) | 1.03x | +| log | sorted_geometric | 1024 | 256 | 3.8 μs | 5.9 μs | 3.9 μs | 16.9 μs | 7.9 μs | 3.8 μs | 8.0 μs | Linear (3.8 μs) | 1.01x | +| log | sorted_geometric | 1024 | 1024 | 10.9 μs | 18.0 μs | 12.5 μs | 77.1 μs | 77.0 μs | 10.9 μs | 74.3 μs | Linear (10.9 μs) | 1.00x | +| log | sorted_geometric | 1024 | 4096 | 36.6 μs | 61.5 μs | 46.0 μs | 326.5 μs | 190.6 μs | 36.7 μs | 188.4 μs | Linear (36.6 μs) | 1.00x | +| log | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| log | sorted_geometric | 4096 | 4 | 6.0 μs | 240 ns | 210 ns | 250 ns | 170 ns | 240 ns | 150 ns | Binary (170 ns) | 1.41x | +| log | sorted_geometric | 4096 | 16 | 6.4 μs | 770 ns | 620 ns | 1.1 μs | 540 ns | 660 ns | 480 ns | Binary (540 ns) | 1.22x | +| log | sorted_geometric | 4096 | 64 | 7.7 μs | 2.5 μs | 1.9 μs | 4.7 μs | 2.0 μs | 2.0 μs | 1.9 μs | ExpFromLeft (1.9 μs) | 1.02x | +| log | sorted_geometric | 4096 | 256 | 9.6 μs | 7.9 μs | 5.9 μs | 19.5 μs | 10.7 μs | 6.0 μs | 10.0 μs | ExpFromLeft (5.9 μs) | 1.02x | +| log | sorted_geometric | 4096 | 1024 | 16.0 μs | 24.0 μs | 15.9 μs | 107.4 μs | 100.2 μs | 15.9 μs | 92.3 μs | ExpFromLeft (15.9 μs) | 1.00x | +| log | sorted_geometric | 4096 | 4096 | 43.1 μs | 70.6 μs | 48.8 μs | 453.2 μs | 321.8 μs | 43.0 μs | 312.1 μs | Linear (43.1 μs) | 1.00x | +| log | sorted_geometric | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| log | sorted_geometric | 16384 | 4 | 22.7 μs | 270 ns | 230 ns | 260 ns | 190 ns | 240 ns | 170 ns | Binary (190 ns) | 1.26x | +| log | sorted_geometric | 16384 | 16 | 24.3 μs | 929 ns | 690 ns | 1.3 μs | 610 ns | 710 ns | 570 ns | Binary (610 ns) | 1.16x | +| log | sorted_geometric | 16384 | 64 | 25.8 μs | 3.1 μs | 2.4 μs | 5.4 μs | 2.4 μs | 2.4 μs | 2.2 μs | ExpFromLeft (2.4 μs) | 1.01x | +| log | sorted_geometric | 16384 | 256 | 30.9 μs | 10.4 μs | 7.8 μs | 22.9 μs | 14.4 μs | 7.9 μs | 14.2 μs | ExpFromLeft (7.8 μs) | 1.01x | +| log | sorted_geometric | 16384 | 1024 | 38.2 μs | 32.8 μs | 24.6 μs | 135.8 μs | 127.6 μs | 24.9 μs | 127.5 μs | ExpFromLeft (24.6 μs) | 1.01x | +| log | sorted_geometric | 16384 | 4096 | 63.3 μs | 94.5 μs | 64.4 μs | 563.6 μs | 425.4 μs | 63.0 μs | 420.4 μs | Linear (63.3 μs) | 1.00x | +| log | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| log | sorted_geometric | 65536 | 4 | 93.7 μs | 310 ns | 250 ns | 290 ns | 200 ns | 280 ns | 180 ns | Binary (200 ns) | 1.40x | +| log | sorted_geometric | 65536 | 16 | 95.7 μs | 1.1 μs | 809 ns | 1.4 μs | 690 ns | 830 ns | 660 ns | Binary (690 ns) | 1.20x | +| log | sorted_geometric | 65536 | 64 | 97.6 μs | 3.8 μs | 2.7 μs | 6.1 μs | 2.9 μs | 2.8 μs | 2.9 μs | ExpFromLeft (2.7 μs) | 1.03x | +| log | sorted_geometric | 65536 | 256 | 102.9 μs | 13.4 μs | 10.3 μs | 27.6 μs | 17.8 μs | 10.6 μs | 15.8 μs | ExpFromLeft (10.3 μs) | 1.03x | +| log | sorted_geometric | 65536 | 1024 | 113.9 μs | 44.3 μs | 33.8 μs | 185.2 μs | 158.6 μs | 33.6 μs | 164.0 μs | ExpFromLeft (33.8 μs) | 1.00x | +| log | sorted_geometric | 65536 | 4096 | 148.2 μs | 132.0 μs | 100.5 μs | 718.7 μs | 515.2 μs | 101.1 μs | 519.4 μs | ExpFromLeft (100.5 μs) | 1.01x | +| log | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 50 ns | 60 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| log | sorted_bimodal | 16 | 4 | 90 ns | 120 ns | 100 ns | 170 ns | 99 ns | 110 ns | 80 ns | Linear (90 ns) | 1.22x | +| log | sorted_bimodal | 16 | 16 | 190 ns | 280 ns | 220 ns | 540 ns | 250 ns | 210 ns | 210 ns | Linear (190 ns) | 1.11x | +| log | sorted_bimodal | 16 | 64 | 570 ns | 930 ns | 770 ns | 2.1 μs | 899 ns | 600 ns | 800 ns | Linear (570 ns) | 1.05x | +| log | sorted_bimodal | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 8.1 μs | 3.4 μs | 2.1 μs | 2.9 μs | Linear (2.1 μs) | 1.00x | +| log | sorted_bimodal | 16 | 1024 | 8.0 μs | 13.3 μs | 10.7 μs | 31.7 μs | 13.3 μs | 7.9 μs | 11.5 μs | Linear (8.0 μs) | 0.99x | +| log | sorted_bimodal | 16 | 4096 | 31.0 μs | 52.0 μs | 42.3 μs | 125.5 μs | 52.0 μs | 31.0 μs | 45.8 μs | Linear (31.0 μs) | 1.00x | +| log | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_bimodal | 64 | 4 | 120 ns | 130 ns | 110 ns | 190 ns | 110 ns | 130 ns | 90 ns | ExpFromLeft (110 ns) | 1.18x | +| log | sorted_bimodal | 64 | 16 | 240 ns | 320 ns | 250 ns | 650 ns | 320 ns | 259 ns | 280 ns | Linear (240 ns) | 1.08x | +| log | sorted_bimodal | 64 | 64 | 640 ns | 980 ns | 760 ns | 2.5 μs | 1.3 μs | 660 ns | 1.2 μs | Linear (640 ns) | 1.03x | +| log | sorted_bimodal | 64 | 256 | 2.1 μs | 3.6 μs | 2.9 μs | 9.9 μs | 4.8 μs | 2.2 μs | 4.3 μs | Linear (2.1 μs) | 1.02x | +| log | sorted_bimodal | 64 | 1024 | 8.2 μs | 13.6 μs | 11.0 μs | 39.2 μs | 18.4 μs | 8.2 μs | 16.2 μs | Linear (8.2 μs) | 1.00x | +| log | sorted_bimodal | 64 | 4096 | 31.6 μs | 52.5 μs | 42.7 μs | 154.0 μs | 71.5 μs | 31.6 μs | 63.2 μs | Linear (31.6 μs) | 1.00x | +| log | sorted_bimodal | 256 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_bimodal | 256 | 4 | 260 ns | 150 ns | 140 ns | 230 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | +| log | sorted_bimodal | 256 | 16 | 430 ns | 370 ns | 310 ns | 760 ns | 390 ns | 330 ns | 360 ns | ExpFromLeft (310 ns) | 1.06x | +| log | sorted_bimodal | 256 | 64 | 900 ns | 1.2 μs | 910 ns | 3.0 μs | 1.6 μs | 930 ns | 1.5 μs | Linear (900 ns) | 1.03x | +| log | sorted_bimodal | 256 | 256 | 2.4 μs | 3.9 μs | 2.9 μs | 12.3 μs | 6.2 μs | 2.4 μs | 5.8 μs | Linear (2.4 μs) | 1.00x | +| log | sorted_bimodal | 256 | 1024 | 8.8 μs | 15.1 μs | 11.5 μs | 50.8 μs | 23.5 μs | 8.8 μs | 21.8 μs | Linear (8.8 μs) | 1.00x | +| log | sorted_bimodal | 256 | 4096 | 33.1 μs | 56.5 μs | 43.9 μs | 192.1 μs | 90.0 μs | 33.0 μs | 81.2 μs | Linear (33.1 μs) | 1.00x | +| log | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_bimodal | 1024 | 4 | 660 ns | 170 ns | 159 ns | 260 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | +| log | sorted_bimodal | 1024 | 16 | 1.1 μs | 460 ns | 360 ns | 920 ns | 560 ns | 400 ns | 540 ns | ExpFromLeft (360 ns) | 1.11x | +| log | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.4 μs | 1.0 μs | 3.6 μs | 2.1 μs | 1.1 μs | 1.9 μs | ExpFromLeft (1.0 μs) | 1.05x | +| log | sorted_bimodal | 1024 | 256 | 3.7 μs | 4.5 μs | 3.3 μs | 14.7 μs | 7.7 μs | 3.5 μs | 7.0 μs | ExpFromLeft (3.3 μs) | 1.08x | +| log | sorted_bimodal | 1024 | 1024 | 9.8 μs | 15.8 μs | 11.6 μs | 61.0 μs | 30.9 μs | 10.0 μs | 28.7 μs | Linear (9.8 μs) | 1.01x | +| log | sorted_bimodal | 1024 | 4096 | 36.9 μs | 60.7 μs | 46.7 μs | 241.7 μs | 119.7 μs | 36.3 μs | 112.5 μs | Linear (36.9 μs) | 0.98x | +| log | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| log | sorted_bimodal | 4096 | 4 | 5.7 μs | 210 ns | 180 ns | 290 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | +| log | sorted_bimodal | 4096 | 16 | 3.2 μs | 550 ns | 430 ns | 1.1 μs | 580 ns | 450 ns | 560 ns | ExpFromLeft (430 ns) | 1.05x | +| log | sorted_bimodal | 4096 | 64 | 5.6 μs | 1.7 μs | 1.2 μs | 4.3 μs | 2.5 μs | 1.3 μs | 2.4 μs | ExpFromLeft (1.2 μs) | 1.04x | +| log | sorted_bimodal | 4096 | 256 | 7.8 μs | 5.3 μs | 3.9 μs | 17.7 μs | 10.3 μs | 3.9 μs | 9.8 μs | ExpFromLeft (3.9 μs) | 1.00x | +| log | sorted_bimodal | 4096 | 1024 | 15.6 μs | 18.6 μs | 13.8 μs | 78.8 μs | 50.3 μs | 15.8 μs | 46.1 μs | ExpFromLeft (13.8 μs) | 1.15x | +| log | sorted_bimodal | 4096 | 4096 | 44.8 μs | 69.0 μs | 51.3 μs | 337.5 μs | 197.4 μs | 43.8 μs | 194.3 μs | Linear (44.8 μs) | 0.98x | +| log | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 80 ns | 100 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | +| log | sorted_bimodal | 16384 | 4 | 10.1 μs | 230 ns | 190 ns | 340 ns | 170 ns | 230 ns | 170 ns | Binary (170 ns) | 1.35x | +| log | sorted_bimodal | 16384 | 16 | 17.8 μs | 739 ns | 560 ns | 1.3 μs | 660 ns | 580 ns | 630 ns | ExpFromLeft (560 ns) | 1.04x | +| log | sorted_bimodal | 16384 | 64 | 20.4 μs | 2.2 μs | 1.6 μs | 4.9 μs | 2.9 μs | 1.7 μs | 2.8 μs | ExpFromLeft (1.6 μs) | 1.03x | +| log | sorted_bimodal | 16384 | 256 | 25.2 μs | 6.8 μs | 5.0 μs | 20.1 μs | 16.0 μs | 5.1 μs | 15.3 μs | ExpFromLeft (5.0 μs) | 1.03x | +| log | sorted_bimodal | 16384 | 1024 | 34.0 μs | 23.5 μs | 17.1 μs | 103.6 μs | 82.6 μs | 21.8 μs | 80.9 μs | ExpFromLeft (17.1 μs) | 1.28x | +| log | sorted_bimodal | 16384 | 4096 | 74.2 μs | 89.9 μs | 65.4 μs | 455.0 μs | 280.3 μs | 71.9 μs | 273.6 μs | ExpFromLeft (65.4 μs) | 1.10x | +| log | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_bimodal | 65536 | 4 | 50.3 μs | 260 ns | 220 ns | 360 ns | 190 ns | 240 ns | 190 ns | Binary (190 ns) | 1.26x | +| log | sorted_bimodal | 65536 | 16 | 69.2 μs | 860 ns | 640 ns | 1.4 μs | 750 ns | 660 ns | 710 ns | ExpFromLeft (640 ns) | 1.03x | +| log | sorted_bimodal | 65536 | 64 | 89.6 μs | 2.8 μs | 2.2 μs | 5.7 μs | 3.4 μs | 2.2 μs | 3.2 μs | ExpFromLeft (2.2 μs) | 0.99x | +| log | sorted_bimodal | 65536 | 256 | 94.4 μs | 9.1 μs | 6.7 μs | 23.4 μs | 18.5 μs | 6.7 μs | 17.6 μs | ExpFromLeft (6.7 μs) | 1.01x | +| log | sorted_bimodal | 65536 | 1024 | 110.1 μs | 32.2 μs | 24.0 μs | 151.1 μs | 107.9 μs | 24.1 μs | 109.0 μs | ExpFromLeft (24.0 μs) | 1.00x | +| log | sorted_bimodal | 65536 | 4096 | 167.5 μs | 149.9 μs | 116.5 μs | 598.4 μs | 356.9 μs | 115.1 μs | 358.7 μs | ExpFromLeft (116.5 μs) | 0.99x | +| log | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| log | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| log | sorted_repeated | 16 | 16 | 170 ns | 260 ns | 210 ns | 630 ns | 230 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | +| log | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 680 ns | 2.4 μs | 790 ns | 580 ns | 640 ns | Linear (550 ns) | 1.05x | +| log | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 9.3 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.02x | +| log | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 37.1 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.00x | +| log | sorted_repeated | 16 | 4096 | 30.8 μs | 55.0 μs | 39.0 μs | 147.5 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | +| log | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 90 ns | 60 ns | 70 ns | 50 ns | ExpFromLeft (50 ns) | 1.40x | +| log | sorted_repeated | 64 | 4 | 80 ns | 90 ns | 90 ns | 210 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| log | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 200 ns | 750 ns | 320 ns | 190 ns | 260 ns | Linear (170 ns) | 1.12x | +| log | sorted_repeated | 64 | 64 | 550 ns | 919 ns | 690 ns | 2.9 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | +| log | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 11.2 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | +| log | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 44.5 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | +| log | sorted_repeated | 64 | 4096 | 30.8 μs | 55.1 μs | 39.0 μs | 178.0 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| log | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 110 ns | 270 ns | 130 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| log | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 970 ns | 380 ns | 200 ns | 350 ns | Linear (170 ns) | 1.18x | +| log | sorted_repeated | 256 | 64 | 550 ns | 930 ns | 690 ns | 3.7 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | +| log | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 3.2 μs | 14.6 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| log | sorted_repeated | 256 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 58.4 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.7 μs) | 1.00x | +| log | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 233.0 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | +| log | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 290 ns | 140 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | +| log | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 220 ns | 1.1 μs | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | +| log | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 4.1 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| log | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 16.3 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| log | sorted_repeated | 1024 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 64.7 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.7 μs) | 1.00x | +| log | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.0 μs | 39.3 μs | 258.6 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | +| log | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| log | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 340 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | +| log | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 1.2 μs | 530 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | +| log | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 710 ns | 4.7 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | +| log | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 18.8 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| log | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 75.0 μs | 31.1 μs | 7.8 μs | 28.5 μs | Linear (7.8 μs) | 1.00x | +| log | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.0 μs | 299.9 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| log | sorted_repeated | 16384 | 1 | 90 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| log | sorted_repeated | 16384 | 4 | 90 ns | 110 ns | 110 ns | 390 ns | 190 ns | 120 ns | 170 ns | Linear (90 ns) | 1.33x | +| log | sorted_repeated | 16384 | 16 | 180 ns | 290 ns | 240 ns | 1.4 μs | 600 ns | 210 ns | 560 ns | Linear (180 ns) | 1.17x | +| log | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 720 ns | 5.4 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | +| log | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 21.5 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | +| log | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 86.0 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | +| log | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.1 μs | 39.3 μs | 342.9 μs | 144.0 μs | 30.8 μs | 133.5 μs | Linear (30.8 μs) | 1.00x | +| log | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| log | sorted_repeated | 65536 | 4 | 100 ns | 110 ns | 110 ns | 430 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| log | sorted_repeated | 65536 | 16 | 190 ns | 300 ns | 230 ns | 1.5 μs | 690 ns | 210 ns | 640 ns | Linear (190 ns) | 1.11x | +| log | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 710 ns | 6.1 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| log | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 23.8 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.02x | +| log | sorted_repeated | 65536 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 95.4 μs | 40.8 μs | 7.8 μs | 38.2 μs | Linear (7.7 μs) | 1.01x | +| log | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 380.7 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| log | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| log | unsorted | 16 | 4 | 100 ns | 90 ns | 100 ns | 100 ns | 100 ns | 110 ns | 70 ns | Gallop (90 ns) | 1.22x | +| log | unsorted | 16 | 16 | 230 ns | 230 ns | 220 ns | 230 ns | 220 ns | 230 ns | 210 ns | ExpFromLeft (220 ns) | 1.05x | +| log | unsorted | 16 | 64 | 730 ns | 730 ns | 740 ns | 720 ns | 720 ns | 740 ns | 720 ns | InterpSearch (720 ns) | 1.03x | +| log | unsorted | 16 | 256 | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.8 μs | 3.3 μs | 3.3 μs | Binary (2.8 μs) | 1.17x | +| log | unsorted | 16 | 1024 | 14.3 μs | 13.7 μs | 13.7 μs | 13.5 μs | 13.6 μs | 13.5 μs | 13.7 μs | InterpSearch (13.5 μs) | 1.00x | +| log | unsorted | 16 | 4096 | 92.7 μs | 88.1 μs | 88.6 μs | 88.9 μs | 88.3 μs | 88.2 μs | 92.6 μs | Gallop (88.1 μs) | 1.00x | +| log | unsorted | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| log | unsorted | 64 | 4 | 110 ns | 100 ns | 110 ns | 110 ns | 120 ns | 130 ns | 90 ns | Gallop (100 ns) | 1.30x | +| log | unsorted | 64 | 16 | 280 ns | 280 ns | 270 ns | 279 ns | 280 ns | 290 ns | 270 ns | ExpFromLeft (270 ns) | 1.07x | +| log | unsorted | 64 | 64 | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | InterpSearch (1.0 μs) | 1.00x | +| log | unsorted | 64 | 256 | 5.6 μs | 5.6 μs | 5.5 μs | 5.5 μs | 5.5 μs | 5.5 μs | 5.8 μs | Binary (5.5 μs) | 1.00x | +| log | unsorted | 64 | 1024 | 29.8 μs | 29.5 μs | 29.6 μs | 29.4 μs | 29.4 μs | 29.3 μs | 31.4 μs | InterpSearch (29.4 μs) | 1.00x | +| log | unsorted | 64 | 4096 | 172.7 μs | 166.7 μs | 166.4 μs | 165.5 μs | 167.9 μs | 167.0 μs | 173.3 μs | InterpSearch (165.5 μs) | 1.01x | +| log | unsorted | 256 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| log | unsorted | 256 | 4 | 130 ns | 130 ns | 120 ns | 120 ns | 120 ns | 130 ns | 110 ns | InterpSearch (120 ns) | 1.08x | +| log | unsorted | 256 | 16 | 340 ns | 350 ns | 360 ns | 350 ns | 340 ns | 360 ns | 340 ns | Binary (340 ns) | 1.06x | +| log | unsorted | 256 | 64 | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | Binary (1.5 μs) | 1.01x | +| log | unsorted | 256 | 256 | 8.4 μs | 8.1 μs | 8.0 μs | 8.1 μs | 8.0 μs | 7.7 μs | 8.0 μs | ExpFromLeft (8.0 μs) | 0.96x | +| log | unsorted | 256 | 1024 | 47.7 μs | 47.3 μs | 45.2 μs | 46.6 μs | 45.4 μs | 45.9 μs | 46.0 μs | ExpFromLeft (45.2 μs) | 1.01x | +| log | unsorted | 256 | 4096 | 254.6 μs | 258.8 μs | 252.9 μs | 250.5 μs | 250.1 μs | 252.7 μs | 258.4 μs | Binary (250.1 μs) | 1.01x | +| log | unsorted | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| log | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 129 ns | InterpSearch (140 ns) | 1.07x | +| log | unsorted | 1024 | 16 | 420 ns | 420 ns | 420 ns | 410 ns | 420 ns | 430 ns | 420 ns | InterpSearch (410 ns) | 1.05x | +| log | unsorted | 1024 | 64 | 1.9 μs | 1.9 μs | 1.9 μs | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | Binary (1.8 μs) | 0.99x | +| log | unsorted | 1024 | 256 | 10.0 μs | 9.9 μs | 9.5 μs | 9.8 μs | 9.8 μs | 9.8 μs | 10.0 μs | ExpFromLeft (9.5 μs) | 1.03x | +| log | unsorted | 1024 | 1024 | 69.6 μs | 68.8 μs | 68.3 μs | 67.9 μs | 67.7 μs | 67.1 μs | 70.7 μs | Binary (67.7 μs) | 0.99x | +| log | unsorted | 1024 | 4096 | 346.5 μs | 348.4 μs | 347.6 μs | 341.8 μs | 340.3 μs | 343.2 μs | 346.4 μs | Binary (340.3 μs) | 1.01x | +| log | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| log | unsorted | 4096 | 4 | 160 ns | 150 ns | 160 ns | 160 ns | 160 ns | 170 ns | 150 ns | Gallop (150 ns) | 1.13x | +| log | unsorted | 4096 | 16 | 490 ns | 500 ns | 490 ns | 500 ns | 500 ns | 500 ns | 480 ns | ExpFromLeft (490 ns) | 1.02x | +| log | unsorted | 4096 | 64 | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | InterpSearch (2.1 μs) | 1.00x | +| log | unsorted | 4096 | 256 | 11.8 μs | 11.5 μs | 11.4 μs | 11.4 μs | 11.4 μs | 11.1 μs | 11.9 μs | Binary (11.4 μs) | 0.97x | +| log | unsorted | 4096 | 1024 | 89.7 μs | 88.0 μs | 87.5 μs | 86.4 μs | 85.7 μs | 87.0 μs | 89.5 μs | Binary (85.7 μs) | 1.02x | +| log | unsorted | 4096 | 4096 | 428.6 μs | 431.1 μs | 423.5 μs | 430.9 μs | 423.9 μs | 422.9 μs | 430.9 μs | ExpFromLeft (423.5 μs) | 1.00x | +| log | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 120 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | +| log | unsorted | 16384 | 4 | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | 180 ns | 160 ns | ExpFromLeft (170 ns) | 1.06x | +| log | unsorted | 16384 | 16 | 570 ns | 580 ns | 570 ns | 570 ns | 570 ns | 580 ns | 560 ns | InterpSearch (570 ns) | 1.02x | +| log | unsorted | 16384 | 64 | 2.5 μs | 2.5 μs | 2.5 μs | 2.5 μs | 2.5 μs | 2.5 μs | 2.5 μs | InterpSearch (2.5 μs) | 1.01x | +| log | unsorted | 16384 | 256 | 13.2 μs | 12.8 μs | 12.9 μs | 12.8 μs | 12.7 μs | 12.7 μs | 15.5 μs | Binary (12.7 μs) | 1.00x | +| log | unsorted | 16384 | 1024 | 116.9 μs | 114.2 μs | 113.5 μs | 112.5 μs | 112.5 μs | 112.1 μs | 112.7 μs | InterpSearch (112.5 μs) | 1.00x | +| log | unsorted | 16384 | 4096 | 552.6 μs | 550.7 μs | 551.9 μs | 549.2 μs | 552.4 μs | 552.0 μs | 547.4 μs | InterpSearch (549.2 μs) | 1.00x | +| log | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | +| log | unsorted | 65536 | 4 | 200 ns | 200 ns | 200 ns | 210 ns | 200 ns | 210 ns | 190 ns | ExpFromLeft (200 ns) | 1.05x | +| log | unsorted | 65536 | 16 | 660 ns | 660 ns | 660 ns | 660 ns | 660 ns | 670 ns | 640 ns | InterpSearch (660 ns) | 1.02x | +| log | unsorted | 65536 | 64 | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.9 μs | InterpSearch (2.8 μs) | 1.00x | +| log | unsorted | 65536 | 256 | 15.8 μs | 15.6 μs | 15.5 μs | 15.4 μs | 15.4 μs | 15.4 μs | 18.2 μs | Binary (15.4 μs) | 1.00x | +| log | unsorted | 65536 | 1024 | 158.2 μs | 154.8 μs | 152.1 μs | 151.9 μs | 151.7 μs | 151.9 μs | 154.8 μs | Binary (151.7 μs) | 1.00x | +| log | unsorted | 65536 | 4096 | 709.2 μs | 708.3 μs | 705.0 μs | 706.6 μs | 707.8 μs | 709.2 μs | 706.6 μs | ExpFromLeft (705.0 μs) | 1.01x | +| jittered | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | sorted_uniform | 16 | 4 | 90 ns | 110 ns | 100 ns | 160 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| jittered | sorted_uniform | 16 | 16 | 180 ns | 280 ns | 210 ns | 520 ns | 220 ns | 210 ns | 190 ns | Linear (180 ns) | 1.17x | +| jittered | sorted_uniform | 16 | 64 | 560 ns | 1.0 μs | 730 ns | 1.9 μs | 1.0 μs | 590 ns | 880 ns | Linear (560 ns) | 1.05x | +| jittered | sorted_uniform | 16 | 256 | 2.3 μs | 3.7 μs | 2.9 μs | 7.7 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.03x | +| jittered | sorted_uniform | 16 | 1024 | 8.1 μs | 14.0 μs | 10.8 μs | 28.2 μs | 12.2 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | +| jittered | sorted_uniform | 16 | 4096 | 31.0 μs | 54.8 μs | 42.4 μs | 109.5 μs | 48.2 μs | 31.1 μs | 40.7 μs | Linear (31.0 μs) | 1.00x | +| jittered | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| jittered | sorted_uniform | 64 | 4 | 130 ns | 130 ns | 120 ns | 150 ns | 100 ns | 140 ns | 90 ns | Binary (100 ns) | 1.40x | +| jittered | sorted_uniform | 64 | 16 | 250 ns | 350 ns | 280 ns | 470 ns | 310 ns | 270 ns | 290 ns | Linear (250 ns) | 1.08x | +| jittered | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 770 ns | 2.0 μs | 1.4 μs | 650 ns | 1.4 μs | Linear (630 ns) | 1.03x | +| jittered | sorted_uniform | 64 | 256 | 2.1 μs | 4.2 μs | 3.1 μs | 9.3 μs | 5.1 μs | 2.2 μs | 4.7 μs | Linear (2.1 μs) | 1.02x | +| jittered | sorted_uniform | 64 | 1024 | 9.2 μs | 14.8 μs | 11.7 μs | 31.4 μs | 17.8 μs | 9.1 μs | 16.0 μs | Linear (9.2 μs) | 0.99x | +| jittered | sorted_uniform | 64 | 4096 | 32.1 μs | 56.0 μs | 43.2 μs | 113.6 μs | 67.2 μs | 32.2 μs | 60.2 μs | Linear (32.1 μs) | 1.00x | +| jittered | sorted_uniform | 256 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_uniform | 256 | 4 | 430 ns | 170 ns | 140 ns | 140 ns | 130 ns | 160 ns | 110 ns | Binary (130 ns) | 1.23x | +| jittered | sorted_uniform | 256 | 16 | 480 ns | 450 ns | 370 ns | 470 ns | 410 ns | 380 ns | 380 ns | ExpFromLeft (370 ns) | 1.03x | +| jittered | sorted_uniform | 256 | 64 | 910 ns | 1.3 μs | 960 ns | 1.9 μs | 1.7 μs | 930 ns | 1.5 μs | Linear (910 ns) | 1.02x | +| jittered | sorted_uniform | 256 | 256 | 2.4 μs | 4.2 μs | 2.9 μs | 9.1 μs | 7.5 μs | 2.4 μs | 7.1 μs | Linear (2.4 μs) | 1.01x | +| jittered | sorted_uniform | 256 | 1024 | 10.2 μs | 17.8 μs | 13.6 μs | 37.1 μs | 27.1 μs | 10.3 μs | 25.5 μs | Linear (10.2 μs) | 1.01x | +| jittered | sorted_uniform | 256 | 4096 | 36.6 μs | 59.4 μs | 46.7 μs | 126.0 μs | 91.7 μs | 48.0 μs | 87.4 μs | Linear (36.6 μs) | 1.31x | +| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | +| jittered | sorted_uniform | 1024 | 4 | 1.5 μs | 190 ns | 160 ns | 150 ns | 150 ns | 200 ns | 120 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_uniform | 1024 | 16 | 1.7 μs | 580 ns | 470 ns | 490 ns | 450 ns | 490 ns | 410 ns | Binary (450 ns) | 1.09x | +| jittered | sorted_uniform | 1024 | 64 | 2.1 μs | 1.7 μs | 1.4 μs | 2.0 μs | 1.9 μs | 2.1 μs | 1.8 μs | ExpFromLeft (1.4 μs) | 1.57x | +| jittered | sorted_uniform | 1024 | 256 | 3.6 μs | 5.2 μs | 3.9 μs | 8.9 μs | 7.7 μs | 3.8 μs | 7.6 μs | Linear (3.6 μs) | 1.06x | +| jittered | sorted_uniform | 1024 | 1024 | 10.8 μs | 17.7 μs | 12.5 μs | 38.9 μs | 56.6 μs | 10.7 μs | 54.0 μs | Linear (10.8 μs) | 0.99x | +| jittered | sorted_uniform | 1024 | 4096 | 48.4 μs | 72.4 μs | 58.0 μs | 148.8 μs | 193.7 μs | 48.6 μs | 186.8 μs | Linear (48.4 μs) | 1.01x | +| jittered | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_uniform | 4096 | 4 | 5.6 μs | 240 ns | 200 ns | 150 ns | 160 ns | 200 ns | 150 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_uniform | 4096 | 16 | 5.8 μs | 720 ns | 550 ns | 470 ns | 540 ns | 530 ns | 490 ns | InterpSearch (470 ns) | 1.13x | +| jittered | sorted_uniform | 4096 | 64 | 7.0 μs | 2.2 μs | 1.7 μs | 2.0 μs | 2.2 μs | 2.2 μs | 1.9 μs | ExpFromLeft (1.7 μs) | 1.31x | +| jittered | sorted_uniform | 4096 | 256 | 8.9 μs | 7.2 μs | 5.3 μs | 9.3 μs | 10.5 μs | 9.8 μs | 10.6 μs | ExpFromLeft (5.3 μs) | 1.84x | +| jittered | sorted_uniform | 4096 | 1024 | 16.5 μs | 24.0 μs | 17.3 μs | 37.6 μs | 95.3 μs | 15.0 μs | 91.3 μs | Linear (16.5 μs) | 0.91x | +| jittered | sorted_uniform | 4096 | 4096 | 68.5 μs | 93.8 μs | 72.7 μs | 155.5 μs | 305.7 μs | 65.1 μs | 297.2 μs | Linear (68.5 μs) | 0.95x | +| jittered | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_uniform | 16384 | 4 | 20.7 μs | 260 ns | 220 ns | 150 ns | 180 ns | 200 ns | 160 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_uniform | 16384 | 16 | 21.9 μs | 890 ns | 660 ns | 500 ns | 590 ns | 560 ns | 560 ns | InterpSearch (500 ns) | 1.12x | +| jittered | sorted_uniform | 16384 | 64 | 24.8 μs | 3.7 μs | 2.2 μs | 2.2 μs | 2.4 μs | 2.3 μs | 2.2 μs | InterpSearch (2.2 μs) | 1.06x | +| jittered | sorted_uniform | 16384 | 256 | 30.5 μs | 9.8 μs | 7.0 μs | 9.2 μs | 13.2 μs | 9.7 μs | 13.3 μs | ExpFromLeft (7.0 μs) | 1.39x | +| jittered | sorted_uniform | 16384 | 1024 | 40.1 μs | 35.0 μs | 25.9 μs | 38.6 μs | 126.5 μs | 40.5 μs | 125.4 μs | ExpFromLeft (25.9 μs) | 1.56x | +| jittered | sorted_uniform | 16384 | 4096 | 115.9 μs | 160.8 μs | 121.1 μs | 153.8 μs | 404.3 μs | 112.0 μs | 397.3 μs | Linear (115.9 μs) | 0.97x | +| jittered | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_uniform | 65536 | 4 | 87.4 μs | 300 ns | 240 ns | 150 ns | 210 ns | 200 ns | 180 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_uniform | 65536 | 16 | 79.4 μs | 1.1 μs | 760 ns | 500 ns | 690 ns | 570 ns | 630 ns | InterpSearch (500 ns) | 1.14x | +| jittered | sorted_uniform | 65536 | 64 | 93.0 μs | 3.6 μs | 2.7 μs | 2.0 μs | 2.8 μs | 2.1 μs | 2.6 μs | InterpSearch (2.0 μs) | 1.09x | +| jittered | sorted_uniform | 65536 | 256 | 102.7 μs | 12.2 μs | 9.7 μs | 9.3 μs | 16.1 μs | 10.0 μs | 17.0 μs | InterpSearch (9.3 μs) | 1.07x | +| jittered | sorted_uniform | 65536 | 1024 | 119.3 μs | 60.6 μs | 44.0 μs | 39.3 μs | 156.2 μs | 41.6 μs | 159.3 μs | InterpSearch (39.3 μs) | 1.06x | +| jittered | sorted_uniform | 65536 | 4096 | 196.4 μs | 252.4 μs | 200.9 μs | 153.0 μs | 493.3 μs | 160.9 μs | 494.8 μs | InterpSearch (153.0 μs) | 1.05x | +| jittered | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| jittered | sorted_dense_burst | 16 | 16 | 170 ns | 270 ns | 220 ns | 500 ns | 230 ns | 200 ns | 190 ns | Linear (170 ns) | 1.18x | +| jittered | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 730 ns | 1.8 μs | 790 ns | 580 ns | 660 ns | Linear (550 ns) | 1.05x | +| jittered | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.01x | +| jittered | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 27.4 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.00x | +| jittered | sorted_dense_burst | 16 | 4096 | 30.8 μs | 55.0 μs | 41.8 μs | 108.9 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 100 ns | 140 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| jittered | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 230 ns | 490 ns | 300 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | +| jittered | sorted_dense_burst | 64 | 64 | 560 ns | 920 ns | 730 ns | 1.8 μs | 1.1 μs | 580 ns | 930 ns | Linear (560 ns) | 1.04x | +| jittered | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | +| jittered | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.7 μs | 10.5 μs | 26.9 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | +| jittered | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.9 μs | 42.0 μs | 107.4 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_dense_burst | 256 | 4 | 80 ns | 100 ns | 100 ns | 150 ns | 120 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | +| jittered | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 500 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| jittered | sorted_dense_burst | 256 | 64 | 550 ns | 940 ns | 740 ns | 1.8 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | +| jittered | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| jittered | sorted_dense_burst | 256 | 1024 | 7.7 μs | 14.0 μs | 10.4 μs | 27.3 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.7 μs) | 1.00x | +| jittered | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.7 μs | 41.6 μs | 108.4 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_dense_burst | 1024 | 4 | 100 ns | 120 ns | 110 ns | 160 ns | 140 ns | 110 ns | 130 ns | Linear (100 ns) | 1.10x | +| jittered | sorted_dense_burst | 1024 | 16 | 180 ns | 290 ns | 250 ns | 490 ns | 460 ns | 210 ns | 400 ns | Linear (180 ns) | 1.17x | +| jittered | sorted_dense_burst | 1024 | 64 | 559 ns | 930 ns | 740 ns | 1.8 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (559 ns) | 1.06x | +| jittered | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| jittered | sorted_dense_burst | 1024 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 27.8 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.01x | +| jittered | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 54.8 μs | 42.0 μs | 110.5 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_dense_burst | 4096 | 4 | 89 ns | 110 ns | 110 ns | 150 ns | 160 ns | 120 ns | 150 ns | Linear (89 ns) | 1.35x | +| jittered | sorted_dense_burst | 4096 | 16 | 180 ns | 290 ns | 250 ns | 490 ns | 540 ns | 260 ns | 490 ns | Linear (180 ns) | 1.44x | +| jittered | sorted_dense_burst | 4096 | 64 | 570 ns | 930 ns | 750 ns | 1.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (570 ns) | 1.04x | +| jittered | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| jittered | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 27.1 μs | 31.1 μs | 7.8 μs | 28.5 μs | Linear (7.7 μs) | 1.01x | +| jittered | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 54.9 μs | 42.0 μs | 107.7 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_dense_burst | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 180 ns | 120 ns | 170 ns | Linear (100 ns) | 1.20x | +| jittered | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 490 ns | 610 ns | 220 ns | 570 ns | Linear (190 ns) | 1.16x | +| jittered | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 749 ns | 1.8 μs | 2.3 μs | 610 ns | 2.1 μs | Linear (570 ns) | 1.07x | +| jittered | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | +| jittered | sorted_dense_burst | 16384 | 1024 | 8.3 μs | 13.7 μs | 10.6 μs | 27.2 μs | 36.1 μs | 7.8 μs | 33.5 μs | Linear (8.3 μs) | 0.94x | +| jittered | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 107.7 μs | 144.1 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 150 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| jittered | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 250 ns | 510 ns | 680 ns | 260 ns | 640 ns | Linear (190 ns) | 1.37x | +| jittered | sorted_dense_burst | 65536 | 64 | 570 ns | 950 ns | 750 ns | 1.8 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| jittered | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | +| jittered | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 27.0 μs | 40.8 μs | 7.8 μs | 38.2 μs | Linear (7.8 μs) | 1.00x | +| jittered | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 107.4 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | sorted_near_start | 16 | 4 | 80 ns | 100 ns | 100 ns | 150 ns | 90 ns | 110 ns | 70 ns | Linear (80 ns) | 1.38x | +| jittered | sorted_near_start | 16 | 16 | 180 ns | 290 ns | 220 ns | 490 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | +| jittered | sorted_near_start | 16 | 64 | 570 ns | 959 ns | 740 ns | 1.8 μs | 810 ns | 610 ns | 679 ns | Linear (570 ns) | 1.07x | +| jittered | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | +| jittered | sorted_near_start | 16 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 27.5 μs | 12.2 μs | 7.9 μs | 10.3 μs | Linear (7.9 μs) | 1.00x | +| jittered | sorted_near_start | 16 | 4096 | 31.1 μs | 55.2 μs | 42.2 μs | 107.0 μs | 47.8 μs | 31.1 μs | 40.3 μs | Linear (31.1 μs) | 1.00x | +| jittered | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | +| jittered | sorted_near_start | 64 | 4 | 140 ns | 130 ns | 110 ns | 150 ns | 110 ns | 120 ns | 90 ns | ExpFromLeft (110 ns) | 1.09x | +| jittered | sorted_near_start | 64 | 16 | 260 ns | 300 ns | 250 ns | 480 ns | 320 ns | 270 ns | 280 ns | ExpFromLeft (250 ns) | 1.08x | +| jittered | sorted_near_start | 64 | 64 | 680 ns | 1.0 μs | 820 ns | 1.9 μs | 1.1 μs | 700 ns | 1.0 μs | Linear (680 ns) | 1.03x | +| jittered | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.2 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.02x | +| jittered | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 28.0 μs | 17.2 μs | 7.9 μs | 15.6 μs | Linear (7.9 μs) | 1.00x | +| jittered | sorted_near_start | 64 | 4096 | 31.8 μs | 56.1 μs | 43.1 μs | 111.0 μs | 67.1 μs | 31.8 μs | 59.9 μs | Linear (31.8 μs) | 1.00x | +| jittered | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_near_start | 256 | 4 | 250 ns | 130 ns | 120 ns | 150 ns | 120 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | +| jittered | sorted_near_start | 256 | 16 | 440 ns | 340 ns | 260 ns | 490 ns | 390 ns | 280 ns | 370 ns | ExpFromLeft (260 ns) | 1.08x | +| jittered | sorted_near_start | 256 | 64 | 890 ns | 1.1 μs | 850 ns | 1.9 μs | 1.6 μs | 920 ns | 1.5 μs | ExpFromLeft (850 ns) | 1.08x | +| jittered | sorted_near_start | 256 | 256 | 2.6 μs | 3.9 μs | 3.1 μs | 7.6 μs | 5.7 μs | 2.6 μs | 5.2 μs | Linear (2.6 μs) | 1.00x | +| jittered | sorted_near_start | 256 | 1024 | 8.5 μs | 14.5 μs | 11.0 μs | 28.8 μs | 22.2 μs | 8.5 μs | 20.3 μs | Linear (8.5 μs) | 1.00x | +| jittered | sorted_near_start | 256 | 4096 | 31.7 μs | 56.3 μs | 42.5 μs | 114.1 μs | 89.7 μs | 31.5 μs | 81.8 μs | Linear (31.7 μs) | 0.99x | +| jittered | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_near_start | 1024 | 4 | 550 ns | 180 ns | 160 ns | 150 ns | 130 ns | 200 ns | 120 ns | Binary (130 ns) | 1.54x | +| jittered | sorted_near_start | 1024 | 16 | 1.3 μs | 400 ns | 330 ns | 470 ns | 500 ns | 350 ns | 450 ns | ExpFromLeft (330 ns) | 1.06x | +| jittered | sorted_near_start | 1024 | 64 | 1.9 μs | 1.2 μs | 880 ns | 2.0 μs | 2.1 μs | 920 ns | 1.9 μs | ExpFromLeft (880 ns) | 1.05x | +| jittered | sorted_near_start | 1024 | 256 | 3.7 μs | 4.5 μs | 3.5 μs | 8.6 μs | 7.7 μs | 3.7 μs | 7.1 μs | ExpFromLeft (3.5 μs) | 1.05x | +| jittered | sorted_near_start | 1024 | 1024 | 10.7 μs | 15.7 μs | 12.3 μs | 31.0 μs | 27.3 μs | 10.6 μs | 25.7 μs | Linear (10.7 μs) | 0.99x | +| jittered | sorted_near_start | 1024 | 4096 | 33.8 μs | 58.1 μs | 44.1 μs | 116.9 μs | 110.4 μs | 33.9 μs | 104.5 μs | Linear (33.8 μs) | 1.00x | +| jittered | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_near_start | 4096 | 4 | 3.6 μs | 220 ns | 180 ns | 150 ns | 160 ns | 200 ns | 150 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_near_start | 4096 | 16 | 3.2 μs | 500 ns | 420 ns | 470 ns | 540 ns | 430 ns | 500 ns | ExpFromLeft (420 ns) | 1.02x | +| jittered | sorted_near_start | 4096 | 64 | 5.3 μs | 1.5 μs | 1.1 μs | 2.0 μs | 2.3 μs | 1.2 μs | 2.2 μs | ExpFromLeft (1.1 μs) | 1.05x | +| jittered | sorted_near_start | 4096 | 256 | 8.2 μs | 4.8 μs | 3.4 μs | 9.0 μs | 11.0 μs | 3.5 μs | 10.5 μs | ExpFromLeft (3.4 μs) | 1.03x | +| jittered | sorted_near_start | 4096 | 1024 | 16.4 μs | 19.1 μs | 14.9 μs | 36.2 μs | 43.0 μs | 16.5 μs | 38.4 μs | ExpFromLeft (14.9 μs) | 1.11x | +| jittered | sorted_near_start | 4096 | 4096 | 42.3 μs | 63.1 μs | 49.7 μs | 123.3 μs | 155.7 μs | 42.1 μs | 140.7 μs | Linear (42.3 μs) | 1.00x | +| jittered | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_near_start | 16384 | 4 | 12.9 μs | 230 ns | 200 ns | 150 ns | 180 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_near_start | 16384 | 16 | 14.5 μs | 660 ns | 510 ns | 460 ns | 600 ns | 530 ns | 560 ns | InterpSearch (460 ns) | 1.15x | +| jittered | sorted_near_start | 16384 | 64 | 24.5 μs | 2.0 μs | 1.4 μs | 2.0 μs | 3.2 μs | 1.5 μs | 2.9 μs | ExpFromLeft (1.4 μs) | 1.03x | +| jittered | sorted_near_start | 16384 | 256 | 23.2 μs | 6.0 μs | 4.5 μs | 9.2 μs | 17.7 μs | 4.4 μs | 16.4 μs | ExpFromLeft (4.5 μs) | 1.00x | +| jittered | sorted_near_start | 16384 | 1024 | 32.8 μs | 21.0 μs | 14.8 μs | 38.4 μs | 74.8 μs | 14.8 μs | 67.5 μs | ExpFromLeft (14.8 μs) | 1.00x | +| jittered | sorted_near_start | 16384 | 4096 | 73.9 μs | 78.7 μs | 62.5 μs | 148.2 μs | 256.1 μs | 73.9 μs | 239.6 μs | ExpFromLeft (62.5 μs) | 1.18x | +| jittered | sorted_near_start | 65536 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_near_start | 65536 | 4 | 49.0 μs | 250 ns | 210 ns | 150 ns | 200 ns | 200 ns | 190 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_near_start | 65536 | 16 | 24.1 μs | 750 ns | 580 ns | 470 ns | 700 ns | 600 ns | 670 ns | InterpSearch (470 ns) | 1.28x | +| jittered | sorted_near_start | 65536 | 64 | 92.7 μs | 2.5 μs | 1.9 μs | 2.0 μs | 3.3 μs | 2.0 μs | 3.2 μs | ExpFromLeft (1.9 μs) | 1.01x | +| jittered | sorted_near_start | 65536 | 256 | 97.9 μs | 8.1 μs | 5.9 μs | 9.0 μs | 20.7 μs | 5.9 μs | 19.5 μs | ExpFromLeft (5.9 μs) | 1.00x | +| jittered | sorted_near_start | 65536 | 1024 | 106.4 μs | 27.3 μs | 19.7 μs | 38.4 μs | 96.6 μs | 18.0 μs | 87.9 μs | ExpFromLeft (19.7 μs) | 0.91x | +| jittered | sorted_near_start | 65536 | 4096 | 157.3 μs | 121.6 μs | 95.3 μs | 154.7 μs | 322.8 μs | 92.5 μs | 296.2 μs | ExpFromLeft (95.3 μs) | 0.97x | +| jittered | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | sorted_arithmetic | 16 | 4 | 100 ns | 120 ns | 120 ns | 150 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | +| jittered | sorted_arithmetic | 16 | 16 | 190 ns | 300 ns | 210 ns | 500 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| jittered | sorted_arithmetic | 16 | 64 | 590 ns | 1.1 μs | 760 ns | 2.0 μs | 1.0 μs | 620 ns | 890 ns | Linear (590 ns) | 1.05x | +| jittered | sorted_arithmetic | 16 | 256 | 2.3 μs | 3.7 μs | 3.0 μs | 7.8 μs | 3.3 μs | 2.4 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | +| jittered | sorted_arithmetic | 16 | 1024 | 11.3 μs | 18.7 μs | 14.2 μs | 28.2 μs | 12.1 μs | 8.1 μs | 10.5 μs | Linear (11.3 μs) | 0.71x | +| jittered | sorted_arithmetic | 16 | 4096 | 31.1 μs | 54.9 μs | 42.3 μs | 109.7 μs | 47.9 μs | 31.1 μs | 40.7 μs | Linear (31.1 μs) | 1.00x | +| jittered | sorted_arithmetic | 64 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 50 ns | 50 ns | Binary (60 ns) | 0.83x | +| jittered | sorted_arithmetic | 64 | 4 | 170 ns | 140 ns | 140 ns | 150 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | +| jittered | sorted_arithmetic | 64 | 16 | 260 ns | 410 ns | 320 ns | 490 ns | 300 ns | 290 ns | 260 ns | Linear (260 ns) | 1.12x | +| jittered | sorted_arithmetic | 64 | 64 | 640 ns | 1.2 μs | 789 ns | 2.1 μs | 1.3 μs | 670 ns | 1.1 μs | Linear (640 ns) | 1.05x | +| jittered | sorted_arithmetic | 64 | 256 | 2.5 μs | 4.1 μs | 3.1 μs | 7.8 μs | 5.4 μs | 2.6 μs | 4.7 μs | Linear (2.5 μs) | 1.02x | +| jittered | sorted_arithmetic | 64 | 1024 | 9.0 μs | 14.8 μs | 11.7 μs | 31.7 μs | 17.8 μs | 9.0 μs | 15.9 μs | Linear (9.0 μs) | 1.01x | +| jittered | sorted_arithmetic | 64 | 4096 | 32.2 μs | 56.1 μs | 43.2 μs | 113.1 μs | 67.3 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | +| jittered | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_arithmetic | 256 | 4 | 470 ns | 180 ns | 160 ns | 140 ns | 130 ns | 180 ns | 110 ns | Binary (130 ns) | 1.38x | +| jittered | sorted_arithmetic | 256 | 16 | 650 ns | 530 ns | 400 ns | 460 ns | 390 ns | 430 ns | 340 ns | Binary (390 ns) | 1.10x | +| jittered | sorted_arithmetic | 256 | 64 | 1.0 μs | 1.7 μs | 1.3 μs | 2.0 μs | 1.4 μs | 1.1 μs | 1.3 μs | Linear (1.0 μs) | 1.02x | +| jittered | sorted_arithmetic | 256 | 256 | 2.5 μs | 4.4 μs | 2.9 μs | 8.4 μs | 7.1 μs | 2.5 μs | 6.8 μs | Linear (2.5 μs) | 1.01x | +| jittered | sorted_arithmetic | 256 | 1024 | 10.1 μs | 16.1 μs | 12.2 μs | 30.0 μs | 27.1 μs | 10.1 μs | 25.0 μs | Linear (10.1 μs) | 1.00x | +| jittered | sorted_arithmetic | 256 | 4096 | 36.0 μs | 59.6 μs | 46.6 μs | 124.5 μs | 91.4 μs | 35.8 μs | 83.3 μs | Linear (36.0 μs) | 1.00x | +| jittered | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| jittered | sorted_arithmetic | 1024 | 4 | 1.6 μs | 210 ns | 170 ns | 150 ns | 150 ns | 190 ns | 130 ns | InterpSearch (150 ns) | 1.27x | +| jittered | sorted_arithmetic | 1024 | 16 | 1.7 μs | 700 ns | 520 ns | 470 ns | 450 ns | 540 ns | 410 ns | Binary (450 ns) | 1.20x | +| jittered | sorted_arithmetic | 1024 | 64 | 2.2 μs | 2.2 μs | 1.6 μs | 1.9 μs | 1.7 μs | 2.1 μs | 1.6 μs | ExpFromLeft (1.6 μs) | 1.25x | +| jittered | sorted_arithmetic | 1024 | 256 | 4.5 μs | 6.2 μs | 4.7 μs | 7.2 μs | 8.3 μs | 3.6 μs | 8.0 μs | Linear (4.5 μs) | 0.80x | +| jittered | sorted_arithmetic | 1024 | 1024 | 10.6 μs | 19.0 μs | 12.4 μs | 36.6 μs | 75.8 μs | 10.4 μs | 77.0 μs | Linear (10.6 μs) | 0.98x | +| jittered | sorted_arithmetic | 1024 | 4096 | 41.5 μs | 64.6 μs | 49.7 μs | 119.0 μs | 197.0 μs | 41.5 μs | 192.3 μs | Linear (41.5 μs) | 1.00x | +| jittered | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| jittered | sorted_arithmetic | 4096 | 4 | 6.0 μs | 240 ns | 200 ns | 150 ns | 160 ns | 190 ns | 150 ns | InterpSearch (150 ns) | 1.27x | +| jittered | sorted_arithmetic | 4096 | 16 | 6.4 μs | 820 ns | 610 ns | 520 ns | 540 ns | 580 ns | 490 ns | InterpSearch (520 ns) | 1.12x | +| jittered | sorted_arithmetic | 4096 | 64 | 6.4 μs | 2.7 μs | 1.9 μs | 1.9 μs | 2.0 μs | 2.0 μs | 1.9 μs | InterpSearch (1.9 μs) | 1.08x | +| jittered | sorted_arithmetic | 4096 | 256 | 8.7 μs | 8.7 μs | 6.6 μs | 8.0 μs | 8.2 μs | 8.6 μs | 8.1 μs | ExpFromLeft (6.6 μs) | 1.30x | +| jittered | sorted_arithmetic | 4096 | 1024 | 14.5 μs | 25.0 μs | 18.8 μs | 29.9 μs | 86.1 μs | 14.5 μs | 75.9 μs | Linear (14.5 μs) | 1.00x | +| jittered | sorted_arithmetic | 4096 | 4096 | 39.0 μs | 66.3 μs | 44.2 μs | 116.3 μs | 314.0 μs | 39.0 μs | 310.8 μs | Linear (39.0 μs) | 1.00x | +| jittered | sorted_arithmetic | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 90 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_arithmetic | 16384 | 4 | 23.4 μs | 270 ns | 230 ns | 150 ns | 180 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_arithmetic | 16384 | 16 | 23.8 μs | 1.0 μs | 720 ns | 500 ns | 620 ns | 560 ns | 570 ns | InterpSearch (500 ns) | 1.12x | +| jittered | sorted_arithmetic | 16384 | 64 | 25.3 μs | 3.4 μs | 2.2 μs | 2.0 μs | 2.3 μs | 2.1 μs | 2.2 μs | InterpSearch (2.0 μs) | 1.05x | +| jittered | sorted_arithmetic | 16384 | 256 | 26.2 μs | 10.8 μs | 8.0 μs | 7.7 μs | 13.6 μs | 8.0 μs | 13.3 μs | InterpSearch (7.7 μs) | 1.04x | +| jittered | sorted_arithmetic | 16384 | 1024 | 33.1 μs | 33.5 μs | 25.3 μs | 31.7 μs | 107.3 μs | 32.2 μs | 106.4 μs | ExpFromLeft (25.3 μs) | 1.28x | +| jittered | sorted_arithmetic | 16384 | 4096 | 59.0 μs | 101.9 μs | 78.0 μs | 123.0 μs | 405.6 μs | 59.0 μs | 397.3 μs | Linear (59.0 μs) | 1.00x | +| jittered | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_arithmetic | 65536 | 4 | 93.0 μs | 320 ns | 250 ns | 150 ns | 210 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | +| jittered | sorted_arithmetic | 65536 | 16 | 93.6 μs | 1.2 μs | 1.1 μs | 470 ns | 730 ns | 530 ns | 660 ns | InterpSearch (470 ns) | 1.13x | +| jittered | sorted_arithmetic | 65536 | 64 | 95.8 μs | 4.0 μs | 2.8 μs | 1.9 μs | 2.9 μs | 2.1 μs | 2.7 μs | InterpSearch (1.9 μs) | 1.09x | +| jittered | sorted_arithmetic | 65536 | 256 | 101.7 μs | 14.9 μs | 10.5 μs | 9.2 μs | 13.2 μs | 9.7 μs | 13.0 μs | InterpSearch (9.2 μs) | 1.06x | +| jittered | sorted_arithmetic | 65536 | 1024 | 105.3 μs | 44.0 μs | 33.1 μs | 32.0 μs | 115.6 μs | 33.8 μs | 116.8 μs | InterpSearch (32.0 μs) | 1.06x | +| jittered | sorted_arithmetic | 65536 | 4096 | 131.6 μs | 134.6 μs | 102.1 μs | 118.8 μs | 419.4 μs | 126.4 μs | 410.8 μs | ExpFromLeft (102.1 μs) | 1.24x | +| jittered | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 50 ns | 50 ns | 40 ns | Binary (50 ns) | 1.00x | +| jittered | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| jittered | sorted_geometric | 16 | 16 | 190 ns | 310 ns | 220 ns | 490 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| jittered | sorted_geometric | 16 | 64 | 560 ns | 1.0 μs | 730 ns | 2.0 μs | 990 ns | 590 ns | 820 ns | Linear (560 ns) | 1.05x | +| jittered | sorted_geometric | 16 | 256 | 2.3 μs | 3.8 μs | 2.9 μs | 7.9 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | +| jittered | sorted_geometric | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 28.7 μs | 12.1 μs | 8.1 μs | 10.3 μs | Linear (8.1 μs) | 1.00x | +| jittered | sorted_geometric | 16 | 4096 | 31.1 μs | 55.6 μs | 42.3 μs | 111.4 μs | 47.6 μs | 31.1 μs | 40.1 μs | Linear (31.1 μs) | 1.00x | +| jittered | sorted_geometric | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| jittered | sorted_geometric | 64 | 4 | 170 ns | 140 ns | 120 ns | 150 ns | 110 ns | 140 ns | 100 ns | Binary (110 ns) | 1.27x | +| jittered | sorted_geometric | 64 | 16 | 270 ns | 370 ns | 300 ns | 460 ns | 300 ns | 290 ns | 270 ns | Linear (270 ns) | 1.07x | +| jittered | sorted_geometric | 64 | 64 | 640 ns | 1.1 μs | 740 ns | 1.9 μs | 1.2 μs | 660 ns | 1.1 μs | Linear (640 ns) | 1.03x | +| jittered | sorted_geometric | 64 | 256 | 2.3 μs | 4.2 μs | 3.1 μs | 8.6 μs | 5.3 μs | 2.3 μs | 5.0 μs | Linear (2.3 μs) | 1.00x | +| jittered | sorted_geometric | 64 | 1024 | 9.1 μs | 14.9 μs | 11.7 μs | 30.9 μs | 17.7 μs | 9.1 μs | 15.9 μs | Linear (9.1 μs) | 1.00x | +| jittered | sorted_geometric | 64 | 4096 | 32.1 μs | 56.6 μs | 43.2 μs | 112.0 μs | 67.1 μs | 32.2 μs | 60.3 μs | Linear (32.1 μs) | 1.00x | +| jittered | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_geometric | 256 | 4 | 490 ns | 180 ns | 150 ns | 150 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | +| jittered | sorted_geometric | 256 | 16 | 530 ns | 490 ns | 380 ns | 470 ns | 370 ns | 410 ns | 350 ns | Binary (370 ns) | 1.11x | +| jittered | sorted_geometric | 256 | 64 | 920 ns | 1.4 μs | 1.0 μs | 2.0 μs | 1.4 μs | 940 ns | 1.2 μs | Linear (920 ns) | 1.02x | +| jittered | sorted_geometric | 256 | 256 | 2.4 μs | 4.5 μs | 2.9 μs | 8.5 μs | 6.6 μs | 2.5 μs | 6.1 μs | Linear (2.4 μs) | 1.01x | +| jittered | sorted_geometric | 256 | 1024 | 10.1 μs | 16.5 μs | 12.7 μs | 34.9 μs | 27.6 μs | 10.1 μs | 25.9 μs | Linear (10.1 μs) | 1.00x | +| jittered | sorted_geometric | 256 | 4096 | 36.4 μs | 59.6 μs | 46.4 μs | 123.7 μs | 91.2 μs | 36.5 μs | 83.2 μs | Linear (36.4 μs) | 1.00x | +| jittered | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| jittered | sorted_geometric | 1024 | 4 | 1.6 μs | 200 ns | 180 ns | 150 ns | 150 ns | 200 ns | 130 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_geometric | 1024 | 16 | 1.9 μs | 630 ns | 490 ns | 470 ns | 450 ns | 500 ns | 410 ns | Binary (450 ns) | 1.11x | +| jittered | sorted_geometric | 1024 | 64 | 2.1 μs | 1.9 μs | 1.4 μs | 2.0 μs | 1.7 μs | 1.5 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.01x | +| jittered | sorted_geometric | 1024 | 256 | 3.6 μs | 5.5 μs | 3.8 μs | 8.6 μs | 7.9 μs | 3.6 μs | 7.2 μs | Linear (3.6 μs) | 0.99x | +| jittered | sorted_geometric | 1024 | 1024 | 11.2 μs | 18.8 μs | 12.6 μs | 34.3 μs | 66.0 μs | 11.3 μs | 65.0 μs | Linear (11.2 μs) | 1.00x | +| jittered | sorted_geometric | 1024 | 4096 | 42.5 μs | 66.0 μs | 51.0 μs | 130.6 μs | 192.8 μs | 42.7 μs | 191.9 μs | Linear (42.5 μs) | 1.00x | +| jittered | sorted_geometric | 4096 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | +| jittered | sorted_geometric | 4096 | 4 | 6.0 μs | 230 ns | 180 ns | 150 ns | 160 ns | 180 ns | 150 ns | InterpSearch (150 ns) | 1.20x | +| jittered | sorted_geometric | 4096 | 16 | 6.3 μs | 760 ns | 590 ns | 460 ns | 540 ns | 620 ns | 490 ns | InterpSearch (460 ns) | 1.35x | +| jittered | sorted_geometric | 4096 | 64 | 7.3 μs | 2.4 μs | 1.8 μs | 2.0 μs | 2.0 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.8 μs) | 1.02x | +| jittered | sorted_geometric | 4096 | 256 | 8.7 μs | 7.5 μs | 5.7 μs | 8.9 μs | 10.3 μs | 5.8 μs | 9.7 μs | ExpFromLeft (5.7 μs) | 1.01x | +| jittered | sorted_geometric | 4096 | 1024 | 15.8 μs | 24.2 μs | 16.8 μs | 36.0 μs | 95.1 μs | 15.8 μs | 88.1 μs | Linear (15.8 μs) | 1.00x | +| jittered | sorted_geometric | 4096 | 4096 | 48.4 μs | 76.7 μs | 53.0 μs | 137.8 μs | 309.0 μs | 48.0 μs | 300.4 μs | Linear (48.4 μs) | 0.99x | +| jittered | sorted_geometric | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_geometric | 16384 | 4 | 23.4 μs | 270 ns | 230 ns | 140 ns | 180 ns | 190 ns | 170 ns | InterpSearch (140 ns) | 1.36x | +| jittered | sorted_geometric | 16384 | 16 | 23.9 μs | 920 ns | 690 ns | 470 ns | 600 ns | 700 ns | 570 ns | InterpSearch (470 ns) | 1.49x | +| jittered | sorted_geometric | 16384 | 64 | 25.5 μs | 3.1 μs | 2.4 μs | 2.1 μs | 2.3 μs | 2.4 μs | 2.2 μs | InterpSearch (2.1 μs) | 1.13x | +| jittered | sorted_geometric | 16384 | 256 | 29.8 μs | 10.2 μs | 7.6 μs | 9.1 μs | 13.4 μs | 7.6 μs | 13.2 μs | ExpFromLeft (7.6 μs) | 1.00x | +| jittered | sorted_geometric | 16384 | 1024 | 36.3 μs | 31.7 μs | 24.5 μs | 36.6 μs | 124.1 μs | 24.8 μs | 122.2 μs | ExpFromLeft (24.5 μs) | 1.01x | +| jittered | sorted_geometric | 16384 | 4096 | 69.3 μs | 101.1 μs | 72.6 μs | 139.4 μs | 416.3 μs | 69.3 μs | 409.8 μs | Linear (69.3 μs) | 1.00x | +| jittered | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_geometric | 65536 | 4 | 90.2 μs | 310 ns | 260 ns | 150 ns | 200 ns | 200 ns | 190 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_geometric | 65536 | 16 | 92.2 μs | 1.1 μs | 820 ns | 470 ns | 710 ns | 810 ns | 690 ns | InterpSearch (470 ns) | 1.72x | +| jittered | sorted_geometric | 65536 | 64 | 93.3 μs | 3.8 μs | 2.8 μs | 2.3 μs | 2.9 μs | 2.9 μs | 2.7 μs | InterpSearch (2.3 μs) | 1.26x | +| jittered | sorted_geometric | 65536 | 256 | 101.3 μs | 13.7 μs | 10.4 μs | 9.6 μs | 16.9 μs | 10.2 μs | 17.9 μs | InterpSearch (9.6 μs) | 1.07x | +| jittered | sorted_geometric | 65536 | 1024 | 119.2 μs | 47.0 μs | 37.2 μs | 40.0 μs | 153.8 μs | 35.1 μs | 157.1 μs | ExpFromLeft (37.2 μs) | 0.95x | +| jittered | sorted_geometric | 65536 | 4096 | 151.7 μs | 137.0 μs | 108.0 μs | 142.7 μs | 502.4 μs | 109.3 μs | 504.0 μs | ExpFromLeft (108.0 μs) | 1.01x | +| jittered | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| jittered | sorted_bimodal | 16 | 4 | 90 ns | 120 ns | 110 ns | 150 ns | 100 ns | 110 ns | 80 ns | Linear (90 ns) | 1.22x | +| jittered | sorted_bimodal | 16 | 16 | 180 ns | 290 ns | 220 ns | 480 ns | 240 ns | 220 ns | 209 ns | Linear (180 ns) | 1.22x | +| jittered | sorted_bimodal | 16 | 64 | 610 ns | 960 ns | 780 ns | 1.9 μs | 900 ns | 630 ns | 790 ns | Linear (610 ns) | 1.03x | +| jittered | sorted_bimodal | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.0 μs | 3.3 μs | 2.1 μs | 2.9 μs | Linear (2.1 μs) | 1.01x | +| jittered | sorted_bimodal | 16 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 27.5 μs | 12.8 μs | 7.8 μs | 11.1 μs | Linear (7.9 μs) | 0.99x | +| jittered | sorted_bimodal | 16 | 4096 | 30.8 μs | 52.9 μs | 42.1 μs | 105.8 μs | 50.8 μs | 30.9 μs | 44.3 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 150 ns | 150 ns | 100 ns | 150 ns | 90 ns | Binary (100 ns) | 1.50x | +| jittered | sorted_bimodal | 64 | 16 | 260 ns | 320 ns | 230 ns | 470 ns | 340 ns | 290 ns | 300 ns | ExpFromLeft (230 ns) | 1.26x | +| jittered | sorted_bimodal | 64 | 64 | 620 ns | 980 ns | 730 ns | 2.0 μs | 1.3 μs | 660 ns | 1.2 μs | Linear (620 ns) | 1.06x | +| jittered | sorted_bimodal | 64 | 256 | 2.3 μs | 3.7 μs | 2.9 μs | 7.6 μs | 4.4 μs | 2.3 μs | 4.0 μs | Linear (2.3 μs) | 1.01x | +| jittered | sorted_bimodal | 64 | 1024 | 8.1 μs | 13.9 μs | 10.8 μs | 28.0 μs | 16.9 μs | 8.1 μs | 15.3 μs | Linear (8.1 μs) | 1.00x | +| jittered | sorted_bimodal | 64 | 4096 | 31.1 μs | 54.7 μs | 42.3 μs | 108.6 μs | 67.0 μs | 31.1 μs | 60.3 μs | Linear (31.1 μs) | 1.00x | +| jittered | sorted_bimodal | 256 | 1 | 80 ns | 70 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_bimodal | 256 | 4 | 450 ns | 150 ns | 140 ns | 150 ns | 130 ns | 160 ns | 110 ns | Binary (130 ns) | 1.23x | +| jittered | sorted_bimodal | 256 | 16 | 550 ns | 370 ns | 300 ns | 480 ns | 380 ns | 300 ns | 380 ns | ExpFromLeft (300 ns) | 1.00x | +| jittered | sorted_bimodal | 256 | 64 | 930 ns | 1.1 μs | 750 ns | 2.1 μs | 1.8 μs | 950 ns | 1.7 μs | ExpFromLeft (750 ns) | 1.27x | +| jittered | sorted_bimodal | 256 | 256 | 2.6 μs | 4.2 μs | 3.2 μs | 9.0 μs | 6.4 μs | 2.6 μs | 5.9 μs | Linear (2.6 μs) | 1.01x | +| jittered | sorted_bimodal | 256 | 1024 | 9.2 μs | 14.7 μs | 11.6 μs | 31.0 μs | 22.4 μs | 9.2 μs | 20.6 μs | Linear (9.2 μs) | 1.00x | +| jittered | sorted_bimodal | 256 | 4096 | 32.3 μs | 55.8 μs | 43.0 μs | 115.3 μs | 86.5 μs | 32.2 μs | 79.5 μs | Linear (32.3 μs) | 1.00x | +| jittered | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_bimodal | 1024 | 4 | 1.4 μs | 180 ns | 140 ns | 150 ns | 140 ns | 190 ns | 130 ns | ExpFromLeft (140 ns) | 1.36x | +| jittered | sorted_bimodal | 1024 | 16 | 1.6 μs | 480 ns | 389 ns | 470 ns | 450 ns | 400 ns | 410 ns | ExpFromLeft (389 ns) | 1.03x | +| jittered | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 950 ns | 2.0 μs | 1.9 μs | 980 ns | 1.8 μs | ExpFromLeft (950 ns) | 1.03x | +| jittered | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.1 μs | 2.8 μs | 8.8 μs | 8.5 μs | 3.5 μs | 8.0 μs | ExpFromLeft (2.8 μs) | 1.25x | +| jittered | sorted_bimodal | 1024 | 1024 | 11.7 μs | 17.2 μs | 13.6 μs | 36.9 μs | 30.5 μs | 11.8 μs | 28.4 μs | Linear (11.7 μs) | 1.01x | +| jittered | sorted_bimodal | 1024 | 4096 | 36.8 μs | 58.8 μs | 46.5 μs | 124.0 μs | 108.6 μs | 36.7 μs | 102.0 μs | Linear (36.8 μs) | 1.00x | +| jittered | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_bimodal | 4096 | 4 | 5.2 μs | 200 ns | 190 ns | 150 ns | 160 ns | 200 ns | 140 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_bimodal | 4096 | 16 | 6.1 μs | 630 ns | 510 ns | 470 ns | 550 ns | 530 ns | 500 ns | InterpSearch (470 ns) | 1.13x | +| jittered | sorted_bimodal | 4096 | 64 | 6.5 μs | 1.7 μs | 1.3 μs | 2.1 μs | 2.2 μs | 1.3 μs | 2.2 μs | ExpFromLeft (1.3 μs) | 1.02x | +| jittered | sorted_bimodal | 4096 | 256 | 9.6 μs | 5.9 μs | 5.0 μs | 9.5 μs | 11.5 μs | 5.0 μs | 10.7 μs | ExpFromLeft (5.0 μs) | 1.00x | +| jittered | sorted_bimodal | 4096 | 1024 | 14.4 μs | 17.6 μs | 12.2 μs | 37.9 μs | 59.5 μs | 14.7 μs | 55.2 μs | ExpFromLeft (12.2 μs) | 1.21x | +| jittered | sorted_bimodal | 4096 | 4096 | 51.1 μs | 69.4 μs | 56.0 μs | 145.2 μs | 180.4 μs | 51.3 μs | 168.0 μs | Linear (51.1 μs) | 1.00x | +| jittered | sorted_bimodal | 16384 | 1 | 90 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_bimodal | 16384 | 4 | 22.5 μs | 250 ns | 200 ns | 150 ns | 190 ns | 200 ns | 160 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_bimodal | 16384 | 16 | 22.1 μs | 720 ns | 550 ns | 470 ns | 600 ns | 560 ns | 570 ns | InterpSearch (470 ns) | 1.19x | +| jittered | sorted_bimodal | 16384 | 64 | 25.1 μs | 2.3 μs | 1.7 μs | 2.0 μs | 2.7 μs | 1.8 μs | 2.5 μs | ExpFromLeft (1.7 μs) | 1.02x | +| jittered | sorted_bimodal | 16384 | 256 | 26.2 μs | 6.7 μs | 5.2 μs | 9.1 μs | 15.1 μs | 5.2 μs | 14.4 μs | ExpFromLeft (5.2 μs) | 1.00x | +| jittered | sorted_bimodal | 16384 | 1024 | 33.1 μs | 22.9 μs | 16.6 μs | 38.5 μs | 87.9 μs | 15.9 μs | 87.4 μs | ExpFromLeft (16.6 μs) | 0.96x | +| jittered | sorted_bimodal | 16384 | 4096 | 79.5 μs | 89.8 μs | 67.1 μs | 157.9 μs | 270.5 μs | 79.2 μs | 263.6 μs | ExpFromLeft (67.1 μs) | 1.18x | +| jittered | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_bimodal | 65536 | 4 | 82.9 μs | 260 ns | 210 ns | 150 ns | 180 ns | 200 ns | 190 ns | InterpSearch (150 ns) | 1.33x | +| jittered | sorted_bimodal | 65536 | 16 | 92.4 μs | 860 ns | 640 ns | 490 ns | 750 ns | 660 ns | 690 ns | InterpSearch (490 ns) | 1.35x | +| jittered | sorted_bimodal | 65536 | 64 | 94.9 μs | 2.9 μs | 2.2 μs | 2.0 μs | 3.1 μs | 2.2 μs | 2.8 μs | InterpSearch (2.0 μs) | 1.11x | +| jittered | sorted_bimodal | 65536 | 256 | 97.7 μs | 9.0 μs | 6.9 μs | 9.2 μs | 18.1 μs | 6.9 μs | 18.7 μs | ExpFromLeft (6.9 μs) | 1.00x | +| jittered | sorted_bimodal | 65536 | 1024 | 107.6 μs | 31.5 μs | 25.2 μs | 38.6 μs | 114.2 μs | 23.2 μs | 112.4 μs | ExpFromLeft (25.2 μs) | 0.92x | +| jittered | sorted_bimodal | 65536 | 4096 | 182.8 μs | 149.4 μs | 109.6 μs | 160.6 μs | 349.7 μs | 107.8 μs | 345.6 μs | ExpFromLeft (109.6 μs) | 0.98x | +| jittered | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | sorted_repeated | 16 | 4 | 80 ns | 100 ns | 80 ns | 150 ns | 90 ns | 100 ns | 80 ns | ExpFromLeft (80 ns) | 1.25x | +| jittered | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 200 ns | 460 ns | 230 ns | 200 ns | 200 ns | Linear (170 ns) | 1.18x | +| jittered | sorted_repeated | 16 | 64 | 550 ns | 910 ns | 690 ns | 1.7 μs | 789 ns | 570 ns | 700 ns | Linear (550 ns) | 1.04x | +| jittered | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.02x | +| jittered | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 25.8 μs | 11.8 μs | 7.8 μs | 10.3 μs | Linear (7.7 μs) | 1.00x | +| jittered | sorted_repeated | 16 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 103.3 μs | 47.2 μs | 30.8 μs | 41.0 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | +| jittered | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 100 ns | 140 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| jittered | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 200 ns | 460 ns | 310 ns | 200 ns | 270 ns | Linear (170 ns) | 1.18x | +| jittered | sorted_repeated | 64 | 64 | 560 ns | 920 ns | 690 ns | 1.7 μs | 1.1 μs | 580 ns | 920 ns | Linear (560 ns) | 1.04x | +| jittered | sorted_repeated | 64 | 256 | 2.8 μs | 4.7 μs | 3.2 μs | 6.5 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.8 μs) | 0.71x | +| jittered | sorted_repeated | 64 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 25.8 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.8 μs) | 1.00x | +| jittered | sorted_repeated | 64 | 4096 | 30.8 μs | 54.8 μs | 39.4 μs | 103.3 μs | 66.6 μs | 32.9 μs | 56.7 μs | Linear (30.8 μs) | 1.07x | +| jittered | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 100 ns | 140 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| jittered | sorted_repeated | 256 | 16 | 220 ns | 350 ns | 250 ns | 500 ns | 399 ns | 240 ns | 340 ns | Linear (220 ns) | 1.09x | +| jittered | sorted_repeated | 256 | 64 | 550 ns | 930 ns | 710 ns | 1.7 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | +| jittered | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| jittered | sorted_repeated | 256 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 26.0 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | +| jittered | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 103.3 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| jittered | sorted_repeated | 1024 | 4 | 90 ns | 110 ns | 100 ns | 150 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | +| jittered | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 210 ns | 490 ns | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | +| jittered | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 1.8 μs | 1.7 μs | 580 ns | 1.5 μs | Linear (560 ns) | 1.04x | +| jittered | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 7.0 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| jittered | sorted_repeated | 1024 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 27.7 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.8 μs) | 1.00x | +| jittered | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.0 μs | 39.2 μs | 110.5 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| jittered | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 110 ns | 140 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | +| jittered | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 230 ns | 450 ns | 530 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | +| jittered | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 700 ns | 1.7 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | +| jittered | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| jittered | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 25.8 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | +| jittered | sorted_repeated | 4096 | 4096 | 30.8 μs | 54.9 μs | 39.5 μs | 103.2 μs | 124.6 μs | 30.8 μs | 114.1 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_repeated | 16384 | 4 | 90 ns | 120 ns | 110 ns | 140 ns | 180 ns | 130 ns | 170 ns | Linear (90 ns) | 1.44x | +| jittered | sorted_repeated | 16384 | 16 | 190 ns | 300 ns | 220 ns | 450 ns | 610 ns | 220 ns | 560 ns | Linear (190 ns) | 1.16x | +| jittered | sorted_repeated | 16384 | 64 | 570 ns | 940 ns | 710 ns | 1.7 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | +| jittered | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 9.0 μs | 2.0 μs | 8.3 μs | Linear (2.0 μs) | 1.02x | +| jittered | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 25.9 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.00x | +| jittered | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 103.3 μs | 144.1 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | +| jittered | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | sorted_repeated | 65536 | 4 | 100 ns | 110 ns | 110 ns | 140 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| jittered | sorted_repeated | 65536 | 16 | 190 ns | 370 ns | 290 ns | 460 ns | 690 ns | 220 ns | 630 ns | Linear (190 ns) | 1.16x | +| jittered | sorted_repeated | 65536 | 64 | 580 ns | 950 ns | 720 ns | 1.7 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (580 ns) | 1.03x | +| jittered | sorted_repeated | 65536 | 256 | 2.1 μs | 3.5 μs | 2.5 μs | 6.5 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.1 μs) | 0.96x | +| jittered | sorted_repeated | 65536 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 25.9 μs | 40.8 μs | 8.3 μs | 38.1 μs | Linear (7.7 μs) | 1.07x | +| jittered | sorted_repeated | 65536 | 4096 | 32.9 μs | 55.0 μs | 39.5 μs | 103.3 μs | 163.2 μs | 30.8 μs | 152.3 μs | Linear (32.9 μs) | 0.94x | +| jittered | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| jittered | unsorted | 16 | 4 | 100 ns | 90 ns | 90 ns | 100 ns | 90 ns | 110 ns | 70 ns | ExpFromLeft (90 ns) | 1.22x | +| jittered | unsorted | 16 | 16 | 210 ns | 210 ns | 200 ns | 200 ns | 210 ns | 220 ns | 200 ns | InterpSearch (200 ns) | 1.10x | +| jittered | unsorted | 16 | 64 | 700 ns | 700 ns | 680 ns | 700 ns | 690 ns | 700 ns | 680 ns | ExpFromLeft (680 ns) | 1.03x | +| jittered | unsorted | 16 | 256 | 3.2 μs | 3.2 μs | 3.2 μs | 3.2 μs | 3.1 μs | 3.2 μs | 3.0 μs | Binary (3.1 μs) | 1.01x | +| jittered | unsorted | 16 | 1024 | 20.5 μs | 20.5 μs | 19.9 μs | 19.9 μs | 19.8 μs | 20.0 μs | 22.0 μs | Binary (19.8 μs) | 1.01x | +| jittered | unsorted | 16 | 4096 | 143.7 μs | 139.7 μs | 141.1 μs | 138.7 μs | 138.9 μs | 139.9 μs | 143.7 μs | InterpSearch (138.7 μs) | 1.01x | +| jittered | unsorted | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| jittered | unsorted | 64 | 4 | 100 ns | 100 ns | 100 ns | 100 ns | 100 ns | 120 ns | 90 ns | InterpSearch (100 ns) | 1.20x | +| jittered | unsorted | 64 | 16 | 290 ns | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 270 ns | InterpSearch (280 ns) | 1.04x | +| jittered | unsorted | 64 | 64 | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | InterpSearch (1.1 μs) | 1.02x | +| jittered | unsorted | 64 | 256 | 5.9 μs | 5.9 μs | 5.9 μs | 6.0 μs | 5.9 μs | 6.1 μs | 5.8 μs | Linear (5.9 μs) | 1.03x | +| jittered | unsorted | 64 | 1024 | 40.1 μs | 39.8 μs | 39.7 μs | 39.8 μs | 39.3 μs | 39.5 μs | 40.3 μs | Binary (39.3 μs) | 1.00x | +| jittered | unsorted | 64 | 4096 | 222.6 μs | 222.0 μs | 221.7 μs | 220.6 μs | 222.3 μs | 224.2 μs | 225.7 μs | InterpSearch (220.6 μs) | 1.02x | +| jittered | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | unsorted | 256 | 4 | 130 ns | 130 ns | 130 ns | 120 ns | 120 ns | 130 ns | 110 ns | InterpSearch (120 ns) | 1.08x | +| jittered | unsorted | 256 | 16 | 370 ns | 370 ns | 370 ns | 360 ns | 370 ns | 370 ns | 360 ns | InterpSearch (360 ns) | 1.03x | +| jittered | unsorted | 256 | 64 | 1.3 μs | 1.3 μs | 1.4 μs | 1.3 μs | 1.4 μs | 1.4 μs | 1.3 μs | InterpSearch (1.3 μs) | 1.02x | +| jittered | unsorted | 256 | 256 | 6.5 μs | 6.5 μs | 6.4 μs | 6.5 μs | 6.5 μs | 6.5 μs | 6.6 μs | ExpFromLeft (6.4 μs) | 1.01x | +| jittered | unsorted | 256 | 1024 | 55.0 μs | 54.8 μs | 54.0 μs | 54.3 μs | 54.2 μs | 53.4 μs | 53.1 μs | ExpFromLeft (54.0 μs) | 0.99x | +| jittered | unsorted | 256 | 4096 | 309.1 μs | 307.9 μs | 305.5 μs | 303.5 μs | 303.4 μs | 305.2 μs | 306.5 μs | Binary (303.4 μs) | 1.01x | +| jittered | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| jittered | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| jittered | unsorted | 1024 | 16 | 420 ns | 419 ns | 420 ns | 420 ns | 430 ns | 430 ns | 410 ns | Gallop (419 ns) | 1.03x | +| jittered | unsorted | 1024 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | ExpFromLeft (1.6 μs) | 1.00x | +| jittered | unsorted | 1024 | 256 | 7.9 μs | 7.9 μs | 7.8 μs | 7.8 μs | 7.8 μs | 7.9 μs | 8.3 μs | InterpSearch (7.8 μs) | 1.00x | +| jittered | unsorted | 1024 | 1024 | 80.4 μs | 78.2 μs | 77.5 μs | 76.0 μs | 76.1 μs | 76.1 μs | 78.0 μs | InterpSearch (76.0 μs) | 1.00x | +| jittered | unsorted | 1024 | 4096 | 412.6 μs | 410.4 μs | 410.2 μs | 411.7 μs | 409.3 μs | 410.2 μs | 407.2 μs | Binary (409.3 μs) | 1.00x | +| jittered | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| jittered | unsorted | 4096 | 4 | 150 ns | 150 ns | 150 ns | 160 ns | 150 ns | 170 ns | 140 ns | ExpFromLeft (150 ns) | 1.13x | +| jittered | unsorted | 4096 | 16 | 490 ns | 500 ns | 490 ns | 490 ns | 500 ns | 500 ns | 490 ns | InterpSearch (490 ns) | 1.02x | +| jittered | unsorted | 4096 | 64 | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | ExpFromLeft (1.9 μs) | 1.02x | +| jittered | unsorted | 4096 | 256 | 8.9 μs | 8.7 μs | 8.5 μs | 8.6 μs | 8.5 μs | 8.6 μs | 11.2 μs | ExpFromLeft (8.5 μs) | 1.01x | +| jittered | unsorted | 4096 | 1024 | 98.2 μs | 96.1 μs | 94.8 μs | 94.4 μs | 94.0 μs | 93.3 μs | 98.4 μs | Binary (94.0 μs) | 0.99x | +| jittered | unsorted | 4096 | 4096 | 492.8 μs | 494.1 μs | 489.8 μs | 490.6 μs | 490.2 μs | 491.3 μs | 493.6 μs | ExpFromLeft (489.8 μs) | 1.00x | +| jittered | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| jittered | unsorted | 16384 | 4 | 170 ns | 180 ns | 180 ns | 180 ns | 180 ns | 190 ns | 170 ns | Linear (170 ns) | 1.12x | +| jittered | unsorted | 16384 | 16 | 580 ns | 580 ns | 590 ns | 580 ns | 580 ns | 590 ns | 570 ns | InterpSearch (580 ns) | 1.02x | +| jittered | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | InterpSearch (2.3 μs) | 1.01x | +| jittered | unsorted | 16384 | 256 | 11.1 μs | 10.9 μs | 10.6 μs | 10.7 μs | 10.7 μs | 10.7 μs | 12.8 μs | ExpFromLeft (10.6 μs) | 1.01x | +| jittered | unsorted | 16384 | 1024 | 142.1 μs | 138.8 μs | 135.7 μs | 136.1 μs | 135.4 μs | 135.4 μs | 141.1 μs | Binary (135.4 μs) | 1.00x | +| jittered | unsorted | 16384 | 4096 | 665.1 μs | 665.0 μs | 665.5 μs | 670.2 μs | 669.7 μs | 670.3 μs | 670.2 μs | Gallop (665.0 μs) | 1.01x | +| jittered | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| jittered | unsorted | 65536 | 4 | 200 ns | 200 ns | 190 ns | 200 ns | 200 ns | 200 ns | 190 ns | ExpFromLeft (190 ns) | 1.05x | +| jittered | unsorted | 65536 | 16 | 680 ns | 680 ns | 670 ns | 660 ns | 660 ns | 680 ns | 650 ns | InterpSearch (660 ns) | 1.03x | +| jittered | unsorted | 65536 | 64 | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | Linear (2.8 μs) | 1.01x | +| jittered | unsorted | 65536 | 256 | 14.5 μs | 14.0 μs | 13.9 μs | 13.9 μs | 13.9 μs | 13.8 μs | 16.9 μs | ExpFromLeft (13.9 μs) | 0.99x | +| jittered | unsorted | 65536 | 1024 | 190.5 μs | 186.6 μs | 186.0 μs | 183.7 μs | 184.0 μs | 184.6 μs | 190.6 μs | InterpSearch (183.7 μs) | 1.00x | +| jittered | unsorted | 65536 | 4096 | 867.2 μs | 867.6 μs | 867.5 μs | 867.1 μs | 868.1 μs | 867.2 μs | 866.4 μs | InterpSearch (867.1 μs) | 1.00x | +| random | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| random | sorted_uniform | 16 | 4 | 90 ns | 110 ns | 110 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| random | sorted_uniform | 16 | 16 | 190 ns | 280 ns | 220 ns | 509 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| random | sorted_uniform | 16 | 64 | 560 ns | 979 ns | 740 ns | 1.9 μs | 900 ns | 590 ns | 780 ns | Linear (560 ns) | 1.05x | +| random | sorted_uniform | 16 | 256 | 2.2 μs | 3.7 μs | 2.8 μs | 7.8 μs | 3.2 μs | 2.2 μs | 2.7 μs | Linear (2.2 μs) | 1.01x | +| random | sorted_uniform | 16 | 1024 | 8.0 μs | 14.1 μs | 10.8 μs | 29.3 μs | 12.2 μs | 8.0 μs | 10.5 μs | Linear (8.0 μs) | 1.00x | +| random | sorted_uniform | 16 | 4096 | 31.4 μs | 58.1 μs | 42.2 μs | 117.2 μs | 47.9 μs | 31.0 μs | 40.6 μs | Linear (31.4 μs) | 0.99x | +| random | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| random | sorted_uniform | 64 | 4 | 110 ns | 120 ns | 110 ns | 160 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | +| random | sorted_uniform | 64 | 16 | 240 ns | 330 ns | 270 ns | 500 ns | 310 ns | 260 ns | 270 ns | Linear (240 ns) | 1.08x | +| random | sorted_uniform | 64 | 64 | 670 ns | 1.1 μs | 760 ns | 1.9 μs | 1.4 μs | 710 ns | 1.3 μs | Linear (670 ns) | 1.06x | +| random | sorted_uniform | 64 | 256 | 2.3 μs | 4.0 μs | 3.1 μs | 8.3 μs | 5.0 μs | 2.3 μs | 4.5 μs | Linear (2.3 μs) | 0.99x | +| random | sorted_uniform | 64 | 1024 | 9.0 μs | 14.8 μs | 11.6 μs | 32.5 μs | 17.7 μs | 9.0 μs | 15.9 μs | Linear (9.0 μs) | 1.00x | +| random | sorted_uniform | 64 | 4096 | 32.1 μs | 55.9 μs | 43.2 μs | 121.1 μs | 67.3 μs | 32.1 μs | 60.0 μs | Linear (32.1 μs) | 1.00x | +| random | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_uniform | 256 | 4 | 440 ns | 160 ns | 150 ns | 180 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | +| random | sorted_uniform | 256 | 16 | 510 ns | 440 ns | 380 ns | 580 ns | 380 ns | 390 ns | 370 ns | ExpFromLeft (380 ns) | 1.03x | +| random | sorted_uniform | 256 | 64 | 920 ns | 1.3 μs | 1.0 μs | 2.7 μs | 1.7 μs | 920 ns | 1.6 μs | Linear (920 ns) | 1.00x | +| random | sorted_uniform | 256 | 256 | 2.4 μs | 4.2 μs | 2.9 μs | 9.6 μs | 6.8 μs | 2.4 μs | 6.6 μs | Linear (2.4 μs) | 1.00x | +| random | sorted_uniform | 256 | 1024 | 9.6 μs | 16.6 μs | 13.0 μs | 42.5 μs | 25.6 μs | 9.7 μs | 23.7 μs | Linear (9.6 μs) | 1.01x | +| random | sorted_uniform | 256 | 4096 | 36.2 μs | 59.3 μs | 46.6 μs | 158.7 μs | 91.0 μs | 36.1 μs | 83.7 μs | Linear (36.2 μs) | 1.00x | +| random | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (70 ns) | 0.86x | +| random | sorted_uniform | 1024 | 4 | 1.4 μs | 180 ns | 150 ns | 180 ns | 139 ns | 180 ns | 130 ns | Binary (139 ns) | 1.29x | +| random | sorted_uniform | 1024 | 16 | 1.6 μs | 600 ns | 480 ns | 640 ns | 450 ns | 500 ns | 410 ns | Binary (450 ns) | 1.11x | +| random | sorted_uniform | 1024 | 64 | 2.0 μs | 1.8 μs | 1.3 μs | 2.6 μs | 1.8 μs | 1.4 μs | 1.8 μs | ExpFromLeft (1.3 μs) | 1.04x | +| random | sorted_uniform | 1024 | 256 | 3.6 μs | 5.2 μs | 3.9 μs | 10.2 μs | 8.2 μs | 3.5 μs | 7.8 μs | Linear (3.6 μs) | 0.98x | +| random | sorted_uniform | 1024 | 1024 | 10.5 μs | 17.8 μs | 12.5 μs | 48.0 μs | 45.4 μs | 13.7 μs | 42.5 μs | Linear (10.5 μs) | 1.31x | +| random | sorted_uniform | 1024 | 4096 | 44.1 μs | 69.5 μs | 55.1 μs | 187.7 μs | 169.8 μs | 44.0 μs | 166.1 μs | Linear (44.1 μs) | 1.00x | +| random | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| random | sorted_uniform | 4096 | 4 | 4.4 μs | 240 ns | 190 ns | 190 ns | 160 ns | 220 ns | 150 ns | Binary (160 ns) | 1.38x | +| random | sorted_uniform | 4096 | 16 | 6.7 μs | 790 ns | 690 ns | 680 ns | 550 ns | 720 ns | 499 ns | Binary (550 ns) | 1.31x | +| random | sorted_uniform | 4096 | 64 | 7.4 μs | 2.3 μs | 1.8 μs | 2.6 μs | 2.1 μs | 1.8 μs | 2.0 μs | ExpFromLeft (1.8 μs) | 1.03x | +| random | sorted_uniform | 4096 | 256 | 8.5 μs | 7.0 μs | 5.1 μs | 10.5 μs | 10.9 μs | 5.2 μs | 10.4 μs | ExpFromLeft (5.1 μs) | 1.01x | +| random | sorted_uniform | 4096 | 1024 | 15.6 μs | 23.4 μs | 17.4 μs | 50.3 μs | 90.4 μs | 16.0 μs | 84.7 μs | Linear (15.6 μs) | 1.03x | +| random | sorted_uniform | 4096 | 4096 | 77.5 μs | 100.8 μs | 81.0 μs | 220.8 μs | 280.7 μs | 74.3 μs | 272.1 μs | Linear (77.5 μs) | 0.96x | +| random | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_uniform | 16384 | 4 | 17.9 μs | 270 ns | 220 ns | 210 ns | 180 ns | 250 ns | 170 ns | Binary (180 ns) | 1.39x | +| random | sorted_uniform | 16384 | 16 | 23.0 μs | 870 ns | 650 ns | 740 ns | 600 ns | 690 ns | 560 ns | Binary (600 ns) | 1.15x | +| random | sorted_uniform | 16384 | 64 | 25.2 μs | 3.0 μs | 2.3 μs | 3.0 μs | 2.5 μs | 2.3 μs | 2.3 μs | ExpFromLeft (2.3 μs) | 1.02x | +| random | sorted_uniform | 16384 | 256 | 30.4 μs | 9.6 μs | 7.4 μs | 11.9 μs | 12.7 μs | 7.4 μs | 13.0 μs | ExpFromLeft (7.4 μs) | 0.99x | +| random | sorted_uniform | 16384 | 1024 | 37.9 μs | 33.5 μs | 25.6 μs | 61.1 μs | 124.6 μs | 23.8 μs | 124.5 μs | ExpFromLeft (25.6 μs) | 0.93x | +| random | sorted_uniform | 16384 | 4096 | 115.0 μs | 161.1 μs | 121.5 μs | 283.2 μs | 384.5 μs | 114.2 μs | 388.6 μs | Linear (115.0 μs) | 0.99x | +| random | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | InterpSearch (80 ns) | 1.00x | +| random | sorted_uniform | 65536 | 4 | 16.9 μs | 270 ns | 220 ns | 220 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | +| random | sorted_uniform | 65536 | 16 | 80.0 μs | 1.1 μs | 750 ns | 780 ns | 690 ns | 790 ns | 650 ns | Binary (690 ns) | 1.14x | +| random | sorted_uniform | 65536 | 64 | 91.7 μs | 3.6 μs | 2.6 μs | 3.3 μs | 2.9 μs | 2.6 μs | 2.7 μs | ExpFromLeft (2.6 μs) | 1.01x | +| random | sorted_uniform | 65536 | 256 | 102.6 μs | 12.9 μs | 9.5 μs | 13.5 μs | 15.9 μs | 9.6 μs | 17.1 μs | ExpFromLeft (9.5 μs) | 1.01x | +| random | sorted_uniform | 65536 | 1024 | 122.0 μs | 60.7 μs | 44.2 μs | 75.2 μs | 154.8 μs | 40.2 μs | 161.6 μs | ExpFromLeft (44.2 μs) | 0.91x | +| random | sorted_uniform | 65536 | 4096 | 199.0 μs | 246.4 μs | 200.4 μs | 351.2 μs | 484.6 μs | 200.5 μs | 487.9 μs | Linear (199.0 μs) | 1.01x | +| random | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| random | sorted_dense_burst | 16 | 4 | 80 ns | 90 ns | 90 ns | 150 ns | 80 ns | 100 ns | 70 ns | Binary (80 ns) | 1.25x | +| random | sorted_dense_burst | 16 | 16 | 180 ns | 280 ns | 230 ns | 510 ns | 230 ns | 190 ns | 190 ns | Linear (180 ns) | 1.06x | +| random | sorted_dense_burst | 16 | 64 | 550 ns | 960 ns | 730 ns | 1.9 μs | 810 ns | 580 ns | 660 ns | Linear (550 ns) | 1.05x | +| random | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 7.3 μs | 3.0 μs | 2.0 μs | 2.7 μs | Linear (2.0 μs) | 1.01x | +| random | sorted_dense_burst | 16 | 1024 | 7.8 μs | 14.5 μs | 10.6 μs | 29.3 μs | 12.0 μs | 7.9 μs | 9.6 μs | Linear (7.8 μs) | 1.00x | +| random | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.9 μs | 42.1 μs | 113.3 μs | 47.2 μs | 32.9 μs | 38.4 μs | Linear (30.8 μs) | 1.07x | +| random | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| random | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 90 ns | 209 ns | 130 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| random | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 220 ns | 540 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | +| random | sorted_dense_burst | 64 | 64 | 550 ns | 930 ns | 730 ns | 2.0 μs | 1.1 μs | 580 ns | 920 ns | Linear (550 ns) | 1.05x | +| random | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 3.4 μs | 7.9 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | +| random | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 31.4 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | +| random | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.9 μs | 42.0 μs | 125.2 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 220 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| random | sorted_dense_burst | 256 | 16 | 170 ns | 279 ns | 230 ns | 790 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| random | sorted_dense_burst | 256 | 64 | 550 ns | 930 ns | 740 ns | 3.0 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | +| random | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.7 μs | 5.6 μs | 2.9 μs | 4.9 μs | Linear (2.0 μs) | 1.43x | +| random | sorted_dense_burst | 256 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 46.4 μs | 21.4 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | +| random | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.0 μs | 42.1 μs | 184.9 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_dense_burst | 1024 | 4 | 110 ns | 130 ns | 110 ns | 200 ns | 140 ns | 120 ns | 130 ns | ExpFromLeft (110 ns) | 1.09x | +| random | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 250 ns | 700 ns | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | +| random | sorted_dense_burst | 1024 | 64 | 770 ns | 1.2 μs | 950 ns | 2.8 μs | 1.8 μs | 590 ns | 1.5 μs | Linear (770 ns) | 0.77x | +| random | sorted_dense_burst | 1024 | 256 | 2.5 μs | 3.5 μs | 2.7 μs | 10.5 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.5 μs) | 0.82x | +| random | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 41.6 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | +| random | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.1 μs | 41.9 μs | 166.1 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 130 ns | 230 ns | 170 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | +| random | sorted_dense_burst | 4096 | 16 | 180 ns | 280 ns | 240 ns | 860 ns | 540 ns | 250 ns | 490 ns | Linear (180 ns) | 1.39x | +| random | sorted_dense_burst | 4096 | 64 | 560 ns | 930 ns | 740 ns | 3.2 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | +| random | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 12.6 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | +| random | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 50.2 μs | 31.2 μs | 7.8 μs | 28.5 μs | Linear (7.8 μs) | 1.00x | +| random | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 201.0 μs | 124.7 μs | 30.9 μs | 114.1 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 210 ns | 180 ns | 120 ns | 160 ns | Linear (100 ns) | 1.20x | +| random | sorted_dense_burst | 16384 | 16 | 180 ns | 289 ns | 240 ns | 750 ns | 610 ns | 210 ns | 560 ns | Linear (180 ns) | 1.17x | +| random | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 760 ns | 2.9 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | +| random | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.3 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | +| random | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 45.1 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.00x | +| random | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.0 μs | 42.1 μs | 179.9 μs | 143.9 μs | 30.9 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| random | sorted_dense_burst | 65536 | 4 | 100 ns | 130 ns | 110 ns | 250 ns | 200 ns | 120 ns | 180 ns | Linear (100 ns) | 1.20x | +| random | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 250 ns | 950 ns | 680 ns | 210 ns | 640 ns | Linear (190 ns) | 1.11x | +| random | sorted_dense_burst | 65536 | 64 | 570 ns | 940 ns | 750 ns | 3.6 μs | 2.6 μs | 610 ns | 2.4 μs | Linear (570 ns) | 1.07x | +| random | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 14.1 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | +| random | sorted_dense_burst | 65536 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 56.1 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.7 μs) | 1.01x | +| random | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 222.6 μs | 163.1 μs | 30.8 μs | 152.4 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| random | sorted_near_start | 16 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 80 ns | 110 ns | 70 ns | Binary (80 ns) | 1.38x | +| random | sorted_near_start | 16 | 16 | 180 ns | 290 ns | 210 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | +| random | sorted_near_start | 16 | 64 | 570 ns | 950 ns | 760 ns | 1.8 μs | 790 ns | 610 ns | 680 ns | Linear (570 ns) | 1.07x | +| random | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | +| random | sorted_near_start | 16 | 1024 | 7.9 μs | 13.9 μs | 14.1 μs | 26.9 μs | 12.1 μs | 7.9 μs | 10.2 μs | Linear (7.9 μs) | 1.00x | +| random | sorted_near_start | 16 | 4096 | 31.1 μs | 55.3 μs | 42.3 μs | 107.1 μs | 47.7 μs | 31.1 μs | 40.3 μs | Linear (31.1 μs) | 1.00x | +| random | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| random | sorted_near_start | 64 | 4 | 160 ns | 120 ns | 110 ns | 150 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | +| random | sorted_near_start | 64 | 16 | 220 ns | 300 ns | 240 ns | 470 ns | 310 ns | 250 ns | 280 ns | Linear (220 ns) | 1.14x | +| random | sorted_near_start | 64 | 64 | 690 ns | 1.0 μs | 840 ns | 1.9 μs | 1.1 μs | 700 ns | 1.0 μs | Linear (690 ns) | 1.01x | +| random | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | +| random | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 27.5 μs | 17.1 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.00x | +| random | sorted_near_start | 64 | 4096 | 31.4 μs | 74.5 μs | 56.4 μs | 110.4 μs | 66.8 μs | 31.4 μs | 60.0 μs | Linear (31.4 μs) | 1.00x | +| random | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_near_start | 256 | 4 | 110 ns | 120 ns | 120 ns | 160 ns | 130 ns | 130 ns | 110 ns | Linear (110 ns) | 1.18x | +| random | sorted_near_start | 256 | 16 | 390 ns | 330 ns | 260 ns | 500 ns | 440 ns | 270 ns | 450 ns | ExpFromLeft (260 ns) | 1.04x | +| random | sorted_near_start | 256 | 64 | 890 ns | 1.1 μs | 840 ns | 2.0 μs | 1.5 μs | 900 ns | 1.4 μs | ExpFromLeft (840 ns) | 1.07x | +| random | sorted_near_start | 256 | 256 | 2.5 μs | 3.9 μs | 3.1 μs | 7.8 μs | 5.7 μs | 2.5 μs | 5.2 μs | Linear (2.5 μs) | 1.01x | +| random | sorted_near_start | 256 | 1024 | 8.5 μs | 14.5 μs | 11.0 μs | 29.6 μs | 22.1 μs | 8.4 μs | 20.3 μs | Linear (8.5 μs) | 0.99x | +| random | sorted_near_start | 256 | 4096 | 31.5 μs | 56.1 μs | 42.7 μs | 117.4 μs | 88.6 μs | 31.4 μs | 80.7 μs | Linear (31.5 μs) | 1.00x | +| random | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 50 ns | Gallop (60 ns) | 1.00x | +| random | sorted_near_start | 1024 | 4 | 860 ns | 160 ns | 180 ns | 180 ns | 140 ns | 170 ns | 130 ns | Binary (140 ns) | 1.21x | +| random | sorted_near_start | 1024 | 16 | 1.1 μs | 379 ns | 290 ns | 590 ns | 460 ns | 330 ns | 430 ns | ExpFromLeft (290 ns) | 1.14x | +| random | sorted_near_start | 1024 | 64 | 2.0 μs | 1.2 μs | 880 ns | 2.1 μs | 1.9 μs | 930 ns | 1.8 μs | ExpFromLeft (880 ns) | 1.06x | +| random | sorted_near_start | 1024 | 256 | 3.9 μs | 4.4 μs | 3.4 μs | 9.1 μs | 7.2 μs | 3.9 μs | 6.7 μs | ExpFromLeft (3.4 μs) | 1.15x | +| random | sorted_near_start | 1024 | 1024 | 10.1 μs | 15.6 μs | 12.1 μs | 35.2 μs | 27.2 μs | 10.1 μs | 25.6 μs | Linear (10.1 μs) | 1.00x | +| random | sorted_near_start | 1024 | 4096 | 34.0 μs | 58.2 μs | 44.5 μs | 136.0 μs | 110.1 μs | 33.6 μs | 103.7 μs | Linear (34.0 μs) | 0.99x | +| random | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| random | sorted_near_start | 4096 | 4 | 2.1 μs | 210 ns | 180 ns | 190 ns | 160 ns | 200 ns | 140 ns | Binary (160 ns) | 1.25x | +| random | sorted_near_start | 4096 | 16 | 3.7 μs | 530 ns | 430 ns | 650 ns | 550 ns | 440 ns | 490 ns | ExpFromLeft (430 ns) | 1.02x | +| random | sorted_near_start | 4096 | 64 | 6.0 μs | 1.5 μs | 1.1 μs | 2.5 μs | 2.2 μs | 1.2 μs | 2.1 μs | ExpFromLeft (1.1 μs) | 1.02x | +| random | sorted_near_start | 4096 | 256 | 7.7 μs | 4.7 μs | 3.3 μs | 10.2 μs | 10.6 μs | 3.5 μs | 9.6 μs | ExpFromLeft (3.3 μs) | 1.04x | +| random | sorted_near_start | 4096 | 1024 | 16.2 μs | 18.4 μs | 14.3 μs | 44.1 μs | 40.1 μs | 16.2 μs | 36.1 μs | ExpFromLeft (14.3 μs) | 1.14x | +| random | sorted_near_start | 4096 | 4096 | 41.3 μs | 63.2 μs | 48.9 μs | 166.9 μs | 151.3 μs | 41.7 μs | 137.9 μs | Linear (41.3 μs) | 1.01x | +| random | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_near_start | 16384 | 4 | 19.0 μs | 239 ns | 200 ns | 220 ns | 180 ns | 230 ns | 160 ns | Binary (180 ns) | 1.28x | +| random | sorted_near_start | 16384 | 16 | 21.0 μs | 630 ns | 500 ns | 710 ns | 680 ns | 520 ns | 660 ns | ExpFromLeft (500 ns) | 1.04x | +| random | sorted_near_start | 16384 | 64 | 22.7 μs | 2.0 μs | 1.5 μs | 2.8 μs | 3.0 μs | 1.5 μs | 2.7 μs | ExpFromLeft (1.5 μs) | 1.02x | +| random | sorted_near_start | 16384 | 256 | 23.6 μs | 6.1 μs | 4.3 μs | 11.7 μs | 16.9 μs | 4.4 μs | 16.5 μs | ExpFromLeft (4.3 μs) | 1.03x | +| random | sorted_near_start | 16384 | 1024 | 33.2 μs | 20.7 μs | 15.0 μs | 53.4 μs | 71.8 μs | 15.2 μs | 65.4 μs | ExpFromLeft (15.0 μs) | 1.01x | +| random | sorted_near_start | 16384 | 4096 | 70.4 μs | 77.8 μs | 61.7 μs | 213.8 μs | 235.8 μs | 70.6 μs | 228.5 μs | ExpFromLeft (61.7 μs) | 1.14x | +| random | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | InterpSearch (80 ns) | 1.00x | +| random | sorted_near_start | 65536 | 4 | 34.1 μs | 250 ns | 210 ns | 240 ns | 200 ns | 240 ns | 180 ns | Binary (200 ns) | 1.20x | +| random | sorted_near_start | 65536 | 16 | 80.7 μs | 820 ns | 620 ns | 710 ns | 680 ns | 650 ns | 630 ns | ExpFromLeft (620 ns) | 1.05x | +| random | sorted_near_start | 65536 | 64 | 78.7 μs | 2.6 μs | 2.0 μs | 2.8 μs | 3.4 μs | 2.0 μs | 3.3 μs | ExpFromLeft (2.0 μs) | 1.02x | +| random | sorted_near_start | 65536 | 256 | 86.7 μs | 7.8 μs | 5.8 μs | 11.6 μs | 20.9 μs | 6.0 μs | 20.0 μs | ExpFromLeft (5.8 μs) | 1.03x | +| random | sorted_near_start | 65536 | 1024 | 99.7 μs | 26.5 μs | 19.3 μs | 53.4 μs | 92.0 μs | 19.6 μs | 85.1 μs | ExpFromLeft (19.3 μs) | 1.02x | +| random | sorted_near_start | 65536 | 4096 | 158.9 μs | 127.0 μs | 102.7 μs | 247.3 μs | 307.4 μs | 100.6 μs | 289.2 μs | ExpFromLeft (102.7 μs) | 0.98x | +| random | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 60 ns | ExpFromLeft (50 ns) | 1.00x | +| random | sorted_arithmetic | 16 | 4 | 100 ns | 110 ns | 120 ns | 160 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | +| random | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 220 ns | 500 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| random | sorted_arithmetic | 16 | 64 | 560 ns | 1.0 μs | 780 ns | 2.0 μs | 930 ns | 590 ns | 770 ns | Linear (560 ns) | 1.05x | +| random | sorted_arithmetic | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 8.2 μs | 3.2 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.01x | +| random | sorted_arithmetic | 16 | 1024 | 8.0 μs | 14.0 μs | 10.8 μs | 31.0 μs | 12.1 μs | 8.1 μs | 10.2 μs | Linear (8.0 μs) | 1.00x | +| random | sorted_arithmetic | 16 | 4096 | 31.1 μs | 55.1 μs | 42.3 μs | 120.7 μs | 46.8 μs | 31.1 μs | 40.0 μs | Linear (31.1 μs) | 1.00x | +| random | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| random | sorted_arithmetic | 64 | 4 | 170 ns | 150 ns | 130 ns | 150 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | +| random | sorted_arithmetic | 64 | 16 | 260 ns | 370 ns | 280 ns | 510 ns | 300 ns | 280 ns | 270 ns | Linear (260 ns) | 1.08x | +| random | sorted_arithmetic | 64 | 64 | 640 ns | 1.1 μs | 760 ns | 2.0 μs | 1.4 μs | 670 ns | 1.3 μs | Linear (640 ns) | 1.05x | +| random | sorted_arithmetic | 64 | 256 | 2.2 μs | 4.0 μs | 3.0 μs | 8.1 μs | 5.1 μs | 2.3 μs | 4.5 μs | Linear (2.2 μs) | 1.01x | +| random | sorted_arithmetic | 64 | 1024 | 8.8 μs | 14.7 μs | 11.5 μs | 33.6 μs | 17.7 μs | 8.9 μs | 15.9 μs | Linear (8.8 μs) | 1.00x | +| random | sorted_arithmetic | 64 | 4096 | 32.2 μs | 55.8 μs | 43.2 μs | 126.4 μs | 67.6 μs | 32.2 μs | 60.4 μs | Linear (32.2 μs) | 1.00x | +| random | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_arithmetic | 256 | 4 | 500 ns | 180 ns | 150 ns | 160 ns | 160 ns | 170 ns | 110 ns | ExpFromLeft (150 ns) | 1.13x | +| random | sorted_arithmetic | 256 | 16 | 540 ns | 510 ns | 410 ns | 600 ns | 370 ns | 440 ns | 340 ns | Binary (370 ns) | 1.19x | +| random | sorted_arithmetic | 256 | 64 | 910 ns | 1.4 μs | 1.1 μs | 2.3 μs | 1.4 μs | 950 ns | 1.3 μs | Linear (910 ns) | 1.04x | +| random | sorted_arithmetic | 256 | 256 | 2.4 μs | 4.2 μs | 2.8 μs | 9.5 μs | 6.9 μs | 2.4 μs | 6.4 μs | Linear (2.4 μs) | 1.01x | +| random | sorted_arithmetic | 256 | 1024 | 9.8 μs | 17.0 μs | 12.9 μs | 41.7 μs | 25.1 μs | 9.7 μs | 23.3 μs | Linear (9.8 μs) | 1.00x | +| random | sorted_arithmetic | 256 | 4096 | 36.1 μs | 59.3 μs | 46.4 μs | 155.2 μs | 90.1 μs | 36.0 μs | 83.3 μs | Linear (36.1 μs) | 1.00x | +| random | sorted_arithmetic | 1024 | 1 | 60 ns | 60 ns | 70 ns | 80 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| random | sorted_arithmetic | 1024 | 4 | 1.6 μs | 210 ns | 170 ns | 180 ns | 140 ns | 210 ns | 130 ns | Binary (140 ns) | 1.50x | +| random | sorted_arithmetic | 1024 | 16 | 1.9 μs | 660 ns | 500 ns | 660 ns | 440 ns | 540 ns | 420 ns | Binary (440 ns) | 1.23x | +| random | sorted_arithmetic | 1024 | 64 | 2.1 μs | 1.9 μs | 1.5 μs | 2.5 μs | 1.7 μs | 1.5 μs | 1.6 μs | ExpFromLeft (1.5 μs) | 1.04x | +| random | sorted_arithmetic | 1024 | 256 | 3.6 μs | 5.7 μs | 4.0 μs | 10.4 μs | 7.8 μs | 3.5 μs | 8.0 μs | Linear (3.6 μs) | 0.98x | +| random | sorted_arithmetic | 1024 | 1024 | 10.2 μs | 17.5 μs | 12.1 μs | 46.6 μs | 55.8 μs | 10.4 μs | 52.9 μs | Linear (10.2 μs) | 1.02x | +| random | sorted_arithmetic | 1024 | 4096 | 45.2 μs | 70.3 μs | 55.3 μs | 191.7 μs | 181.6 μs | 45.2 μs | 174.4 μs | Linear (45.2 μs) | 1.00x | +| random | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| random | sorted_arithmetic | 4096 | 4 | 5.9 μs | 240 ns | 200 ns | 180 ns | 170 ns | 230 ns | 140 ns | Binary (170 ns) | 1.35x | +| random | sorted_arithmetic | 4096 | 16 | 6.5 μs | 810 ns | 580 ns | 600 ns | 520 ns | 620 ns | 470 ns | Binary (520 ns) | 1.19x | +| random | sorted_arithmetic | 4096 | 64 | 7.8 μs | 2.5 μs | 1.9 μs | 2.5 μs | 2.1 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.9 μs) | 1.04x | +| random | sorted_arithmetic | 4096 | 256 | 9.2 μs | 7.8 μs | 5.8 μs | 9.9 μs | 10.1 μs | 5.9 μs | 11.3 μs | ExpFromLeft (5.8 μs) | 1.01x | +| random | sorted_arithmetic | 4096 | 1024 | 15.0 μs | 24.2 μs | 17.8 μs | 45.2 μs | 106.5 μs | 15.0 μs | 101.5 μs | Linear (15.0 μs) | 1.00x | +| random | sorted_arithmetic | 4096 | 4096 | 66.1 μs | 96.8 μs | 71.8 μs | 211.4 μs | 295.7 μs | 64.6 μs | 294.5 μs | Linear (66.1 μs) | 0.98x | +| random | sorted_arithmetic | 16384 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_arithmetic | 16384 | 4 | 22.6 μs | 280 ns | 220 ns | 160 ns | 190 ns | 250 ns | 160 ns | InterpSearch (160 ns) | 1.56x | +| random | sorted_arithmetic | 16384 | 16 | 24.5 μs | 950 ns | 710 ns | 730 ns | 600 ns | 730 ns | 560 ns | Binary (600 ns) | 1.22x | +| random | sorted_arithmetic | 16384 | 64 | 25.9 μs | 3.2 μs | 2.3 μs | 2.8 μs | 2.6 μs | 2.4 μs | 2.4 μs | ExpFromLeft (2.3 μs) | 1.02x | +| random | sorted_arithmetic | 16384 | 256 | 31.3 μs | 10.4 μs | 7.8 μs | 11.6 μs | 13.4 μs | 7.9 μs | 13.1 μs | ExpFromLeft (7.8 μs) | 1.01x | +| random | sorted_arithmetic | 16384 | 1024 | 44.1 μs | 35.1 μs | 27.7 μs | 60.3 μs | 133.6 μs | 26.6 μs | 136.6 μs | ExpFromLeft (27.7 μs) | 0.96x | +| random | sorted_arithmetic | 16384 | 4096 | 113.5 μs | 150.1 μs | 104.3 μs | 295.6 μs | 426.9 μs | 113.9 μs | 420.5 μs | ExpFromLeft (104.3 μs) | 1.09x | +| random | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | InterpSearch (80 ns) | 1.00x | +| random | sorted_arithmetic | 65536 | 4 | 92.9 μs | 310 ns | 250 ns | 200 ns | 200 ns | 280 ns | 190 ns | InterpSearch (200 ns) | 1.40x | +| random | sorted_arithmetic | 65536 | 16 | 95.6 μs | 1.1 μs | 820 ns | 800 ns | 709 ns | 860 ns | 660 ns | Binary (709 ns) | 1.21x | +| random | sorted_arithmetic | 65536 | 64 | 98.1 μs | 3.9 μs | 2.9 μs | 3.4 μs | 2.8 μs | 2.9 μs | 2.7 μs | Binary (2.8 μs) | 1.04x | +| random | sorted_arithmetic | 65536 | 256 | 103.7 μs | 13.6 μs | 10.3 μs | 13.7 μs | 15.8 μs | 10.1 μs | 16.4 μs | ExpFromLeft (10.3 μs) | 0.98x | +| random | sorted_arithmetic | 65536 | 1024 | 121.9 μs | 50.5 μs | 39.5 μs | 75.1 μs | 164.7 μs | 35.7 μs | 169.8 μs | ExpFromLeft (39.5 μs) | 0.90x | +| random | sorted_arithmetic | 65536 | 4096 | 197.6 μs | 231.8 μs | 192.0 μs | 358.6 μs | 517.4 μs | 193.3 μs | 520.6 μs | ExpFromLeft (192.0 μs) | 1.01x | +| random | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| random | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 110 ns | 160 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | +| random | sorted_geometric | 16 | 16 | 199 ns | 290 ns | 210 ns | 480 ns | 230 ns | 210 ns | 190 ns | Linear (199 ns) | 1.06x | +| random | sorted_geometric | 16 | 64 | 580 ns | 1.0 μs | 750 ns | 1.9 μs | 1.0 μs | 590 ns | 850 ns | Linear (580 ns) | 1.02x | +| random | sorted_geometric | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 7.6 μs | 3.2 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.01x | +| random | sorted_geometric | 16 | 1024 | 8.1 μs | 14.0 μs | 10.8 μs | 28.5 μs | 12.2 μs | 8.1 μs | 10.3 μs | Linear (8.1 μs) | 1.00x | +| random | sorted_geometric | 16 | 4096 | 31.1 μs | 54.9 μs | 42.3 μs | 111.7 μs | 47.9 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | +| random | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| random | sorted_geometric | 64 | 4 | 170 ns | 140 ns | 130 ns | 150 ns | 100 ns | 150 ns | 90 ns | Binary (100 ns) | 1.50x | +| random | sorted_geometric | 64 | 16 | 270 ns | 360 ns | 290 ns | 510 ns | 300 ns | 290 ns | 270 ns | Linear (270 ns) | 1.07x | +| random | sorted_geometric | 64 | 64 | 790 ns | 1.1 μs | 740 ns | 1.9 μs | 1.2 μs | 659 ns | 1.1 μs | ExpFromLeft (740 ns) | 0.89x | +| random | sorted_geometric | 64 | 256 | 2.2 μs | 4.0 μs | 2.9 μs | 8.4 μs | 5.0 μs | 2.2 μs | 4.6 μs | Linear (2.2 μs) | 1.03x | +| random | sorted_geometric | 64 | 1024 | 8.9 μs | 14.8 μs | 11.6 μs | 33.4 μs | 17.6 μs | 8.9 μs | 16.0 μs | Linear (8.9 μs) | 1.00x | +| random | sorted_geometric | 64 | 4096 | 45.2 μs | 74.7 μs | 56.6 μs | 133.2 μs | 66.9 μs | 32.2 μs | 60.5 μs | Linear (45.2 μs) | 0.71x | +| random | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_geometric | 256 | 4 | 490 ns | 180 ns | 150 ns | 150 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | +| random | sorted_geometric | 256 | 16 | 530 ns | 490 ns | 400 ns | 540 ns | 370 ns | 410 ns | 340 ns | Binary (370 ns) | 1.11x | +| random | sorted_geometric | 256 | 64 | 920 ns | 1.4 μs | 1.0 μs | 2.1 μs | 1.5 μs | 940 ns | 1.4 μs | Linear (920 ns) | 1.02x | +| random | sorted_geometric | 256 | 256 | 2.4 μs | 4.2 μs | 2.8 μs | 8.4 μs | 6.9 μs | 2.5 μs | 6.4 μs | Linear (2.4 μs) | 1.01x | +| random | sorted_geometric | 256 | 1024 | 9.4 μs | 16.1 μs | 12.4 μs | 37.1 μs | 25.6 μs | 9.4 μs | 23.6 μs | Linear (9.4 μs) | 1.00x | +| random | sorted_geometric | 256 | 4096 | 35.8 μs | 59.1 μs | 46.1 μs | 139.7 μs | 90.6 μs | 35.6 μs | 82.3 μs | Linear (35.8 μs) | 1.00x | +| random | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_geometric | 1024 | 4 | 1.6 μs | 200 ns | 170 ns | 160 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| random | sorted_geometric | 1024 | 16 | 1.8 μs | 630 ns | 500 ns | 560 ns | 440 ns | 499 ns | 420 ns | Binary (440 ns) | 1.13x | +| random | sorted_geometric | 1024 | 64 | 2.0 μs | 1.9 μs | 1.8 μs | 2.2 μs | 1.7 μs | 1.4 μs | 1.6 μs | Binary (1.7 μs) | 0.86x | +| random | sorted_geometric | 1024 | 256 | 3.6 μs | 5.4 μs | 3.9 μs | 9.1 μs | 7.6 μs | 3.5 μs | 7.2 μs | Linear (3.6 μs) | 0.97x | +| random | sorted_geometric | 1024 | 1024 | 9.7 μs | 18.2 μs | 12.2 μs | 41.9 μs | 48.3 μs | 10.2 μs | 45.8 μs | Linear (9.7 μs) | 1.05x | +| random | sorted_geometric | 1024 | 4096 | 42.5 μs | 67.8 μs | 52.5 μs | 170.6 μs | 172.7 μs | 42.3 μs | 169.8 μs | Linear (42.5 μs) | 0.99x | +| random | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| random | sorted_geometric | 4096 | 4 | 6.2 μs | 230 ns | 190 ns | 170 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | +| random | sorted_geometric | 4096 | 16 | 6.5 μs | 770 ns | 590 ns | 680 ns | 520 ns | 610 ns | 490 ns | Binary (520 ns) | 1.17x | +| random | sorted_geometric | 4096 | 64 | 7.4 μs | 2.5 μs | 1.8 μs | 2.8 μs | 2.0 μs | 1.9 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.02x | +| random | sorted_geometric | 4096 | 256 | 8.9 μs | 7.4 μs | 5.6 μs | 11.3 μs | 10.7 μs | 5.7 μs | 11.8 μs | ExpFromLeft (5.6 μs) | 1.02x | +| random | sorted_geometric | 4096 | 1024 | 15.7 μs | 23.1 μs | 16.9 μs | 54.1 μs | 89.6 μs | 18.5 μs | 83.0 μs | Linear (15.7 μs) | 1.18x | +| random | sorted_geometric | 4096 | 4096 | 62.8 μs | 91.3 μs | 69.9 μs | 235.5 μs | 280.0 μs | 59.2 μs | 275.5 μs | Linear (62.8 μs) | 0.94x | +| random | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| random | sorted_geometric | 16384 | 4 | 23.4 μs | 270 ns | 220 ns | 180 ns | 180 ns | 260 ns | 170 ns | InterpSearch (180 ns) | 1.44x | +| random | sorted_geometric | 16384 | 16 | 23.8 μs | 910 ns | 680 ns | 730 ns | 610 ns | 710 ns | 560 ns | Binary (610 ns) | 1.16x | +| random | sorted_geometric | 16384 | 64 | 25.4 μs | 3.1 μs | 2.3 μs | 3.0 μs | 2.4 μs | 2.4 μs | 2.2 μs | ExpFromLeft (2.3 μs) | 1.01x | +| random | sorted_geometric | 16384 | 256 | 30.0 μs | 10.0 μs | 7.7 μs | 12.7 μs | 12.8 μs | 7.7 μs | 13.9 μs | ExpFromLeft (7.7 μs) | 0.99x | +| random | sorted_geometric | 16384 | 1024 | 38.1 μs | 33.6 μs | 26.5 μs | 59.9 μs | 122.3 μs | 24.8 μs | 123.7 μs | ExpFromLeft (26.5 μs) | 0.94x | +| random | sorted_geometric | 16384 | 4096 | 108.8 μs | 145.6 μs | 110.8 μs | 289.0 μs | 403.0 μs | 113.6 μs | 393.4 μs | Linear (108.8 μs) | 1.04x | +| random | sorted_geometric | 65536 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| random | sorted_geometric | 65536 | 4 | 93.0 μs | 300 ns | 250 ns | 210 ns | 210 ns | 290 ns | 190 ns | InterpSearch (210 ns) | 1.38x | +| random | sorted_geometric | 65536 | 16 | 93.5 μs | 1.1 μs | 789 ns | 860 ns | 700 ns | 800 ns | 670 ns | Binary (700 ns) | 1.14x | +| random | sorted_geometric | 65536 | 64 | 95.3 μs | 3.7 μs | 2.7 μs | 3.6 μs | 3.0 μs | 2.7 μs | 2.8 μs | ExpFromLeft (2.7 μs) | 1.01x | +| random | sorted_geometric | 65536 | 256 | 101.9 μs | 13.6 μs | 10.3 μs | 15.0 μs | 16.9 μs | 10.3 μs | 16.7 μs | ExpFromLeft (10.3 μs) | 1.00x | +| random | sorted_geometric | 65536 | 1024 | 122.5 μs | 57.3 μs | 43.9 μs | 81.4 μs | 156.0 μs | 39.9 μs | 158.9 μs | ExpFromLeft (43.9 μs) | 0.91x | +| random | sorted_geometric | 65536 | 4096 | 180.9 μs | 225.0 μs | 184.6 μs | 367.5 μs | 502.9 μs | 182.9 μs | 502.1 μs | Linear (180.9 μs) | 1.01x | +| random | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 50 ns | 70 ns | 50 ns | Binary (50 ns) | 1.40x | +| random | sorted_bimodal | 16 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | +| random | sorted_bimodal | 16 | 16 | 190 ns | 290 ns | 220 ns | 480 ns | 240 ns | 210 ns | 200 ns | Linear (190 ns) | 1.11x | +| random | sorted_bimodal | 16 | 64 | 620 ns | 1.0 μs | 770 ns | 1.9 μs | 840 ns | 640 ns | 730 ns | Linear (620 ns) | 1.03x | +| random | sorted_bimodal | 16 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.3 μs | 3.1 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.01x | +| random | sorted_bimodal | 16 | 1024 | 7.9 μs | 14.5 μs | 10.6 μs | 28.8 μs | 12.1 μs | 8.0 μs | 10.5 μs | Linear (7.9 μs) | 1.00x | +| random | sorted_bimodal | 16 | 4096 | 31.3 μs | 57.9 μs | 42.1 μs | 114.3 μs | 47.9 μs | 30.9 μs | 40.8 μs | Linear (31.3 μs) | 0.99x | +| random | sorted_bimodal | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| random | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 120 ns | 160 ns | 110 ns | 130 ns | 90 ns | Binary (110 ns) | 1.18x | +| random | sorted_bimodal | 64 | 16 | 269 ns | 320 ns | 230 ns | 490 ns | 350 ns | 280 ns | 310 ns | ExpFromLeft (230 ns) | 1.22x | +| random | sorted_bimodal | 64 | 64 | 850 ns | 1.3 μs | 990 ns | 2.1 μs | 1.3 μs | 870 ns | 1.1 μs | Linear (850 ns) | 1.02x | +| random | sorted_bimodal | 64 | 256 | 2.2 μs | 3.6 μs | 2.9 μs | 7.6 μs | 4.3 μs | 2.2 μs | 3.9 μs | Linear (2.2 μs) | 1.00x | +| random | sorted_bimodal | 64 | 1024 | 8.0 μs | 13.9 μs | 10.8 μs | 28.5 μs | 16.9 μs | 8.0 μs | 15.2 μs | Linear (8.0 μs) | 1.00x | +| random | sorted_bimodal | 64 | 4096 | 31.0 μs | 54.8 μs | 42.2 μs | 112.5 μs | 66.7 μs | 31.1 μs | 59.8 μs | Linear (31.0 μs) | 1.00x | +| random | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_bimodal | 256 | 4 | 420 ns | 150 ns | 140 ns | 170 ns | 130 ns | 150 ns | 110 ns | Binary (130 ns) | 1.15x | +| random | sorted_bimodal | 256 | 16 | 560 ns | 370 ns | 310 ns | 530 ns | 410 ns | 320 ns | 380 ns | ExpFromLeft (310 ns) | 1.03x | +| random | sorted_bimodal | 256 | 64 | 930 ns | 1.1 μs | 760 ns | 2.0 μs | 1.7 μs | 950 ns | 1.6 μs | ExpFromLeft (760 ns) | 1.25x | +| random | sorted_bimodal | 256 | 256 | 2.6 μs | 4.0 μs | 3.1 μs | 8.8 μs | 6.1 μs | 2.6 μs | 5.7 μs | Linear (2.6 μs) | 1.01x | +| random | sorted_bimodal | 256 | 1024 | 9.0 μs | 14.7 μs | 11.5 μs | 33.0 μs | 22.5 μs | 9.1 μs | 20.6 μs | Linear (9.0 μs) | 1.00x | +| random | sorted_bimodal | 256 | 4096 | 32.3 μs | 56.0 μs | 43.1 μs | 125.8 μs | 86.3 μs | 32.3 μs | 79.4 μs | Linear (32.3 μs) | 1.00x | +| random | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 80 ns | 80 ns | 60 ns | ExpFromLeft (60 ns) | 1.33x | +| random | sorted_bimodal | 1024 | 4 | 1.5 μs | 190 ns | 180 ns | 200 ns | 140 ns | 190 ns | 120 ns | Binary (140 ns) | 1.36x | +| random | sorted_bimodal | 1024 | 16 | 1.7 μs | 480 ns | 400 ns | 680 ns | 450 ns | 390 ns | 400 ns | ExpFromLeft (400 ns) | 0.97x | +| random | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 930 ns | 2.6 μs | 2.0 μs | 970 ns | 2.2 μs | ExpFromLeft (930 ns) | 1.04x | +| random | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.1 μs | 2.9 μs | 11.3 μs | 8.2 μs | 3.5 μs | 7.5 μs | ExpFromLeft (2.9 μs) | 1.22x | +| random | sorted_bimodal | 1024 | 1024 | 10.7 μs | 16.2 μs | 12.5 μs | 45.8 μs | 29.6 μs | 10.7 μs | 27.2 μs | Linear (10.7 μs) | 1.00x | +| random | sorted_bimodal | 1024 | 4096 | 36.3 μs | 58.6 μs | 45.8 μs | 169.4 μs | 108.5 μs | 36.2 μs | 102.1 μs | Linear (36.3 μs) | 1.00x | +| random | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_bimodal | 4096 | 4 | 5.8 μs | 240 ns | 190 ns | 190 ns | 160 ns | 220 ns | 150 ns | Binary (160 ns) | 1.38x | +| random | sorted_bimodal | 4096 | 16 | 6.2 μs | 590 ns | 469 ns | 650 ns | 590 ns | 490 ns | 540 ns | ExpFromLeft (469 ns) | 1.04x | +| random | sorted_bimodal | 4096 | 64 | 6.6 μs | 1.7 μs | 1.3 μs | 2.6 μs | 2.2 μs | 1.4 μs | 1.9 μs | ExpFromLeft (1.3 μs) | 1.03x | +| random | sorted_bimodal | 4096 | 256 | 7.9 μs | 5.1 μs | 3.6 μs | 10.3 μs | 10.4 μs | 3.7 μs | 10.2 μs | ExpFromLeft (3.6 μs) | 1.02x | +| random | sorted_bimodal | 4096 | 1024 | 15.0 μs | 17.6 μs | 12.8 μs | 45.3 μs | 51.4 μs | 14.7 μs | 47.7 μs | ExpFromLeft (12.8 μs) | 1.15x | +| random | sorted_bimodal | 4096 | 4096 | 46.0 μs | 67.6 μs | 53.4 μs | 180.3 μs | 167.9 μs | 46.5 μs | 151.3 μs | Linear (46.0 μs) | 1.01x | +| random | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_bimodal | 16384 | 4 | 21.7 μs | 250 ns | 210 ns | 210 ns | 180 ns | 219 ns | 170 ns | Binary (180 ns) | 1.22x | +| random | sorted_bimodal | 16384 | 16 | 22.4 μs | 740 ns | 570 ns | 670 ns | 600 ns | 600 ns | 560 ns | ExpFromLeft (570 ns) | 1.05x | +| random | sorted_bimodal | 16384 | 64 | 24.6 μs | 2.2 μs | 2.1 μs | 2.6 μs | 2.7 μs | 1.7 μs | 2.5 μs | ExpFromLeft (2.1 μs) | 0.82x | +| random | sorted_bimodal | 16384 | 256 | 25.9 μs | 6.6 μs | 5.0 μs | 10.3 μs | 15.2 μs | 5.1 μs | 14.9 μs | ExpFromLeft (5.0 μs) | 1.00x | +| random | sorted_bimodal | 16384 | 1024 | 33.4 μs | 22.8 μs | 16.3 μs | 48.6 μs | 84.9 μs | 15.9 μs | 82.0 μs | ExpFromLeft (16.3 μs) | 0.98x | +| random | sorted_bimodal | 16384 | 4096 | 85.6 μs | 94.0 μs | 74.0 μs | 215.3 μs | 259.6 μs | 84.5 μs | 241.2 μs | ExpFromLeft (74.0 μs) | 1.14x | +| random | sorted_bimodal | 65536 | 1 | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | Gallop (70 ns) | 1.14x | +| random | sorted_bimodal | 65536 | 4 | 89.2 μs | 270 ns | 230 ns | 230 ns | 200 ns | 260 ns | 180 ns | Binary (200 ns) | 1.30x | +| random | sorted_bimodal | 65536 | 16 | 93.6 μs | 830 ns | 620 ns | 730 ns | 680 ns | 640 ns | 630 ns | ExpFromLeft (620 ns) | 1.03x | +| random | sorted_bimodal | 65536 | 64 | 91.2 μs | 2.9 μs | 2.2 μs | 2.7 μs | 2.8 μs | 2.2 μs | 2.7 μs | ExpFromLeft (2.2 μs) | 0.99x | +| random | sorted_bimodal | 65536 | 256 | 97.4 μs | 9.1 μs | 6.8 μs | 11.0 μs | 18.5 μs | 7.1 μs | 18.2 μs | ExpFromLeft (6.8 μs) | 1.03x | +| random | sorted_bimodal | 65536 | 1024 | 108.8 μs | 32.0 μs | 24.3 μs | 53.9 μs | 109.5 μs | 23.1 μs | 110.8 μs | ExpFromLeft (24.3 μs) | 0.95x | +| random | sorted_bimodal | 65536 | 4096 | 184.5 μs | 148.3 μs | 112.5 μs | 266.4 μs | 347.3 μs | 111.1 μs | 339.4 μs | ExpFromLeft (112.5 μs) | 0.99x | +| random | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 40 ns | ExpFromLeft (50 ns) | 1.20x | +| random | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 170 ns | 90 ns | 100 ns | 80 ns | Linear (80 ns) | 1.25x | +| random | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 210 ns | 550 ns | 220 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | +| random | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 690 ns | 2.0 μs | 790 ns | 580 ns | 640 ns | Linear (550 ns) | 1.05x | +| random | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 7.9 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.01x | +| random | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 31.7 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.00x | +| random | sorted_repeated | 16 | 4096 | 30.8 μs | 54.9 μs | 39.0 μs | 125.3 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 70 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| random | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 80 ns | 190 ns | 100 ns | 110 ns | 90 ns | ExpFromLeft (80 ns) | 1.38x | +| random | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 220 ns | 650 ns | 310 ns | 199 ns | 270 ns | Linear (170 ns) | 1.17x | +| random | sorted_repeated | 64 | 64 | 550 ns | 920 ns | 700 ns | 2.5 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | +| random | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 9.7 μs | 4.2 μs | 2.1 μs | 3.6 μs | Linear (2.0 μs) | 1.08x | +| random | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 38.6 μs | 16.7 μs | 8.3 μs | 14.2 μs | Linear (7.7 μs) | 1.07x | +| random | sorted_repeated | 64 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 154.4 μs | 70.5 μs | 44.3 μs | 60.7 μs | Linear (30.8 μs) | 1.44x | +| random | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 90 ns | 190 ns | 120 ns | 110 ns | 110 ns | ExpFromLeft (90 ns) | 1.22x | +| random | sorted_repeated | 256 | 16 | 220 ns | 350 ns | 250 ns | 700 ns | 400 ns | 240 ns | 340 ns | Linear (220 ns) | 1.09x | +| random | sorted_repeated | 256 | 64 | 560 ns | 929 ns | 700 ns | 2.5 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (560 ns) | 1.04x | +| random | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 10.0 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| random | sorted_repeated | 256 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 39.9 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.01x | +| random | sorted_repeated | 256 | 4096 | 30.8 μs | 54.9 μs | 39.5 μs | 159.4 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 70 ns | 80 ns | 60 ns | 70 ns | 60 ns | Binary (60 ns) | 1.17x | +| random | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 110 ns | 210 ns | 140 ns | 110 ns | 130 ns | Linear (90 ns) | 1.22x | +| random | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 210 ns | 750 ns | 460 ns | 200 ns | 420 ns | Linear (180 ns) | 1.11x | +| random | sorted_repeated | 1024 | 64 | 560 ns | 940 ns | 700 ns | 2.9 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| random | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 11.2 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | +| random | sorted_repeated | 1024 | 1024 | 7.8 μs | 13.9 μs | 10.0 μs | 44.8 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | +| random | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.7 μs | 39.8 μs | 178.8 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_repeated | 4096 | 4 | 90 ns | 120 ns | 100 ns | 220 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | +| random | sorted_repeated | 4096 | 16 | 180 ns | 280 ns | 220 ns | 770 ns | 540 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | +| random | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 700 ns | 2.9 μs | 2.0 μs | 600 ns | 1.8 μs | Linear (560 ns) | 1.07x | +| random | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 11.4 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | +| random | sorted_repeated | 4096 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 45.5 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.7 μs) | 1.01x | +| random | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.1 μs | 182.2 μs | 124.7 μs | 30.8 μs | 114.3 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| random | sorted_repeated | 16384 | 4 | 90 ns | 110 ns | 110 ns | 190 ns | 180 ns | 120 ns | 170 ns | Linear (90 ns) | 1.33x | +| random | sorted_repeated | 16384 | 16 | 180 ns | 290 ns | 230 ns | 680 ns | 610 ns | 210 ns | 560 ns | Linear (180 ns) | 1.17x | +| random | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 700 ns | 2.6 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | +| random | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 10.1 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | +| random | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 40.1 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | +| random | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.0 μs | 39.2 μs | 160.0 μs | 144.1 μs | 30.8 μs | 133.7 μs | Linear (30.8 μs) | 1.00x | +| random | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 70 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| random | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 240 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| random | sorted_repeated | 65536 | 16 | 190 ns | 300 ns | 230 ns | 850 ns | 690 ns | 220 ns | 640 ns | Linear (190 ns) | 1.16x | +| random | sorted_repeated | 65536 | 64 | 570 ns | 949 ns | 710 ns | 3.2 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| random | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 12.9 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.00x | +| random | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 51.1 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 0.99x | +| random | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.0 μs | 39.2 μs | 204.0 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| random | unsorted | 16 | 1 | 60 ns | 50 ns | 50 ns | 60 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| random | unsorted | 16 | 4 | 90 ns | 100 ns | 90 ns | 100 ns | 100 ns | 100 ns | 70 ns | ExpFromLeft (90 ns) | 1.11x | +| random | unsorted | 16 | 16 | 210 ns | 210 ns | 219 ns | 210 ns | 210 ns | 220 ns | 200 ns | InterpSearch (210 ns) | 1.05x | +| random | unsorted | 16 | 64 | 710 ns | 700 ns | 880 ns | 710 ns | 690 ns | 720 ns | 680 ns | Binary (690 ns) | 1.04x | +| random | unsorted | 16 | 256 | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | InterpSearch (2.7 μs) | 1.00x | +| random | unsorted | 16 | 1024 | 15.2 μs | 15.2 μs | 15.2 μs | 15.0 μs | 14.9 μs | 14.8 μs | 15.6 μs | Binary (14.9 μs) | 0.99x | +| random | unsorted | 16 | 4096 | 115.4 μs | 115.3 μs | 113.3 μs | 113.0 μs | 112.7 μs | 112.9 μs | 116.5 μs | Binary (112.7 μs) | 1.00x | +| random | unsorted | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| random | unsorted | 64 | 4 | 110 ns | 100 ns | 100 ns | 100 ns | 110 ns | 110 ns | 90 ns | InterpSearch (100 ns) | 1.10x | +| random | unsorted | 64 | 16 | 280 ns | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 260 ns | InterpSearch (280 ns) | 1.04x | +| random | unsorted | 64 | 64 | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | Binary (1.1 μs) | 0.99x | +| random | unsorted | 64 | 256 | 6.4 μs | 6.3 μs | 6.3 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.4 μs | Binary (6.2 μs) | 1.00x | +| random | unsorted | 64 | 1024 | 37.7 μs | 37.4 μs | 36.9 μs | 37.5 μs | 36.8 μs | 36.7 μs | 39.1 μs | Binary (36.8 μs) | 1.00x | +| random | unsorted | 64 | 4096 | 206.5 μs | 204.7 μs | 202.8 μs | 202.5 μs | 201.9 μs | 203.8 μs | 200.7 μs | Binary (201.9 μs) | 1.01x | +| random | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| random | unsorted | 256 | 4 | 120 ns | 120 ns | 120 ns | 120 ns | 130 ns | 130 ns | 110 ns | InterpSearch (120 ns) | 1.08x | +| random | unsorted | 256 | 16 | 350 ns | 350 ns | 340 ns | 350 ns | 340 ns | 360 ns | 340 ns | ExpFromLeft (340 ns) | 1.06x | +| random | unsorted | 256 | 64 | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.5 μs | InterpSearch (1.4 μs) | 1.01x | +| random | unsorted | 256 | 256 | 7.3 μs | 7.2 μs | 7.2 μs | 7.1 μs | 7.1 μs | 7.1 μs | 7.3 μs | Binary (7.1 μs) | 1.00x | +| random | unsorted | 256 | 1024 | 51.5 μs | 51.3 μs | 50.9 μs | 50.6 μs | 49.6 μs | 50.2 μs | 51.2 μs | Binary (49.6 μs) | 1.01x | +| random | unsorted | 256 | 4096 | 280.9 μs | 278.4 μs | 273.9 μs | 272.8 μs | 274.6 μs | 275.9 μs | 278.2 μs | InterpSearch (272.8 μs) | 1.01x | +| random | unsorted | 1024 | 1 | 70 ns | 60 ns | 70 ns | 80 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| random | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 150 ns | 140 ns | 150 ns | 130 ns | ExpFromLeft (140 ns) | 1.07x | +| random | unsorted | 1024 | 16 | 410 ns | 420 ns | 420 ns | 430 ns | 420 ns | 430 ns | 410 ns | Linear (410 ns) | 1.05x | +| random | unsorted | 1024 | 64 | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.8 μs | 1.7 μs | Linear (1.7 μs) | 1.02x | +| random | unsorted | 1024 | 256 | 8.3 μs | 8.0 μs | 8.0 μs | 8.0 μs | 8.0 μs | 8.0 μs | 8.3 μs | Binary (8.0 μs) | 1.00x | +| random | unsorted | 1024 | 1024 | 77.0 μs | 76.3 μs | 75.1 μs | 74.4 μs | 74.1 μs | 73.7 μs | 75.9 μs | Binary (74.1 μs) | 0.99x | +| random | unsorted | 1024 | 4096 | 379.5 μs | 380.8 μs | 380.3 μs | 377.5 μs | 381.1 μs | 380.0 μs | 378.8 μs | InterpSearch (377.5 μs) | 1.01x | +| random | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| random | unsorted | 4096 | 4 | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 170 ns | 140 ns | InterpSearch (160 ns) | 1.06x | +| random | unsorted | 4096 | 16 | 490 ns | 500 ns | 480 ns | 490 ns | 510 ns | 500 ns | 480 ns | ExpFromLeft (480 ns) | 1.04x | +| random | unsorted | 4096 | 64 | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | Gallop (1.9 μs) | 1.01x | +| random | unsorted | 4096 | 256 | 9.8 μs | 9.8 μs | 9.4 μs | 9.5 μs | 9.4 μs | 9.5 μs | 11.0 μs | ExpFromLeft (9.4 μs) | 1.01x | +| random | unsorted | 4096 | 1024 | 96.3 μs | 94.0 μs | 93.0 μs | 92.1 μs | 91.6 μs | 91.5 μs | 95.5 μs | Binary (91.6 μs) | 1.00x | +| random | unsorted | 4096 | 4096 | 483.4 μs | 479.6 μs | 478.6 μs | 481.5 μs | 480.6 μs | 481.0 μs | 485.3 μs | ExpFromLeft (478.6 μs) | 1.01x | +| random | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| random | unsorted | 16384 | 4 | 180 ns | 180 ns | 180 ns | 180 ns | 180 ns | 180 ns | 170 ns | InterpSearch (180 ns) | 1.00x | +| random | unsorted | 16384 | 16 | 570 ns | 580 ns | 580 ns | 580 ns | 570 ns | 580 ns | 560 ns | Binary (570 ns) | 1.02x | +| random | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.2 μs | 2.3 μs | 2.2 μs | Binary (2.2 μs) | 1.02x | +| random | unsorted | 16384 | 256 | 11.2 μs | 11.1 μs | 11.1 μs | 11.1 μs | 11.1 μs | 11.1 μs | 14.1 μs | ExpFromLeft (11.1 μs) | 1.00x | +| random | unsorted | 16384 | 1024 | 139.6 μs | 135.6 μs | 134.0 μs | 134.5 μs | 132.2 μs | 131.6 μs | 138.4 μs | Binary (132.2 μs) | 1.00x | +| random | unsorted | 16384 | 4096 | 660.5 μs | 661.2 μs | 660.3 μs | 666.5 μs | 658.7 μs | 660.7 μs | 660.5 μs | Binary (658.7 μs) | 1.00x | +| random | unsorted | 65536 | 1 | 80 ns | 80 ns | 70 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| random | unsorted | 65536 | 4 | 200 ns | 190 ns | 200 ns | 190 ns | 200 ns | 210 ns | 190 ns | InterpSearch (190 ns) | 1.11x | +| random | unsorted | 65536 | 16 | 710 ns | 710 ns | 710 ns | 700 ns | 720 ns | 720 ns | 690 ns | InterpSearch (700 ns) | 1.03x | +| random | unsorted | 65536 | 64 | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | Gallop (2.8 μs) | 1.01x | +| random | unsorted | 65536 | 256 | 13.9 μs | 13.7 μs | 13.7 μs | 13.6 μs | 13.6 μs | 13.3 μs | 18.5 μs | Binary (13.6 μs) | 0.98x | +| random | unsorted | 65536 | 1024 | 187.8 μs | 183.9 μs | 183.2 μs | 182.0 μs | 181.6 μs | 181.4 μs | 185.2 μs | Binary (181.6 μs) | 1.00x | +| random | unsorted | 65536 | 4096 | 845.5 μs | 843.9 μs | 846.9 μs | 846.7 μs | 846.0 μs | 845.3 μs | 844.8 μs | Gallop (843.9 μs) | 1.00x | +| two_scale | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 40 ns | ExpFromLeft (50 ns) | 1.20x | +| two_scale | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 100 ns | 160 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| two_scale | sorted_uniform | 16 | 16 | 170 ns | 260 ns | 210 ns | 540 ns | 230 ns | 200 ns | 190 ns | Linear (170 ns) | 1.18x | +| two_scale | sorted_uniform | 16 | 64 | 560 ns | 970 ns | 740 ns | 2.2 μs | 910 ns | 600 ns | 750 ns | Linear (560 ns) | 1.07x | +| two_scale | sorted_uniform | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 8.8 μs | 3.1 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.01x | +| two_scale | sorted_uniform | 16 | 1024 | 7.9 μs | 13.9 μs | 10.7 μs | 33.4 μs | 12.2 μs | 7.9 μs | 10.1 μs | Linear (7.9 μs) | 1.00x | +| two_scale | sorted_uniform | 16 | 4096 | 30.9 μs | 55.5 μs | 42.1 μs | 131.4 μs | 48.8 μs | 31.4 μs | 40.8 μs | Linear (30.9 μs) | 1.02x | +| two_scale | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_uniform | 64 | 4 | 120 ns | 130 ns | 130 ns | 200 ns | 110 ns | 140 ns | 90 ns | Binary (110 ns) | 1.27x | +| two_scale | sorted_uniform | 64 | 16 | 210 ns | 320 ns | 240 ns | 710 ns | 350 ns | 240 ns | 310 ns | Linear (210 ns) | 1.14x | +| two_scale | sorted_uniform | 64 | 64 | 590 ns | 1.0 μs | 730 ns | 2.6 μs | 1.3 μs | 630 ns | 1.2 μs | Linear (590 ns) | 1.07x | +| two_scale | sorted_uniform | 64 | 256 | 2.4 μs | 4.1 μs | 3.1 μs | 11.2 μs | 4.8 μs | 2.4 μs | 4.3 μs | Linear (2.4 μs) | 1.01x | +| two_scale | sorted_uniform | 64 | 1024 | 8.5 μs | 15.0 μs | 11.1 μs | 43.7 μs | 17.4 μs | 8.5 μs | 15.5 μs | Linear (8.5 μs) | 1.00x | +| two_scale | sorted_uniform | 64 | 4096 | 31.9 μs | 58.4 μs | 42.7 μs | 167.6 μs | 68.4 μs | 32.0 μs | 59.6 μs | Linear (31.9 μs) | 1.00x | +| two_scale | sorted_uniform | 256 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_uniform | 256 | 4 | 150 ns | 150 ns | 140 ns | 250 ns | 120 ns | 150 ns | 110 ns | Binary (120 ns) | 1.25x | +| two_scale | sorted_uniform | 256 | 16 | 340 ns | 410 ns | 350 ns | 870 ns | 370 ns | 340 ns | 339 ns | Linear (340 ns) | 1.00x | +| two_scale | sorted_uniform | 256 | 64 | 720 ns | 1.2 μs | 830 ns | 3.2 μs | 1.6 μs | 760 ns | 1.6 μs | Linear (720 ns) | 1.06x | +| two_scale | sorted_uniform | 256 | 256 | 2.2 μs | 4.0 μs | 2.8 μs | 13.4 μs | 6.6 μs | 2.2 μs | 6.0 μs | Linear (2.2 μs) | 1.01x | +| two_scale | sorted_uniform | 256 | 1024 | 9.9 μs | 16.0 μs | 12.7 μs | 56.7 μs | 23.7 μs | 9.9 μs | 21.6 μs | Linear (9.9 μs) | 1.00x | +| two_scale | sorted_uniform | 256 | 4096 | 33.8 μs | 58.0 μs | 44.6 μs | 214.4 μs | 88.3 μs | 33.7 μs | 80.6 μs | Linear (33.8 μs) | 1.00x | +| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 80 ns | 130 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| two_scale | sorted_uniform | 1024 | 4 | 740 ns | 180 ns | 160 ns | 270 ns | 150 ns | 190 ns | 130 ns | Binary (150 ns) | 1.27x | +| two_scale | sorted_uniform | 1024 | 16 | 1.1 μs | 520 ns | 400 ns | 980 ns | 480 ns | 440 ns | 440 ns | ExpFromLeft (400 ns) | 1.10x | +| two_scale | sorted_uniform | 1024 | 64 | 1.3 μs | 1.5 μs | 1.2 μs | 4.0 μs | 1.8 μs | 1.2 μs | 1.8 μs | ExpFromLeft (1.2 μs) | 1.03x | +| two_scale | sorted_uniform | 1024 | 256 | 2.7 μs | 4.7 μs | 3.2 μs | 16.1 μs | 8.2 μs | 2.8 μs | 7.9 μs | Linear (2.7 μs) | 1.03x | +| two_scale | sorted_uniform | 1024 | 1024 | 10.3 μs | 17.4 μs | 12.4 μs | 71.7 μs | 34.6 μs | 10.3 μs | 33.0 μs | Linear (10.3 μs) | 1.00x | +| two_scale | sorted_uniform | 1024 | 4096 | 40.0 μs | 63.5 μs | 50.2 μs | 291.1 μs | 120.0 μs | 40.0 μs | 114.1 μs | Linear (40.0 μs) | 1.00x | +| two_scale | sorted_uniform | 4096 | 1 | 70 ns | 80 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | sorted_uniform | 4096 | 4 | 1.0 μs | 210 ns | 190 ns | 340 ns | 170 ns | 220 ns | 140 ns | Binary (170 ns) | 1.29x | +| two_scale | sorted_uniform | 4096 | 16 | 3.1 μs | 730 ns | 540 ns | 1.1 μs | 550 ns | 560 ns | 520 ns | ExpFromLeft (540 ns) | 1.04x | +| two_scale | sorted_uniform | 4096 | 64 | 4.2 μs | 2.0 μs | 1.6 μs | 4.6 μs | 2.2 μs | 1.6 μs | 2.5 μs | ExpFromLeft (1.6 μs) | 1.05x | +| two_scale | sorted_uniform | 4096 | 256 | 5.2 μs | 6.2 μs | 4.5 μs | 18.8 μs | 11.0 μs | 4.5 μs | 10.2 μs | ExpFromLeft (4.5 μs) | 1.00x | +| two_scale | sorted_uniform | 4096 | 1024 | 15.5 μs | 23.4 μs | 15.0 μs | 95.4 μs | 74.0 μs | 15.5 μs | 66.5 μs | ExpFromLeft (15.0 μs) | 1.03x | +| two_scale | sorted_uniform | 4096 | 4096 | 54.7 μs | 79.6 μs | 62.5 μs | 414.4 μs | 216.7 μs | 53.6 μs | 209.5 μs | Linear (54.7 μs) | 0.98x | +| two_scale | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| two_scale | sorted_uniform | 16384 | 4 | 7.4 μs | 240 ns | 200 ns | 360 ns | 180 ns | 230 ns | 160 ns | Binary (180 ns) | 1.28x | +| two_scale | sorted_uniform | 16384 | 16 | 11.8 μs | 810 ns | 610 ns | 1.3 μs | 600 ns | 640 ns | 570 ns | Binary (600 ns) | 1.07x | +| two_scale | sorted_uniform | 16384 | 64 | 13.3 μs | 2.7 μs | 2.0 μs | 5.3 μs | 2.6 μs | 2.1 μs | 2.4 μs | ExpFromLeft (2.0 μs) | 1.04x | +| two_scale | sorted_uniform | 16384 | 256 | 16.6 μs | 8.3 μs | 6.4 μs | 22.7 μs | 14.7 μs | 6.5 μs | 14.4 μs | ExpFromLeft (6.4 μs) | 1.02x | +| two_scale | sorted_uniform | 16384 | 1024 | 23.5 μs | 29.1 μs | 20.1 μs | 127.8 μs | 106.0 μs | 20.4 μs | 104.5 μs | ExpFromLeft (20.1 μs) | 1.02x | +| two_scale | sorted_uniform | 16384 | 4096 | 102.7 μs | 127.3 μs | 97.3 μs | 529.1 μs | 327.1 μs | 98.7 μs | 319.7 μs | ExpFromLeft (97.3 μs) | 1.01x | +| two_scale | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_uniform | 65536 | 4 | 39.5 μs | 280 ns | 220 ns | 390 ns | 200 ns | 250 ns | 190 ns | Binary (200 ns) | 1.25x | +| two_scale | sorted_uniform | 65536 | 16 | 42.4 μs | 940 ns | 690 ns | 1.5 μs | 720 ns | 729 ns | 680 ns | ExpFromLeft (690 ns) | 1.06x | +| two_scale | sorted_uniform | 65536 | 64 | 47.2 μs | 3.2 μs | 2.4 μs | 5.9 μs | 2.9 μs | 2.5 μs | 2.8 μs | ExpFromLeft (2.4 μs) | 1.04x | +| two_scale | sorted_uniform | 65536 | 256 | 54.5 μs | 11.0 μs | 8.4 μs | 26.6 μs | 19.2 μs | 8.5 μs | 16.8 μs | ExpFromLeft (8.4 μs) | 1.01x | +| two_scale | sorted_uniform | 65536 | 1024 | 73.1 μs | 44.4 μs | 33.7 μs | 173.1 μs | 131.8 μs | 31.0 μs | 135.6 μs | ExpFromLeft (33.7 μs) | 0.92x | +| two_scale | sorted_uniform | 65536 | 4096 | 188.7 μs | 202.3 μs | 159.1 μs | 681.2 μs | 414.0 μs | 158.0 μs | 413.9 μs | ExpFromLeft (159.1 μs) | 0.99x | +| two_scale | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| two_scale | sorted_dense_burst | 16 | 4 | 80 ns | 90 ns | 90 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| two_scale | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 220 ns | 630 ns | 230 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | +| two_scale | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 720 ns | 2.3 μs | 780 ns | 580 ns | 640 ns | Linear (550 ns) | 1.05x | +| two_scale | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.9 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.01x | +| two_scale | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 35.4 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.01x | +| two_scale | sorted_dense_burst | 16 | 4096 | 30.8 μs | 55.1 μs | 41.9 μs | 141.0 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| two_scale | sorted_dense_burst | 64 | 4 | 80 ns | 90 ns | 90 ns | 210 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| two_scale | sorted_dense_burst | 64 | 16 | 180 ns | 270 ns | 220 ns | 790 ns | 310 ns | 190 ns | 260 ns | Linear (180 ns) | 1.06x | +| two_scale | sorted_dense_burst | 64 | 64 | 549 ns | 930 ns | 729 ns | 3.0 μs | 1.4 μs | 580 ns | 920 ns | Linear (549 ns) | 1.06x | +| two_scale | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.4 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | +| two_scale | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.7 μs | 10.6 μs | 45.2 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | +| two_scale | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 180.3 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 250 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| two_scale | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 950 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| two_scale | sorted_dense_burst | 256 | 64 | 550 ns | 920 ns | 740 ns | 3.6 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | +| two_scale | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 14.0 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| two_scale | sorted_dense_burst | 256 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 55.9 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.7 μs) | 1.01x | +| two_scale | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 222.8 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 100 ns | 290 ns | 140 ns | 110 ns | 130 ns | Linear (90 ns) | 1.22x | +| two_scale | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 240 ns | 1.1 μs | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | +| two_scale | sorted_dense_burst | 1024 | 64 | 560 ns | 939 ns | 740 ns | 4.2 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| two_scale | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.4 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| two_scale | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.9 μs | 10.6 μs | 65.4 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.1 μs | 42.1 μs | 260.7 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 130 ns | 350 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | +| two_scale | sorted_dense_burst | 4096 | 16 | 190 ns | 290 ns | 240 ns | 1.2 μs | 530 ns | 210 ns | 490 ns | Linear (190 ns) | 1.11x | +| two_scale | sorted_dense_burst | 4096 | 64 | 560 ns | 930 ns | 740 ns | 4.8 μs | 2.0 μs | 600 ns | 1.8 μs | Linear (560 ns) | 1.07x | +| two_scale | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 18.8 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| two_scale | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 74.7 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 54.9 μs | 42.1 μs | 299.4 μs | 124.7 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| two_scale | sorted_dense_burst | 16384 | 4 | 90 ns | 110 ns | 100 ns | 380 ns | 180 ns | 120 ns | 170 ns | Linear (90 ns) | 1.33x | +| two_scale | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 1.4 μs | 600 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | +| two_scale | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 740 ns | 5.5 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | +| two_scale | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 21.6 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | +| two_scale | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 85.9 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 343.8 μs | 144.1 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_dense_burst | 65536 | 4 | 100 ns | 110 ns | 110 ns | 520 ns | 250 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| two_scale | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 260 ns | 1.6 μs | 690 ns | 210 ns | 640 ns | Linear (190 ns) | 1.11x | +| two_scale | sorted_dense_burst | 65536 | 64 | 570 ns | 940 ns | 750 ns | 6.2 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| two_scale | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.6 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | +| two_scale | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 97.3 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.01x | +| two_scale | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.1 μs | 386.4 μs | 163.2 μs | 30.9 μs | 152.6 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| two_scale | sorted_near_start | 16 | 4 | 90 ns | 110 ns | 100 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| two_scale | sorted_near_start | 16 | 16 | 190 ns | 280 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | +| two_scale | sorted_near_start | 16 | 64 | 570 ns | 950 ns | 760 ns | 1.7 μs | 810 ns | 590 ns | 690 ns | Linear (570 ns) | 1.04x | +| two_scale | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.7 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.02x | +| two_scale | sorted_near_start | 16 | 1024 | 11.2 μs | 14.0 μs | 10.8 μs | 26.7 μs | 12.0 μs | 7.9 μs | 10.2 μs | ExpFromLeft (10.8 μs) | 0.74x | +| two_scale | sorted_near_start | 16 | 4096 | 31.0 μs | 55.2 μs | 42.2 μs | 105.9 μs | 47.5 μs | 31.0 μs | 40.1 μs | Linear (31.0 μs) | 1.00x | +| two_scale | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 70 ns | 70 ns | 50 ns | Gallop (50 ns) | 1.40x | +| two_scale | sorted_near_start | 64 | 4 | 150 ns | 120 ns | 120 ns | 150 ns | 110 ns | 120 ns | 90 ns | Binary (110 ns) | 1.09x | +| two_scale | sorted_near_start | 64 | 16 | 220 ns | 310 ns | 230 ns | 520 ns | 320 ns | 240 ns | 289 ns | Linear (220 ns) | 1.09x | +| two_scale | sorted_near_start | 64 | 64 | 630 ns | 980 ns | 780 ns | 1.8 μs | 1.1 μs | 650 ns | 990 ns | Linear (630 ns) | 1.03x | +| two_scale | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.0 μs | 4.4 μs | 2.1 μs | 4.0 μs | Linear (2.1 μs) | 1.01x | +| two_scale | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.8 μs | 27.7 μs | 16.9 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.01x | +| two_scale | sorted_near_start | 64 | 4096 | 31.4 μs | 55.6 μs | 42.6 μs | 111.3 μs | 66.2 μs | 31.4 μs | 60.3 μs | Linear (31.4 μs) | 1.00x | +| two_scale | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_near_start | 256 | 4 | 270 ns | 130 ns | 110 ns | 220 ns | 129 ns | 290 ns | 100 ns | ExpFromLeft (110 ns) | 2.64x | +| two_scale | sorted_near_start | 256 | 16 | 540 ns | 390 ns | 320 ns | 670 ns | 380 ns | 290 ns | 359 ns | ExpFromLeft (320 ns) | 0.91x | +| two_scale | sorted_near_start | 256 | 64 | 920 ns | 1.1 μs | 810 ns | 2.6 μs | 1.5 μs | 940 ns | 1.3 μs | ExpFromLeft (810 ns) | 1.16x | +| two_scale | sorted_near_start | 256 | 256 | 2.5 μs | 3.9 μs | 3.0 μs | 10.3 μs | 5.7 μs | 2.5 μs | 5.2 μs | Linear (2.5 μs) | 1.01x | +| two_scale | sorted_near_start | 256 | 1024 | 8.3 μs | 14.3 μs | 10.9 μs | 40.0 μs | 22.3 μs | 8.4 μs | 20.4 μs | Linear (8.3 μs) | 1.01x | +| two_scale | sorted_near_start | 256 | 4096 | 31.6 μs | 56.3 μs | 42.8 μs | 161.3 μs | 87.8 μs | 31.6 μs | 80.2 μs | Linear (31.6 μs) | 1.00x | +| two_scale | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| two_scale | sorted_near_start | 1024 | 4 | 1.4 μs | 170 ns | 150 ns | 230 ns | 140 ns | 180 ns | 130 ns | Binary (140 ns) | 1.29x | +| two_scale | sorted_near_start | 1024 | 16 | 1.7 μs | 420 ns | 330 ns | 740 ns | 470 ns | 340 ns | 440 ns | ExpFromLeft (330 ns) | 1.03x | +| two_scale | sorted_near_start | 1024 | 64 | 2.0 μs | 1.2 μs | 870 ns | 2.9 μs | 2.1 μs | 920 ns | 2.0 μs | ExpFromLeft (870 ns) | 1.06x | +| two_scale | sorted_near_start | 1024 | 256 | 3.8 μs | 4.3 μs | 3.3 μs | 11.8 μs | 7.3 μs | 3.8 μs | 6.7 μs | ExpFromLeft (3.3 μs) | 1.13x | +| two_scale | sorted_near_start | 1024 | 1024 | 10.4 μs | 15.5 μs | 12.0 μs | 47.0 μs | 27.5 μs | 10.4 μs | 26.0 μs | Linear (10.4 μs) | 1.00x | +| two_scale | sorted_near_start | 1024 | 4096 | 33.5 μs | 57.2 μs | 43.5 μs | 188.2 μs | 108.7 μs | 35.2 μs | 102.0 μs | Linear (33.5 μs) | 1.05x | +| two_scale | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | sorted_near_start | 4096 | 4 | 3.7 μs | 210 ns | 170 ns | 270 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | +| two_scale | sorted_near_start | 4096 | 16 | 3.9 μs | 500 ns | 390 ns | 940 ns | 550 ns | 420 ns | 530 ns | ExpFromLeft (390 ns) | 1.08x | +| two_scale | sorted_near_start | 4096 | 64 | 6.5 μs | 1.4 μs | 1.1 μs | 3.7 μs | 2.4 μs | 1.1 μs | 2.3 μs | ExpFromLeft (1.1 μs) | 1.04x | +| two_scale | sorted_near_start | 4096 | 256 | 8.1 μs | 4.6 μs | 3.4 μs | 14.6 μs | 10.1 μs | 3.5 μs | 9.2 μs | ExpFromLeft (3.4 μs) | 1.03x | +| two_scale | sorted_near_start | 4096 | 1024 | 15.9 μs | 17.7 μs | 13.6 μs | 62.2 μs | 40.3 μs | 15.8 μs | 36.3 μs | ExpFromLeft (13.6 μs) | 1.16x | +| two_scale | sorted_near_start | 4096 | 4096 | 41.8 μs | 61.9 μs | 48.2 μs | 241.8 μs | 152.5 μs | 41.7 μs | 138.1 μs | Linear (41.8 μs) | 1.00x | +| two_scale | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | sorted_near_start | 16384 | 4 | 20.5 μs | 220 ns | 190 ns | 310 ns | 170 ns | 230 ns | 170 ns | Binary (170 ns) | 1.35x | +| two_scale | sorted_near_start | 16384 | 16 | 22.6 μs | 630 ns | 510 ns | 1.1 μs | 640 ns | 510 ns | 560 ns | ExpFromLeft (510 ns) | 1.00x | +| two_scale | sorted_near_start | 16384 | 64 | 23.8 μs | 1.8 μs | 1.4 μs | 4.3 μs | 3.0 μs | 1.4 μs | 2.7 μs | ExpFromLeft (1.4 μs) | 1.02x | +| two_scale | sorted_near_start | 16384 | 256 | 25.0 μs | 5.8 μs | 4.2 μs | 17.8 μs | 16.9 μs | 4.4 μs | 16.4 μs | ExpFromLeft (4.2 μs) | 1.05x | +| two_scale | sorted_near_start | 16384 | 1024 | 33.2 μs | 20.2 μs | 14.7 μs | 82.1 μs | 70.6 μs | 15.2 μs | 64.7 μs | ExpFromLeft (14.7 μs) | 1.03x | +| two_scale | sorted_near_start | 16384 | 4096 | 68.7 μs | 75.0 μs | 71.2 μs | 348.7 μs | 237.3 μs | 69.0 μs | 227.1 μs | Linear (68.7 μs) | 1.00x | +| two_scale | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_near_start | 65536 | 4 | 53.1 μs | 250 ns | 230 ns | 350 ns | 200 ns | 240 ns | 180 ns | Binary (200 ns) | 1.20x | +| two_scale | sorted_near_start | 65536 | 16 | 86.2 μs | 820 ns | 620 ns | 1.2 μs | 670 ns | 630 ns | 620 ns | ExpFromLeft (620 ns) | 1.02x | +| two_scale | sorted_near_start | 65536 | 64 | 85.2 μs | 2.6 μs | 1.9 μs | 4.9 μs | 3.3 μs | 1.9 μs | 3.2 μs | ExpFromLeft (1.9 μs) | 1.01x | +| two_scale | sorted_near_start | 65536 | 256 | 94.1 μs | 7.6 μs | 5.8 μs | 20.8 μs | 20.6 μs | 5.8 μs | 19.1 μs | ExpFromLeft (5.8 μs) | 0.99x | +| two_scale | sorted_near_start | 65536 | 1024 | 103.4 μs | 27.1 μs | 19.4 μs | 113.9 μs | 90.7 μs | 19.7 μs | 84.3 μs | ExpFromLeft (19.4 μs) | 1.02x | +| two_scale | sorted_near_start | 65536 | 4096 | 160.5 μs | 121.3 μs | 97.6 μs | 475.2 μs | 305.4 μs | 96.3 μs | 289.0 μs | ExpFromLeft (97.6 μs) | 0.99x | +| two_scale | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| two_scale | sorted_arithmetic | 16 | 4 | 100 ns | 110 ns | 100 ns | 159 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| two_scale | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 220 ns | 530 ns | 240 ns | 200 ns | 200 ns | Linear (190 ns) | 1.05x | +| two_scale | sorted_arithmetic | 16 | 64 | 570 ns | 1.0 μs | 770 ns | 2.1 μs | 910 ns | 600 ns | 800 ns | Linear (570 ns) | 1.05x | +| two_scale | sorted_arithmetic | 16 | 256 | 2.2 μs | 3.6 μs | 2.8 μs | 8.6 μs | 3.2 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.01x | +| two_scale | sorted_arithmetic | 16 | 1024 | 7.9 μs | 13.7 μs | 10.7 μs | 32.7 μs | 12.5 μs | 7.9 μs | 10.5 μs | Linear (7.9 μs) | 1.00x | +| two_scale | sorted_arithmetic | 16 | 4096 | 30.9 μs | 54.2 μs | 42.2 μs | 128.6 μs | 49.2 μs | 31.0 μs | 42.3 μs | Linear (30.9 μs) | 1.00x | +| two_scale | sorted_arithmetic | 64 | 1 | 60 ns | 60 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| two_scale | sorted_arithmetic | 64 | 4 | 170 ns | 140 ns | 130 ns | 180 ns | 110 ns | 170 ns | 100 ns | Binary (110 ns) | 1.55x | +| two_scale | sorted_arithmetic | 64 | 16 | 260 ns | 360 ns | 250 ns | 680 ns | 300 ns | 280 ns | 270 ns | ExpFromLeft (250 ns) | 1.12x | +| two_scale | sorted_arithmetic | 64 | 64 | 630 ns | 1.0 μs | 740 ns | 2.6 μs | 1.4 μs | 660 ns | 1.3 μs | Linear (630 ns) | 1.05x | +| two_scale | sorted_arithmetic | 64 | 256 | 2.4 μs | 4.0 μs | 3.1 μs | 11.0 μs | 4.8 μs | 2.5 μs | 4.3 μs | Linear (2.4 μs) | 1.00x | +| two_scale | sorted_arithmetic | 64 | 1024 | 8.5 μs | 14.3 μs | 11.1 μs | 42.9 μs | 17.4 μs | 8.5 μs | 15.2 μs | Linear (8.5 μs) | 1.00x | +| two_scale | sorted_arithmetic | 64 | 4096 | 31.5 μs | 55.3 μs | 42.7 μs | 165.7 μs | 67.6 μs | 31.5 μs | 59.7 μs | Linear (31.5 μs) | 1.00x | +| two_scale | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_arithmetic | 256 | 4 | 510 ns | 180 ns | 150 ns | 190 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | +| two_scale | sorted_arithmetic | 256 | 16 | 570 ns | 460 ns | 380 ns | 800 ns | 370 ns | 399 ns | 340 ns | Binary (370 ns) | 1.08x | +| two_scale | sorted_arithmetic | 256 | 64 | 920 ns | 1.2 μs | 860 ns | 3.2 μs | 1.8 μs | 959 ns | 1.5 μs | ExpFromLeft (860 ns) | 1.12x | +| two_scale | sorted_arithmetic | 256 | 256 | 2.5 μs | 4.0 μs | 2.8 μs | 13.6 μs | 6.5 μs | 2.5 μs | 6.0 μs | Linear (2.5 μs) | 0.99x | +| two_scale | sorted_arithmetic | 256 | 1024 | 9.7 μs | 15.7 μs | 12.3 μs | 58.1 μs | 23.9 μs | 9.7 μs | 21.9 μs | Linear (9.7 μs) | 1.00x | +| two_scale | sorted_arithmetic | 256 | 4096 | 33.7 μs | 57.4 μs | 44.3 μs | 212.8 μs | 88.4 μs | 33.7 μs | 80.3 μs | Linear (33.7 μs) | 1.00x | +| two_scale | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| two_scale | sorted_arithmetic | 1024 | 4 | 1.6 μs | 200 ns | 180 ns | 210 ns | 150 ns | 190 ns | 130 ns | Binary (150 ns) | 1.27x | +| two_scale | sorted_arithmetic | 1024 | 16 | 1.9 μs | 610 ns | 480 ns | 930 ns | 450 ns | 500 ns | 420 ns | Binary (450 ns) | 1.11x | +| two_scale | sorted_arithmetic | 1024 | 64 | 2.1 μs | 1.7 μs | 1.3 μs | 3.8 μs | 1.8 μs | 1.3 μs | 1.6 μs | ExpFromLeft (1.3 μs) | 1.03x | +| two_scale | sorted_arithmetic | 1024 | 256 | 3.5 μs | 4.9 μs | 3.3 μs | 16.2 μs | 8.2 μs | 3.5 μs | 8.0 μs | ExpFromLeft (3.3 μs) | 1.07x | +| two_scale | sorted_arithmetic | 1024 | 1024 | 10.4 μs | 17.1 μs | 12.1 μs | 74.2 μs | 36.3 μs | 10.6 μs | 34.4 μs | Linear (10.4 μs) | 1.03x | +| two_scale | sorted_arithmetic | 1024 | 4096 | 41.3 μs | 63.9 μs | 50.2 μs | 301.8 μs | 121.7 μs | 41.2 μs | 116.4 μs | Linear (41.3 μs) | 1.00x | +| two_scale | sorted_arithmetic | 4096 | 1 | 70 ns | 90 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | sorted_arithmetic | 4096 | 4 | 6.0 μs | 240 ns | 200 ns | 230 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | +| two_scale | sorted_arithmetic | 4096 | 16 | 6.4 μs | 740 ns | 590 ns | 1.1 μs | 520 ns | 600 ns | 490 ns | Binary (520 ns) | 1.15x | +| two_scale | sorted_arithmetic | 4096 | 64 | 7.8 μs | 2.2 μs | 1.7 μs | 4.5 μs | 2.0 μs | 1.8 μs | 1.9 μs | ExpFromLeft (1.7 μs) | 1.02x | +| two_scale | sorted_arithmetic | 4096 | 256 | 8.3 μs | 6.6 μs | 5.2 μs | 18.9 μs | 11.4 μs | 5.3 μs | 11.0 μs | ExpFromLeft (5.2 μs) | 1.03x | +| two_scale | sorted_arithmetic | 4096 | 1024 | 14.8 μs | 20.6 μs | 13.6 μs | 100.8 μs | 84.5 μs | 14.8 μs | 76.9 μs | ExpFromLeft (13.6 μs) | 1.09x | +| two_scale | sorted_arithmetic | 4096 | 4096 | 57.3 μs | 81.3 μs | 63.1 μs | 424.2 μs | 227.0 μs | 57.2 μs | 225.1 μs | Linear (57.3 μs) | 1.00x | +| two_scale | sorted_arithmetic | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | sorted_arithmetic | 16384 | 4 | 23.6 μs | 270 ns | 220 ns | 260 ns | 180 ns | 240 ns | 170 ns | Binary (180 ns) | 1.33x | +| two_scale | sorted_arithmetic | 16384 | 16 | 24.2 μs | 900 ns | 679 ns | 1.2 μs | 610 ns | 690 ns | 570 ns | Binary (610 ns) | 1.13x | +| two_scale | sorted_arithmetic | 16384 | 64 | 25.7 μs | 2.9 μs | 2.2 μs | 5.1 μs | 2.5 μs | 2.2 μs | 2.3 μs | ExpFromLeft (2.2 μs) | 1.01x | +| two_scale | sorted_arithmetic | 16384 | 256 | 30.6 μs | 9.0 μs | 6.8 μs | 22.5 μs | 15.6 μs | 6.7 μs | 14.5 μs | ExpFromLeft (6.8 μs) | 1.00x | +| two_scale | sorted_arithmetic | 16384 | 1024 | 37.0 μs | 29.2 μs | 23.4 μs | 134.1 μs | 114.7 μs | 23.2 μs | 112.8 μs | ExpFromLeft (23.4 μs) | 0.99x | +| two_scale | sorted_arithmetic | 16384 | 4096 | 99.8 μs | 117.3 μs | 87.3 μs | 547.2 μs | 354.3 μs | 93.9 μs | 341.4 μs | ExpFromLeft (87.3 μs) | 1.08x | +| two_scale | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_arithmetic | 65536 | 4 | 93.1 μs | 310 ns | 240 ns | 270 ns | 200 ns | 270 ns | 190 ns | Binary (200 ns) | 1.35x | +| two_scale | sorted_arithmetic | 65536 | 16 | 93.6 μs | 1.1 μs | 760 ns | 1.4 μs | 710 ns | 790 ns | 660 ns | Binary (710 ns) | 1.11x | +| two_scale | sorted_arithmetic | 65536 | 64 | 95.4 μs | 3.6 μs | 2.7 μs | 5.9 μs | 3.0 μs | 2.7 μs | 2.8 μs | ExpFromLeft (2.7 μs) | 1.01x | +| two_scale | sorted_arithmetic | 65536 | 256 | 100.3 μs | 11.7 μs | 8.9 μs | 27.7 μs | 18.4 μs | 9.2 μs | 12.9 μs | ExpFromLeft (8.9 μs) | 1.04x | +| two_scale | sorted_arithmetic | 65536 | 1024 | 118.7 μs | 42.9 μs | 32.1 μs | 183.2 μs | 141.0 μs | 30.3 μs | 143.4 μs | ExpFromLeft (32.1 μs) | 0.94x | +| two_scale | sorted_arithmetic | 65536 | 4096 | 195.6 μs | 190.8 μs | 153.7 μs | 699.3 μs | 455.7 μs | 152.3 μs | 453.8 μs | ExpFromLeft (153.7 μs) | 0.99x | +| two_scale | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| two_scale | sorted_geometric | 16 | 4 | 90 ns | 110 ns | 110 ns | 170 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | +| two_scale | sorted_geometric | 16 | 16 | 190 ns | 290 ns | 220 ns | 610 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | +| two_scale | sorted_geometric | 16 | 64 | 580 ns | 1.0 μs | 770 ns | 2.3 μs | 860 ns | 610 ns | 700 ns | Linear (580 ns) | 1.05x | +| two_scale | sorted_geometric | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 9.1 μs | 3.1 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.02x | +| two_scale | sorted_geometric | 16 | 1024 | 8.0 μs | 14.1 μs | 10.7 μs | 35.9 μs | 12.2 μs | 8.0 μs | 10.3 μs | Linear (8.0 μs) | 1.00x | +| two_scale | sorted_geometric | 16 | 4096 | 31.1 μs | 55.4 μs | 42.3 μs | 140.4 μs | 48.0 μs | 31.1 μs | 39.9 μs | Linear (31.1 μs) | 1.00x | +| two_scale | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| two_scale | sorted_geometric | 64 | 4 | 170 ns | 140 ns | 130 ns | 180 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | +| two_scale | sorted_geometric | 64 | 16 | 260 ns | 340 ns | 270 ns | 720 ns | 310 ns | 280 ns | 260 ns | Linear (260 ns) | 1.08x | +| two_scale | sorted_geometric | 64 | 64 | 660 ns | 1.0 μs | 800 ns | 3.0 μs | 1.2 μs | 670 ns | 1.1 μs | Linear (660 ns) | 1.02x | +| two_scale | sorted_geometric | 64 | 256 | 2.3 μs | 3.8 μs | 2.9 μs | 11.7 μs | 4.8 μs | 2.3 μs | 4.2 μs | Linear (2.3 μs) | 1.02x | +| two_scale | sorted_geometric | 64 | 1024 | 8.2 μs | 14.6 μs | 11.1 μs | 46.8 μs | 17.6 μs | 8.2 μs | 15.3 μs | Linear (8.2 μs) | 1.00x | +| two_scale | sorted_geometric | 64 | 4096 | 32.1 μs | 56.5 μs | 43.1 μs | 183.2 μs | 73.8 μs | 45.2 μs | 63.8 μs | Linear (32.1 μs) | 1.41x | +| two_scale | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 70 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_geometric | 256 | 4 | 530 ns | 170 ns | 160 ns | 210 ns | 130 ns | 180 ns | 110 ns | Binary (130 ns) | 1.38x | +| two_scale | sorted_geometric | 256 | 16 | 540 ns | 420 ns | 350 ns | 860 ns | 380 ns | 360 ns | 340 ns | ExpFromLeft (350 ns) | 1.03x | +| two_scale | sorted_geometric | 256 | 64 | 920 ns | 1.2 μs | 920 ns | 3.6 μs | 1.5 μs | 930 ns | 1.3 μs | ExpFromLeft (920 ns) | 1.01x | +| two_scale | sorted_geometric | 256 | 256 | 2.5 μs | 4.1 μs | 3.1 μs | 14.4 μs | 6.1 μs | 3.4 μs | 5.7 μs | Linear (2.5 μs) | 1.32x | +| two_scale | sorted_geometric | 256 | 1024 | 8.8 μs | 15.3 μs | 11.4 μs | 58.9 μs | 23.8 μs | 8.8 μs | 21.6 μs | Linear (8.8 μs) | 1.00x | +| two_scale | sorted_geometric | 256 | 4096 | 33.8 μs | 58.7 μs | 44.9 μs | 229.9 μs | 90.3 μs | 33.7 μs | 82.3 μs | Linear (33.8 μs) | 1.00x | +| two_scale | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_geometric | 1024 | 4 | 1.6 μs | 210 ns | 170 ns | 230 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| two_scale | sorted_geometric | 1024 | 16 | 1.8 μs | 520 ns | 400 ns | 990 ns | 460 ns | 440 ns | 390 ns | ExpFromLeft (400 ns) | 1.10x | +| two_scale | sorted_geometric | 1024 | 64 | 2.3 μs | 1.5 μs | 1.1 μs | 4.0 μs | 1.8 μs | 1.2 μs | 1.6 μs | ExpFromLeft (1.1 μs) | 1.05x | +| two_scale | sorted_geometric | 1024 | 256 | 3.6 μs | 4.9 μs | 3.6 μs | 16.6 μs | 7.5 μs | 3.7 μs | 6.9 μs | Linear (3.6 μs) | 1.01x | +| two_scale | sorted_geometric | 1024 | 1024 | 10.0 μs | 16.6 μs | 12.3 μs | 71.4 μs | 32.7 μs | 10.3 μs | 30.1 μs | Linear (10.0 μs) | 1.03x | +| two_scale | sorted_geometric | 1024 | 4096 | 48.3 μs | 62.4 μs | 46.4 μs | 292.4 μs | 144.9 μs | 36.3 μs | 140.7 μs | ExpFromLeft (46.4 μs) | 0.78x | +| two_scale | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| two_scale | sorted_geometric | 4096 | 4 | 6.0 μs | 230 ns | 190 ns | 240 ns | 160 ns | 240 ns | 150 ns | Binary (160 ns) | 1.50x | +| two_scale | sorted_geometric | 4096 | 16 | 6.3 μs | 660 ns | 490 ns | 1.1 μs | 520 ns | 520 ns | 490 ns | ExpFromLeft (490 ns) | 1.06x | +| two_scale | sorted_geometric | 4096 | 64 | 7.1 μs | 2.0 μs | 1.5 μs | 4.7 μs | 2.1 μs | 1.5 μs | 2.1 μs | ExpFromLeft (1.5 μs) | 1.04x | +| two_scale | sorted_geometric | 4096 | 256 | 9.3 μs | 6.2 μs | 4.5 μs | 19.3 μs | 9.7 μs | 4.7 μs | 9.3 μs | ExpFromLeft (4.5 μs) | 1.02x | +| two_scale | sorted_geometric | 4096 | 1024 | 16.1 μs | 20.6 μs | 15.6 μs | 92.4 μs | 54.0 μs | 15.7 μs | 46.7 μs | ExpFromLeft (15.6 μs) | 1.00x | +| two_scale | sorted_geometric | 4096 | 4096 | 47.1 μs | 74.6 μs | 55.4 μs | 395.4 μs | 228.1 μs | 46.0 μs | 219.4 μs | Linear (47.1 μs) | 0.98x | +| two_scale | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| two_scale | sorted_geometric | 16384 | 4 | 23.4 μs | 260 ns | 230 ns | 270 ns | 180 ns | 260 ns | 170 ns | Binary (180 ns) | 1.44x | +| two_scale | sorted_geometric | 16384 | 16 | 23.8 μs | 790 ns | 620 ns | 1.3 μs | 600 ns | 640 ns | 560 ns | Binary (600 ns) | 1.07x | +| two_scale | sorted_geometric | 16384 | 64 | 24.9 μs | 2.6 μs | 1.9 μs | 5.3 μs | 2.8 μs | 2.0 μs | 2.6 μs | ExpFromLeft (1.9 μs) | 1.03x | +| two_scale | sorted_geometric | 16384 | 256 | 28.1 μs | 7.9 μs | 5.8 μs | 22.7 μs | 15.6 μs | 5.9 μs | 14.9 μs | ExpFromLeft (5.8 μs) | 1.01x | +| two_scale | sorted_geometric | 16384 | 1024 | 38.3 μs | 27.4 μs | 20.3 μs | 118.9 μs | 86.0 μs | 21.1 μs | 81.6 μs | ExpFromLeft (20.3 μs) | 1.04x | +| two_scale | sorted_geometric | 16384 | 4096 | 80.6 μs | 107.1 μs | 81.4 μs | 503.8 μs | 309.8 μs | 78.9 μs | 309.0 μs | Linear (80.6 μs) | 0.98x | +| two_scale | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 69 ns | 80 ns | 80 ns | 70 ns | InterpSearch (69 ns) | 1.16x | +| two_scale | sorted_geometric | 65536 | 4 | 94.2 μs | 300 ns | 240 ns | 280 ns | 200 ns | 270 ns | 180 ns | Binary (200 ns) | 1.35x | +| two_scale | sorted_geometric | 65536 | 16 | 95.0 μs | 950 ns | 750 ns | 1.4 μs | 690 ns | 770 ns | 630 ns | Binary (690 ns) | 1.12x | +| two_scale | sorted_geometric | 65536 | 64 | 106.4 μs | 3.2 μs | 2.8 μs | 6.1 μs | 3.4 μs | 2.4 μs | 3.0 μs | ExpFromLeft (2.8 μs) | 0.87x | +| two_scale | sorted_geometric | 65536 | 256 | 96.9 μs | 10.1 μs | 7.8 μs | 27.9 μs | 19.4 μs | 7.7 μs | 17.9 μs | ExpFromLeft (7.8 μs) | 0.98x | +| two_scale | sorted_geometric | 65536 | 1024 | 110.7 μs | 41.0 μs | 30.6 μs | 178.1 μs | 114.7 μs | 30.3 μs | 113.1 μs | ExpFromLeft (30.6 μs) | 0.99x | +| two_scale | sorted_geometric | 65536 | 4096 | 160.6 μs | 170.4 μs | 138.1 μs | 668.6 μs | 401.4 μs | 138.0 μs | 397.9 μs | ExpFromLeft (138.1 μs) | 1.00x | +| two_scale | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| two_scale | sorted_bimodal | 16 | 4 | 90 ns | 110 ns | 100 ns | 170 ns | 90 ns | 100 ns | 80 ns | Binary (90 ns) | 1.11x | +| two_scale | sorted_bimodal | 16 | 16 | 190 ns | 290 ns | 240 ns | 570 ns | 250 ns | 200 ns | 200 ns | Linear (190 ns) | 1.05x | +| two_scale | sorted_bimodal | 16 | 64 | 570 ns | 970 ns | 770 ns | 2.2 μs | 880 ns | 600 ns | 780 ns | Linear (570 ns) | 1.05x | +| two_scale | sorted_bimodal | 16 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 8.2 μs | 3.3 μs | 2.1 μs | 2.8 μs | Linear (2.1 μs) | 1.01x | +| two_scale | sorted_bimodal | 16 | 1024 | 8.0 μs | 14.2 μs | 10.6 μs | 32.2 μs | 12.8 μs | 8.0 μs | 10.9 μs | Linear (8.0 μs) | 1.00x | +| two_scale | sorted_bimodal | 16 | 4096 | 31.3 μs | 56.5 μs | 42.1 μs | 126.5 μs | 49.9 μs | 30.9 μs | 42.5 μs | Linear (31.3 μs) | 0.99x | +| two_scale | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_bimodal | 64 | 4 | 120 ns | 120 ns | 110 ns | 190 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | +| two_scale | sorted_bimodal | 64 | 16 | 220 ns | 300 ns | 230 ns | 649 ns | 310 ns | 240 ns | 280 ns | Linear (220 ns) | 1.09x | +| two_scale | sorted_bimodal | 64 | 64 | 610 ns | 970 ns | 770 ns | 2.6 μs | 1.3 μs | 640 ns | 1.1 μs | Linear (610 ns) | 1.05x | +| two_scale | sorted_bimodal | 64 | 256 | 2.2 μs | 3.5 μs | 2.9 μs | 10.0 μs | 4.6 μs | 2.2 μs | 4.0 μs | Linear (2.2 μs) | 1.01x | +| two_scale | sorted_bimodal | 64 | 1024 | 8.0 μs | 13.5 μs | 10.7 μs | 38.9 μs | 17.6 μs | 8.0 μs | 15.6 μs | Linear (8.0 μs) | 1.00x | +| two_scale | sorted_bimodal | 64 | 4096 | 31.0 μs | 53.3 μs | 42.3 μs | 154.1 μs | 70.1 μs | 31.1 μs | 61.3 μs | Linear (31.0 μs) | 1.00x | +| two_scale | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_bimodal | 256 | 4 | 270 ns | 140 ns | 140 ns | 210 ns | 120 ns | 160 ns | 110 ns | Binary (120 ns) | 1.33x | +| two_scale | sorted_bimodal | 256 | 16 | 370 ns | 350 ns | 270 ns | 720 ns | 450 ns | 280 ns | 420 ns | ExpFromLeft (270 ns) | 1.04x | +| two_scale | sorted_bimodal | 256 | 64 | 870 ns | 1.0 μs | 770 ns | 2.8 μs | 1.7 μs | 870 ns | 1.5 μs | ExpFromLeft (770 ns) | 1.13x | +| two_scale | sorted_bimodal | 256 | 256 | 2.6 μs | 4.0 μs | 3.2 μs | 11.8 μs | 5.9 μs | 2.6 μs | 5.5 μs | Linear (2.6 μs) | 1.00x | +| two_scale | sorted_bimodal | 256 | 1024 | 8.7 μs | 14.3 μs | 11.2 μs | 44.9 μs | 22.3 μs | 8.7 μs | 20.3 μs | Linear (8.7 μs) | 1.00x | +| two_scale | sorted_bimodal | 256 | 4096 | 31.8 μs | 55.4 μs | 42.8 μs | 174.2 μs | 87.0 μs | 31.8 μs | 79.0 μs | Linear (31.8 μs) | 1.00x | +| two_scale | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_bimodal | 1024 | 4 | 850 ns | 190 ns | 160 ns | 240 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | +| two_scale | sorted_bimodal | 1024 | 16 | 870 ns | 420 ns | 350 ns | 900 ns | 490 ns | 360 ns | 450 ns | ExpFromLeft (350 ns) | 1.03x | +| two_scale | sorted_bimodal | 1024 | 64 | 1.6 μs | 1.2 μs | 900 ns | 3.5 μs | 2.0 μs | 940 ns | 1.9 μs | ExpFromLeft (900 ns) | 1.04x | +| two_scale | sorted_bimodal | 1024 | 256 | 2.9 μs | 4.0 μs | 2.9 μs | 14.6 μs | 7.9 μs | 2.9 μs | 7.5 μs | Linear (2.9 μs) | 1.01x | +| two_scale | sorted_bimodal | 1024 | 1024 | 10.6 μs | 15.7 μs | 12.3 μs | 60.1 μs | 28.4 μs | 10.6 μs | 26.3 μs | Linear (10.6 μs) | 1.00x | +| two_scale | sorted_bimodal | 1024 | 4096 | 34.8 μs | 57.6 μs | 44.6 μs | 228.2 μs | 108.0 μs | 34.7 μs | 99.7 μs | Linear (34.8 μs) | 1.00x | +| two_scale | sorted_bimodal | 4096 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 69 ns | 70 ns | 60 ns | Binary (69 ns) | 1.01x | +| two_scale | sorted_bimodal | 4096 | 4 | 3.0 μs | 200 ns | 170 ns | 290 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | +| two_scale | sorted_bimodal | 4096 | 16 | 3.2 μs | 500 ns | 410 ns | 1.1 μs | 580 ns | 430 ns | 550 ns | ExpFromLeft (410 ns) | 1.05x | +| two_scale | sorted_bimodal | 4096 | 64 | 3.9 μs | 1.5 μs | 1.1 μs | 4.2 μs | 2.4 μs | 1.2 μs | 2.4 μs | ExpFromLeft (1.1 μs) | 1.03x | +| two_scale | sorted_bimodal | 4096 | 256 | 7.0 μs | 4.5 μs | 3.1 μs | 17.2 μs | 11.4 μs | 3.3 μs | 10.5 μs | ExpFromLeft (3.1 μs) | 1.04x | +| two_scale | sorted_bimodal | 4096 | 1024 | 13.3 μs | 17.0 μs | 12.7 μs | 74.5 μs | 42.8 μs | 13.2 μs | 37.7 μs | ExpFromLeft (12.7 μs) | 1.04x | +| two_scale | sorted_bimodal | 4096 | 4096 | 43.4 μs | 61.9 μs | 48.6 μs | 298.1 μs | 146.5 μs | 43.2 μs | 130.7 μs | Linear (43.4 μs) | 1.00x | +| two_scale | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| two_scale | sorted_bimodal | 16384 | 4 | 9.9 μs | 230 ns | 200 ns | 320 ns | 180 ns | 220 ns | 160 ns | Binary (180 ns) | 1.22x | +| two_scale | sorted_bimodal | 16384 | 16 | 11.4 μs | 660 ns | 520 ns | 1.2 μs | 620 ns | 530 ns | 570 ns | ExpFromLeft (520 ns) | 1.02x | +| two_scale | sorted_bimodal | 16384 | 64 | 12.7 μs | 2.0 μs | 1.5 μs | 4.9 μs | 2.9 μs | 1.6 μs | 2.7 μs | ExpFromLeft (1.5 μs) | 1.02x | +| two_scale | sorted_bimodal | 16384 | 256 | 18.3 μs | 5.8 μs | 4.4 μs | 19.8 μs | 15.8 μs | 4.4 μs | 14.7 μs | ExpFromLeft (4.4 μs) | 1.01x | +| two_scale | sorted_bimodal | 16384 | 1024 | 30.6 μs | 19.9 μs | 14.5 μs | 98.0 μs | 74.5 μs | 14.2 μs | 72.8 μs | ExpFromLeft (14.5 μs) | 0.98x | +| two_scale | sorted_bimodal | 16384 | 4096 | 69.1 μs | 75.7 μs | 58.9 μs | 414.5 μs | 227.7 μs | 80.5 μs | 222.6 μs | ExpFromLeft (58.9 μs) | 1.37x | +| two_scale | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_bimodal | 65536 | 4 | 84.0 μs | 300 ns | 230 ns | 350 ns | 200 ns | 260 ns | 180 ns | Binary (200 ns) | 1.30x | +| two_scale | sorted_bimodal | 65536 | 16 | 92.4 μs | 890 ns | 650 ns | 1.4 μs | 760 ns | 680 ns | 710 ns | ExpFromLeft (650 ns) | 1.05x | +| two_scale | sorted_bimodal | 65536 | 64 | 48.3 μs | 2.6 μs | 2.0 μs | 5.5 μs | 2.9 μs | 2.0 μs | 2.8 μs | ExpFromLeft (2.0 μs) | 1.01x | +| two_scale | sorted_bimodal | 65536 | 256 | 92.5 μs | 7.9 μs | 6.1 μs | 24.2 μs | 20.3 μs | 6.1 μs | 19.1 μs | ExpFromLeft (6.1 μs) | 1.00x | +| two_scale | sorted_bimodal | 65536 | 1024 | 101.2 μs | 26.4 μs | 19.9 μs | 140.7 μs | 95.5 μs | 19.5 μs | 95.3 μs | ExpFromLeft (19.9 μs) | 0.98x | +| two_scale | sorted_bimodal | 65536 | 4096 | 172.4 μs | 118.0 μs | 93.2 μs | 559.9 μs | 286.0 μs | 91.9 μs | 285.8 μs | ExpFromLeft (93.2 μs) | 0.99x | +| two_scale | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| two_scale | sorted_repeated | 16 | 4 | 79 ns | 90 ns | 100 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (79 ns) | 1.27x | +| two_scale | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 220 ns | 620 ns | 220 ns | 200 ns | 180 ns | Linear (170 ns) | 1.18x | +| two_scale | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 680 ns | 2.4 μs | 790 ns | 570 ns | 630 ns | Linear (550 ns) | 1.04x | +| two_scale | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 9.3 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.02x | +| two_scale | sorted_repeated | 16 | 1024 | 7.7 μs | 13.7 μs | 10.0 μs | 36.9 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.00x | +| two_scale | sorted_repeated | 16 | 4096 | 30.8 μs | 54.9 μs | 39.3 μs | 147.5 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_repeated | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 90 ns | 230 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| two_scale | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 220 ns | 810 ns | 310 ns | 200 ns | 270 ns | Linear (170 ns) | 1.18x | +| two_scale | sorted_repeated | 64 | 64 | 559 ns | 920 ns | 709 ns | 3.1 μs | 1.1 μs | 580 ns | 920 ns | Linear (559 ns) | 1.04x | +| two_scale | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 12.1 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | +| two_scale | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 48.0 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | +| two_scale | sorted_repeated | 64 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 191.8 μs | 66.5 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 59 ns | 60 ns | 50 ns | Binary (59 ns) | 1.02x | +| two_scale | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 100 ns | 260 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| two_scale | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 950 ns | 390 ns | 190 ns | 340 ns | Linear (170 ns) | 1.12x | +| two_scale | sorted_repeated | 256 | 64 | 550 ns | 920 ns | 700 ns | 3.7 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | +| two_scale | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 14.4 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| two_scale | sorted_repeated | 256 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 57.9 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | +| two_scale | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 231.4 μs | 86.1 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 290 ns | 150 ns | 110 ns | 120 ns | Linear (90 ns) | 1.22x | +| two_scale | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 220 ns | 1.1 μs | 450 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | +| two_scale | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 4.1 μs | 1.7 μs | 580 ns | 1.5 μs | Linear (560 ns) | 1.04x | +| two_scale | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 16.3 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| two_scale | sorted_repeated | 1024 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 64.8 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | +| two_scale | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.1 μs | 39.3 μs | 259.6 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 360 ns | 170 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | +| two_scale | sorted_repeated | 4096 | 16 | 180 ns | 300 ns | 220 ns | 1.3 μs | 530 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | +| two_scale | sorted_repeated | 4096 | 64 | 710 ns | 1.1 μs | 690 ns | 5.0 μs | 2.0 μs | 600 ns | 1.8 μs | ExpFromLeft (690 ns) | 0.87x | +| two_scale | sorted_repeated | 4096 | 256 | 2.0 μs | 3.7 μs | 2.5 μs | 19.7 μs | 7.8 μs | 2.1 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| two_scale | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 77.9 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | +| two_scale | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.1 μs | 311.8 μs | 124.4 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | sorted_repeated | 16384 | 4 | 90 ns | 120 ns | 110 ns | 390 ns | 180 ns | 120 ns | 160 ns | Linear (90 ns) | 1.33x | +| two_scale | sorted_repeated | 16384 | 16 | 190 ns | 290 ns | 230 ns | 1.4 μs | 610 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | +| two_scale | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 710 ns | 5.4 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | +| two_scale | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 21.6 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | +| two_scale | sorted_repeated | 16384 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 86.1 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.7 μs) | 1.01x | +| two_scale | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.1 μs | 39.6 μs | 344.5 μs | 144.0 μs | 30.8 μs | 133.7 μs | Linear (30.8 μs) | 1.00x | +| two_scale | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 430 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| two_scale | sorted_repeated | 65536 | 16 | 190 ns | 300 ns | 230 ns | 1.6 μs | 690 ns | 210 ns | 630 ns | Linear (190 ns) | 1.11x | +| two_scale | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 710 ns | 6.1 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| two_scale | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 24.2 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.02x | +| two_scale | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 96.8 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.01x | +| two_scale | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 384.6 μs | 163.2 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| two_scale | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| two_scale | unsorted | 16 | 4 | 100 ns | 100 ns | 100 ns | 100 ns | 90 ns | 100 ns | 80 ns | Binary (90 ns) | 1.11x | +| two_scale | unsorted | 16 | 16 | 210 ns | 200 ns | 210 ns | 210 ns | 210 ns | 220 ns | 190 ns | Gallop (200 ns) | 1.10x | +| two_scale | unsorted | 16 | 64 | 710 ns | 720 ns | 700 ns | 700 ns | 710 ns | 710 ns | 750 ns | InterpSearch (700 ns) | 1.01x | +| two_scale | unsorted | 16 | 256 | 3.5 μs | 3.5 μs | 3.5 μs | 3.4 μs | 3.3 μs | 3.4 μs | 3.4 μs | Binary (3.3 μs) | 1.02x | +| two_scale | unsorted | 16 | 1024 | 18.4 μs | 18.1 μs | 18.2 μs | 18.2 μs | 18.1 μs | 18.1 μs | 18.4 μs | Binary (18.1 μs) | 1.00x | +| two_scale | unsorted | 16 | 4096 | 98.5 μs | 97.8 μs | 102.3 μs | 99.2 μs | 97.9 μs | 98.4 μs | 98.7 μs | Gallop (97.8 μs) | 1.01x | +| two_scale | unsorted | 64 | 1 | 60 ns | 50 ns | 50 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| two_scale | unsorted | 64 | 4 | 100 ns | 110 ns | 100 ns | 110 ns | 100 ns | 110 ns | 90 ns | ExpFromLeft (100 ns) | 1.10x | +| two_scale | unsorted | 64 | 16 | 280 ns | 280 ns | 280 ns | 280 ns | 270 ns | 280 ns | 260 ns | Binary (270 ns) | 1.04x | +| two_scale | unsorted | 64 | 64 | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | ExpFromLeft (1.2 μs) | 1.02x | +| two_scale | unsorted | 64 | 256 | 6.7 μs | 6.6 μs | 6.7 μs | 6.6 μs | 6.6 μs | 6.7 μs | 6.7 μs | InterpSearch (6.6 μs) | 1.01x | +| two_scale | unsorted | 64 | 1024 | 36.1 μs | 36.1 μs | 35.4 μs | 35.4 μs | 35.4 μs | 36.0 μs | 35.0 μs | Binary (35.4 μs) | 1.02x | +| two_scale | unsorted | 64 | 4096 | 166.2 μs | 165.8 μs | 165.0 μs | 165.2 μs | 164.9 μs | 165.2 μs | 169.8 μs | Binary (164.9 μs) | 1.00x | +| two_scale | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | unsorted | 256 | 4 | 130 ns | 130 ns | 130 ns | 130 ns | 120 ns | 130 ns | 110 ns | Binary (120 ns) | 1.08x | +| two_scale | unsorted | 256 | 16 | 350 ns | 350 ns | 350 ns | 350 ns | 360 ns | 350 ns | 340 ns | InterpSearch (350 ns) | 1.00x | +| two_scale | unsorted | 256 | 64 | 1.7 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | InterpSearch (1.6 μs) | 1.00x | +| two_scale | unsorted | 256 | 256 | 8.9 μs | 9.0 μs | 9.1 μs | 9.1 μs | 8.8 μs | 9.0 μs | 8.9 μs | Binary (8.8 μs) | 1.01x | +| two_scale | unsorted | 256 | 1024 | 51.8 μs | 50.6 μs | 49.8 μs | 50.7 μs | 49.6 μs | 50.1 μs | 52.3 μs | Binary (49.6 μs) | 1.01x | +| two_scale | unsorted | 256 | 4096 | 253.1 μs | 257.7 μs | 251.8 μs | 251.4 μs | 251.2 μs | 252.2 μs | 258.8 μs | Binary (251.2 μs) | 1.00x | +| two_scale | unsorted | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| two_scale | unsorted | 1024 | 4 | 140 ns | 140 ns | 150 ns | 140 ns | 140 ns | 140 ns | 129 ns | InterpSearch (140 ns) | 1.00x | +| two_scale | unsorted | 1024 | 16 | 420 ns | 420 ns | 420 ns | 430 ns | 430 ns | 430 ns | 410 ns | ExpFromLeft (420 ns) | 1.02x | +| two_scale | unsorted | 1024 | 64 | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.8 μs | Binary (1.7 μs) | 1.02x | +| two_scale | unsorted | 1024 | 256 | 9.2 μs | 9.0 μs | 8.9 μs | 8.9 μs | 8.9 μs | 8.7 μs | 9.7 μs | ExpFromLeft (8.9 μs) | 0.98x | +| two_scale | unsorted | 1024 | 1024 | 69.2 μs | 67.5 μs | 67.2 μs | 66.8 μs | 67.1 μs | 67.1 μs | 69.0 μs | InterpSearch (66.8 μs) | 1.00x | +| two_scale | unsorted | 1024 | 4096 | 339.7 μs | 340.6 μs | 337.1 μs | 334.7 μs | 334.2 μs | 334.3 μs | 340.2 μs | Binary (334.2 μs) | 1.00x | +| two_scale | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | unsorted | 4096 | 4 | 150 ns | 150 ns | 150 ns | 150 ns | 160 ns | 170 ns | 140 ns | InterpSearch (150 ns) | 1.13x | +| two_scale | unsorted | 4096 | 16 | 490 ns | 490 ns | 490 ns | 490 ns | 490 ns | 500 ns | 480 ns | InterpSearch (490 ns) | 1.02x | +| two_scale | unsorted | 4096 | 64 | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | InterpSearch (2.0 μs) | 1.02x | +| two_scale | unsorted | 4096 | 256 | 10.5 μs | 10.2 μs | 10.3 μs | 10.1 μs | 10.0 μs | 10.0 μs | 10.6 μs | Binary (10.0 μs) | 1.00x | +| two_scale | unsorted | 4096 | 1024 | 90.7 μs | 89.3 μs | 88.8 μs | 88.7 μs | 86.7 μs | 87.8 μs | 91.5 μs | Binary (86.7 μs) | 1.01x | +| two_scale | unsorted | 4096 | 4096 | 439.6 μs | 440.4 μs | 435.2 μs | 440.3 μs | 434.5 μs | 434.6 μs | 434.1 μs | Binary (434.5 μs) | 1.00x | +| two_scale | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| two_scale | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 180 ns | 180 ns | 180 ns | 160 ns | Gallop (170 ns) | 1.06x | +| two_scale | unsorted | 16384 | 16 | 630 ns | 640 ns | 640 ns | 640 ns | 620 ns | 620 ns | 630 ns | Binary (620 ns) | 1.00x | +| two_scale | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | ExpFromLeft (2.3 μs) | 1.01x | +| two_scale | unsorted | 16384 | 256 | 12.8 μs | 12.7 μs | 12.5 μs | 12.5 μs | 12.3 μs | 12.3 μs | 15.4 μs | Binary (12.3 μs) | 1.00x | +| two_scale | unsorted | 16384 | 1024 | 130.2 μs | 126.6 μs | 124.5 μs | 123.5 μs | 120.2 μs | 119.7 μs | 126.9 μs | Binary (120.2 μs) | 1.00x | +| two_scale | unsorted | 16384 | 4096 | 600.4 μs | 601.6 μs | 601.6 μs | 601.8 μs | 601.7 μs | 600.6 μs | 601.6 μs | Linear (600.4 μs) | 1.00x | +| two_scale | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| two_scale | unsorted | 65536 | 4 | 190 ns | 200 ns | 190 ns | 190 ns | 200 ns | 200 ns | 190 ns | InterpSearch (190 ns) | 1.05x | +| two_scale | unsorted | 65536 | 16 | 650 ns | 640 ns | 650 ns | 660 ns | 649 ns | 670 ns | 650 ns | Gallop (640 ns) | 1.05x | +| two_scale | unsorted | 65536 | 64 | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | ExpFromLeft (2.7 μs) | 1.01x | +| two_scale | unsorted | 65536 | 256 | 14.8 μs | 14.7 μs | 14.7 μs | 14.6 μs | 14.3 μs | 14.3 μs | 17.7 μs | Binary (14.3 μs) | 1.00x | +| two_scale | unsorted | 65536 | 1024 | 170.1 μs | 166.2 μs | 163.4 μs | 165.5 μs | 164.8 μs | 163.4 μs | 168.5 μs | ExpFromLeft (163.4 μs) | 1.00x | +| two_scale | unsorted | 65536 | 4096 | 753.3 μs | 752.6 μs | 755.3 μs | 755.4 μs | 754.4 μs | 753.0 μs | 751.9 μs | Gallop (752.6 μs) | 1.00x | +| power2 | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| power2 | sorted_uniform | 16 | 4 | 90 ns | 100 ns | 100 ns | 170 ns | 90 ns | 100 ns | 70 ns | Binary (90 ns) | 1.11x | +| power2 | sorted_uniform | 16 | 16 | 190 ns | 290 ns | 210 ns | 520 ns | 240 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| power2 | sorted_uniform | 16 | 64 | 590 ns | 1.0 μs | 750 ns | 2.1 μs | 960 ns | 620 ns | 810 ns | Linear (590 ns) | 1.05x | +| power2 | sorted_uniform | 16 | 256 | 2.2 μs | 3.8 μs | 2.9 μs | 8.4 μs | 3.3 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.00x | +| power2 | sorted_uniform | 16 | 1024 | 8.1 μs | 14.7 μs | 10.8 μs | 31.7 μs | 12.6 μs | 8.0 μs | 10.5 μs | Linear (8.1 μs) | 0.99x | +| power2 | sorted_uniform | 16 | 4096 | 31.0 μs | 54.5 μs | 42.3 μs | 121.9 μs | 48.7 μs | 31.1 μs | 41.2 μs | Linear (31.0 μs) | 1.00x | +| power2 | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 60 ns | 90 ns | 70 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | +| power2 | sorted_uniform | 64 | 4 | 140 ns | 140 ns | 140 ns | 190 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | +| power2 | sorted_uniform | 64 | 16 | 250 ns | 340 ns | 270 ns | 640 ns | 340 ns | 280 ns | 310 ns | Linear (250 ns) | 1.12x | +| power2 | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 750 ns | 2.5 μs | 1.5 μs | 670 ns | 1.4 μs | Linear (630 ns) | 1.06x | +| power2 | sorted_uniform | 64 | 256 | 2.3 μs | 4.1 μs | 3.1 μs | 10.6 μs | 5.2 μs | 2.3 μs | 4.5 μs | Linear (2.3 μs) | 1.02x | +| power2 | sorted_uniform | 64 | 1024 | 8.9 μs | 14.8 μs | 11.6 μs | 41.4 μs | 17.7 μs | 8.9 μs | 15.9 μs | Linear (8.9 μs) | 1.00x | +| power2 | sorted_uniform | 64 | 4096 | 32.1 μs | 55.6 μs | 43.1 μs | 158.4 μs | 67.6 μs | 32.1 μs | 60.2 μs | Linear (32.1 μs) | 1.00x | +| power2 | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_uniform | 256 | 4 | 330 ns | 150 ns | 140 ns | 220 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | +| power2 | sorted_uniform | 256 | 16 | 440 ns | 430 ns | 360 ns | 830 ns | 420 ns | 389 ns | 370 ns | ExpFromLeft (360 ns) | 1.08x | +| power2 | sorted_uniform | 256 | 64 | 880 ns | 1.3 μs | 930 ns | 3.1 μs | 1.6 μs | 910 ns | 1.4 μs | Linear (880 ns) | 1.03x | +| power2 | sorted_uniform | 256 | 256 | 2.4 μs | 4.1 μs | 2.8 μs | 13.4 μs | 7.6 μs | 3.2 μs | 6.8 μs | Linear (2.4 μs) | 1.35x | +| power2 | sorted_uniform | 256 | 1024 | 9.9 μs | 16.9 μs | 13.2 μs | 53.8 μs | 25.8 μs | 9.9 μs | 23.7 μs | Linear (9.9 μs) | 1.01x | +| power2 | sorted_uniform | 256 | 4096 | 35.5 μs | 59.0 μs | 46.1 μs | 203.2 μs | 90.3 μs | 35.4 μs | 83.7 μs | Linear (35.5 μs) | 1.00x | +| power2 | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| power2 | sorted_uniform | 1024 | 4 | 740 ns | 190 ns | 160 ns | 280 ns | 140 ns | 190 ns | 120 ns | Binary (140 ns) | 1.36x | +| power2 | sorted_uniform | 1024 | 16 | 1.6 μs | 590 ns | 470 ns | 960 ns | 450 ns | 490 ns | 410 ns | Binary (450 ns) | 1.09x | +| power2 | sorted_uniform | 1024 | 64 | 1.8 μs | 1.6 μs | 1.3 μs | 3.7 μs | 1.8 μs | 1.3 μs | 1.6 μs | ExpFromLeft (1.3 μs) | 1.03x | +| power2 | sorted_uniform | 1024 | 256 | 3.5 μs | 5.1 μs | 3.7 μs | 15.5 μs | 8.3 μs | 3.5 μs | 8.1 μs | Linear (3.5 μs) | 1.01x | +| power2 | sorted_uniform | 1024 | 1024 | 13.7 μs | 21.8 μs | 15.9 μs | 69.4 μs | 49.9 μs | 13.7 μs | 48.7 μs | Linear (13.7 μs) | 1.00x | +| power2 | sorted_uniform | 1024 | 4096 | 45.4 μs | 69.1 μs | 54.3 μs | 271.3 μs | 181.6 μs | 45.2 μs | 175.7 μs | Linear (45.4 μs) | 1.00x | +| power2 | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_uniform | 4096 | 4 | 3.0 μs | 220 ns | 180 ns | 310 ns | 160 ns | 210 ns | 150 ns | Binary (160 ns) | 1.31x | +| power2 | sorted_uniform | 4096 | 16 | 5.7 μs | 700 ns | 550 ns | 1.1 μs | 560 ns | 570 ns | 520 ns | ExpFromLeft (550 ns) | 1.04x | +| power2 | sorted_uniform | 4096 | 64 | 6.6 μs | 2.1 μs | 1.6 μs | 4.3 μs | 2.1 μs | 1.7 μs | 1.9 μs | ExpFromLeft (1.6 μs) | 1.04x | +| power2 | sorted_uniform | 4096 | 256 | 9.1 μs | 6.7 μs | 5.0 μs | 17.7 μs | 11.1 μs | 5.1 μs | 10.9 μs | ExpFromLeft (5.0 μs) | 1.02x | +| power2 | sorted_uniform | 4096 | 1024 | 16.9 μs | 22.9 μs | 17.0 μs | 85.0 μs | 88.9 μs | 15.7 μs | 83.4 μs | Linear (16.9 μs) | 0.93x | +| power2 | sorted_uniform | 4096 | 4096 | 64.1 μs | 90.8 μs | 67.7 μs | 371.6 μs | 286.4 μs | 62.8 μs | 281.8 μs | Linear (64.1 μs) | 0.98x | +| power2 | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_uniform | 16384 | 4 | 5.2 μs | 240 ns | 200 ns | 350 ns | 180 ns | 220 ns | 170 ns | Binary (180 ns) | 1.22x | +| power2 | sorted_uniform | 16384 | 16 | 17.5 μs | 840 ns | 660 ns | 1.3 μs | 590 ns | 670 ns | 560 ns | Binary (590 ns) | 1.14x | +| power2 | sorted_uniform | 16384 | 64 | 23.6 μs | 2.9 μs | 2.1 μs | 5.0 μs | 2.5 μs | 2.2 μs | 2.3 μs | ExpFromLeft (2.1 μs) | 1.03x | +| power2 | sorted_uniform | 16384 | 256 | 28.6 μs | 9.3 μs | 7.0 μs | 21.3 μs | 14.0 μs | 7.1 μs | 13.6 μs | ExpFromLeft (7.0 μs) | 1.01x | +| power2 | sorted_uniform | 16384 | 1024 | 38.9 μs | 33.4 μs | 25.2 μs | 114.6 μs | 118.7 μs | 24.2 μs | 117.4 μs | ExpFromLeft (25.2 μs) | 0.96x | +| power2 | sorted_uniform | 16384 | 4096 | 112.7 μs | 155.6 μs | 117.1 μs | 487.5 μs | 386.5 μs | 111.9 μs | 380.3 μs | Linear (112.7 μs) | 0.99x | +| power2 | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| power2 | sorted_uniform | 65536 | 4 | 20.3 μs | 280 ns | 220 ns | 390 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | +| power2 | sorted_uniform | 65536 | 16 | 72.2 μs | 1.0 μs | 749 ns | 1.4 μs | 690 ns | 770 ns | 650 ns | Binary (690 ns) | 1.12x | +| power2 | sorted_uniform | 65536 | 64 | 89.0 μs | 3.6 μs | 2.5 μs | 5.9 μs | 2.8 μs | 2.6 μs | 2.7 μs | ExpFromLeft (2.5 μs) | 1.02x | +| power2 | sorted_uniform | 65536 | 256 | 93.4 μs | 12.2 μs | 8.9 μs | 26.0 μs | 17.3 μs | 9.2 μs | 15.6 μs | ExpFromLeft (8.9 μs) | 1.03x | +| power2 | sorted_uniform | 65536 | 1024 | 113.6 μs | 56.3 μs | 40.1 μs | 147.9 μs | 148.4 μs | 36.5 μs | 154.4 μs | ExpFromLeft (40.1 μs) | 0.91x | +| power2 | sorted_uniform | 65536 | 4096 | 196.7 μs | 242.6 μs | 190.2 μs | 597.2 μs | 473.5 μs | 189.8 μs | 478.7 μs | ExpFromLeft (190.2 μs) | 1.00x | +| power2 | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| power2 | sorted_dense_burst | 16 | 4 | 80 ns | 110 ns | 90 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| power2 | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 220 ns | 560 ns | 230 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | +| power2 | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 730 ns | 2.1 μs | 790 ns | 580 ns | 650 ns | Linear (550 ns) | 1.05x | +| power2 | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.2 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.02x | +| power2 | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 32.5 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.01x | +| power2 | sorted_dense_burst | 16 | 4096 | 30.8 μs | 55.0 μs | 41.9 μs | 129.9 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| power2 | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 90 ns | 200 ns | 110 ns | 100 ns | 90 ns | Linear (80 ns) | 1.25x | +| power2 | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 230 ns | 720 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | +| power2 | sorted_dense_burst | 64 | 64 | 550 ns | 920 ns | 740 ns | 2.8 μs | 1.1 μs | 610 ns | 940 ns | Linear (550 ns) | 1.11x | +| power2 | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 10.9 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | +| power2 | sorted_dense_burst | 64 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 43.5 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.8 μs) | 1.00x | +| power2 | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.7 μs | 42.0 μs | 173.4 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 260 ns | 130 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| power2 | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 910 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| power2 | sorted_dense_burst | 256 | 64 | 560 ns | 940 ns | 730 ns | 3.5 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (560 ns) | 1.04x | +| power2 | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 13.7 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| power2 | sorted_dense_burst | 256 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 54.6 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.00x | +| power2 | sorted_dense_burst | 256 | 4096 | 30.8 μs | 54.8 μs | 42.1 μs | 217.8 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_dense_burst | 1024 | 4 | 90 ns | 110 ns | 100 ns | 280 ns | 139 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | +| power2 | sorted_dense_burst | 1024 | 16 | 190 ns | 280 ns | 240 ns | 1.0 μs | 460 ns | 210 ns | 419 ns | Linear (190 ns) | 1.11x | +| power2 | sorted_dense_burst | 1024 | 64 | 560 ns | 930 ns | 730 ns | 4.0 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| power2 | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 15.9 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| power2 | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 63.6 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.01x | +| power2 | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 253.8 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (70 ns) | 0.86x | +| power2 | sorted_dense_burst | 4096 | 4 | 100 ns | 110 ns | 100 ns | 320 ns | 160 ns | 120 ns | 150 ns | ExpFromLeft (100 ns) | 1.20x | +| power2 | sorted_dense_burst | 4096 | 16 | 180 ns | 290 ns | 250 ns | 1.2 μs | 540 ns | 210 ns | 480 ns | Linear (180 ns) | 1.17x | +| power2 | sorted_dense_burst | 4096 | 64 | 560 ns | 939 ns | 750 ns | 4.7 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | +| power2 | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 18.4 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | +| power2 | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 73.3 μs | 31.1 μs | 7.8 μs | 28.5 μs | Linear (7.7 μs) | 1.01x | +| power2 | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 292.8 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_dense_burst | 16384 | 4 | 90 ns | 110 ns | 110 ns | 370 ns | 179 ns | 130 ns | 160 ns | Linear (90 ns) | 1.44x | +| power2 | sorted_dense_burst | 16384 | 16 | 180 ns | 290 ns | 240 ns | 1.4 μs | 600 ns | 210 ns | 560 ns | Linear (180 ns) | 1.17x | +| power2 | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 740 ns | 5.3 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | +| power2 | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 21.2 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | +| power2 | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 14.1 μs | 10.6 μs | 84.0 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.01x | +| power2 | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.0 μs | 42.1 μs | 335.7 μs | 144.1 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| power2 | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 440 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| power2 | sorted_dense_burst | 65536 | 16 | 190 ns | 290 ns | 250 ns | 1.6 μs | 680 ns | 220 ns | 630 ns | Linear (190 ns) | 1.16x | +| power2 | sorted_dense_burst | 65536 | 64 | 570 ns | 950 ns | 750 ns | 6.2 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| power2 | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.9 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | +| power2 | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 99.3 μs | 40.8 μs | 7.8 μs | 38.2 μs | Linear (7.8 μs) | 1.00x | +| power2 | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 397.0 μs | 163.0 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| power2 | sorted_near_start | 16 | 4 | 90 ns | 120 ns | 100 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| power2 | sorted_near_start | 16 | 16 | 190 ns | 300 ns | 220 ns | 470 ns | 230 ns | 200 ns | 200 ns | Linear (190 ns) | 1.05x | +| power2 | sorted_near_start | 16 | 64 | 780 ns | 1.2 μs | 740 ns | 1.7 μs | 790 ns | 600 ns | 680 ns | ExpFromLeft (740 ns) | 0.81x | +| power2 | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 3.0 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | +| power2 | sorted_near_start | 16 | 1024 | 7.9 μs | 13.9 μs | 10.7 μs | 26.6 μs | 12.1 μs | 7.9 μs | 10.3 μs | Linear (7.9 μs) | 1.00x | +| power2 | sorted_near_start | 16 | 4096 | 31.0 μs | 55.1 μs | 42.0 μs | 105.7 μs | 47.8 μs | 31.1 μs | 40.4 μs | Linear (31.0 μs) | 1.00x | +| power2 | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| power2 | sorted_near_start | 64 | 4 | 170 ns | 130 ns | 110 ns | 160 ns | 110 ns | 130 ns | 100 ns | ExpFromLeft (110 ns) | 1.18x | +| power2 | sorted_near_start | 64 | 16 | 240 ns | 300 ns | 250 ns | 520 ns | 320 ns | 260 ns | 290 ns | Linear (240 ns) | 1.08x | +| power2 | sorted_near_start | 64 | 64 | 880 ns | 1.3 μs | 1.0 μs | 2.0 μs | 1.1 μs | 730 ns | 990 ns | Linear (880 ns) | 0.83x | +| power2 | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.4 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | +| power2 | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 29.3 μs | 17.2 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.00x | +| power2 | sorted_near_start | 64 | 4096 | 31.6 μs | 55.7 μs | 42.7 μs | 118.2 μs | 66.8 μs | 31.7 μs | 59.7 μs | Linear (31.6 μs) | 1.00x | +| power2 | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_near_start | 256 | 4 | 320 ns | 140 ns | 120 ns | 200 ns | 120 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | +| power2 | sorted_near_start | 256 | 16 | 530 ns | 340 ns | 250 ns | 650 ns | 400 ns | 280 ns | 350 ns | ExpFromLeft (250 ns) | 1.12x | +| power2 | sorted_near_start | 256 | 64 | 870 ns | 1.1 μs | 870 ns | 2.6 μs | 1.5 μs | 900 ns | 1.4 μs | ExpFromLeft (870 ns) | 1.03x | +| power2 | sorted_near_start | 256 | 256 | 2.5 μs | 4.0 μs | 3.0 μs | 9.9 μs | 5.6 μs | 2.6 μs | 5.2 μs | Linear (2.5 μs) | 1.01x | +| power2 | sorted_near_start | 256 | 1024 | 8.3 μs | 14.5 μs | 11.1 μs | 39.6 μs | 22.2 μs | 8.4 μs | 20.3 μs | Linear (8.3 μs) | 1.00x | +| power2 | sorted_near_start | 256 | 4096 | 31.7 μs | 56.3 μs | 42.5 μs | 156.5 μs | 88.8 μs | 31.6 μs | 81.1 μs | Linear (31.7 μs) | 1.00x | +| power2 | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| power2 | sorted_near_start | 1024 | 4 | 1.1 μs | 170 ns | 160 ns | 250 ns | 140 ns | 180 ns | 130 ns | Binary (140 ns) | 1.29x | +| power2 | sorted_near_start | 1024 | 16 | 1.3 μs | 410 ns | 320 ns | 800 ns | 490 ns | 340 ns | 460 ns | ExpFromLeft (320 ns) | 1.06x | +| power2 | sorted_near_start | 1024 | 64 | 1.9 μs | 1.2 μs | 870 ns | 3.1 μs | 2.0 μs | 930 ns | 1.8 μs | ExpFromLeft (870 ns) | 1.07x | +| power2 | sorted_near_start | 1024 | 256 | 3.8 μs | 4.4 μs | 3.5 μs | 13.0 μs | 7.2 μs | 3.8 μs | 6.8 μs | ExpFromLeft (3.5 μs) | 1.11x | +| power2 | sorted_near_start | 1024 | 1024 | 10.1 μs | 15.6 μs | 12.1 μs | 50.2 μs | 27.3 μs | 10.1 μs | 25.7 μs | Linear (10.1 μs) | 1.00x | +| power2 | sorted_near_start | 1024 | 4096 | 34.0 μs | 58.0 μs | 44.2 μs | 200.7 μs | 109.7 μs | 34.1 μs | 103.9 μs | Linear (34.0 μs) | 1.00x | +| power2 | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 90 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_near_start | 4096 | 4 | 5.3 μs | 200 ns | 180 ns | 260 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | +| power2 | sorted_near_start | 4096 | 16 | 5.2 μs | 470 ns | 380 ns | 980 ns | 520 ns | 400 ns | 490 ns | ExpFromLeft (380 ns) | 1.05x | +| power2 | sorted_near_start | 4096 | 64 | 5.9 μs | 1.5 μs | 1.1 μs | 3.8 μs | 2.4 μs | 1.1 μs | 2.3 μs | ExpFromLeft (1.1 μs) | 1.05x | +| power2 | sorted_near_start | 4096 | 256 | 7.6 μs | 4.8 μs | 3.3 μs | 16.0 μs | 11.3 μs | 3.4 μs | 10.3 μs | ExpFromLeft (3.3 μs) | 1.02x | +| power2 | sorted_near_start | 4096 | 1024 | 19.3 μs | 22.3 μs | 17.2 μs | 66.3 μs | 40.0 μs | 16.0 μs | 36.6 μs | ExpFromLeft (17.2 μs) | 0.93x | +| power2 | sorted_near_start | 4096 | 4096 | 41.1 μs | 63.0 μs | 48.5 μs | 254.2 μs | 155.9 μs | 41.1 μs | 141.4 μs | Linear (41.1 μs) | 1.00x | +| power2 | sorted_near_start | 16384 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | +| power2 | sorted_near_start | 16384 | 4 | 9.2 μs | 230 ns | 180 ns | 320 ns | 180 ns | 210 ns | 170 ns | ExpFromLeft (180 ns) | 1.17x | +| power2 | sorted_near_start | 16384 | 16 | 20.1 μs | 650 ns | 490 ns | 1.1 μs | 610 ns | 520 ns | 560 ns | ExpFromLeft (490 ns) | 1.06x | +| power2 | sorted_near_start | 16384 | 64 | 23.0 μs | 1.9 μs | 1.4 μs | 4.4 μs | 3.0 μs | 1.4 μs | 2.8 μs | ExpFromLeft (1.4 μs) | 1.04x | +| power2 | sorted_near_start | 16384 | 256 | 24.2 μs | 5.9 μs | 4.3 μs | 18.2 μs | 18.4 μs | 4.2 μs | 17.7 μs | ExpFromLeft (4.3 μs) | 0.99x | +| power2 | sorted_near_start | 16384 | 1024 | 33.4 μs | 20.5 μs | 14.3 μs | 84.8 μs | 75.6 μs | 14.7 μs | 69.9 μs | ExpFromLeft (14.3 μs) | 1.03x | +| power2 | sorted_near_start | 16384 | 4096 | 69.7 μs | 75.5 μs | 59.6 μs | 351.9 μs | 246.6 μs | 69.3 μs | 231.4 μs | ExpFromLeft (59.6 μs) | 1.16x | +| power2 | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| power2 | sorted_near_start | 65536 | 4 | 73.4 μs | 270 ns | 210 ns | 360 ns | 200 ns | 240 ns | 239 ns | Binary (200 ns) | 1.20x | +| power2 | sorted_near_start | 65536 | 16 | 80.8 μs | 760 ns | 730 ns | 1.6 μs | 730 ns | 610 ns | 690 ns | ExpFromLeft (730 ns) | 0.84x | +| power2 | sorted_near_start | 65536 | 64 | 96.5 μs | 2.6 μs | 2.3 μs | 5.1 μs | 3.5 μs | 1.9 μs | 3.2 μs | ExpFromLeft (2.3 μs) | 0.84x | +| power2 | sorted_near_start | 65536 | 256 | 84.4 μs | 7.7 μs | 5.8 μs | 21.1 μs | 20.7 μs | 5.8 μs | 19.6 μs | ExpFromLeft (5.8 μs) | 1.01x | +| power2 | sorted_near_start | 65536 | 1024 | 101.6 μs | 26.2 μs | 18.8 μs | 115.8 μs | 92.2 μs | 18.6 μs | 85.6 μs | ExpFromLeft (18.8 μs) | 0.99x | +| power2 | sorted_near_start | 65536 | 4096 | 151.2 μs | 113.9 μs | 90.0 μs | 486.9 μs | 305.3 μs | 87.7 μs | 292.2 μs | ExpFromLeft (90.0 μs) | 0.97x | +| power2 | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| power2 | sorted_arithmetic | 16 | 4 | 100 ns | 120 ns | 110 ns | 160 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | +| power2 | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 210 ns | 510 ns | 240 ns | 210 ns | 200 ns | Linear (190 ns) | 1.11x | +| power2 | sorted_arithmetic | 16 | 64 | 580 ns | 990 ns | 750 ns | 2.0 μs | 950 ns | 610 ns | 790 ns | Linear (580 ns) | 1.05x | +| power2 | sorted_arithmetic | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 8.2 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.2 μs) | 1.01x | +| power2 | sorted_arithmetic | 16 | 1024 | 8.0 μs | 13.9 μs | 10.8 μs | 31.0 μs | 12.4 μs | 8.1 μs | 10.6 μs | Linear (8.0 μs) | 1.01x | +| power2 | sorted_arithmetic | 16 | 4096 | 31.1 μs | 54.5 μs | 42.3 μs | 121.6 μs | 48.0 μs | 31.1 μs | 41.2 μs | Linear (31.1 μs) | 1.00x | +| power2 | sorted_arithmetic | 64 | 1 | 60 ns | 60 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| power2 | sorted_arithmetic | 64 | 4 | 170 ns | 140 ns | 130 ns | 170 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | +| power2 | sorted_arithmetic | 64 | 16 | 290 ns | 390 ns | 300 ns | 620 ns | 310 ns | 280 ns | 270 ns | Linear (290 ns) | 0.97x | +| power2 | sorted_arithmetic | 64 | 64 | 660 ns | 1.1 μs | 760 ns | 2.5 μs | 1.3 μs | 680 ns | 1.2 μs | Linear (660 ns) | 1.03x | +| power2 | sorted_arithmetic | 64 | 256 | 2.4 μs | 4.0 μs | 3.0 μs | 10.6 μs | 5.2 μs | 2.4 μs | 4.6 μs | Linear (2.4 μs) | 1.00x | +| power2 | sorted_arithmetic | 64 | 1024 | 8.9 μs | 14.7 μs | 11.5 μs | 41.6 μs | 17.8 μs | 8.9 μs | 15.7 μs | Linear (8.9 μs) | 1.00x | +| power2 | sorted_arithmetic | 64 | 4096 | 32.1 μs | 55.9 μs | 43.1 μs | 158.7 μs | 67.6 μs | 32.1 μs | 60.0 μs | Linear (32.1 μs) | 1.00x | +| power2 | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_arithmetic | 256 | 4 | 470 ns | 180 ns | 150 ns | 190 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | +| power2 | sorted_arithmetic | 256 | 16 | 550 ns | 500 ns | 400 ns | 750 ns | 380 ns | 410 ns | 330 ns | Binary (380 ns) | 1.08x | +| power2 | sorted_arithmetic | 256 | 64 | 920 ns | 1.4 μs | 960 ns | 3.0 μs | 1.4 μs | 950 ns | 1.3 μs | Linear (920 ns) | 1.03x | +| power2 | sorted_arithmetic | 256 | 256 | 2.6 μs | 4.4 μs | 3.0 μs | 12.8 μs | 7.3 μs | 2.6 μs | 6.7 μs | Linear (2.6 μs) | 1.01x | +| power2 | sorted_arithmetic | 256 | 1024 | 9.8 μs | 16.0 μs | 12.2 μs | 55.8 μs | 25.8 μs | 9.9 μs | 24.9 μs | Linear (9.8 μs) | 1.01x | +| power2 | sorted_arithmetic | 256 | 4096 | 35.7 μs | 59.2 μs | 45.9 μs | 204.5 μs | 91.4 μs | 35.7 μs | 83.7 μs | Linear (35.7 μs) | 1.00x | +| power2 | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_arithmetic | 1024 | 4 | 1.5 μs | 210 ns | 180 ns | 210 ns | 150 ns | 200 ns | 130 ns | Binary (150 ns) | 1.33x | +| power2 | sorted_arithmetic | 1024 | 16 | 1.7 μs | 620 ns | 490 ns | 890 ns | 450 ns | 520 ns | 420 ns | Binary (450 ns) | 1.16x | +| power2 | sorted_arithmetic | 1024 | 64 | 2.1 μs | 1.9 μs | 1.4 μs | 3.7 μs | 1.8 μs | 1.5 μs | 1.5 μs | ExpFromLeft (1.4 μs) | 1.03x | +| power2 | sorted_arithmetic | 1024 | 256 | 3.8 μs | 5.8 μs | 3.9 μs | 15.2 μs | 8.1 μs | 3.9 μs | 7.5 μs | Linear (3.8 μs) | 1.01x | +| power2 | sorted_arithmetic | 1024 | 1024 | 13.6 μs | 21.8 μs | 16.2 μs | 69.2 μs | 72.1 μs | 10.7 μs | 71.6 μs | Linear (13.6 μs) | 0.79x | +| power2 | sorted_arithmetic | 1024 | 4096 | 37.5 μs | 62.0 μs | 46.6 μs | 279.9 μs | 188.4 μs | 37.6 μs | 180.8 μs | Linear (37.5 μs) | 1.00x | +| power2 | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_arithmetic | 4096 | 4 | 5.7 μs | 240 ns | 200 ns | 230 ns | 160 ns | 220 ns | 150 ns | Binary (160 ns) | 1.38x | +| power2 | sorted_arithmetic | 4096 | 16 | 6.0 μs | 750 ns | 589 ns | 1.0 μs | 530 ns | 620 ns | 490 ns | Binary (530 ns) | 1.17x | +| power2 | sorted_arithmetic | 4096 | 64 | 7.2 μs | 2.5 μs | 1.9 μs | 4.2 μs | 2.0 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.9 μs) | 0.99x | +| power2 | sorted_arithmetic | 4096 | 256 | 8.8 μs | 7.8 μs | 5.9 μs | 18.2 μs | 11.4 μs | 6.0 μs | 11.2 μs | ExpFromLeft (5.9 μs) | 1.02x | +| power2 | sorted_arithmetic | 4096 | 1024 | 16.0 μs | 24.1 μs | 15.8 μs | 89.7 μs | 99.1 μs | 16.0 μs | 90.6 μs | ExpFromLeft (15.8 μs) | 1.01x | +| power2 | sorted_arithmetic | 4096 | 4096 | 43.3 μs | 70.6 μs | 49.0 μs | 374.9 μs | 312.2 μs | 43.3 μs | 307.4 μs | Linear (43.3 μs) | 1.00x | +| power2 | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_arithmetic | 16384 | 4 | 22.6 μs | 270 ns | 230 ns | 250 ns | 190 ns | 240 ns | 170 ns | Binary (190 ns) | 1.26x | +| power2 | sorted_arithmetic | 16384 | 16 | 23.5 μs | 920 ns | 680 ns | 1.2 μs | 600 ns | 710 ns | 570 ns | Binary (600 ns) | 1.18x | +| power2 | sorted_arithmetic | 16384 | 64 | 24.4 μs | 3.2 μs | 2.4 μs | 5.0 μs | 2.4 μs | 2.4 μs | 2.3 μs | ExpFromLeft (2.4 μs) | 1.02x | +| power2 | sorted_arithmetic | 16384 | 256 | 28.2 μs | 10.1 μs | 7.5 μs | 21.0 μs | 14.0 μs | 7.5 μs | 13.8 μs | ExpFromLeft (7.5 μs) | 1.00x | +| power2 | sorted_arithmetic | 16384 | 1024 | 36.2 μs | 32.6 μs | 24.4 μs | 122.2 μs | 125.8 μs | 24.9 μs | 124.0 μs | ExpFromLeft (24.4 μs) | 1.02x | +| power2 | sorted_arithmetic | 16384 | 4096 | 65.3 μs | 98.0 μs | 65.4 μs | 506.3 μs | 425.1 μs | 65.2 μs | 411.6 μs | Linear (65.3 μs) | 1.00x | +| power2 | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| power2 | sorted_arithmetic | 65536 | 4 | 87.8 μs | 300 ns | 240 ns | 270 ns | 200 ns | 270 ns | 190 ns | Binary (200 ns) | 1.35x | +| power2 | sorted_arithmetic | 65536 | 16 | 88.5 μs | 1.1 μs | 790 ns | 1.4 μs | 700 ns | 820 ns | 650 ns | Binary (700 ns) | 1.17x | +| power2 | sorted_arithmetic | 65536 | 64 | 92.4 μs | 3.7 μs | 2.7 μs | 5.7 μs | 2.8 μs | 2.8 μs | 2.6 μs | ExpFromLeft (2.7 μs) | 1.03x | +| power2 | sorted_arithmetic | 65536 | 256 | 97.6 μs | 13.2 μs | 9.9 μs | 25.3 μs | 18.3 μs | 9.9 μs | 16.4 μs | ExpFromLeft (9.9 μs) | 1.00x | +| power2 | sorted_arithmetic | 65536 | 1024 | 109.9 μs | 45.5 μs | 34.2 μs | 152.8 μs | 153.6 μs | 33.9 μs | 158.1 μs | ExpFromLeft (34.2 μs) | 0.99x | +| power2 | sorted_arithmetic | 65536 | 4096 | 142.2 μs | 134.6 μs | 100.7 μs | 613.7 μs | 501.1 μs | 101.9 μs | 509.1 μs | ExpFromLeft (100.7 μs) | 1.01x | +| power2 | sorted_geometric | 16 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| power2 | sorted_geometric | 16 | 4 | 100 ns | 120 ns | 120 ns | 150 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | +| power2 | sorted_geometric | 16 | 16 | 190 ns | 280 ns | 219 ns | 510 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | +| power2 | sorted_geometric | 16 | 64 | 630 ns | 1.0 μs | 780 ns | 2.1 μs | 1.0 μs | 660 ns | 880 ns | Linear (630 ns) | 1.05x | +| power2 | sorted_geometric | 16 | 256 | 2.3 μs | 3.7 μs | 3.0 μs | 8.4 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | +| power2 | sorted_geometric | 16 | 1024 | 8.1 μs | 14.1 μs | 10.8 μs | 31.5 μs | 12.2 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | +| power2 | sorted_geometric | 16 | 4096 | 31.1 μs | 55.4 μs | 42.3 μs | 123.8 μs | 47.1 μs | 31.1 μs | 39.9 μs | Linear (31.1 μs) | 1.00x | +| power2 | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| power2 | sorted_geometric | 64 | 4 | 170 ns | 150 ns | 140 ns | 170 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | +| power2 | sorted_geometric | 64 | 16 | 270 ns | 390 ns | 290 ns | 660 ns | 300 ns | 280 ns | 270 ns | Linear (270 ns) | 1.04x | +| power2 | sorted_geometric | 64 | 64 | 660 ns | 1.1 μs | 780 ns | 2.6 μs | 1.2 μs | 690 ns | 1.1 μs | Linear (660 ns) | 1.05x | +| power2 | sorted_geometric | 64 | 256 | 2.4 μs | 4.0 μs | 3.1 μs | 11.0 μs | 5.2 μs | 2.4 μs | 4.8 μs | Linear (2.4 μs) | 1.00x | +| power2 | sorted_geometric | 64 | 1024 | 9.2 μs | 14.9 μs | 11.7 μs | 42.8 μs | 17.6 μs | 9.2 μs | 15.8 μs | Linear (9.2 μs) | 1.00x | +| power2 | sorted_geometric | 64 | 4096 | 32.2 μs | 56.4 μs | 43.2 μs | 162.9 μs | 67.1 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | +| power2 | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_geometric | 256 | 4 | 490 ns | 180 ns | 160 ns | 190 ns | 130 ns | 180 ns | 110 ns | Binary (130 ns) | 1.38x | +| power2 | sorted_geometric | 256 | 16 | 630 ns | 520 ns | 510 ns | 800 ns | 370 ns | 430 ns | 340 ns | Binary (370 ns) | 1.16x | +| power2 | sorted_geometric | 256 | 64 | 970 ns | 1.5 μs | 1.1 μs | 3.2 μs | 1.4 μs | 980 ns | 1.2 μs | Linear (970 ns) | 1.01x | +| power2 | sorted_geometric | 256 | 256 | 2.8 μs | 4.6 μs | 3.2 μs | 13.0 μs | 6.7 μs | 2.9 μs | 6.3 μs | Linear (2.8 μs) | 1.03x | +| power2 | sorted_geometric | 256 | 1024 | 9.5 μs | 15.6 μs | 11.8 μs | 56.3 μs | 27.0 μs | 9.5 μs | 25.0 μs | Linear (9.5 μs) | 1.00x | +| power2 | sorted_geometric | 256 | 4096 | 34.9 μs | 59.5 μs | 46.1 μs | 208.6 μs | 90.7 μs | 35.0 μs | 83.5 μs | Linear (34.9 μs) | 1.00x | +| power2 | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | +| power2 | sorted_geometric | 1024 | 4 | 1.5 μs | 210 ns | 170 ns | 220 ns | 150 ns | 200 ns | 130 ns | Binary (150 ns) | 1.33x | +| power2 | sorted_geometric | 1024 | 16 | 1.8 μs | 630 ns | 500 ns | 920 ns | 450 ns | 520 ns | 400 ns | Binary (450 ns) | 1.16x | +| power2 | sorted_geometric | 1024 | 64 | 2.1 μs | 1.9 μs | 1.5 μs | 3.7 μs | 1.7 μs | 1.5 μs | 1.5 μs | ExpFromLeft (1.5 μs) | 1.03x | +| power2 | sorted_geometric | 1024 | 256 | 3.9 μs | 6.3 μs | 5.8 μs | 16.2 μs | 8.0 μs | 4.8 μs | 7.3 μs | Linear (3.9 μs) | 1.22x | +| power2 | sorted_geometric | 1024 | 1024 | 11.2 μs | 18.1 μs | 12.4 μs | 70.3 μs | 85.2 μs | 11.2 μs | 84.6 μs | Linear (11.2 μs) | 1.00x | +| power2 | sorted_geometric | 1024 | 4096 | 37.1 μs | 61.2 μs | 45.8 μs | 281.8 μs | 195.9 μs | 37.2 μs | 192.4 μs | Linear (37.1 μs) | 1.00x | +| power2 | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| power2 | sorted_geometric | 4096 | 4 | 5.9 μs | 240 ns | 190 ns | 230 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | +| power2 | sorted_geometric | 4096 | 16 | 6.2 μs | 780 ns | 570 ns | 1.1 μs | 530 ns | 630 ns | 490 ns | Binary (530 ns) | 1.19x | +| power2 | sorted_geometric | 4096 | 64 | 7.3 μs | 2.5 μs | 1.9 μs | 4.3 μs | 2.0 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.9 μs) | 1.01x | +| power2 | sorted_geometric | 4096 | 256 | 8.9 μs | 7.9 μs | 6.2 μs | 17.8 μs | 10.7 μs | 6.3 μs | 10.9 μs | ExpFromLeft (6.2 μs) | 1.01x | +| power2 | sorted_geometric | 4096 | 1024 | 16.2 μs | 25.2 μs | 18.0 μs | 86.7 μs | 101.6 μs | 16.2 μs | 97.9 μs | Linear (16.2 μs) | 1.00x | +| power2 | sorted_geometric | 4096 | 4096 | 43.3 μs | 70.2 μs | 48.2 μs | 377.6 μs | 316.8 μs | 43.4 μs | 310.2 μs | Linear (43.3 μs) | 1.00x | +| power2 | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| power2 | sorted_geometric | 16384 | 4 | 22.6 μs | 280 ns | 240 ns | 250 ns | 180 ns | 270 ns | 170 ns | Binary (180 ns) | 1.50x | +| power2 | sorted_geometric | 16384 | 16 | 23.2 μs | 940 ns | 690 ns | 1.2 μs | 610 ns | 720 ns | 560 ns | Binary (610 ns) | 1.18x | +| power2 | sorted_geometric | 16384 | 64 | 24.6 μs | 3.2 μs | 2.4 μs | 5.0 μs | 2.4 μs | 2.4 μs | 2.2 μs | Binary (2.4 μs) | 1.03x | +| power2 | sorted_geometric | 16384 | 256 | 28.7 μs | 10.2 μs | 7.8 μs | 21.2 μs | 14.6 μs | 7.8 μs | 13.7 μs | ExpFromLeft (7.8 μs) | 1.01x | +| power2 | sorted_geometric | 16384 | 1024 | 36.1 μs | 33.0 μs | 26.0 μs | 118.3 μs | 131.2 μs | 26.3 μs | 132.5 μs | ExpFromLeft (26.0 μs) | 1.01x | +| power2 | sorted_geometric | 16384 | 4096 | 64.6 μs | 99.5 μs | 71.9 μs | 500.6 μs | 422.6 μs | 64.5 μs | 425.5 μs | Linear (64.6 μs) | 1.00x | +| power2 | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| power2 | sorted_geometric | 65536 | 4 | 94.0 μs | 310 ns | 260 ns | 280 ns | 210 ns | 300 ns | 190 ns | Binary (210 ns) | 1.43x | +| power2 | sorted_geometric | 65536 | 16 | 94.0 μs | 1.1 μs | 820 ns | 1.4 μs | 720 ns | 840 ns | 680 ns | Binary (720 ns) | 1.17x | +| power2 | sorted_geometric | 65536 | 64 | 95.1 μs | 3.8 μs | 2.8 μs | 5.9 μs | 2.9 μs | 2.8 μs | 2.9 μs | ExpFromLeft (2.8 μs) | 1.01x | +| power2 | sorted_geometric | 65536 | 256 | 100.2 μs | 13.7 μs | 10.6 μs | 27.5 μs | 18.2 μs | 10.7 μs | 16.9 μs | ExpFromLeft (10.6 μs) | 1.01x | +| power2 | sorted_geometric | 65536 | 1024 | 111.7 μs | 44.7 μs | 34.5 μs | 153.2 μs | 161.7 μs | 33.8 μs | 167.2 μs | ExpFromLeft (34.5 μs) | 0.98x | +| power2 | sorted_geometric | 65536 | 4096 | 140.2 μs | 131.9 μs | 106.4 μs | 615.3 μs | 512.3 μs | 108.5 μs | 519.0 μs | ExpFromLeft (106.4 μs) | 1.02x | +| power2 | sorted_bimodal | 16 | 1 | 60 ns | 60 ns | 50 ns | 90 ns | 70 ns | 70 ns | 50 ns | ExpFromLeft (50 ns) | 1.40x | +| power2 | sorted_bimodal | 16 | 4 | 100 ns | 120 ns | 110 ns | 160 ns | 100 ns | 110 ns | 80 ns | Binary (100 ns) | 1.10x | +| power2 | sorted_bimodal | 16 | 16 | 190 ns | 320 ns | 240 ns | 490 ns | 250 ns | 220 ns | 200 ns | Linear (190 ns) | 1.16x | +| power2 | sorted_bimodal | 16 | 64 | 570 ns | 970 ns | 770 ns | 1.9 μs | 910 ns | 590 ns | 790 ns | Linear (570 ns) | 1.04x | +| power2 | sorted_bimodal | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.4 μs | 3.4 μs | 2.1 μs | 3.0 μs | Linear (2.1 μs) | 1.00x | +| power2 | sorted_bimodal | 16 | 1024 | 8.0 μs | 13.9 μs | 10.7 μs | 29.1 μs | 13.1 μs | 8.0 μs | 11.6 μs | Linear (8.0 μs) | 1.00x | +| power2 | sorted_bimodal | 16 | 4096 | 31.3 μs | 55.0 μs | 42.1 μs | 113.0 μs | 51.6 μs | 30.9 μs | 45.5 μs | Linear (31.3 μs) | 0.99x | +| power2 | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 50 ns | InterpSearch (60 ns) | 1.00x | +| power2 | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 110 ns | 180 ns | 110 ns | 140 ns | 90 ns | ExpFromLeft (110 ns) | 1.27x | +| power2 | sorted_bimodal | 64 | 16 | 250 ns | 320 ns | 250 ns | 570 ns | 320 ns | 280 ns | 270 ns | ExpFromLeft (250 ns) | 1.12x | +| power2 | sorted_bimodal | 64 | 64 | 620 ns | 1.0 μs | 760 ns | 2.3 μs | 1.2 μs | 660 ns | 1.1 μs | Linear (620 ns) | 1.06x | +| power2 | sorted_bimodal | 64 | 256 | 2.2 μs | 3.8 μs | 2.9 μs | 9.4 μs | 4.6 μs | 2.3 μs | 4.1 μs | Linear (2.2 μs) | 1.01x | +| power2 | sorted_bimodal | 64 | 1024 | 8.3 μs | 14.0 μs | 11.0 μs | 35.7 μs | 17.2 μs | 8.3 μs | 15.5 μs | Linear (8.3 μs) | 1.00x | +| power2 | sorted_bimodal | 64 | 4096 | 31.3 μs | 54.6 μs | 42.5 μs | 140.2 μs | 67.3 μs | 31.3 μs | 60.7 μs | Linear (31.3 μs) | 1.00x | +| power2 | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_bimodal | 256 | 4 | 380 ns | 140 ns | 130 ns | 210 ns | 120 ns | 150 ns | 110 ns | Binary (120 ns) | 1.25x | +| power2 | sorted_bimodal | 256 | 16 | 540 ns | 380 ns | 300 ns | 720 ns | 400 ns | 330 ns | 380 ns | ExpFromLeft (300 ns) | 1.10x | +| power2 | sorted_bimodal | 256 | 64 | 950 ns | 1.1 μs | 800 ns | 2.9 μs | 1.6 μs | 980 ns | 1.5 μs | ExpFromLeft (800 ns) | 1.23x | +| power2 | sorted_bimodal | 256 | 256 | 2.6 μs | 4.0 μs | 3.0 μs | 11.3 μs | 6.6 μs | 2.6 μs | 6.0 μs | Linear (2.6 μs) | 0.99x | +| power2 | sorted_bimodal | 256 | 1024 | 9.3 μs | 14.9 μs | 11.8 μs | 45.3 μs | 23.2 μs | 9.2 μs | 21.1 μs | Linear (9.3 μs) | 1.00x | +| power2 | sorted_bimodal | 256 | 4096 | 32.9 μs | 56.3 μs | 43.7 μs | 173.4 μs | 87.9 μs | 32.8 μs | 80.3 μs | Linear (32.9 μs) | 1.00x | +| power2 | sorted_bimodal | 1024 | 1 | 70 ns | 70 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_bimodal | 1024 | 4 | 1.3 μs | 180 ns | 160 ns | 240 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | +| power2 | sorted_bimodal | 1024 | 16 | 1.7 μs | 500 ns | 390 ns | 880 ns | 440 ns | 410 ns | 410 ns | ExpFromLeft (390 ns) | 1.05x | +| power2 | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.4 μs | 1.0 μs | 3.4 μs | 1.8 μs | 1.1 μs | 1.7 μs | ExpFromLeft (1.0 μs) | 1.05x | +| power2 | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.3 μs | 3.0 μs | 13.8 μs | 8.1 μs | 3.5 μs | 7.5 μs | ExpFromLeft (3.0 μs) | 1.17x | +| power2 | sorted_bimodal | 1024 | 1024 | 10.7 μs | 16.2 μs | 12.1 μs | 58.4 μs | 31.3 μs | 10.7 μs | 29.7 μs | Linear (10.7 μs) | 1.00x | +| power2 | sorted_bimodal | 1024 | 4096 | 37.7 μs | 60.3 μs | 47.2 μs | 223.8 μs | 114.1 μs | 37.7 μs | 106.1 μs | Linear (37.7 μs) | 1.00x | +| power2 | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_bimodal | 4096 | 4 | 5.7 μs | 220 ns | 190 ns | 270 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | +| power2 | sorted_bimodal | 4096 | 16 | 5.6 μs | 600 ns | 460 ns | 960 ns | 530 ns | 490 ns | 510 ns | ExpFromLeft (460 ns) | 1.07x | +| power2 | sorted_bimodal | 4096 | 64 | 6.7 μs | 1.8 μs | 1.3 μs | 3.9 μs | 2.3 μs | 1.4 μs | 2.0 μs | ExpFromLeft (1.3 μs) | 1.04x | +| power2 | sorted_bimodal | 4096 | 256 | 8.1 μs | 5.5 μs | 3.9 μs | 16.2 μs | 10.7 μs | 4.0 μs | 10.7 μs | ExpFromLeft (3.9 μs) | 1.02x | +| power2 | sorted_bimodal | 4096 | 1024 | 15.4 μs | 18.5 μs | 12.7 μs | 76.9 μs | 61.1 μs | 15.2 μs | 55.0 μs | ExpFromLeft (12.7 μs) | 1.19x | +| power2 | sorted_bimodal | 4096 | 4096 | 48.1 μs | 69.2 μs | 52.0 μs | 309.9 μs | 201.8 μs | 47.0 μs | 188.9 μs | Linear (48.1 μs) | 0.98x | +| power2 | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | +| power2 | sorted_bimodal | 16384 | 4 | 17.0 μs | 240 ns | 200 ns | 310 ns | 180 ns | 230 ns | 170 ns | Binary (180 ns) | 1.28x | +| power2 | sorted_bimodal | 16384 | 16 | 22.1 μs | 720 ns | 550 ns | 1.2 μs | 630 ns | 590 ns | 610 ns | ExpFromLeft (550 ns) | 1.07x | +| power2 | sorted_bimodal | 16384 | 64 | 22.5 μs | 2.3 μs | 1.7 μs | 4.6 μs | 2.8 μs | 1.8 μs | 2.7 μs | ExpFromLeft (1.7 μs) | 1.03x | +| power2 | sorted_bimodal | 16384 | 256 | 26.1 μs | 6.9 μs | 5.3 μs | 19.3 μs | 15.8 μs | 5.3 μs | 14.5 μs | ExpFromLeft (5.3 μs) | 1.00x | +| power2 | sorted_bimodal | 16384 | 1024 | 34.5 μs | 23.8 μs | 17.2 μs | 101.0 μs | 92.8 μs | 17.0 μs | 93.9 μs | ExpFromLeft (17.2 μs) | 0.99x | +| power2 | sorted_bimodal | 16384 | 4096 | 83.8 μs | 94.9 μs | 73.2 μs | 430.5 μs | 297.7 μs | 81.4 μs | 286.1 μs | ExpFromLeft (73.2 μs) | 1.11x | +| power2 | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| power2 | sorted_bimodal | 65536 | 4 | 79.1 μs | 290 ns | 240 ns | 370 ns | 200 ns | 270 ns | 180 ns | Binary (200 ns) | 1.35x | +| power2 | sorted_bimodal | 65536 | 16 | 80.3 μs | 920 ns | 650 ns | 1.4 μs | 670 ns | 690 ns | 630 ns | ExpFromLeft (650 ns) | 1.06x | +| power2 | sorted_bimodal | 65536 | 64 | 92.4 μs | 3.0 μs | 2.3 μs | 5.4 μs | 3.2 μs | 2.3 μs | 3.1 μs | ExpFromLeft (2.3 μs) | 1.00x | +| power2 | sorted_bimodal | 65536 | 256 | 95.6 μs | 9.4 μs | 7.2 μs | 22.3 μs | 19.5 μs | 7.3 μs | 17.4 μs | ExpFromLeft (7.2 μs) | 1.00x | +| power2 | sorted_bimodal | 65536 | 1024 | 106.6 μs | 35.4 μs | 26.7 μs | 132.7 μs | 118.9 μs | 25.5 μs | 120.5 μs | ExpFromLeft (26.7 μs) | 0.96x | +| power2 | sorted_bimodal | 65536 | 4096 | 180.3 μs | 160.4 μs | 125.7 μs | 547.8 μs | 378.9 μs | 126.3 μs | 370.2 μs | ExpFromLeft (125.7 μs) | 1.00x | +| power2 | sorted_repeated | 16 | 1 | 70 ns | 60 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| power2 | sorted_repeated | 16 | 4 | 80 ns | 100 ns | 100 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| power2 | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 220 ns | 620 ns | 230 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | +| power2 | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 690 ns | 2.3 μs | 790 ns | 580 ns | 720 ns | Linear (550 ns) | 1.05x | +| power2 | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 9.2 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.02x | +| power2 | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 36.6 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.01x | +| power2 | sorted_repeated | 16 | 4096 | 30.8 μs | 54.9 μs | 39.6 μs | 146.2 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 90 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| power2 | sorted_repeated | 64 | 4 | 100 ns | 90 ns | 90 ns | 220 ns | 110 ns | 110 ns | 90 ns | ExpFromLeft (90 ns) | 1.22x | +| power2 | sorted_repeated | 64 | 16 | 180 ns | 270 ns | 200 ns | 780 ns | 300 ns | 190 ns | 270 ns | Linear (180 ns) | 1.06x | +| power2 | sorted_repeated | 64 | 64 | 560 ns | 920 ns | 700 ns | 3.0 μs | 1.1 μs | 580 ns | 920 ns | Linear (560 ns) | 1.04x | +| power2 | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 11.7 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | +| power2 | sorted_repeated | 64 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 47.0 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.8 μs) | 1.00x | +| power2 | sorted_repeated | 64 | 4096 | 30.8 μs | 55.1 μs | 39.4 μs | 186.4 μs | 66.5 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_repeated | 256 | 4 | 90 ns | 120 ns | 100 ns | 270 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| power2 | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 920 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| power2 | sorted_repeated | 256 | 64 | 550 ns | 940 ns | 700 ns | 3.5 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | +| power2 | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 13.9 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| power2 | sorted_repeated | 256 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 55.7 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.8 μs) | 1.00x | +| power2 | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 222.3 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 300 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | +| power2 | sorted_repeated | 1024 | 16 | 180 ns | 290 ns | 220 ns | 1.1 μs | 460 ns | 210 ns | 410 ns | Linear (180 ns) | 1.17x | +| power2 | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 4.1 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| power2 | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 16.4 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | +| power2 | sorted_repeated | 1024 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 65.0 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.00x | +| power2 | sorted_repeated | 1024 | 4096 | 30.8 μs | 56.1 μs | 39.2 μs | 260.0 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 350 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | +| power2 | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 1.2 μs | 520 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | +| power2 | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 710 ns | 4.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | +| power2 | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 18.9 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| power2 | sorted_repeated | 4096 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 75.9 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.7 μs) | 1.01x | +| power2 | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 302.3 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_repeated | 16384 | 1 | 80 ns | 90 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | sorted_repeated | 16384 | 4 | 100 ns | 110 ns | 110 ns | 400 ns | 180 ns | 120 ns | 160 ns | Linear (100 ns) | 1.20x | +| power2 | sorted_repeated | 16384 | 16 | 190 ns | 290 ns | 220 ns | 1.4 μs | 600 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | +| power2 | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 710 ns | 5.5 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | +| power2 | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 22.1 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | +| power2 | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 88.4 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.00x | +| power2 | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.1 μs | 39.2 μs | 353.1 μs | 144.2 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | +| power2 | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| power2 | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 430 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| power2 | sorted_repeated | 65536 | 16 | 190 ns | 290 ns | 220 ns | 1.6 μs | 680 ns | 220 ns | 640 ns | Linear (190 ns) | 1.16x | +| power2 | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 709 ns | 6.2 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| power2 | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 24.8 μs | 10.2 μs | 2.1 μs | 9.6 μs | Linear (2.0 μs) | 1.03x | +| power2 | sorted_repeated | 65536 | 1024 | 7.8 μs | 14.0 μs | 9.9 μs | 99.1 μs | 40.7 μs | 7.8 μs | 38.2 μs | Linear (7.8 μs) | 1.00x | +| power2 | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.1 μs | 39.4 μs | 396.4 μs | 163.2 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| power2 | unsorted | 16 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 70 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| power2 | unsorted | 16 | 4 | 90 ns | 90 ns | 100 ns | 90 ns | 100 ns | 100 ns | 70 ns | InterpSearch (90 ns) | 1.11x | +| power2 | unsorted | 16 | 16 | 220 ns | 210 ns | 210 ns | 200 ns | 210 ns | 210 ns | 180 ns | InterpSearch (200 ns) | 1.05x | +| power2 | unsorted | 16 | 64 | 690 ns | 680 ns | 700 ns | 680 ns | 700 ns | 710 ns | 680 ns | InterpSearch (680 ns) | 1.04x | +| power2 | unsorted | 16 | 256 | 2.9 μs | 3.0 μs | 2.9 μs | 3.0 μs | 3.0 μs | 3.0 μs | 2.9 μs | ExpFromLeft (2.9 μs) | 1.00x | +| power2 | unsorted | 16 | 1024 | 16.9 μs | 16.7 μs | 16.5 μs | 16.6 μs | 16.5 μs | 16.7 μs | 18.6 μs | Binary (16.5 μs) | 1.01x | +| power2 | unsorted | 16 | 4096 | 130.4 μs | 127.2 μs | 126.8 μs | 126.8 μs | 126.3 μs | 126.1 μs | 128.0 μs | Binary (126.3 μs) | 1.00x | +| power2 | unsorted | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | unsorted | 64 | 4 | 110 ns | 110 ns | 100 ns | 110 ns | 110 ns | 110 ns | 90 ns | ExpFromLeft (100 ns) | 1.10x | +| power2 | unsorted | 64 | 16 | 280 ns | 270 ns | 280 ns | 280 ns | 280 ns | 290 ns | 270 ns | Gallop (270 ns) | 1.07x | +| power2 | unsorted | 64 | 64 | 1.1 μs | 1.1 μs | 1.0 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.0 μs | ExpFromLeft (1.0 μs) | 1.03x | +| power2 | unsorted | 64 | 256 | 5.0 μs | 5.0 μs | 5.0 μs | 5.0 μs | 5.0 μs | 5.0 μs | 5.1 μs | InterpSearch (5.0 μs) | 1.00x | +| power2 | unsorted | 64 | 1024 | 38.2 μs | 37.9 μs | 38.3 μs | 38.0 μs | 38.7 μs | 38.0 μs | 40.2 μs | Gallop (37.9 μs) | 1.00x | +| power2 | unsorted | 64 | 4096 | 207.9 μs | 205.7 μs | 206.0 μs | 206.0 μs | 206.5 μs | 204.9 μs | 208.3 μs | Gallop (205.7 μs) | 1.00x | +| power2 | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | unsorted | 256 | 4 | 119 ns | 120 ns | 120 ns | 120 ns | 130 ns | 130 ns | 110 ns | Linear (119 ns) | 1.09x | +| power2 | unsorted | 256 | 16 | 340 ns | 350 ns | 350 ns | 349 ns | 350 ns | 350 ns | 330 ns | Linear (340 ns) | 1.03x | +| power2 | unsorted | 256 | 64 | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | ExpFromLeft (1.4 μs) | 1.01x | +| power2 | unsorted | 256 | 256 | 7.2 μs | 7.1 μs | 7.1 μs | 7.0 μs | 6.9 μs | 7.0 μs | 7.2 μs | Binary (6.9 μs) | 1.02x | +| power2 | unsorted | 256 | 1024 | 52.5 μs | 52.0 μs | 51.7 μs | 51.3 μs | 51.2 μs | 51.1 μs | 52.0 μs | Binary (51.2 μs) | 1.00x | +| power2 | unsorted | 256 | 4096 | 298.3 μs | 293.5 μs | 290.7 μs | 290.9 μs | 290.3 μs | 291.4 μs | 294.6 μs | Binary (290.3 μs) | 1.00x | +| power2 | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 69 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| power2 | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 149 ns | 130 ns | InterpSearch (140 ns) | 1.06x | +| power2 | unsorted | 1024 | 16 | 430 ns | 410 ns | 410 ns | 420 ns | 430 ns | 440 ns | 410 ns | ExpFromLeft (410 ns) | 1.07x | +| power2 | unsorted | 1024 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | InterpSearch (1.6 μs) | 1.01x | +| power2 | unsorted | 1024 | 256 | 8.0 μs | 7.9 μs | 7.9 μs | 7.8 μs | 7.9 μs | 7.9 μs | 8.8 μs | InterpSearch (7.8 μs) | 1.02x | +| power2 | unsorted | 1024 | 1024 | 77.3 μs | 76.5 μs | 75.5 μs | 74.8 μs | 73.8 μs | 73.7 μs | 77.8 μs | Binary (73.8 μs) | 1.00x | +| power2 | unsorted | 1024 | 4096 | 388.3 μs | 385.9 μs | 385.2 μs | 390.4 μs | 389.1 μs | 386.6 μs | 387.2 μs | ExpFromLeft (385.2 μs) | 1.00x | +| power2 | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| power2 | unsorted | 4096 | 4 | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 140 ns | InterpSearch (160 ns) | 1.00x | +| power2 | unsorted | 4096 | 16 | 500 ns | 500 ns | 490 ns | 490 ns | 490 ns | 510 ns | 480 ns | InterpSearch (490 ns) | 1.04x | +| power2 | unsorted | 4096 | 64 | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | Gallop (2.0 μs) | 1.00x | +| power2 | unsorted | 4096 | 256 | 10.0 μs | 9.9 μs | 9.9 μs | 9.9 μs | 9.8 μs | 9.6 μs | 10.9 μs | Binary (9.8 μs) | 0.98x | +| power2 | unsorted | 4096 | 1024 | 96.9 μs | 94.9 μs | 93.8 μs | 90.6 μs | 91.8 μs | 91.6 μs | 94.7 μs | InterpSearch (90.6 μs) | 1.01x | +| power2 | unsorted | 4096 | 4096 | 474.6 μs | 470.7 μs | 471.6 μs | 469.4 μs | 468.6 μs | 474.7 μs | 472.6 μs | Binary (468.6 μs) | 1.01x | +| power2 | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 120 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | +| power2 | unsorted | 16384 | 4 | 170 ns | 170 ns | 180 ns | 180 ns | 180 ns | 190 ns | 160 ns | Gallop (170 ns) | 1.12x | +| power2 | unsorted | 16384 | 16 | 570 ns | 570 ns | 560 ns | 570 ns | 580 ns | 580 ns | 560 ns | ExpFromLeft (560 ns) | 1.04x | +| power2 | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.2 μs | InterpSearch (2.3 μs) | 1.00x | +| power2 | unsorted | 16384 | 256 | 12.0 μs | 11.6 μs | 11.4 μs | 11.4 μs | 11.4 μs | 11.4 μs | 14.8 μs | ExpFromLeft (11.4 μs) | 1.01x | +| power2 | unsorted | 16384 | 1024 | 134.5 μs | 131.3 μs | 129.4 μs | 128.1 μs | 127.6 μs | 127.3 μs | 134.1 μs | Binary (127.6 μs) | 1.00x | +| power2 | unsorted | 16384 | 4096 | 629.9 μs | 632.0 μs | 629.5 μs | 631.2 μs | 630.9 μs | 629.7 μs | 630.1 μs | ExpFromLeft (629.5 μs) | 1.00x | +| power2 | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| power2 | unsorted | 65536 | 4 | 190 ns | 200 ns | 190 ns | 200 ns | 190 ns | 200 ns | 180 ns | ExpFromLeft (190 ns) | 1.05x | +| power2 | unsorted | 65536 | 16 | 700 ns | 710 ns | 700 ns | 700 ns | 710 ns | 710 ns | 690 ns | InterpSearch (700 ns) | 1.01x | +| power2 | unsorted | 65536 | 64 | 2.7 μs | 2.7 μs | 2.6 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | ExpFromLeft (2.6 μs) | 1.01x | +| power2 | unsorted | 65536 | 256 | 14.3 μs | 14.0 μs | 13.6 μs | 13.5 μs | 13.6 μs | 13.4 μs | 18.0 μs | InterpSearch (13.5 μs) | 0.99x | +| power2 | unsorted | 65536 | 1024 | 179.4 μs | 176.4 μs | 176.4 μs | 175.0 μs | 174.0 μs | 173.1 μs | 178.5 μs | Binary (174.0 μs) | 0.99x | +| power2 | unsorted | 65536 | 4096 | 798.1 μs | 797.6 μs | 797.0 μs | 796.8 μs | 795.3 μs | 796.4 μs | 794.1 μs | Binary (795.3 μs) | 1.00x | +| sqrt | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| sqrt | sorted_uniform | 16 | 4 | 90 ns | 100 ns | 90 ns | 160 ns | 90 ns | 110 ns | 70 ns | ExpFromLeft (90 ns) | 1.22x | +| sqrt | sorted_uniform | 16 | 16 | 190 ns | 310 ns | 220 ns | 530 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| sqrt | sorted_uniform | 16 | 64 | 560 ns | 1.0 μs | 750 ns | 2.2 μs | 980 ns | 600 ns | 860 ns | Linear (560 ns) | 1.07x | +| sqrt | sorted_uniform | 16 | 256 | 2.3 μs | 3.8 μs | 3.0 μs | 8.4 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | +| sqrt | sorted_uniform | 16 | 1024 | 8.1 μs | 14.0 μs | 10.8 μs | 32.8 μs | 12.2 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | +| sqrt | sorted_uniform | 16 | 4096 | 31.1 μs | 55.0 μs | 42.3 μs | 128.7 μs | 47.7 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | +| sqrt | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| sqrt | sorted_uniform | 64 | 4 | 90 ns | 110 ns | 100 ns | 180 ns | 110 ns | 120 ns | 90 ns | Linear (90 ns) | 1.33x | +| sqrt | sorted_uniform | 64 | 16 | 310 ns | 410 ns | 340 ns | 670 ns | 320 ns | 320 ns | 260 ns | Linear (310 ns) | 1.03x | +| sqrt | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 790 ns | 2.4 μs | 1.3 μs | 670 ns | 1.1 μs | Linear (630 ns) | 1.06x | +| sqrt | sorted_uniform | 64 | 256 | 2.3 μs | 4.0 μs | 3.0 μs | 10.5 μs | 5.3 μs | 2.3 μs | 4.7 μs | Linear (2.3 μs) | 1.02x | +| sqrt | sorted_uniform | 64 | 1024 | 9.1 μs | 14.9 μs | 11.7 μs | 41.1 μs | 17.7 μs | 9.1 μs | 16.0 μs | Linear (9.1 μs) | 1.00x | +| sqrt | sorted_uniform | 64 | 4096 | 32.2 μs | 56.1 μs | 43.2 μs | 158.3 μs | 67.0 μs | 32.2 μs | 60.4 μs | Linear (32.2 μs) | 1.00x | +| sqrt | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_uniform | 256 | 4 | 180 ns | 140 ns | 120 ns | 240 ns | 130 ns | 150 ns | 110 ns | ExpFromLeft (120 ns) | 1.25x | +| sqrt | sorted_uniform | 256 | 16 | 480 ns | 440 ns | 350 ns | 800 ns | 370 ns | 370 ns | 340 ns | ExpFromLeft (350 ns) | 1.06x | +| sqrt | sorted_uniform | 256 | 64 | 910 ns | 1.3 μs | 970 ns | 3.1 μs | 1.5 μs | 940 ns | 1.4 μs | Linear (910 ns) | 1.03x | +| sqrt | sorted_uniform | 256 | 256 | 2.4 μs | 4.2 μs | 2.9 μs | 13.0 μs | 7.2 μs | 2.4 μs | 6.8 μs | Linear (2.4 μs) | 1.00x | +| sqrt | sorted_uniform | 256 | 1024 | 9.6 μs | 16.4 μs | 12.4 μs | 52.4 μs | 26.7 μs | 9.6 μs | 24.7 μs | Linear (9.6 μs) | 1.00x | +| sqrt | sorted_uniform | 256 | 4096 | 36.6 μs | 59.3 μs | 46.6 μs | 199.8 μs | 91.6 μs | 36.5 μs | 83.8 μs | Linear (36.6 μs) | 1.00x | +| sqrt | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_uniform | 1024 | 4 | 940 ns | 200 ns | 170 ns | 270 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| sqrt | sorted_uniform | 1024 | 16 | 1.8 μs | 630 ns | 480 ns | 930 ns | 450 ns | 490 ns | 420 ns | Binary (450 ns) | 1.09x | +| sqrt | sorted_uniform | 1024 | 64 | 1.9 μs | 1.7 μs | 1.3 μs | 3.8 μs | 1.9 μs | 1.3 μs | 1.7 μs | ExpFromLeft (1.3 μs) | 1.02x | +| sqrt | sorted_uniform | 1024 | 256 | 3.6 μs | 5.0 μs | 3.7 μs | 14.8 μs | 8.1 μs | 3.7 μs | 7.3 μs | Linear (3.6 μs) | 1.03x | +| sqrt | sorted_uniform | 1024 | 1024 | 10.0 μs | 17.9 μs | 12.6 μs | 65.4 μs | 48.9 μs | 10.2 μs | 44.0 μs | Linear (10.0 μs) | 1.02x | +| sqrt | sorted_uniform | 1024 | 4096 | 45.3 μs | 69.9 μs | 54.0 μs | 262.1 μs | 183.8 μs | 45.0 μs | 182.8 μs | Linear (45.3 μs) | 0.99x | +| sqrt | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_uniform | 4096 | 4 | 2.6 μs | 220 ns | 190 ns | 290 ns | 160 ns | 209 ns | 150 ns | Binary (160 ns) | 1.31x | +| sqrt | sorted_uniform | 4096 | 16 | 5.9 μs | 690 ns | 520 ns | 1.1 μs | 520 ns | 550 ns | 480 ns | ExpFromLeft (520 ns) | 1.06x | +| sqrt | sorted_uniform | 4096 | 64 | 6.8 μs | 2.2 μs | 1.7 μs | 4.3 μs | 2.1 μs | 1.7 μs | 2.0 μs | ExpFromLeft (1.7 μs) | 1.02x | +| sqrt | sorted_uniform | 4096 | 256 | 8.5 μs | 7.2 μs | 5.0 μs | 17.8 μs | 11.3 μs | 5.2 μs | 10.6 μs | ExpFromLeft (5.0 μs) | 1.03x | +| sqrt | sorted_uniform | 4096 | 1024 | 15.8 μs | 22.6 μs | 15.9 μs | 82.6 μs | 83.3 μs | 15.8 μs | 79.0 μs | Linear (15.8 μs) | 1.00x | +| sqrt | sorted_uniform | 4096 | 4096 | 63.1 μs | 90.4 μs | 68.0 μs | 350.5 μs | 286.2 μs | 58.5 μs | 278.1 μs | Linear (63.1 μs) | 0.93x | +| sqrt | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_uniform | 16384 | 4 | 8.1 μs | 240 ns | 200 ns | 350 ns | 170 ns | 230 ns | 160 ns | Binary (170 ns) | 1.35x | +| sqrt | sorted_uniform | 16384 | 16 | 24.2 μs | 870 ns | 650 ns | 1.2 μs | 630 ns | 680 ns | 560 ns | Binary (630 ns) | 1.08x | +| sqrt | sorted_uniform | 16384 | 64 | 22.8 μs | 2.9 μs | 2.2 μs | 5.0 μs | 2.4 μs | 2.2 μs | 2.2 μs | ExpFromLeft (2.2 μs) | 1.03x | +| sqrt | sorted_uniform | 16384 | 256 | 27.4 μs | 8.9 μs | 6.7 μs | 19.9 μs | 13.7 μs | 6.7 μs | 13.0 μs | ExpFromLeft (6.7 μs) | 1.01x | +| sqrt | sorted_uniform | 16384 | 1024 | 38.6 μs | 32.8 μs | 24.5 μs | 108.5 μs | 114.8 μs | 23.8 μs | 113.4 μs | ExpFromLeft (24.5 μs) | 0.97x | +| sqrt | sorted_uniform | 16384 | 4096 | 108.5 μs | 149.5 μs | 114.0 μs | 464.3 μs | 381.7 μs | 104.7 μs | 374.0 μs | Linear (108.5 μs) | 0.96x | +| sqrt | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 109 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | sorted_uniform | 65536 | 4 | 31.0 μs | 290 ns | 219 ns | 400 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | +| sqrt | sorted_uniform | 65536 | 16 | 82.0 μs | 1.0 μs | 750 ns | 1.5 μs | 690 ns | 760 ns | 650 ns | Binary (690 ns) | 1.10x | +| sqrt | sorted_uniform | 65536 | 64 | 92.8 μs | 3.6 μs | 2.6 μs | 5.8 μs | 2.9 μs | 2.7 μs | 2.8 μs | ExpFromLeft (2.6 μs) | 1.02x | +| sqrt | sorted_uniform | 65536 | 256 | 99.3 μs | 12.0 μs | 8.9 μs | 25.2 μs | 16.8 μs | 9.2 μs | 16.3 μs | ExpFromLeft (8.9 μs) | 1.03x | +| sqrt | sorted_uniform | 65536 | 1024 | 113.3 μs | 53.5 μs | 38.6 μs | 152.8 μs | 142.6 μs | 36.9 μs | 147.9 μs | ExpFromLeft (38.6 μs) | 0.96x | +| sqrt | sorted_uniform | 65536 | 4096 | 182.1 μs | 240.1 μs | 188.3 μs | 611.1 μs | 470.7 μs | 190.8 μs | 470.1 μs | Linear (182.1 μs) | 1.05x | +| sqrt | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| sqrt | sorted_dense_burst | 16 | 4 | 80 ns | 90 ns | 90 ns | 179 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| sqrt | sorted_dense_burst | 16 | 16 | 170 ns | 270 ns | 240 ns | 620 ns | 230 ns | 180 ns | 180 ns | Linear (170 ns) | 1.06x | +| sqrt | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 740 ns | 2.3 μs | 780 ns | 570 ns | 649 ns | Linear (550 ns) | 1.04x | +| sqrt | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.7 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.03x | +| sqrt | sorted_dense_burst | 16 | 1024 | 11.1 μs | 18.5 μs | 14.0 μs | 35.1 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (11.1 μs) | 0.70x | +| sqrt | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.9 μs | 41.9 μs | 139.9 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| sqrt | sorted_dense_burst | 64 | 4 | 90 ns | 110 ns | 100 ns | 200 ns | 110 ns | 100 ns | 90 ns | Linear (90 ns) | 1.11x | +| sqrt | sorted_dense_burst | 64 | 16 | 170 ns | 280 ns | 220 ns | 710 ns | 300 ns | 200 ns | 270 ns | Linear (170 ns) | 1.18x | +| sqrt | sorted_dense_burst | 64 | 64 | 550 ns | 939 ns | 730 ns | 2.6 μs | 1.1 μs | 580 ns | 940 ns | Linear (550 ns) | 1.05x | +| sqrt | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 10.2 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | +| sqrt | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.7 μs | 10.5 μs | 40.6 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | +| sqrt | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 161.9 μs | 66.5 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_dense_burst | 256 | 4 | 80 ns | 100 ns | 100 ns | 230 ns | 130 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | +| sqrt | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 240 ns | 850 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| sqrt | sorted_dense_burst | 256 | 64 | 760 ns | 1.2 μs | 940 ns | 3.3 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (760 ns) | 0.78x | +| sqrt | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 12.6 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.01x | +| sqrt | sorted_dense_burst | 256 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 50.4 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.8 μs) | 1.01x | +| sqrt | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.1 μs | 42.1 μs | 200.6 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 90 ns | 270 ns | 140 ns | 120 ns | 130 ns | ExpFromLeft (90 ns) | 1.33x | +| sqrt | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 240 ns | 1.0 μs | 450 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | +| sqrt | sorted_dense_burst | 1024 | 64 | 560 ns | 930 ns | 740 ns | 3.9 μs | 1.7 μs | 589 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| sqrt | sorted_dense_burst | 1024 | 256 | 2.8 μs | 4.7 μs | 3.6 μs | 15.5 μs | 6.8 μs | 2.9 μs | 5.9 μs | Linear (2.8 μs) | 1.01x | +| sqrt | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 60.5 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | +| sqrt | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 42.1 μs | 241.7 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 110 ns | 310 ns | 160 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | +| sqrt | sorted_dense_burst | 4096 | 16 | 190 ns | 290 ns | 240 ns | 1.2 μs | 530 ns | 210 ns | 490 ns | Linear (190 ns) | 1.11x | +| sqrt | sorted_dense_burst | 4096 | 64 | 560 ns | 930 ns | 740 ns | 4.5 μs | 2.0 μs | 600 ns | 1.8 μs | Linear (560 ns) | 1.07x | +| sqrt | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 17.6 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| sqrt | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 70.4 μs | 31.1 μs | 7.8 μs | 28.5 μs | Linear (7.7 μs) | 1.01x | +| sqrt | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 281.6 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 350 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | +| sqrt | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 1.3 μs | 600 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | +| sqrt | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 750 ns | 5.1 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | +| sqrt | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 20.2 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | +| sqrt | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 80.5 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | +| sqrt | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.1 μs | 42.1 μs | 321.9 μs | 144.1 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 390 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| sqrt | sorted_dense_burst | 65536 | 16 | 190 ns | 290 ns | 250 ns | 1.5 μs | 690 ns | 220 ns | 630 ns | Linear (190 ns) | 1.16x | +| sqrt | sorted_dense_burst | 65536 | 64 | 570 ns | 950 ns | 740 ns | 5.8 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| sqrt | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 23.3 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | +| sqrt | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 92.7 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.00x | +| sqrt | sorted_dense_burst | 65536 | 4096 | 44.3 μs | 73.8 μs | 55.8 μs | 371.4 μs | 163.2 μs | 30.8 μs | 152.5 μs | Linear (44.3 μs) | 0.70x | +| sqrt | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| sqrt | sorted_near_start | 16 | 4 | 80 ns | 100 ns | 100 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| sqrt | sorted_near_start | 16 | 16 | 180 ns | 280 ns | 240 ns | 510 ns | 220 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | +| sqrt | sorted_near_start | 16 | 64 | 570 ns | 940 ns | 749 ns | 2.0 μs | 800 ns | 600 ns | 670 ns | Linear (570 ns) | 1.05x | +| sqrt | sorted_near_start | 16 | 256 | 2.8 μs | 4.7 μs | 3.6 μs | 8.2 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.8 μs) | 0.72x | +| sqrt | sorted_near_start | 16 | 1024 | 7.8 μs | 14.0 μs | 10.7 μs | 30.1 μs | 12.2 μs | 7.9 μs | 10.3 μs | Linear (7.8 μs) | 1.00x | +| sqrt | sorted_near_start | 16 | 4096 | 31.1 μs | 55.2 μs | 42.2 μs | 119.1 μs | 47.7 μs | 31.1 μs | 40.3 μs | Linear (31.1 μs) | 1.00x | +| sqrt | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 70 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| sqrt | sorted_near_start | 64 | 4 | 100 ns | 110 ns | 100 ns | 180 ns | 100 ns | 120 ns | 90 ns | ExpFromLeft (100 ns) | 1.20x | +| sqrt | sorted_near_start | 64 | 16 | 210 ns | 290 ns | 230 ns | 560 ns | 360 ns | 230 ns | 310 ns | Linear (210 ns) | 1.10x | +| sqrt | sorted_near_start | 64 | 64 | 660 ns | 1.0 μs | 820 ns | 2.2 μs | 1.1 μs | 700 ns | 990 ns | Linear (660 ns) | 1.06x | +| sqrt | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 8.6 μs | 4.2 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | +| sqrt | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 33.8 μs | 16.9 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.00x | +| sqrt | sorted_near_start | 64 | 4096 | 31.6 μs | 56.2 μs | 43.0 μs | 134.8 μs | 67.0 μs | 31.6 μs | 60.1 μs | Linear (31.6 μs) | 1.00x | +| sqrt | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 70 ns | 50 ns | ExpFromLeft (60 ns) | 1.17x | +| sqrt | sorted_near_start | 256 | 4 | 260 ns | 140 ns | 120 ns | 200 ns | 130 ns | 130 ns | 110 ns | ExpFromLeft (120 ns) | 1.08x | +| sqrt | sorted_near_start | 256 | 16 | 300 ns | 330 ns | 250 ns | 659 ns | 400 ns | 270 ns | 350 ns | ExpFromLeft (250 ns) | 1.08x | +| sqrt | sorted_near_start | 256 | 64 | 900 ns | 1.1 μs | 860 ns | 2.6 μs | 1.6 μs | 900 ns | 1.4 μs | ExpFromLeft (860 ns) | 1.05x | +| sqrt | sorted_near_start | 256 | 256 | 2.6 μs | 3.9 μs | 3.1 μs | 10.7 μs | 5.6 μs | 2.6 μs | 5.2 μs | Linear (2.6 μs) | 1.00x | +| sqrt | sorted_near_start | 256 | 1024 | 8.7 μs | 14.4 μs | 11.0 μs | 42.4 μs | 22.4 μs | 8.8 μs | 20.4 μs | Linear (8.7 μs) | 1.02x | +| sqrt | sorted_near_start | 256 | 4096 | 31.5 μs | 56.2 μs | 42.6 μs | 167.5 μs | 89.1 μs | 31.7 μs | 82.2 μs | Linear (31.5 μs) | 1.01x | +| sqrt | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| sqrt | sorted_near_start | 1024 | 4 | 1.0 μs | 180 ns | 160 ns | 250 ns | 140 ns | 180 ns | 130 ns | Binary (140 ns) | 1.29x | +| sqrt | sorted_near_start | 1024 | 16 | 1.3 μs | 410 ns | 320 ns | 840 ns | 450 ns | 350 ns | 450 ns | ExpFromLeft (320 ns) | 1.09x | +| sqrt | sorted_near_start | 1024 | 64 | 1.8 μs | 1.2 μs | 880 ns | 3.3 μs | 2.1 μs | 930 ns | 1.9 μs | ExpFromLeft (880 ns) | 1.06x | +| sqrt | sorted_near_start | 1024 | 256 | 3.6 μs | 4.5 μs | 3.3 μs | 13.5 μs | 7.6 μs | 3.6 μs | 7.0 μs | ExpFromLeft (3.3 μs) | 1.09x | +| sqrt | sorted_near_start | 1024 | 1024 | 10.4 μs | 15.8 μs | 12.2 μs | 53.4 μs | 27.4 μs | 10.5 μs | 25.5 μs | Linear (10.4 μs) | 1.01x | +| sqrt | sorted_near_start | 1024 | 4096 | 33.8 μs | 58.0 μs | 44.1 μs | 211.7 μs | 111.5 μs | 34.0 μs | 105.3 μs | Linear (33.8 μs) | 1.01x | +| sqrt | sorted_near_start | 4096 | 1 | 70 ns | 60 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | +| sqrt | sorted_near_start | 4096 | 4 | 900 ns | 170 ns | 160 ns | 280 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (160 ns) | 1.06x | +| sqrt | sorted_near_start | 4096 | 16 | 5.1 μs | 530 ns | 420 ns | 960 ns | 520 ns | 450 ns | 490 ns | ExpFromLeft (420 ns) | 1.07x | +| sqrt | sorted_near_start | 4096 | 64 | 4.3 μs | 1.5 μs | 1.1 μs | 3.9 μs | 2.5 μs | 1.1 μs | 2.3 μs | ExpFromLeft (1.1 μs) | 1.04x | +| sqrt | sorted_near_start | 4096 | 256 | 8.1 μs | 4.8 μs | 3.4 μs | 15.9 μs | 10.5 μs | 3.5 μs | 9.7 μs | ExpFromLeft (3.4 μs) | 1.02x | +| sqrt | sorted_near_start | 4096 | 1024 | 16.3 μs | 18.4 μs | 14.0 μs | 67.1 μs | 42.6 μs | 16.1 μs | 37.3 μs | ExpFromLeft (14.0 μs) | 1.15x | +| sqrt | sorted_near_start | 4096 | 4096 | 43.0 μs | 63.3 μs | 49.1 μs | 271.4 μs | 156.0 μs | 43.0 μs | 140.1 μs | Linear (43.0 μs) | 1.00x | +| sqrt | sorted_near_start | 16384 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_near_start | 16384 | 4 | 3.1 μs | 230 ns | 180 ns | 320 ns | 190 ns | 220 ns | 170 ns | ExpFromLeft (180 ns) | 1.22x | +| sqrt | sorted_near_start | 16384 | 16 | 17.3 μs | 630 ns | 500 ns | 1.2 μs | 600 ns | 500 ns | 550 ns | ExpFromLeft (500 ns) | 1.00x | +| sqrt | sorted_near_start | 16384 | 64 | 15.3 μs | 1.8 μs | 1.4 μs | 4.4 μs | 3.0 μs | 1.4 μs | 2.9 μs | ExpFromLeft (1.4 μs) | 1.02x | +| sqrt | sorted_near_start | 16384 | 256 | 24.6 μs | 5.9 μs | 4.2 μs | 18.8 μs | 17.9 μs | 4.3 μs | 16.5 μs | ExpFromLeft (4.2 μs) | 1.01x | +| sqrt | sorted_near_start | 16384 | 1024 | 33.4 μs | 21.2 μs | 14.8 μs | 83.0 μs | 73.8 μs | 15.3 μs | 69.0 μs | ExpFromLeft (14.8 μs) | 1.03x | +| sqrt | sorted_near_start | 16384 | 4096 | 70.4 μs | 77.6 μs | 60.7 μs | 364.8 μs | 246.2 μs | 70.3 μs | 231.9 μs | ExpFromLeft (60.7 μs) | 1.16x | +| sqrt | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | sorted_near_start | 65536 | 4 | 74.8 μs | 260 ns | 230 ns | 370 ns | 200 ns | 240 ns | 180 ns | Binary (200 ns) | 1.20x | +| sqrt | sorted_near_start | 65536 | 16 | 36.1 μs | 710 ns | 540 ns | 1.3 μs | 770 ns | 560 ns | 740 ns | ExpFromLeft (540 ns) | 1.04x | +| sqrt | sorted_near_start | 65536 | 64 | 82.6 μs | 2.4 μs | 1.8 μs | 5.1 μs | 3.7 μs | 1.8 μs | 3.6 μs | ExpFromLeft (1.8 μs) | 1.02x | +| sqrt | sorted_near_start | 65536 | 256 | 72.4 μs | 7.6 μs | 5.7 μs | 21.7 μs | 20.3 μs | 5.6 μs | 18.7 μs | ExpFromLeft (5.7 μs) | 0.99x | +| sqrt | sorted_near_start | 65536 | 1024 | 102.0 μs | 27.0 μs | 19.4 μs | 109.6 μs | 90.3 μs | 19.1 μs | 86.5 μs | ExpFromLeft (19.4 μs) | 0.98x | +| sqrt | sorted_near_start | 65536 | 4096 | 152.8 μs | 114.1 μs | 89.4 μs | 477.5 μs | 310.2 μs | 88.1 μs | 289.8 μs | ExpFromLeft (89.4 μs) | 0.99x | +| sqrt | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| sqrt | sorted_arithmetic | 16 | 4 | 100 ns | 120 ns | 110 ns | 160 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | +| sqrt | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 220 ns | 540 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| sqrt | sorted_arithmetic | 16 | 64 | 559 ns | 1.1 μs | 750 ns | 2.1 μs | 1.1 μs | 590 ns | 890 ns | Linear (559 ns) | 1.06x | +| sqrt | sorted_arithmetic | 16 | 256 | 2.3 μs | 3.8 μs | 3.0 μs | 8.6 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | +| sqrt | sorted_arithmetic | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 32.8 μs | 12.0 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | +| sqrt | sorted_arithmetic | 16 | 4096 | 31.1 μs | 55.8 μs | 42.4 μs | 129.1 μs | 47.2 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | +| sqrt | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 50 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| sqrt | sorted_arithmetic | 64 | 4 | 170 ns | 140 ns | 120 ns | 170 ns | 110 ns | 140 ns | 100 ns | Binary (110 ns) | 1.27x | +| sqrt | sorted_arithmetic | 64 | 16 | 270 ns | 370 ns | 290 ns | 660 ns | 300 ns | 300 ns | 270 ns | Linear (270 ns) | 1.11x | +| sqrt | sorted_arithmetic | 64 | 64 | 640 ns | 1.1 μs | 750 ns | 2.6 μs | 1.3 μs | 660 ns | 1.1 μs | Linear (640 ns) | 1.03x | +| sqrt | sorted_arithmetic | 64 | 256 | 2.4 μs | 4.1 μs | 3.1 μs | 10.8 μs | 5.4 μs | 2.5 μs | 5.0 μs | Linear (2.4 μs) | 1.02x | +| sqrt | sorted_arithmetic | 64 | 1024 | 9.1 μs | 14.9 μs | 11.7 μs | 43.2 μs | 17.7 μs | 9.1 μs | 16.0 μs | Linear (9.1 μs) | 1.00x | +| sqrt | sorted_arithmetic | 64 | 4096 | 45.2 μs | 74.8 μs | 56.6 μs | 164.8 μs | 67.0 μs | 32.2 μs | 60.2 μs | Linear (45.2 μs) | 0.71x | +| sqrt | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_arithmetic | 256 | 4 | 480 ns | 160 ns | 150 ns | 190 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | +| sqrt | sorted_arithmetic | 256 | 16 | 530 ns | 470 ns | 370 ns | 760 ns | 370 ns | 400 ns | 330 ns | ExpFromLeft (370 ns) | 1.08x | +| sqrt | sorted_arithmetic | 256 | 64 | 960 ns | 1.4 μs | 1.0 μs | 3.0 μs | 1.4 μs | 930 ns | 1.2 μs | Linear (960 ns) | 0.97x | +| sqrt | sorted_arithmetic | 256 | 256 | 2.5 μs | 4.5 μs | 3.0 μs | 12.4 μs | 6.4 μs | 2.6 μs | 6.0 μs | Linear (2.5 μs) | 1.01x | +| sqrt | sorted_arithmetic | 256 | 1024 | 9.7 μs | 16.2 μs | 12.3 μs | 53.6 μs | 28.0 μs | 9.7 μs | 25.9 μs | Linear (9.7 μs) | 1.00x | +| sqrt | sorted_arithmetic | 256 | 4096 | 47.0 μs | 58.7 μs | 45.2 μs | 200.5 μs | 90.7 μs | 34.9 μs | 83.8 μs | ExpFromLeft (45.2 μs) | 0.77x | +| sqrt | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| sqrt | sorted_arithmetic | 1024 | 4 | 1.6 μs | 200 ns | 180 ns | 210 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| sqrt | sorted_arithmetic | 1024 | 16 | 1.8 μs | 610 ns | 480 ns | 890 ns | 440 ns | 500 ns | 420 ns | Binary (440 ns) | 1.14x | +| sqrt | sorted_arithmetic | 1024 | 64 | 2.2 μs | 1.8 μs | 1.4 μs | 3.6 μs | 1.7 μs | 1.4 μs | 1.5 μs | ExpFromLeft (1.4 μs) | 1.04x | +| sqrt | sorted_arithmetic | 1024 | 256 | 3.7 μs | 5.7 μs | 4.3 μs | 15.2 μs | 7.3 μs | 3.7 μs | 7.8 μs | Linear (3.7 μs) | 1.00x | +| sqrt | sorted_arithmetic | 1024 | 1024 | 10.7 μs | 18.4 μs | 12.3 μs | 63.9 μs | 69.2 μs | 10.8 μs | 67.6 μs | Linear (10.7 μs) | 1.01x | +| sqrt | sorted_arithmetic | 1024 | 4096 | 38.9 μs | 62.4 μs | 47.7 μs | 270.5 μs | 200.8 μs | 49.7 μs | 196.3 μs | Linear (38.9 μs) | 1.28x | +| sqrt | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_arithmetic | 4096 | 4 | 6.0 μs | 230 ns | 190 ns | 230 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | +| sqrt | sorted_arithmetic | 4096 | 16 | 6.2 μs | 760 ns | 570 ns | 1.0 μs | 530 ns | 600 ns | 480 ns | Binary (530 ns) | 1.13x | +| sqrt | sorted_arithmetic | 4096 | 64 | 7.0 μs | 2.4 μs | 1.8 μs | 4.2 μs | 2.0 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.8 μs) | 1.03x | +| sqrt | sorted_arithmetic | 4096 | 256 | 8.7 μs | 7.4 μs | 5.5 μs | 17.5 μs | 11.4 μs | 5.6 μs | 10.1 μs | ExpFromLeft (5.5 μs) | 1.03x | +| sqrt | sorted_arithmetic | 4096 | 1024 | 16.4 μs | 23.9 μs | 18.1 μs | 85.5 μs | 92.4 μs | 16.3 μs | 86.4 μs | Linear (16.4 μs) | 1.00x | +| sqrt | sorted_arithmetic | 4096 | 4096 | 44.0 μs | 73.6 μs | 49.7 μs | 355.0 μs | 306.9 μs | 44.1 μs | 293.1 μs | Linear (44.0 μs) | 1.00x | +| sqrt | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 119 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_arithmetic | 16384 | 4 | 23.4 μs | 270 ns | 220 ns | 250 ns | 180 ns | 250 ns | 170 ns | Binary (180 ns) | 1.39x | +| sqrt | sorted_arithmetic | 16384 | 16 | 23.9 μs | 910 ns | 680 ns | 1.2 μs | 600 ns | 700 ns | 570 ns | Binary (600 ns) | 1.17x | +| sqrt | sorted_arithmetic | 16384 | 64 | 24.5 μs | 3.1 μs | 2.3 μs | 4.9 μs | 2.5 μs | 2.3 μs | 2.3 μs | ExpFromLeft (2.3 μs) | 1.01x | +| sqrt | sorted_arithmetic | 16384 | 256 | 28.9 μs | 10.0 μs | 7.4 μs | 20.1 μs | 15.0 μs | 7.4 μs | 13.9 μs | ExpFromLeft (7.4 μs) | 1.01x | +| sqrt | sorted_arithmetic | 16384 | 1024 | 35.8 μs | 32.0 μs | 23.8 μs | 110.8 μs | 121.2 μs | 24.3 μs | 119.4 μs | ExpFromLeft (23.8 μs) | 1.02x | +| sqrt | sorted_arithmetic | 16384 | 4096 | 65.8 μs | 96.7 μs | 72.0 μs | 477.3 μs | 409.7 μs | 65.8 μs | 395.6 μs | Linear (65.8 μs) | 1.00x | +| sqrt | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | sorted_arithmetic | 65536 | 4 | 93.0 μs | 300 ns | 250 ns | 270 ns | 200 ns | 280 ns | 190 ns | Binary (200 ns) | 1.40x | +| sqrt | sorted_arithmetic | 65536 | 16 | 93.4 μs | 1.4 μs | 1.0 μs | 1.4 μs | 710 ns | 810 ns | 640 ns | Binary (710 ns) | 1.14x | +| sqrt | sorted_arithmetic | 65536 | 64 | 95.2 μs | 3.6 μs | 2.7 μs | 5.7 μs | 2.8 μs | 2.7 μs | 2.7 μs | ExpFromLeft (2.7 μs) | 1.01x | +| sqrt | sorted_arithmetic | 65536 | 256 | 97.8 μs | 13.2 μs | 10.1 μs | 23.9 μs | 15.9 μs | 10.2 μs | 15.6 μs | ExpFromLeft (10.1 μs) | 1.01x | +| sqrt | sorted_arithmetic | 65536 | 1024 | 111.7 μs | 45.2 μs | 34.4 μs | 159.6 μs | 147.9 μs | 34.5 μs | 153.0 μs | ExpFromLeft (34.4 μs) | 1.00x | +| sqrt | sorted_arithmetic | 65536 | 4096 | 142.1 μs | 131.1 μs | 99.8 μs | 643.9 μs | 495.4 μs | 101.4 μs | 499.6 μs | ExpFromLeft (99.8 μs) | 1.02x | +| sqrt | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 60 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| sqrt | sorted_geometric | 16 | 4 | 100 ns | 120 ns | 100 ns | 150 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | +| sqrt | sorted_geometric | 16 | 16 | 190 ns | 290 ns | 220 ns | 510 ns | 240 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| sqrt | sorted_geometric | 16 | 64 | 590 ns | 970 ns | 750 ns | 2.0 μs | 1.0 μs | 790 ns | 840 ns | Linear (590 ns) | 1.34x | +| sqrt | sorted_geometric | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 8.1 μs | 3.3 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.02x | +| sqrt | sorted_geometric | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 31.4 μs | 12.2 μs | 8.1 μs | 10.3 μs | Linear (8.1 μs) | 1.00x | +| sqrt | sorted_geometric | 16 | 4096 | 31.1 μs | 55.7 μs | 42.3 μs | 123.1 μs | 47.6 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | +| sqrt | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| sqrt | sorted_geometric | 64 | 4 | 170 ns | 130 ns | 120 ns | 170 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | +| sqrt | sorted_geometric | 64 | 16 | 259 ns | 340 ns | 260 ns | 600 ns | 300 ns | 280 ns | 260 ns | Linear (259 ns) | 1.08x | +| sqrt | sorted_geometric | 64 | 64 | 650 ns | 1.1 μs | 790 ns | 2.4 μs | 1.2 μs | 700 ns | 1.1 μs | Linear (650 ns) | 1.08x | +| sqrt | sorted_geometric | 64 | 256 | 2.3 μs | 3.9 μs | 2.9 μs | 9.9 μs | 4.9 μs | 2.3 μs | 4.3 μs | Linear (2.3 μs) | 1.00x | +| sqrt | sorted_geometric | 64 | 1024 | 8.6 μs | 14.8 μs | 11.4 μs | 38.8 μs | 17.6 μs | 8.6 μs | 16.0 μs | Linear (8.6 μs) | 1.00x | +| sqrt | sorted_geometric | 64 | 4096 | 32.1 μs | 56.4 μs | 43.2 μs | 149.3 μs | 67.0 μs | 32.2 μs | 60.4 μs | Linear (32.1 μs) | 1.00x | +| sqrt | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_geometric | 256 | 4 | 450 ns | 150 ns | 130 ns | 180 ns | 130 ns | 160 ns | 110 ns | ExpFromLeft (130 ns) | 1.23x | +| sqrt | sorted_geometric | 256 | 16 | 640 ns | 470 ns | 420 ns | 730 ns | 400 ns | 440 ns | 350 ns | Binary (400 ns) | 1.10x | +| sqrt | sorted_geometric | 256 | 64 | 920 ns | 1.3 μs | 980 ns | 2.8 μs | 1.5 μs | 960 ns | 1.4 μs | Linear (920 ns) | 1.04x | +| sqrt | sorted_geometric | 256 | 256 | 2.5 μs | 4.3 μs | 3.0 μs | 11.7 μs | 6.1 μs | 2.5 μs | 5.7 μs | Linear (2.5 μs) | 1.01x | +| sqrt | sorted_geometric | 256 | 1024 | 9.2 μs | 15.6 μs | 11.6 μs | 48.8 μs | 25.0 μs | 9.2 μs | 23.7 μs | Linear (9.2 μs) | 1.01x | +| sqrt | sorted_geometric | 256 | 4096 | 34.1 μs | 58.6 μs | 44.8 μs | 187.2 μs | 90.8 μs | 34.0 μs | 84.0 μs | Linear (34.1 μs) | 1.00x | +| sqrt | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_geometric | 1024 | 4 | 1.5 μs | 200 ns | 160 ns | 200 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| sqrt | sorted_geometric | 1024 | 16 | 1.7 μs | 550 ns | 410 ns | 830 ns | 440 ns | 460 ns | 410 ns | ExpFromLeft (410 ns) | 1.12x | +| sqrt | sorted_geometric | 1024 | 64 | 2.1 μs | 1.6 μs | 1.2 μs | 3.4 μs | 1.8 μs | 1.2 μs | 1.7 μs | ExpFromLeft (1.2 μs) | 1.03x | +| sqrt | sorted_geometric | 1024 | 256 | 3.6 μs | 5.2 μs | 3.7 μs | 14.0 μs | 7.3 μs | 3.6 μs | 7.1 μs | Linear (3.6 μs) | 1.01x | +| sqrt | sorted_geometric | 1024 | 1024 | 10.5 μs | 17.8 μs | 12.6 μs | 60.3 μs | 38.4 μs | 10.5 μs | 35.3 μs | Linear (10.5 μs) | 1.00x | +| sqrt | sorted_geometric | 1024 | 4096 | 36.7 μs | 62.4 μs | 46.7 μs | 243.4 μs | 179.3 μs | 36.9 μs | 174.5 μs | Linear (36.7 μs) | 1.00x | +| sqrt | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| sqrt | sorted_geometric | 4096 | 4 | 5.6 μs | 220 ns | 190 ns | 220 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | +| sqrt | sorted_geometric | 4096 | 16 | 6.0 μs | 670 ns | 510 ns | 960 ns | 530 ns | 540 ns | 490 ns | ExpFromLeft (510 ns) | 1.06x | +| sqrt | sorted_geometric | 4096 | 64 | 6.7 μs | 2.1 μs | 1.6 μs | 4.0 μs | 2.1 μs | 1.6 μs | 1.9 μs | ExpFromLeft (1.6 μs) | 1.03x | +| sqrt | sorted_geometric | 4096 | 256 | 8.6 μs | 6.6 μs | 4.9 μs | 16.2 μs | 9.9 μs | 5.0 μs | 9.0 μs | ExpFromLeft (4.9 μs) | 1.03x | +| sqrt | sorted_geometric | 4096 | 1024 | 15.7 μs | 21.5 μs | 15.7 μs | 76.2 μs | 67.3 μs | 15.9 μs | 59.4 μs | Linear (15.7 μs) | 1.01x | +| sqrt | sorted_geometric | 4096 | 4096 | 43.8 μs | 72.2 μs | 51.6 μs | 327.5 μs | 254.1 μs | 43.9 μs | 244.7 μs | Linear (43.8 μs) | 1.00x | +| sqrt | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| sqrt | sorted_geometric | 16384 | 4 | 23.4 μs | 250 ns | 220 ns | 230 ns | 180 ns | 240 ns | 170 ns | Binary (180 ns) | 1.33x | +| sqrt | sorted_geometric | 16384 | 16 | 23.7 μs | 810 ns | 600 ns | 1.1 μs | 600 ns | 630 ns | 560 ns | ExpFromLeft (600 ns) | 1.05x | +| sqrt | sorted_geometric | 16384 | 64 | 24.4 μs | 2.7 μs | 2.0 μs | 4.6 μs | 2.8 μs | 2.0 μs | 2.5 μs | ExpFromLeft (2.0 μs) | 1.02x | +| sqrt | sorted_geometric | 16384 | 256 | 26.8 μs | 8.7 μs | 6.4 μs | 19.1 μs | 15.9 μs | 6.3 μs | 14.5 μs | ExpFromLeft (6.4 μs) | 1.00x | +| sqrt | sorted_geometric | 16384 | 1024 | 35.9 μs | 27.2 μs | 20.2 μs | 101.0 μs | 97.0 μs | 20.7 μs | 91.5 μs | ExpFromLeft (20.2 μs) | 1.02x | +| sqrt | sorted_geometric | 16384 | 4096 | 65.3 μs | 89.2 μs | 65.7 μs | 435.2 μs | 347.9 μs | 65.4 μs | 341.0 μs | Linear (65.3 μs) | 1.00x | +| sqrt | sorted_geometric | 65536 | 1 | 80 ns | 79 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | +| sqrt | sorted_geometric | 65536 | 4 | 88.3 μs | 290 ns | 240 ns | 260 ns | 210 ns | 270 ns | 190 ns | Binary (210 ns) | 1.29x | +| sqrt | sorted_geometric | 65536 | 16 | 88.2 μs | 980 ns | 730 ns | 1.3 μs | 680 ns | 730 ns | 650 ns | Binary (680 ns) | 1.07x | +| sqrt | sorted_geometric | 65536 | 64 | 91.0 μs | 3.3 μs | 2.4 μs | 5.4 μs | 3.1 μs | 2.5 μs | 2.8 μs | ExpFromLeft (2.4 μs) | 1.01x | +| sqrt | sorted_geometric | 65536 | 256 | 96.0 μs | 10.9 μs | 8.1 μs | 23.2 μs | 20.0 μs | 8.2 μs | 17.5 μs | ExpFromLeft (8.1 μs) | 1.00x | +| sqrt | sorted_geometric | 65536 | 1024 | 107.7 μs | 41.4 μs | 30.3 μs | 144.0 μs | 124.0 μs | 30.0 μs | 124.0 μs | ExpFromLeft (30.3 μs) | 0.99x | +| sqrt | sorted_geometric | 65536 | 4096 | 142.4 μs | 119.2 μs | 90.8 μs | 578.3 μs | 433.7 μs | 91.4 μs | 424.1 μs | ExpFromLeft (90.8 μs) | 1.01x | +| sqrt | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| sqrt | sorted_bimodal | 16 | 4 | 90 ns | 110 ns | 100 ns | 150 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | +| sqrt | sorted_bimodal | 16 | 16 | 190 ns | 290 ns | 210 ns | 489 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| sqrt | sorted_bimodal | 16 | 64 | 580 ns | 950 ns | 760 ns | 1.9 μs | 860 ns | 610 ns | 760 ns | Linear (580 ns) | 1.05x | +| sqrt | sorted_bimodal | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 7.2 μs | 3.2 μs | 2.1 μs | 2.7 μs | Linear (2.1 μs) | 1.01x | +| sqrt | sorted_bimodal | 16 | 1024 | 7.8 μs | 13.7 μs | 10.6 μs | 28.1 μs | 12.3 μs | 7.8 μs | 10.6 μs | Linear (7.8 μs) | 1.01x | +| sqrt | sorted_bimodal | 16 | 4096 | 30.9 μs | 54.1 μs | 42.1 μs | 111.7 μs | 49.1 μs | 30.9 μs | 42.0 μs | Linear (30.9 μs) | 1.00x | +| sqrt | sorted_bimodal | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| sqrt | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 120 ns | 170 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | +| sqrt | sorted_bimodal | 64 | 16 | 260 ns | 300 ns | 240 ns | 520 ns | 330 ns | 280 ns | 300 ns | ExpFromLeft (240 ns) | 1.17x | +| sqrt | sorted_bimodal | 64 | 64 | 640 ns | 990 ns | 760 ns | 2.1 μs | 1.2 μs | 680 ns | 1.2 μs | Linear (640 ns) | 1.06x | +| sqrt | sorted_bimodal | 64 | 256 | 2.2 μs | 4.9 μs | 3.7 μs | 8.5 μs | 4.3 μs | 2.3 μs | 4.0 μs | Linear (2.2 μs) | 1.01x | +| sqrt | sorted_bimodal | 64 | 1024 | 8.1 μs | 14.0 μs | 10.8 μs | 31.8 μs | 16.9 μs | 8.1 μs | 15.2 μs | Linear (8.1 μs) | 1.01x | +| sqrt | sorted_bimodal | 64 | 4096 | 31.1 μs | 54.9 μs | 42.3 μs | 126.8 μs | 66.6 μs | 31.1 μs | 60.2 μs | Linear (31.1 μs) | 1.00x | +| sqrt | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 80 ns | 80 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | +| sqrt | sorted_bimodal | 256 | 4 | 440 ns | 140 ns | 130 ns | 180 ns | 120 ns | 150 ns | 110 ns | Binary (120 ns) | 1.25x | +| sqrt | sorted_bimodal | 256 | 16 | 540 ns | 360 ns | 280 ns | 660 ns | 390 ns | 370 ns | 350 ns | ExpFromLeft (280 ns) | 1.32x | +| sqrt | sorted_bimodal | 256 | 64 | 920 ns | 1.1 μs | 800 ns | 2.5 μs | 1.7 μs | 940 ns | 1.5 μs | ExpFromLeft (800 ns) | 1.18x | +| sqrt | sorted_bimodal | 256 | 256 | 2.4 μs | 3.9 μs | 2.8 μs | 10.2 μs | 6.4 μs | 2.5 μs | 6.0 μs | Linear (2.4 μs) | 1.02x | +| sqrt | sorted_bimodal | 256 | 1024 | 9.1 μs | 14.7 μs | 11.5 μs | 40.1 μs | 22.6 μs | 9.1 μs | 20.7 μs | Linear (9.1 μs) | 1.00x | +| sqrt | sorted_bimodal | 256 | 4096 | 32.2 μs | 55.9 μs | 43.0 μs | 154.0 μs | 87.0 μs | 32.2 μs | 79.5 μs | Linear (32.2 μs) | 1.00x | +| sqrt | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_bimodal | 1024 | 4 | 1.4 μs | 150 ns | 140 ns | 220 ns | 140 ns | 160 ns | 120 ns | ExpFromLeft (140 ns) | 1.14x | +| sqrt | sorted_bimodal | 1024 | 16 | 1.6 μs | 420 ns | 330 ns | 750 ns | 500 ns | 350 ns | 440 ns | ExpFromLeft (330 ns) | 1.06x | +| sqrt | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 950 ns | 3.0 μs | 1.9 μs | 980 ns | 1.8 μs | ExpFromLeft (950 ns) | 1.03x | +| sqrt | sorted_bimodal | 1024 | 256 | 3.6 μs | 4.3 μs | 3.0 μs | 12.4 μs | 7.5 μs | 3.6 μs | 7.0 μs | ExpFromLeft (3.0 μs) | 1.21x | +| sqrt | sorted_bimodal | 1024 | 1024 | 9.9 μs | 15.5 μs | 11.7 μs | 49.8 μs | 30.2 μs | 10.3 μs | 28.4 μs | Linear (9.9 μs) | 1.04x | +| sqrt | sorted_bimodal | 1024 | 4096 | 36.5 μs | 58.6 μs | 45.8 μs | 195.3 μs | 108.1 μs | 36.6 μs | 101.5 μs | Linear (36.5 μs) | 1.00x | +| sqrt | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_bimodal | 4096 | 4 | 5.5 μs | 210 ns | 170 ns | 270 ns | 160 ns | 190 ns | 150 ns | Binary (160 ns) | 1.19x | +| sqrt | sorted_bimodal | 4096 | 16 | 5.9 μs | 570 ns | 450 ns | 910 ns | 520 ns | 470 ns | 480 ns | ExpFromLeft (450 ns) | 1.04x | +| sqrt | sorted_bimodal | 4096 | 64 | 5.9 μs | 1.5 μs | 1.1 μs | 3.5 μs | 2.3 μs | 1.2 μs | 2.2 μs | ExpFromLeft (1.1 μs) | 1.03x | +| sqrt | sorted_bimodal | 4096 | 256 | 7.8 μs | 4.8 μs | 3.6 μs | 15.0 μs | 10.5 μs | 3.7 μs | 9.5 μs | ExpFromLeft (3.6 μs) | 1.03x | +| sqrt | sorted_bimodal | 4096 | 1024 | 14.8 μs | 16.8 μs | 12.3 μs | 64.4 μs | 43.8 μs | 14.6 μs | 41.1 μs | ExpFromLeft (12.3 μs) | 1.18x | +| sqrt | sorted_bimodal | 4096 | 4096 | 45.2 μs | 66.3 μs | 49.0 μs | 261.8 μs | 170.5 μs | 44.8 μs | 157.4 μs | Linear (45.2 μs) | 0.99x | +| sqrt | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 80 ns | 110 ns | 70 ns | 70 ns | 60 ns | Binary (70 ns) | 1.00x | +| sqrt | sorted_bimodal | 16384 | 4 | 18.8 μs | 250 ns | 210 ns | 310 ns | 179 ns | 240 ns | 160 ns | Binary (179 ns) | 1.34x | +| sqrt | sorted_bimodal | 16384 | 16 | 22.9 μs | 680 ns | 520 ns | 1.1 μs | 650 ns | 550 ns | 650 ns | ExpFromLeft (520 ns) | 1.06x | +| sqrt | sorted_bimodal | 16384 | 64 | 23.9 μs | 2.0 μs | 1.5 μs | 4.3 μs | 3.1 μs | 1.5 μs | 3.0 μs | ExpFromLeft (1.5 μs) | 1.03x | +| sqrt | sorted_bimodal | 16384 | 256 | 24.1 μs | 6.0 μs | 4.4 μs | 17.3 μs | 14.9 μs | 4.6 μs | 14.8 μs | ExpFromLeft (4.4 μs) | 1.03x | +| sqrt | sorted_bimodal | 16384 | 1024 | 32.8 μs | 20.6 μs | 15.2 μs | 81.5 μs | 77.4 μs | 16.3 μs | 73.8 μs | ExpFromLeft (15.2 μs) | 1.07x | +| sqrt | sorted_bimodal | 16384 | 4096 | 68.2 μs | 75.1 μs | 55.8 μs | 366.4 μs | 246.8 μs | 67.4 μs | 235.8 μs | ExpFromLeft (55.8 μs) | 1.21x | +| sqrt | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | sorted_bimodal | 65536 | 4 | 84.1 μs | 280 ns | 230 ns | 340 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | +| sqrt | sorted_bimodal | 65536 | 16 | 83.5 μs | 780 ns | 600 ns | 1.2 μs | 720 ns | 600 ns | 670 ns | ExpFromLeft (600 ns) | 1.00x | +| sqrt | sorted_bimodal | 65536 | 64 | 92.0 μs | 2.5 μs | 1.9 μs | 4.8 μs | 3.4 μs | 1.9 μs | 3.2 μs | ExpFromLeft (1.9 μs) | 1.03x | +| sqrt | sorted_bimodal | 65536 | 256 | 96.2 μs | 7.9 μs | 5.8 μs | 20.2 μs | 18.6 μs | 5.9 μs | 17.0 μs | ExpFromLeft (5.8 μs) | 1.01x | +| sqrt | sorted_bimodal | 65536 | 1024 | 106.5 μs | 27.1 μs | 20.1 μs | 108.5 μs | 98.3 μs | 21.1 μs | 96.7 μs | ExpFromLeft (20.1 μs) | 1.05x | +| sqrt | sorted_bimodal | 65536 | 4096 | 152.5 μs | 115.3 μs | 88.0 μs | 469.1 μs | 314.1 μs | 85.6 μs | 301.3 μs | ExpFromLeft (88.0 μs) | 0.97x | +| sqrt | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| sqrt | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 160 ns | 90 ns | 100 ns | 80 ns | Linear (80 ns) | 1.25x | +| sqrt | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 210 ns | 560 ns | 220 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | +| sqrt | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 690 ns | 2.0 μs | 790 ns | 580 ns | 660 ns | Linear (550 ns) | 1.05x | +| sqrt | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 7.9 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.01x | +| sqrt | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 31.4 μs | 11.9 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.00x | +| sqrt | sorted_repeated | 16 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 124.8 μs | 47.2 μs | 30.8 μs | 38.4 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| sqrt | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 90 ns | 200 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| sqrt | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 210 ns | 710 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | +| sqrt | sorted_repeated | 64 | 64 | 550 ns | 920 ns | 710 ns | 2.7 μs | 1.1 μs | 580 ns | 920 ns | Linear (550 ns) | 1.05x | +| sqrt | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 10.6 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | +| sqrt | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 42.3 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | +| sqrt | sorted_repeated | 64 | 4096 | 30.8 μs | 54.9 μs | 39.1 μs | 168.3 μs | 66.5 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_repeated | 256 | 1 | 60 ns | 70 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_repeated | 256 | 4 | 80 ns | 100 ns | 100 ns | 230 ns | 130 ns | 120 ns | 110 ns | Linear (80 ns) | 1.50x | +| sqrt | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 830 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| sqrt | sorted_repeated | 256 | 64 | 560 ns | 930 ns | 700 ns | 3.2 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (560 ns) | 1.05x | +| sqrt | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 12.6 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| sqrt | sorted_repeated | 256 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 50.2 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.8 μs) | 1.00x | +| sqrt | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 200.8 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 70 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 90 ns | 270 ns | 140 ns | 110 ns | 120 ns | ExpFromLeft (90 ns) | 1.22x | +| sqrt | sorted_repeated | 1024 | 16 | 179 ns | 280 ns | 230 ns | 990 ns | 450 ns | 210 ns | 420 ns | Linear (179 ns) | 1.17x | +| sqrt | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 3.8 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| sqrt | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 15.1 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | +| sqrt | sorted_repeated | 1024 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 60.4 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.01x | +| sqrt | sorted_repeated | 1024 | 4096 | 30.8 μs | 54.9 μs | 39.0 μs | 241.1 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 330 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | +| sqrt | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 1.1 μs | 530 ns | 210 ns | 480 ns | Linear (180 ns) | 1.17x | +| sqrt | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 710 ns | 4.4 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | +| sqrt | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 17.5 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| sqrt | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 70.0 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 0.99x | +| sqrt | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 279.5 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_repeated | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | sorted_repeated | 16384 | 4 | 100 ns | 110 ns | 110 ns | 360 ns | 180 ns | 120 ns | 170 ns | Linear (100 ns) | 1.20x | +| sqrt | sorted_repeated | 16384 | 16 | 180 ns | 300 ns | 220 ns | 1.3 μs | 610 ns | 220 ns | 570 ns | Linear (180 ns) | 1.22x | +| sqrt | sorted_repeated | 16384 | 64 | 570 ns | 940 ns | 880 ns | 5.2 μs | 2.3 μs | 790 ns | 2.1 μs | Linear (570 ns) | 1.39x | +| sqrt | sorted_repeated | 16384 | 256 | 2.0 μs | 3.6 μs | 2.6 μs | 20.1 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | +| sqrt | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 80.5 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.00x | +| sqrt | sorted_repeated | 16384 | 4096 | 30.8 μs | 54.9 μs | 39.3 μs | 322.2 μs | 144.1 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | +| sqrt | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 140 ns | 410 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| sqrt | sorted_repeated | 65536 | 16 | 190 ns | 290 ns | 230 ns | 1.5 μs | 680 ns | 210 ns | 650 ns | Linear (190 ns) | 1.11x | +| sqrt | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 720 ns | 5.9 μs | 2.6 μs | 609 ns | 2.4 μs | Linear (570 ns) | 1.07x | +| sqrt | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 23.5 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | +| sqrt | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 94.0 μs | 40.7 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.00x | +| sqrt | sorted_repeated | 65536 | 4096 | 30.8 μs | 54.9 μs | 39.4 μs | 376.3 μs | 163.2 μs | 30.8 μs | 152.6 μs | Linear (30.8 μs) | 1.00x | +| sqrt | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| sqrt | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 90 ns | 90 ns | 100 ns | 70 ns | InterpSearch (90 ns) | 1.11x | +| sqrt | unsorted | 16 | 16 | 210 ns | 210 ns | 200 ns | 200 ns | 210 ns | 210 ns | 190 ns | InterpSearch (200 ns) | 1.05x | +| sqrt | unsorted | 16 | 64 | 700 ns | 700 ns | 690 ns | 690 ns | 690 ns | 710 ns | 680 ns | InterpSearch (690 ns) | 1.03x | +| sqrt | unsorted | 16 | 256 | 4.2 μs | 4.3 μs | 4.2 μs | 4.2 μs | 4.2 μs | 4.1 μs | 4.3 μs | Binary (4.2 μs) | 1.00x | +| sqrt | unsorted | 16 | 1024 | 24.0 μs | 23.6 μs | 23.6 μs | 23.4 μs | 23.5 μs | 23.6 μs | 24.4 μs | InterpSearch (23.4 μs) | 1.01x | +| sqrt | unsorted | 16 | 4096 | 129.6 μs | 128.2 μs | 128.0 μs | 128.4 μs | 127.6 μs | 127.7 μs | 130.1 μs | Binary (127.6 μs) | 1.00x | +| sqrt | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| sqrt | unsorted | 64 | 4 | 90 ns | 110 ns | 100 ns | 170 ns | 110 ns | 120 ns | 90 ns | Linear (90 ns) | 1.33x | +| sqrt | unsorted | 64 | 16 | 290 ns | 290 ns | 290 ns | 290 ns | 290 ns | 300 ns | 270 ns | InterpSearch (290 ns) | 1.03x | +| sqrt | unsorted | 64 | 64 | 1.1 μs | 1.0 μs | 1.1 μs | 1.0 μs | 1.0 μs | 1.1 μs | 1.0 μs | Gallop (1.0 μs) | 1.03x | +| sqrt | unsorted | 64 | 256 | 5.9 μs | 6.0 μs | 6.0 μs | 5.9 μs | 5.9 μs | 6.0 μs | 6.2 μs | Linear (5.9 μs) | 1.02x | +| sqrt | unsorted | 64 | 1024 | 40.0 μs | 40.3 μs | 39.6 μs | 39.0 μs | 39.1 μs | 39.2 μs | 39.5 μs | InterpSearch (39.0 μs) | 1.01x | +| sqrt | unsorted | 64 | 4096 | 207.4 μs | 205.8 μs | 205.2 μs | 205.9 μs | 206.1 μs | 205.7 μs | 208.5 μs | ExpFromLeft (205.2 μs) | 1.00x | +| sqrt | unsorted | 256 | 1 | 59 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Linear (59 ns) | 1.02x | +| sqrt | unsorted | 256 | 4 | 120 ns | 120 ns | 130 ns | 120 ns | 130 ns | 130 ns | 110 ns | InterpSearch (120 ns) | 1.08x | +| sqrt | unsorted | 256 | 16 | 350 ns | 340 ns | 340 ns | 350 ns | 350 ns | 360 ns | 340 ns | ExpFromLeft (340 ns) | 1.06x | +| sqrt | unsorted | 256 | 64 | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.4 μs | InterpSearch (1.5 μs) | 1.00x | +| sqrt | unsorted | 256 | 256 | 7.3 μs | 7.4 μs | 7.3 μs | 7.3 μs | 7.3 μs | 7.2 μs | 7.5 μs | Linear (7.3 μs) | 0.99x | +| sqrt | unsorted | 256 | 1024 | 49.8 μs | 48.9 μs | 48.4 μs | 47.5 μs | 47.7 μs | 47.9 μs | 50.1 μs | InterpSearch (47.5 μs) | 1.01x | +| sqrt | unsorted | 256 | 4096 | 281.7 μs | 281.6 μs | 281.9 μs | 280.0 μs | 277.8 μs | 278.8 μs | 283.8 μs | Binary (277.8 μs) | 1.00x | +| sqrt | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| sqrt | unsorted | 1024 | 4 | 140 ns | 150 ns | 150 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| sqrt | unsorted | 1024 | 16 | 430 ns | 430 ns | 430 ns | 430 ns | 430 ns | 440 ns | 409 ns | InterpSearch (430 ns) | 1.02x | +| sqrt | unsorted | 1024 | 64 | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | InterpSearch (1.8 μs) | 1.01x | +| sqrt | unsorted | 1024 | 256 | 8.8 μs | 8.7 μs | 8.6 μs | 8.6 μs | 8.4 μs | 8.5 μs | 8.7 μs | Binary (8.4 μs) | 1.01x | +| sqrt | unsorted | 1024 | 1024 | 73.5 μs | 71.9 μs | 71.3 μs | 71.3 μs | 70.9 μs | 70.4 μs | 73.6 μs | Binary (70.9 μs) | 0.99x | +| sqrt | unsorted | 1024 | 4096 | 369.4 μs | 371.9 μs | 375.4 μs | 376.0 μs | 372.4 μs | 374.0 μs | 373.5 μs | Linear (369.4 μs) | 1.01x | +| sqrt | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | unsorted | 4096 | 4 | 200 ns | 160 ns | 160 ns | 160 ns | 160 ns | 170 ns | 150 ns | InterpSearch (160 ns) | 1.06x | +| sqrt | unsorted | 4096 | 16 | 500 ns | 500 ns | 500 ns | 510 ns | 500 ns | 500 ns | 480 ns | ExpFromLeft (500 ns) | 1.00x | +| sqrt | unsorted | 4096 | 64 | 2.2 μs | 2.1 μs | 2.1 μs | 2.2 μs | 2.2 μs | 2.2 μs | 2.1 μs | ExpFromLeft (2.1 μs) | 1.02x | +| sqrt | unsorted | 4096 | 256 | 10.1 μs | 9.9 μs | 9.8 μs | 9.8 μs | 9.7 μs | 9.7 μs | 10.7 μs | Binary (9.7 μs) | 1.00x | +| sqrt | unsorted | 4096 | 1024 | 93.2 μs | 91.7 μs | 91.1 μs | 90.1 μs | 89.8 μs | 89.9 μs | 94.3 μs | Binary (89.8 μs) | 1.00x | +| sqrt | unsorted | 4096 | 4096 | 458.2 μs | 448.9 μs | 458.8 μs | 458.0 μs | 456.7 μs | 457.4 μs | 457.4 μs | Gallop (448.9 μs) | 1.02x | +| sqrt | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| sqrt | unsorted | 16384 | 4 | 170 ns | 170 ns | 180 ns | 180 ns | 170 ns | 180 ns | 160 ns | Binary (170 ns) | 1.06x | +| sqrt | unsorted | 16384 | 16 | 570 ns | 560 ns | 570 ns | 570 ns | 570 ns | 570 ns | 560 ns | Gallop (560 ns) | 1.02x | +| sqrt | unsorted | 16384 | 64 | 2.4 μs | 2.4 μs | 2.4 μs | 2.3 μs | 2.4 μs | 2.4 μs | 2.3 μs | InterpSearch (2.3 μs) | 1.01x | +| sqrt | unsorted | 16384 | 256 | 11.9 μs | 11.7 μs | 11.6 μs | 11.6 μs | 11.6 μs | 11.6 μs | 13.8 μs | Binary (11.6 μs) | 1.00x | +| sqrt | unsorted | 16384 | 1024 | 130.0 μs | 129.0 μs | 127.7 μs | 127.0 μs | 126.3 μs | 125.7 μs | 131.8 μs | Binary (126.3 μs) | 1.00x | +| sqrt | unsorted | 16384 | 4096 | 615.8 μs | 614.9 μs | 615.8 μs | 617.7 μs | 615.9 μs | 618.0 μs | 617.4 μs | Gallop (614.9 μs) | 1.00x | +| sqrt | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| sqrt | unsorted | 65536 | 4 | 190 ns | 190 ns | 200 ns | 190 ns | 200 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | +| sqrt | unsorted | 65536 | 16 | 670 ns | 660 ns | 660 ns | 670 ns | 670 ns | 670 ns | 650 ns | ExpFromLeft (660 ns) | 1.02x | +| sqrt | unsorted | 65536 | 64 | 3.0 μs | 3.0 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 3.0 μs | Binary (2.9 μs) | 1.00x | +| sqrt | unsorted | 65536 | 256 | 14.6 μs | 14.5 μs | 14.4 μs | 14.4 μs | 14.4 μs | 14.2 μs | 17.3 μs | Binary (14.4 μs) | 0.99x | +| sqrt | unsorted | 65536 | 1024 | 174.2 μs | 171.2 μs | 168.8 μs | 168.5 μs | 167.9 μs | 166.9 μs | 172.8 μs | Binary (167.9 μs) | 0.99x | +| sqrt | unsorted | 65536 | 4096 | 795.6 μs | 794.2 μs | 792.7 μs | 791.6 μs | 792.1 μs | 791.5 μs | 791.8 μs | InterpSearch (791.6 μs) | 1.00x | +| plateau | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| plateau | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 100 ns | 170 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| plateau | sorted_uniform | 16 | 16 | 180 ns | 270 ns | 220 ns | 510 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | +| plateau | sorted_uniform | 16 | 64 | 600 ns | 949 ns | 760 ns | 2.1 μs | 810 ns | 630 ns | 690 ns | Linear (600 ns) | 1.05x | +| plateau | sorted_uniform | 16 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 8.1 μs | 3.0 μs | 2.2 μs | 2.5 μs | Linear (2.1 μs) | 1.01x | +| plateau | sorted_uniform | 16 | 1024 | 8.3 μs | 13.9 μs | 10.6 μs | 31.2 μs | 11.8 μs | 8.3 μs | 10.0 μs | Linear (8.3 μs) | 1.00x | +| plateau | sorted_uniform | 16 | 4096 | 32.9 μs | 55.4 μs | 41.8 μs | 123.4 μs | 47.1 μs | 32.9 μs | 39.8 μs | Linear (32.9 μs) | 1.00x | +| plateau | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| plateau | sorted_uniform | 64 | 4 | 110 ns | 110 ns | 110 ns | 200 ns | 109 ns | 130 ns | 90 ns | Binary (109 ns) | 1.19x | +| plateau | sorted_uniform | 64 | 16 | 200 ns | 270 ns | 230 ns | 680 ns | 310 ns | 230 ns | 270 ns | Linear (200 ns) | 1.15x | +| plateau | sorted_uniform | 64 | 64 | 600 ns | 950 ns | 760 ns | 2.6 μs | 1.1 μs | 640 ns | 970 ns | Linear (600 ns) | 1.07x | +| plateau | sorted_uniform | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 10.4 μs | 4.2 μs | 2.1 μs | 3.7 μs | Linear (2.0 μs) | 1.01x | +| plateau | sorted_uniform | 64 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 40.7 μs | 16.6 μs | 7.8 μs | 14.7 μs | Linear (7.8 μs) | 1.00x | +| plateau | sorted_uniform | 64 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 158.7 μs | 66.5 μs | 30.8 μs | 58.8 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_uniform | 256 | 4 | 210 ns | 130 ns | 120 ns | 220 ns | 120 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | +| plateau | sorted_uniform | 256 | 16 | 280 ns | 290 ns | 250 ns | 720 ns | 380 ns | 259 ns | 360 ns | ExpFromLeft (250 ns) | 1.04x | +| plateau | sorted_uniform | 256 | 64 | 690 ns | 970 ns | 770 ns | 2.8 μs | 1.4 μs | 720 ns | 1.3 μs | Linear (690 ns) | 1.04x | +| plateau | sorted_uniform | 256 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 12.3 μs | 5.4 μs | 2.2 μs | 4.9 μs | Linear (2.1 μs) | 1.01x | +| plateau | sorted_uniform | 256 | 1024 | 7.9 μs | 13.8 μs | 10.6 μs | 53.8 μs | 21.5 μs | 7.9 μs | 19.6 μs | Linear (7.9 μs) | 1.01x | +| plateau | sorted_uniform | 256 | 4096 | 30.9 μs | 55.1 μs | 42.0 μs | 195.4 μs | 86.0 μs | 30.9 μs | 78.3 μs | Linear (30.9 μs) | 1.00x | +| plateau | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_uniform | 1024 | 4 | 550 ns | 140 ns | 130 ns | 250 ns | 150 ns | 160 ns | 130 ns | ExpFromLeft (130 ns) | 1.23x | +| plateau | sorted_uniform | 1024 | 16 | 670 ns | 300 ns | 240 ns | 950 ns | 460 ns | 260 ns | 420 ns | ExpFromLeft (240 ns) | 1.08x | +| plateau | sorted_uniform | 1024 | 64 | 1.1 μs | 980 ns | 780 ns | 3.6 μs | 1.7 μs | 830 ns | 1.6 μs | ExpFromLeft (780 ns) | 1.06x | +| plateau | sorted_uniform | 1024 | 256 | 2.5 μs | 3.5 μs | 2.8 μs | 15.0 μs | 6.5 μs | 2.5 μs | 6.1 μs | Linear (2.5 μs) | 1.01x | +| plateau | sorted_uniform | 1024 | 1024 | 8.2 μs | 13.8 μs | 10.6 μs | 79.9 μs | 26.1 μs | 8.3 μs | 24.4 μs | Linear (8.2 μs) | 1.00x | +| plateau | sorted_uniform | 1024 | 4096 | 31.3 μs | 55.1 μs | 42.1 μs | 296.7 μs | 104.7 μs | 31.3 μs | 97.2 μs | Linear (31.3 μs) | 1.00x | +| plateau | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_uniform | 4096 | 4 | 2.0 μs | 150 ns | 140 ns | 320 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (140 ns) | 1.21x | +| plateau | sorted_uniform | 4096 | 16 | 2.1 μs | 310 ns | 260 ns | 1.0 μs | 550 ns | 290 ns | 510 ns | ExpFromLeft (260 ns) | 1.12x | +| plateau | sorted_uniform | 4096 | 64 | 2.5 μs | 990 ns | 800 ns | 4.2 μs | 2.0 μs | 840 ns | 1.9 μs | ExpFromLeft (800 ns) | 1.05x | +| plateau | sorted_uniform | 4096 | 256 | 3.9 μs | 3.6 μs | 2.8 μs | 18.3 μs | 7.8 μs | 2.9 μs | 7.3 μs | ExpFromLeft (2.8 μs) | 1.04x | +| plateau | sorted_uniform | 4096 | 1024 | 9.7 μs | 13.9 μs | 10.6 μs | 104.6 μs | 31.2 μs | 9.7 μs | 29.1 μs | Linear (9.7 μs) | 1.01x | +| plateau | sorted_uniform | 4096 | 4096 | 32.7 μs | 55.1 μs | 42.1 μs | 438.2 μs | 124.6 μs | 32.7 μs | 116.2 μs | Linear (32.7 μs) | 1.00x | +| plateau | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_uniform | 16384 | 4 | 7.8 μs | 180 ns | 140 ns | 310 ns | 180 ns | 180 ns | 170 ns | ExpFromLeft (140 ns) | 1.29x | +| plateau | sorted_uniform | 16384 | 16 | 7.9 μs | 330 ns | 270 ns | 1.2 μs | 600 ns | 290 ns | 580 ns | ExpFromLeft (270 ns) | 1.07x | +| plateau | sorted_uniform | 16384 | 64 | 8.3 μs | 1.0 μs | 1.0 μs | 5.2 μs | 2.3 μs | 850 ns | 2.2 μs | ExpFromLeft (1.0 μs) | 0.85x | +| plateau | sorted_uniform | 16384 | 256 | 9.7 μs | 3.6 μs | 2.8 μs | 21.7 μs | 9.0 μs | 2.9 μs | 8.6 μs | ExpFromLeft (2.8 μs) | 1.04x | +| plateau | sorted_uniform | 16384 | 1024 | 15.4 μs | 13.9 μs | 10.7 μs | 135.4 μs | 36.0 μs | 11.0 μs | 34.3 μs | ExpFromLeft (10.7 μs) | 1.04x | +| plateau | sorted_uniform | 16384 | 4096 | 38.4 μs | 55.2 μs | 42.1 μs | 556.4 μs | 144.0 μs | 38.4 μs | 136.9 μs | Linear (38.4 μs) | 1.00x | +| plateau | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| plateau | sorted_uniform | 65536 | 4 | 30.8 μs | 180 ns | 170 ns | 390 ns | 200 ns | 180 ns | 180 ns | ExpFromLeft (170 ns) | 1.06x | +| plateau | sorted_uniform | 65536 | 16 | 31.1 μs | 340 ns | 300 ns | 1.4 μs | 680 ns | 290 ns | 670 ns | ExpFromLeft (300 ns) | 0.97x | +| plateau | sorted_uniform | 65536 | 64 | 29.9 μs | 1.0 μs | 820 ns | 5.7 μs | 2.6 μs | 860 ns | 2.5 μs | ExpFromLeft (820 ns) | 1.05x | +| plateau | sorted_uniform | 65536 | 256 | 32.9 μs | 3.6 μs | 2.8 μs | 24.1 μs | 10.2 μs | 2.9 μs | 9.8 μs | ExpFromLeft (2.8 μs) | 1.05x | +| plateau | sorted_uniform | 65536 | 1024 | 38.6 μs | 13.9 μs | 10.7 μs | 178.2 μs | 40.6 μs | 11.1 μs | 38.7 μs | ExpFromLeft (10.7 μs) | 1.04x | +| plateau | sorted_uniform | 65536 | 4096 | 61.7 μs | 55.2 μs | 42.1 μs | 694.6 μs | 162.8 μs | 43.8 μs | 154.7 μs | ExpFromLeft (42.1 μs) | 1.04x | +| plateau | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| plateau | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 110 ns | 70 ns | Linear (80 ns) | 1.38x | +| plateau | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 200 ns | 500 ns | 220 ns | 190 ns | 190 ns | Linear (170 ns) | 1.12x | +| plateau | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 690 ns | 1.9 μs | 780 ns | 579 ns | 670 ns | Linear (550 ns) | 1.05x | +| plateau | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 7.2 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.02x | +| plateau | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 28.8 μs | 11.8 μs | 7.8 μs | 10.0 μs | Linear (7.7 μs) | 1.00x | +| plateau | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.8 μs | 39.5 μs | 115.3 μs | 47.1 μs | 30.8 μs | 39.8 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| plateau | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 90 ns | 190 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| plateau | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 210 ns | 680 ns | 320 ns | 200 ns | 260 ns | Linear (170 ns) | 1.18x | +| plateau | sorted_dense_burst | 64 | 64 | 550 ns | 920 ns | 690 ns | 2.5 μs | 1.1 μs | 580 ns | 920 ns | Linear (550 ns) | 1.05x | +| plateau | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 10.1 μs | 4.2 μs | 2.0 μs | 3.9 μs | Linear (2.0 μs) | 1.03x | +| plateau | sorted_dense_burst | 64 | 1024 | 7.9 μs | 13.7 μs | 10.0 μs | 40.4 μs | 16.8 μs | 7.9 μs | 14.2 μs | Linear (7.9 μs) | 1.00x | +| plateau | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.0 μs | 39.2 μs | 159.9 μs | 66.8 μs | 30.8 μs | 57.0 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 90 ns | 230 ns | 120 ns | 110 ns | 110 ns | ExpFromLeft (90 ns) | 1.22x | +| plateau | sorted_dense_burst | 256 | 16 | 180 ns | 280 ns | 210 ns | 840 ns | 400 ns | 200 ns | 340 ns | Linear (180 ns) | 1.11x | +| plateau | sorted_dense_burst | 256 | 64 | 560 ns | 930 ns | 700 ns | 3.2 μs | 1.4 μs | 590 ns | 1.3 μs | Linear (560 ns) | 1.05x | +| plateau | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 12.5 μs | 5.4 μs | 2.0 μs | 4.9 μs | Linear (2.0 μs) | 1.02x | +| plateau | sorted_dense_burst | 256 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 50.1 μs | 21.4 μs | 7.8 μs | 19.5 μs | Linear (7.7 μs) | 1.01x | +| plateau | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 199.3 μs | 85.6 μs | 30.8 μs | 78.1 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 100 ns | 270 ns | 150 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | +| plateau | sorted_dense_burst | 1024 | 16 | 190 ns | 290 ns | 220 ns | 1.0 μs | 460 ns | 210 ns | 420 ns | Linear (190 ns) | 1.11x | +| plateau | sorted_dense_burst | 1024 | 64 | 559 ns | 930 ns | 700 ns | 3.9 μs | 1.7 μs | 600 ns | 1.6 μs | Linear (559 ns) | 1.07x | +| plateau | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 14.9 μs | 6.6 μs | 2.0 μs | 6.2 μs | Linear (2.0 μs) | 1.02x | +| plateau | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 59.9 μs | 26.4 μs | 7.8 μs | 24.3 μs | Linear (7.8 μs) | 1.00x | +| plateau | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 239.9 μs | 105.4 μs | 30.8 μs | 96.8 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 100 ns | 310 ns | 170 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | +| plateau | sorted_dense_burst | 4096 | 16 | 180 ns | 290 ns | 240 ns | 1.1 μs | 540 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | +| plateau | sorted_dense_burst | 4096 | 64 | 560 ns | 940 ns | 720 ns | 4.5 μs | 2.0 μs | 590 ns | 1.9 μs | Linear (560 ns) | 1.05x | +| plateau | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 17.7 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| plateau | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.9 μs | 10.0 μs | 70.4 μs | 31.3 μs | 7.8 μs | 28.9 μs | Linear (7.7 μs) | 1.01x | +| plateau | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.4 μs | 39.8 μs | 281.4 μs | 125.0 μs | 30.8 μs | 115.5 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_dense_burst | 16384 | 4 | 100 ns | 120 ns | 110 ns | 370 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | +| plateau | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 220 ns | 1.3 μs | 600 ns | 220 ns | 570 ns | Linear (190 ns) | 1.16x | +| plateau | sorted_dense_burst | 16384 | 64 | 570 ns | 950 ns | 720 ns | 5.1 μs | 2.3 μs | 600 ns | 2.2 μs | Linear (570 ns) | 1.05x | +| plateau | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 20.1 μs | 9.0 μs | 2.0 μs | 8.6 μs | Linear (2.0 μs) | 1.02x | +| plateau | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 80.4 μs | 36.7 μs | 11.2 μs | 34.1 μs | Linear (7.8 μs) | 1.44x | +| plateau | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 54.7 μs | 39.4 μs | 322.2 μs | 143.5 μs | 30.8 μs | 136.4 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| plateau | sorted_dense_burst | 65536 | 4 | 110 ns | 120 ns | 120 ns | 410 ns | 200 ns | 130 ns | 180 ns | Linear (110 ns) | 1.18x | +| plateau | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 230 ns | 1.5 μs | 690 ns | 220 ns | 650 ns | Linear (190 ns) | 1.16x | +| plateau | sorted_dense_burst | 65536 | 64 | 580 ns | 949 ns | 710 ns | 5.8 μs | 2.6 μs | 610 ns | 2.5 μs | Linear (580 ns) | 1.05x | +| plateau | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 23.1 μs | 10.2 μs | 2.0 μs | 9.7 μs | Linear (2.0 μs) | 1.01x | +| plateau | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 92.4 μs | 40.9 μs | 7.8 μs | 38.6 μs | Linear (7.8 μs) | 1.00x | +| plateau | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 39.3 μs | 369.5 μs | 163.3 μs | 30.8 μs | 154.5 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| plateau | sorted_near_start | 16 | 4 | 90 ns | 110 ns | 100 ns | 190 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| plateau | sorted_near_start | 16 | 16 | 170 ns | 280 ns | 210 ns | 630 ns | 220 ns | 200 ns | 190 ns | Linear (170 ns) | 1.18x | +| plateau | sorted_near_start | 16 | 64 | 560 ns | 930 ns | 700 ns | 2.3 μs | 780 ns | 589 ns | 680 ns | Linear (560 ns) | 1.05x | +| plateau | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 9.0 μs | 3.0 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | +| plateau | sorted_near_start | 16 | 1024 | 7.8 μs | 13.8 μs | 10.1 μs | 36.3 μs | 11.8 μs | 7.8 μs | 10.1 μs | Linear (7.8 μs) | 1.00x | +| plateau | sorted_near_start | 16 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 144.2 μs | 46.9 μs | 30.8 μs | 40.2 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| plateau | sorted_near_start | 64 | 4 | 110 ns | 110 ns | 110 ns | 210 ns | 110 ns | 130 ns | 90 ns | ExpFromLeft (110 ns) | 1.18x | +| plateau | sorted_near_start | 64 | 16 | 200 ns | 290 ns | 220 ns | 750 ns | 310 ns | 230 ns | 290 ns | Linear (200 ns) | 1.15x | +| plateau | sorted_near_start | 64 | 64 | 590 ns | 940 ns | 710 ns | 2.8 μs | 1.1 μs | 620 ns | 1.0 μs | Linear (590 ns) | 1.05x | +| plateau | sorted_near_start | 64 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 11.1 μs | 4.2 μs | 2.0 μs | 3.8 μs | Linear (2.0 μs) | 1.01x | +| plateau | sorted_near_start | 64 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 44.3 μs | 16.6 μs | 7.8 μs | 15.0 μs | Linear (7.8 μs) | 1.00x | +| plateau | sorted_near_start | 64 | 4096 | 30.8 μs | 54.9 μs | 39.5 μs | 178.0 μs | 66.0 μs | 30.9 μs | 60.0 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_near_start | 256 | 4 | 200 ns | 120 ns | 150 ns | 310 ns | 120 ns | 140 ns | 110 ns | Binary (120 ns) | 1.17x | +| plateau | sorted_near_start | 256 | 16 | 300 ns | 300 ns | 240 ns | 920 ns | 390 ns | 250 ns | 350 ns | ExpFromLeft (240 ns) | 1.04x | +| plateau | sorted_near_start | 256 | 64 | 680 ns | 950 ns | 730 ns | 3.5 μs | 1.4 μs | 710 ns | 1.3 μs | Linear (680 ns) | 1.04x | +| plateau | sorted_near_start | 256 | 256 | 2.3 μs | 3.5 μs | 2.6 μs | 13.8 μs | 5.4 μs | 2.1 μs | 5.0 μs | Linear (2.3 μs) | 0.92x | +| plateau | sorted_near_start | 256 | 1024 | 7.9 μs | 13.8 μs | 10.0 μs | 55.0 μs | 21.6 μs | 7.9 μs | 19.7 μs | Linear (7.9 μs) | 1.00x | +| plateau | sorted_near_start | 256 | 4096 | 30.9 μs | 55.1 μs | 39.6 μs | 222.1 μs | 86.6 μs | 30.9 μs | 78.6 μs | Linear (30.9 μs) | 1.00x | +| plateau | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_near_start | 1024 | 4 | 90 ns | 100 ns | 100 ns | 280 ns | 150 ns | 130 ns | 130 ns | Linear (90 ns) | 1.44x | +| plateau | sorted_near_start | 1024 | 16 | 180 ns | 290 ns | 220 ns | 1.1 μs | 440 ns | 230 ns | 420 ns | Linear (180 ns) | 1.28x | +| plateau | sorted_near_start | 1024 | 64 | 1.1 μs | 970 ns | 740 ns | 4.1 μs | 1.7 μs | 770 ns | 1.6 μs | ExpFromLeft (740 ns) | 1.04x | +| plateau | sorted_near_start | 1024 | 256 | 2.5 μs | 3.5 μs | 2.6 μs | 16.6 μs | 6.9 μs | 3.4 μs | 6.3 μs | Linear (2.5 μs) | 1.37x | +| plateau | sorted_near_start | 1024 | 1024 | 8.3 μs | 13.8 μs | 10.1 μs | 64.6 μs | 25.9 μs | 8.3 μs | 24.4 μs | Linear (8.3 μs) | 1.00x | +| plateau | sorted_near_start | 1024 | 4096 | 31.3 μs | 55.1 μs | 39.7 μs | 264.4 μs | 103.9 μs | 31.3 μs | 97.7 μs | Linear (31.3 μs) | 1.00x | +| plateau | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_near_start | 4096 | 4 | 2.0 μs | 150 ns | 150 ns | 320 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (150 ns) | 1.13x | +| plateau | sorted_near_start | 4096 | 16 | 2.1 μs | 320 ns | 270 ns | 1.2 μs | 540 ns | 270 ns | 510 ns | ExpFromLeft (270 ns) | 1.00x | +| plateau | sorted_near_start | 4096 | 64 | 3.0 μs | 1.3 μs | 920 ns | 4.8 μs | 2.1 μs | 940 ns | 1.9 μs | ExpFromLeft (920 ns) | 1.02x | +| plateau | sorted_near_start | 4096 | 256 | 4.0 μs | 3.6 μs | 2.6 μs | 18.9 μs | 7.8 μs | 2.7 μs | 7.4 μs | ExpFromLeft (2.6 μs) | 1.06x | +| plateau | sorted_near_start | 4096 | 1024 | 9.7 μs | 13.9 μs | 10.0 μs | 75.1 μs | 31.1 μs | 9.7 μs | 29.2 μs | Linear (9.7 μs) | 1.00x | +| plateau | sorted_near_start | 4096 | 4096 | 32.8 μs | 55.1 μs | 39.8 μs | 303.3 μs | 124.1 μs | 32.8 μs | 116.8 μs | Linear (32.8 μs) | 1.00x | +| plateau | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 80 ns | 120 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | +| plateau | sorted_near_start | 16384 | 4 | 100 ns | 110 ns | 110 ns | 360 ns | 180 ns | 130 ns | 160 ns | Linear (100 ns) | 1.30x | +| plateau | sorted_near_start | 16384 | 16 | 7.9 μs | 350 ns | 280 ns | 1.4 μs | 620 ns | 280 ns | 580 ns | ExpFromLeft (280 ns) | 1.00x | +| plateau | sorted_near_start | 16384 | 64 | 8.3 μs | 1.0 μs | 770 ns | 5.3 μs | 2.3 μs | 790 ns | 2.2 μs | ExpFromLeft (770 ns) | 1.03x | +| plateau | sorted_near_start | 16384 | 256 | 9.7 μs | 3.6 μs | 2.6 μs | 21.1 μs | 9.0 μs | 2.8 μs | 8.7 μs | ExpFromLeft (2.6 μs) | 1.05x | +| plateau | sorted_near_start | 16384 | 1024 | 15.4 μs | 13.9 μs | 10.0 μs | 84.8 μs | 36.1 μs | 10.4 μs | 34.3 μs | ExpFromLeft (10.0 μs) | 1.04x | +| plateau | sorted_near_start | 16384 | 4096 | 38.4 μs | 55.1 μs | 39.7 μs | 343.4 μs | 144.4 μs | 38.4 μs | 137.5 μs | Linear (38.4 μs) | 1.00x | +| plateau | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| plateau | sorted_near_start | 65536 | 4 | 31.1 μs | 180 ns | 170 ns | 400 ns | 190 ns | 190 ns | 180 ns | ExpFromLeft (170 ns) | 1.12x | +| plateau | sorted_near_start | 65536 | 16 | 31.1 μs | 350 ns | 280 ns | 1.5 μs | 690 ns | 290 ns | 679 ns | ExpFromLeft (280 ns) | 1.04x | +| plateau | sorted_near_start | 65536 | 64 | 31.5 μs | 1.0 μs | 780 ns | 6.0 μs | 2.6 μs | 800 ns | 2.5 μs | ExpFromLeft (780 ns) | 1.03x | +| plateau | sorted_near_start | 65536 | 256 | 32.9 μs | 3.6 μs | 2.6 μs | 23.9 μs | 10.2 μs | 2.8 μs | 9.7 μs | ExpFromLeft (2.6 μs) | 1.04x | +| plateau | sorted_near_start | 65536 | 1024 | 38.6 μs | 13.9 μs | 10.1 μs | 96.1 μs | 40.6 μs | 10.5 μs | 38.8 μs | ExpFromLeft (10.1 μs) | 1.03x | +| plateau | sorted_near_start | 65536 | 4096 | 61.7 μs | 55.2 μs | 38.8 μs | 395.4 μs | 162.2 μs | 41.1 μs | 154.7 μs | ExpFromLeft (38.8 μs) | 1.06x | +| plateau | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| plateau | sorted_arithmetic | 16 | 4 | 90 ns | 120 ns | 100 ns | 160 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | +| plateau | sorted_arithmetic | 16 | 16 | 180 ns | 280 ns | 220 ns | 520 ns | 220 ns | 210 ns | 200 ns | Linear (180 ns) | 1.17x | +| plateau | sorted_arithmetic | 16 | 64 | 610 ns | 1.0 μs | 760 ns | 2.0 μs | 820 ns | 630 ns | 690 ns | Linear (610 ns) | 1.03x | +| plateau | sorted_arithmetic | 16 | 256 | 2.1 μs | 3.7 μs | 2.7 μs | 8.3 μs | 3.0 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.01x | +| plateau | sorted_arithmetic | 16 | 1024 | 9.5 μs | 14.5 μs | 10.6 μs | 31.8 μs | 11.9 μs | 7.9 μs | 10.2 μs | Linear (9.5 μs) | 0.84x | +| plateau | sorted_arithmetic | 16 | 4096 | 30.8 μs | 55.2 μs | 42.0 μs | 123.7 μs | 55.8 μs | 34.5 μs | 39.9 μs | Linear (30.8 μs) | 1.12x | +| plateau | sorted_arithmetic | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_arithmetic | 64 | 4 | 140 ns | 130 ns | 110 ns | 170 ns | 110 ns | 130 ns | 100 ns | ExpFromLeft (110 ns) | 1.18x | +| plateau | sorted_arithmetic | 64 | 16 | 230 ns | 300 ns | 240 ns | 650 ns | 330 ns | 260 ns | 290 ns | Linear (230 ns) | 1.13x | +| plateau | sorted_arithmetic | 64 | 64 | 650 ns | 1.0 μs | 760 ns | 2.5 μs | 1.1 μs | 690 ns | 1.1 μs | Linear (650 ns) | 1.06x | +| plateau | sorted_arithmetic | 64 | 256 | 2.6 μs | 3.8 μs | 2.7 μs | 9.6 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.6 μs) | 0.82x | +| plateau | sorted_arithmetic | 64 | 1024 | 7.9 μs | 14.7 μs | 10.6 μs | 39.5 μs | 16.7 μs | 8.0 μs | 14.7 μs | Linear (7.9 μs) | 1.01x | +| plateau | sorted_arithmetic | 64 | 4096 | 30.9 μs | 54.9 μs | 42.0 μs | 152.5 μs | 66.4 μs | 30.9 μs | 59.4 μs | Linear (30.9 μs) | 1.00x | +| plateau | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_arithmetic | 256 | 4 | 330 ns | 150 ns | 120 ns | 170 ns | 130 ns | 150 ns | 110 ns | ExpFromLeft (120 ns) | 1.25x | +| plateau | sorted_arithmetic | 256 | 16 | 440 ns | 329 ns | 250 ns | 790 ns | 400 ns | 260 ns | 370 ns | ExpFromLeft (250 ns) | 1.04x | +| plateau | sorted_arithmetic | 256 | 64 | 850 ns | 1.1 μs | 780 ns | 3.0 μs | 1.4 μs | 900 ns | 1.3 μs | ExpFromLeft (780 ns) | 1.15x | +| plateau | sorted_arithmetic | 256 | 256 | 2.3 μs | 3.8 μs | 2.7 μs | 12.0 μs | 5.5 μs | 2.3 μs | 5.0 μs | Linear (2.3 μs) | 1.01x | +| plateau | sorted_arithmetic | 256 | 1024 | 8.1 μs | 14.7 μs | 10.6 μs | 51.3 μs | 21.6 μs | 8.2 μs | 19.7 μs | Linear (8.1 μs) | 1.00x | +| plateau | sorted_arithmetic | 256 | 4096 | 31.5 μs | 58.4 μs | 42.1 μs | 194.5 μs | 86.1 μs | 31.1 μs | 82.0 μs | Linear (31.5 μs) | 0.99x | +| plateau | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_arithmetic | 1024 | 4 | 1.1 μs | 180 ns | 130 ns | 180 ns | 140 ns | 160 ns | 130 ns | ExpFromLeft (130 ns) | 1.23x | +| plateau | sorted_arithmetic | 1024 | 16 | 1.2 μs | 340 ns | 260 ns | 910 ns | 470 ns | 270 ns | 439 ns | ExpFromLeft (260 ns) | 1.04x | +| plateau | sorted_arithmetic | 1024 | 64 | 1.5 μs | 1.0 μs | 770 ns | 3.6 μs | 1.7 μs | 830 ns | 1.6 μs | ExpFromLeft (770 ns) | 1.08x | +| plateau | sorted_arithmetic | 1024 | 256 | 3.0 μs | 3.8 μs | 3.6 μs | 14.9 μs | 7.0 μs | 4.0 μs | 6.2 μs | Linear (3.0 μs) | 1.33x | +| plateau | sorted_arithmetic | 1024 | 1024 | 8.8 μs | 13.9 μs | 10.6 μs | 70.0 μs | 26.2 μs | 8.8 μs | 24.4 μs | Linear (8.8 μs) | 1.00x | +| plateau | sorted_arithmetic | 1024 | 4096 | 31.8 μs | 55.1 μs | 42.1 μs | 306.3 μs | 104.7 μs | 45.5 μs | 97.2 μs | Linear (31.8 μs) | 1.43x | +| plateau | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_arithmetic | 4096 | 4 | 4.0 μs | 190 ns | 140 ns | 190 ns | 170 ns | 160 ns | 140 ns | ExpFromLeft (140 ns) | 1.14x | +| plateau | sorted_arithmetic | 4096 | 16 | 4.0 μs | 370 ns | 260 ns | 1.0 μs | 550 ns | 280 ns | 520 ns | ExpFromLeft (260 ns) | 1.08x | +| plateau | sorted_arithmetic | 4096 | 64 | 4.5 μs | 1.0 μs | 790 ns | 4.2 μs | 2.0 μs | 840 ns | 1.9 μs | ExpFromLeft (790 ns) | 1.06x | +| plateau | sorted_arithmetic | 4096 | 256 | 5.8 μs | 3.6 μs | 2.8 μs | 17.0 μs | 7.8 μs | 2.9 μs | 7.3 μs | ExpFromLeft (2.8 μs) | 1.05x | +| plateau | sorted_arithmetic | 4096 | 1024 | 11.7 μs | 13.9 μs | 10.6 μs | 82.2 μs | 31.3 μs | 11.6 μs | 29.1 μs | ExpFromLeft (10.6 μs) | 1.09x | +| plateau | sorted_arithmetic | 4096 | 4096 | 34.7 μs | 55.1 μs | 42.1 μs | 471.8 μs | 124.7 μs | 34.7 μs | 116.2 μs | Linear (34.7 μs) | 1.00x | +| plateau | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_arithmetic | 16384 | 4 | 15.3 μs | 230 ns | 150 ns | 200 ns | 180 ns | 180 ns | 170 ns | ExpFromLeft (150 ns) | 1.20x | +| plateau | sorted_arithmetic | 16384 | 16 | 15.6 μs | 390 ns | 280 ns | 1.2 μs | 650 ns | 300 ns | 600 ns | ExpFromLeft (280 ns) | 1.07x | +| plateau | sorted_arithmetic | 16384 | 64 | 15.3 μs | 1.1 μs | 800 ns | 4.8 μs | 2.3 μs | 850 ns | 2.2 μs | ExpFromLeft (800 ns) | 1.06x | +| plateau | sorted_arithmetic | 16384 | 256 | 17.0 μs | 3.6 μs | 2.8 μs | 19.6 μs | 9.1 μs | 2.9 μs | 8.7 μs | ExpFromLeft (2.8 μs) | 1.05x | +| plateau | sorted_arithmetic | 16384 | 1024 | 23.0 μs | 13.9 μs | 10.6 μs | 99.8 μs | 36.0 μs | 11.1 μs | 34.3 μs | ExpFromLeft (10.6 μs) | 1.04x | +| plateau | sorted_arithmetic | 16384 | 4096 | 46.2 μs | 55.9 μs | 42.1 μs | 564.2 μs | 144.0 μs | 46.2 μs | 137.1 μs | ExpFromLeft (42.1 μs) | 1.10x | +| plateau | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| plateau | sorted_arithmetic | 65536 | 4 | 63.5 μs | 240 ns | 150 ns | 210 ns | 200 ns | 180 ns | 189 ns | ExpFromLeft (150 ns) | 1.20x | +| plateau | sorted_arithmetic | 65536 | 16 | 62.1 μs | 410 ns | 280 ns | 1.4 μs | 710 ns | 300 ns | 670 ns | ExpFromLeft (280 ns) | 1.07x | +| plateau | sorted_arithmetic | 65536 | 64 | 62.0 μs | 1.1 μs | 820 ns | 5.5 μs | 2.6 μs | 860 ns | 2.5 μs | ExpFromLeft (820 ns) | 1.05x | +| plateau | sorted_arithmetic | 65536 | 256 | 64.0 μs | 3.7 μs | 2.8 μs | 22.5 μs | 10.2 μs | 2.9 μs | 9.7 μs | ExpFromLeft (2.8 μs) | 1.04x | +| plateau | sorted_arithmetic | 65536 | 1024 | 69.4 μs | 14.2 μs | 10.7 μs | 127.0 μs | 40.7 μs | 11.1 μs | 38.7 μs | ExpFromLeft (10.7 μs) | 1.04x | +| plateau | sorted_arithmetic | 65536 | 4096 | 92.3 μs | 55.8 μs | 42.1 μs | 666.5 μs | 162.8 μs | 43.8 μs | 154.7 μs | ExpFromLeft (42.1 μs) | 1.04x | +| plateau | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| plateau | sorted_geometric | 16 | 4 | 90 ns | 110 ns | 100 ns | 160 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | +| plateau | sorted_geometric | 16 | 16 | 180 ns | 280 ns | 220 ns | 520 ns | 220 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | +| plateau | sorted_geometric | 16 | 64 | 570 ns | 980 ns | 780 ns | 2.1 μs | 810 ns | 590 ns | 700 ns | Linear (570 ns) | 1.04x | +| plateau | sorted_geometric | 16 | 256 | 2.0 μs | 3.6 μs | 2.8 μs | 8.2 μs | 3.0 μs | 2.1 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | +| plateau | sorted_geometric | 16 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 31.4 μs | 11.8 μs | 7.8 μs | 10.0 μs | Linear (7.8 μs) | 0.99x | +| plateau | sorted_geometric | 16 | 4096 | 30.8 μs | 55.6 μs | 42.1 μs | 124.3 μs | 47.0 μs | 30.9 μs | 39.9 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| plateau | sorted_geometric | 64 | 4 | 140 ns | 120 ns | 110 ns | 190 ns | 110 ns | 120 ns | 90 ns | ExpFromLeft (110 ns) | 1.09x | +| plateau | sorted_geometric | 64 | 16 | 230 ns | 290 ns | 240 ns | 640 ns | 310 ns | 250 ns | 280 ns | Linear (230 ns) | 1.09x | +| plateau | sorted_geometric | 64 | 64 | 640 ns | 990 ns | 790 ns | 2.5 μs | 1.1 μs | 660 ns | 990 ns | Linear (640 ns) | 1.03x | +| plateau | sorted_geometric | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 10.5 μs | 4.2 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | +| plateau | sorted_geometric | 64 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 40.5 μs | 16.6 μs | 7.9 μs | 14.9 μs | Linear (7.8 μs) | 1.02x | +| plateau | sorted_geometric | 64 | 4096 | 30.9 μs | 55.8 μs | 42.2 μs | 157.0 μs | 66.2 μs | 30.9 μs | 59.4 μs | Linear (30.9 μs) | 1.00x | +| plateau | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_geometric | 256 | 4 | 340 ns | 130 ns | 110 ns | 210 ns | 130 ns | 130 ns | 110 ns | ExpFromLeft (110 ns) | 1.18x | +| plateau | sorted_geometric | 256 | 16 | 430 ns | 310 ns | 250 ns | 770 ns | 420 ns | 270 ns | 370 ns | ExpFromLeft (250 ns) | 1.08x | +| plateau | sorted_geometric | 256 | 64 | 820 ns | 1.0 μs | 830 ns | 3.1 μs | 1.4 μs | 850 ns | 1.3 μs | Linear (820 ns) | 1.04x | +| plateau | sorted_geometric | 256 | 256 | 2.3 μs | 3.6 μs | 2.8 μs | 12.6 μs | 5.5 μs | 2.3 μs | 5.0 μs | Linear (2.3 μs) | 1.01x | +| plateau | sorted_geometric | 256 | 1024 | 8.0 μs | 14.1 μs | 10.6 μs | 54.5 μs | 21.6 μs | 8.0 μs | 19.6 μs | Linear (8.0 μs) | 1.01x | +| plateau | sorted_geometric | 256 | 4096 | 31.1 μs | 55.7 μs | 42.1 μs | 200.6 μs | 86.3 μs | 31.1 μs | 78.5 μs | Linear (31.1 μs) | 1.00x | +| plateau | sorted_geometric | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_geometric | 1024 | 4 | 1.1 μs | 150 ns | 120 ns | 240 ns | 150 ns | 159 ns | 130 ns | ExpFromLeft (120 ns) | 1.32x | +| plateau | sorted_geometric | 1024 | 16 | 1.2 μs | 350 ns | 270 ns | 910 ns | 480 ns | 289 ns | 460 ns | ExpFromLeft (270 ns) | 1.07x | +| plateau | sorted_geometric | 1024 | 64 | 1.6 μs | 1.0 μs | 840 ns | 3.7 μs | 1.7 μs | 870 ns | 1.6 μs | ExpFromLeft (840 ns) | 1.04x | +| plateau | sorted_geometric | 1024 | 256 | 3.0 μs | 3.6 μs | 2.8 μs | 15.6 μs | 6.6 μs | 3.0 μs | 6.2 μs | ExpFromLeft (2.8 μs) | 1.09x | +| plateau | sorted_geometric | 1024 | 1024 | 8.8 μs | 14.1 μs | 10.7 μs | 79.2 μs | 26.1 μs | 8.8 μs | 24.4 μs | Linear (8.8 μs) | 1.00x | +| plateau | sorted_geometric | 1024 | 4096 | 31.8 μs | 55.8 μs | 42.1 μs | 302.9 μs | 104.3 μs | 31.8 μs | 97.5 μs | Linear (31.8 μs) | 1.00x | +| plateau | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_geometric | 4096 | 4 | 3.9 μs | 160 ns | 150 ns | 270 ns | 160 ns | 160 ns | 150 ns | ExpFromLeft (150 ns) | 1.07x | +| plateau | sorted_geometric | 4096 | 16 | 4.0 μs | 360 ns | 290 ns | 1.1 μs | 540 ns | 310 ns | 530 ns | ExpFromLeft (290 ns) | 1.07x | +| plateau | sorted_geometric | 4096 | 64 | 4.5 μs | 1.1 μs | 840 ns | 4.3 μs | 2.0 μs | 890 ns | 1.9 μs | ExpFromLeft (840 ns) | 1.06x | +| plateau | sorted_geometric | 4096 | 256 | 5.6 μs | 3.7 μs | 2.8 μs | 18.2 μs | 7.8 μs | 2.9 μs | 7.3 μs | ExpFromLeft (2.8 μs) | 1.05x | +| plateau | sorted_geometric | 4096 | 1024 | 11.6 μs | 14.1 μs | 10.7 μs | 111.8 μs | 31.1 μs | 11.7 μs | 29.1 μs | ExpFromLeft (10.7 μs) | 1.10x | +| plateau | sorted_geometric | 4096 | 4096 | 34.7 μs | 55.8 μs | 42.2 μs | 453.2 μs | 124.3 μs | 34.7 μs | 116.5 μs | Linear (34.7 μs) | 1.00x | +| plateau | sorted_geometric | 16384 | 1 | 80 ns | 70 ns | 80 ns | 119 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | +| plateau | sorted_geometric | 16384 | 4 | 15.4 μs | 170 ns | 160 ns | 290 ns | 180 ns | 170 ns | 169 ns | ExpFromLeft (160 ns) | 1.06x | +| plateau | sorted_geometric | 16384 | 16 | 15.6 μs | 390 ns | 310 ns | 1.2 μs | 640 ns | 330 ns | 600 ns | ExpFromLeft (310 ns) | 1.06x | +| plateau | sorted_geometric | 16384 | 64 | 16.0 μs | 1.1 μs | 850 ns | 5.1 μs | 2.3 μs | 900 ns | 2.2 μs | ExpFromLeft (850 ns) | 1.06x | +| plateau | sorted_geometric | 16384 | 256 | 17.4 μs | 3.7 μs | 2.8 μs | 21.8 μs | 9.1 μs | 3.0 μs | 8.6 μs | ExpFromLeft (2.8 μs) | 1.04x | +| plateau | sorted_geometric | 16384 | 1024 | 22.6 μs | 14.2 μs | 10.7 μs | 143.0 μs | 36.0 μs | 11.1 μs | 34.4 μs | ExpFromLeft (10.7 μs) | 1.04x | +| plateau | sorted_geometric | 16384 | 4096 | 46.1 μs | 55.8 μs | 42.1 μs | 570.7 μs | 144.0 μs | 46.2 μs | 137.3 μs | ExpFromLeft (42.1 μs) | 1.10x | +| plateau | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| plateau | sorted_geometric | 65536 | 4 | 61.4 μs | 180 ns | 160 ns | 330 ns | 210 ns | 190 ns | 180 ns | ExpFromLeft (160 ns) | 1.19x | +| plateau | sorted_geometric | 65536 | 16 | 62.3 μs | 420 ns | 320 ns | 1.4 μs | 710 ns | 350 ns | 660 ns | ExpFromLeft (320 ns) | 1.09x | +| plateau | sorted_geometric | 65536 | 64 | 63.0 μs | 1.1 μs | 870 ns | 5.7 μs | 2.6 μs | 920 ns | 2.5 μs | ExpFromLeft (870 ns) | 1.06x | +| plateau | sorted_geometric | 65536 | 256 | 63.2 μs | 3.7 μs | 2.9 μs | 24.9 μs | 10.2 μs | 3.0 μs | 9.7 μs | ExpFromLeft (2.9 μs) | 1.05x | +| plateau | sorted_geometric | 65536 | 1024 | 70.0 μs | 14.1 μs | 10.7 μs | 182.2 μs | 40.6 μs | 11.2 μs | 38.7 μs | ExpFromLeft (10.7 μs) | 1.04x | +| plateau | sorted_geometric | 65536 | 4096 | 92.0 μs | 55.9 μs | 42.2 μs | 709.1 μs | 162.6 μs | 43.9 μs | 154.8 μs | ExpFromLeft (42.2 μs) | 1.04x | +| plateau | sorted_bimodal | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| plateau | sorted_bimodal | 16 | 4 | 90 ns | 100 ns | 100 ns | 170 ns | 90 ns | 100 ns | 70 ns | Binary (90 ns) | 1.11x | +| plateau | sorted_bimodal | 16 | 16 | 180 ns | 270 ns | 230 ns | 610 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | +| plateau | sorted_bimodal | 16 | 64 | 570 ns | 950 ns | 760 ns | 2.3 μs | 809 ns | 600 ns | 730 ns | Linear (570 ns) | 1.05x | +| plateau | sorted_bimodal | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.6 μs | 3.0 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.00x | +| plateau | sorted_bimodal | 16 | 1024 | 7.8 μs | 13.9 μs | 10.6 μs | 34.1 μs | 11.8 μs | 7.8 μs | 10.0 μs | Linear (7.8 μs) | 1.00x | +| plateau | sorted_bimodal | 16 | 4096 | 30.8 μs | 55.5 μs | 42.0 μs | 135.9 μs | 47.1 μs | 30.8 μs | 40.1 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_bimodal | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | +| plateau | sorted_bimodal | 64 | 4 | 110 ns | 110 ns | 110 ns | 210 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | +| plateau | sorted_bimodal | 64 | 16 | 210 ns | 270 ns | 220 ns | 740 ns | 320 ns | 230 ns | 270 ns | Linear (210 ns) | 1.10x | +| plateau | sorted_bimodal | 64 | 64 | 600 ns | 950 ns | 760 ns | 2.9 μs | 1.1 μs | 630 ns | 960 ns | Linear (600 ns) | 1.05x | +| plateau | sorted_bimodal | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.4 μs | 4.2 μs | 2.1 μs | 3.7 μs | Linear (2.0 μs) | 1.01x | +| plateau | sorted_bimodal | 64 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 44.4 μs | 16.6 μs | 7.8 μs | 14.8 μs | Linear (7.8 μs) | 1.00x | +| plateau | sorted_bimodal | 64 | 4096 | 30.8 μs | 55.7 μs | 42.0 μs | 176.1 μs | 66.4 μs | 30.9 μs | 58.7 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_bimodal | 256 | 4 | 200 ns | 120 ns | 110 ns | 250 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (110 ns) | 1.27x | +| plateau | sorted_bimodal | 256 | 16 | 290 ns | 290 ns | 250 ns | 910 ns | 380 ns | 250 ns | 350 ns | ExpFromLeft (250 ns) | 1.00x | +| plateau | sorted_bimodal | 256 | 64 | 690 ns | 970 ns | 780 ns | 3.6 μs | 1.4 μs | 710 ns | 1.3 μs | Linear (690 ns) | 1.03x | +| plateau | sorted_bimodal | 256 | 256 | 2.1 μs | 3.6 μs | 2.7 μs | 14.7 μs | 5.4 μs | 2.2 μs | 4.9 μs | Linear (2.1 μs) | 1.01x | +| plateau | sorted_bimodal | 256 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 56.3 μs | 21.6 μs | 7.9 μs | 19.6 μs | Linear (7.9 μs) | 1.00x | +| plateau | sorted_bimodal | 256 | 4096 | 30.9 μs | 55.6 μs | 42.1 μs | 220.8 μs | 86.1 μs | 30.9 μs | 78.2 μs | Linear (30.9 μs) | 1.00x | +| plateau | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | +| plateau | sorted_bimodal | 1024 | 4 | 560 ns | 150 ns | 120 ns | 290 ns | 150 ns | 160 ns | 130 ns | ExpFromLeft (120 ns) | 1.33x | +| plateau | sorted_bimodal | 1024 | 16 | 670 ns | 310 ns | 250 ns | 1.0 μs | 470 ns | 260 ns | 430 ns | ExpFromLeft (250 ns) | 1.04x | +| plateau | sorted_bimodal | 1024 | 64 | 1.1 μs | 989 ns | 990 ns | 4.2 μs | 1.8 μs | 820 ns | 1.6 μs | Gallop (989 ns) | 0.83x | +| plateau | sorted_bimodal | 1024 | 256 | 2.5 μs | 4.7 μs | 3.6 μs | 17.2 μs | 6.6 μs | 2.5 μs | 6.1 μs | Linear (2.5 μs) | 1.01x | +| plateau | sorted_bimodal | 1024 | 1024 | 8.2 μs | 14.0 μs | 10.6 μs | 71.8 μs | 26.2 μs | 8.3 μs | 24.4 μs | Linear (8.2 μs) | 1.00x | +| plateau | sorted_bimodal | 1024 | 4096 | 31.3 μs | 55.6 μs | 42.1 μs | 264.7 μs | 104.6 μs | 31.3 μs | 97.2 μs | Linear (31.3 μs) | 1.00x | +| plateau | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_bimodal | 4096 | 4 | 2.0 μs | 150 ns | 130 ns | 330 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (130 ns) | 1.31x | +| plateau | sorted_bimodal | 4096 | 16 | 2.1 μs | 320 ns | 260 ns | 1.2 μs | 540 ns | 280 ns | 510 ns | ExpFromLeft (260 ns) | 1.08x | +| plateau | sorted_bimodal | 4096 | 64 | 2.5 μs | 999 ns | 790 ns | 4.7 μs | 2.0 μs | 830 ns | 1.9 μs | ExpFromLeft (790 ns) | 1.05x | +| plateau | sorted_bimodal | 4096 | 256 | 3.9 μs | 3.6 μs | 2.8 μs | 19.7 μs | 7.8 μs | 2.9 μs | 7.3 μs | ExpFromLeft (2.8 μs) | 1.04x | +| plateau | sorted_bimodal | 4096 | 1024 | 9.7 μs | 14.1 μs | 10.6 μs | 91.5 μs | 31.2 μs | 9.7 μs | 29.1 μs | Linear (9.7 μs) | 1.00x | +| plateau | sorted_bimodal | 4096 | 4096 | 32.7 μs | 55.6 μs | 42.1 μs | 358.4 μs | 124.6 μs | 32.7 μs | 116.2 μs | Linear (32.7 μs) | 1.00x | +| plateau | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_bimodal | 16384 | 4 | 7.6 μs | 160 ns | 150 ns | 370 ns | 180 ns | 170 ns | 170 ns | ExpFromLeft (150 ns) | 1.13x | +| plateau | sorted_bimodal | 16384 | 16 | 7.9 μs | 330 ns | 270 ns | 1.4 μs | 610 ns | 290 ns | 590 ns | ExpFromLeft (270 ns) | 1.07x | +| plateau | sorted_bimodal | 16384 | 64 | 8.3 μs | 1.0 μs | 810 ns | 5.5 μs | 2.3 μs | 840 ns | 2.2 μs | ExpFromLeft (810 ns) | 1.04x | +| plateau | sorted_bimodal | 16384 | 256 | 9.7 μs | 3.6 μs | 2.8 μs | 23.1 μs | 9.0 μs | 2.9 μs | 8.6 μs | ExpFromLeft (2.8 μs) | 1.04x | +| plateau | sorted_bimodal | 16384 | 1024 | 15.4 μs | 13.9 μs | 10.7 μs | 119.1 μs | 36.0 μs | 11.1 μs | 34.2 μs | ExpFromLeft (10.7 μs) | 1.04x | +| plateau | sorted_bimodal | 16384 | 4096 | 38.5 μs | 55.8 μs | 42.1 μs | 501.1 μs | 143.9 μs | 38.4 μs | 137.0 μs | Linear (38.5 μs) | 1.00x | +| plateau | sorted_bimodal | 65536 | 1 | 80 ns | 70 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | Gallop (70 ns) | 1.14x | +| plateau | sorted_bimodal | 65536 | 4 | 29.8 μs | 180 ns | 160 ns | 410 ns | 200 ns | 190 ns | 190 ns | ExpFromLeft (160 ns) | 1.19x | +| plateau | sorted_bimodal | 65536 | 16 | 30.9 μs | 350 ns | 280 ns | 1.6 μs | 710 ns | 300 ns | 660 ns | ExpFromLeft (280 ns) | 1.07x | +| plateau | sorted_bimodal | 65536 | 64 | 31.6 μs | 1.0 μs | 820 ns | 6.1 μs | 2.6 μs | 850 ns | 2.5 μs | ExpFromLeft (820 ns) | 1.04x | +| plateau | sorted_bimodal | 65536 | 256 | 32.6 μs | 3.6 μs | 2.8 μs | 26.9 μs | 10.2 μs | 2.9 μs | 9.7 μs | ExpFromLeft (2.8 μs) | 1.04x | +| plateau | sorted_bimodal | 65536 | 1024 | 38.7 μs | 14.1 μs | 10.6 μs | 175.2 μs | 40.7 μs | 11.1 μs | 38.7 μs | ExpFromLeft (10.6 μs) | 1.04x | +| plateau | sorted_bimodal | 65536 | 4096 | 61.7 μs | 55.7 μs | 42.1 μs | 678.9 μs | 162.7 μs | 43.8 μs | 154.9 μs | ExpFromLeft (42.1 μs) | 1.04x | +| plateau | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| plateau | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 160 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| plateau | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 200 ns | 500 ns | 230 ns | 190 ns | 190 ns | Linear (170 ns) | 1.12x | +| plateau | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 690 ns | 1.9 μs | 790 ns | 580 ns | 680 ns | Linear (550 ns) | 1.05x | +| plateau | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 7.2 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.01x | +| plateau | sorted_repeated | 16 | 1024 | 7.7 μs | 13.9 μs | 9.8 μs | 28.8 μs | 11.8 μs | 7.8 μs | 10.3 μs | Linear (7.7 μs) | 1.00x | +| plateau | sorted_repeated | 16 | 4096 | 30.8 μs | 54.9 μs | 39.0 μs | 115.1 μs | 47.1 μs | 30.8 μs | 40.0 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| plateau | sorted_repeated | 64 | 4 | 80 ns | 90 ns | 90 ns | 190 ns | 100 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| plateau | sorted_repeated | 64 | 16 | 170 ns | 279 ns | 200 ns | 670 ns | 310 ns | 190 ns | 260 ns | Linear (170 ns) | 1.12x | +| plateau | sorted_repeated | 64 | 64 | 550 ns | 920 ns | 690 ns | 2.5 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | +| plateau | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 10.1 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | +| plateau | sorted_repeated | 64 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 40.0 μs | 16.7 μs | 7.8 μs | 14.3 μs | Linear (7.8 μs) | 1.00x | +| plateau | sorted_repeated | 64 | 4096 | 30.8 μs | 54.9 μs | 39.1 μs | 159.7 μs | 67.1 μs | 30.8 μs | 57.1 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 110 ns | 230 ns | 120 ns | 110 ns | 120 ns | Linear (90 ns) | 1.22x | +| plateau | sorted_repeated | 256 | 16 | 180 ns | 280 ns | 220 ns | 830 ns | 390 ns | 200 ns | 350 ns | Linear (180 ns) | 1.11x | +| plateau | sorted_repeated | 256 | 64 | 550 ns | 920 ns | 710 ns | 3.2 μs | 1.4 μs | 580 ns | 1.3 μs | Linear (550 ns) | 1.05x | +| plateau | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 12.6 μs | 5.4 μs | 2.0 μs | 4.9 μs | Linear (2.0 μs) | 1.02x | +| plateau | sorted_repeated | 256 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 49.7 μs | 21.4 μs | 7.8 μs | 19.5 μs | Linear (7.7 μs) | 1.00x | +| plateau | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.0 μs | 198.9 μs | 85.6 μs | 30.8 μs | 78.0 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | sorted_repeated | 1024 | 4 | 90 ns | 110 ns | 100 ns | 270 ns | 150 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | +| plateau | sorted_repeated | 1024 | 16 | 189 ns | 290 ns | 220 ns | 1.0 μs | 470 ns | 200 ns | 430 ns | Linear (189 ns) | 1.06x | +| plateau | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 690 ns | 3.9 μs | 1.7 μs | 600 ns | 1.6 μs | Linear (560 ns) | 1.07x | +| plateau | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 15.1 μs | 6.6 μs | 2.0 μs | 6.1 μs | Linear (2.0 μs) | 1.02x | +| plateau | sorted_repeated | 1024 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 60.2 μs | 26.3 μs | 7.8 μs | 24.2 μs | Linear (7.7 μs) | 1.01x | +| plateau | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.1 μs | 39.1 μs | 239.4 μs | 105.3 μs | 30.8 μs | 96.9 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_repeated | 4096 | 4 | 90 ns | 120 ns | 100 ns | 310 ns | 160 ns | 130 ns | 150 ns | Linear (90 ns) | 1.44x | +| plateau | sorted_repeated | 4096 | 16 | 230 ns | 360 ns | 260 ns | 1.2 μs | 550 ns | 250 ns | 500 ns | Linear (230 ns) | 1.09x | +| plateau | sorted_repeated | 4096 | 64 | 560 ns | 940 ns | 700 ns | 4.5 μs | 2.0 μs | 600 ns | 1.9 μs | Linear (560 ns) | 1.07x | +| plateau | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 17.6 μs | 7.8 μs | 2.1 μs | 7.3 μs | Linear (2.0 μs) | 1.04x | +| plateau | sorted_repeated | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 70.4 μs | 31.3 μs | 7.8 μs | 28.9 μs | Linear (7.7 μs) | 1.01x | +| plateau | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.0 μs | 281.2 μs | 124.9 μs | 30.8 μs | 115.5 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | sorted_repeated | 16384 | 4 | 100 ns | 110 ns | 110 ns | 370 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | +| plateau | sorted_repeated | 16384 | 16 | 190 ns | 290 ns | 240 ns | 1.3 μs | 610 ns | 220 ns | 580 ns | Linear (190 ns) | 1.16x | +| plateau | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 720 ns | 5.1 μs | 2.3 μs | 600 ns | 2.2 μs | Linear (560 ns) | 1.07x | +| plateau | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 20.2 μs | 9.0 μs | 2.0 μs | 8.6 μs | Linear (2.0 μs) | 1.02x | +| plateau | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 80.5 μs | 35.8 μs | 7.8 μs | 34.2 μs | Linear (7.8 μs) | 1.00x | +| plateau | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.0 μs | 39.3 μs | 321.0 μs | 143.6 μs | 30.8 μs | 136.5 μs | Linear (30.8 μs) | 1.00x | +| plateau | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| plateau | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 420 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| plateau | sorted_repeated | 65536 | 16 | 200 ns | 300 ns | 230 ns | 1.5 μs | 690 ns | 220 ns | 650 ns | Linear (200 ns) | 1.10x | +| plateau | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 710 ns | 6.0 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| plateau | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 23.9 μs | 10.2 μs | 2.0 μs | 9.7 μs | Linear (2.0 μs) | 1.01x | +| plateau | sorted_repeated | 65536 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 95.7 μs | 40.8 μs | 7.8 μs | 38.7 μs | Linear (7.7 μs) | 1.01x | +| plateau | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.1 μs | 39.1 μs | 382.4 μs | 163.2 μs | 30.8 μs | 154.4 μs | Linear (30.8 μs) | 1.00x | +| plateau | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| plateau | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 90 ns | 90 ns | 100 ns | 70 ns | InterpSearch (90 ns) | 1.11x | +| plateau | unsorted | 16 | 16 | 220 ns | 200 ns | 210 ns | 210 ns | 210 ns | 220 ns | 190 ns | Gallop (200 ns) | 1.10x | +| plateau | unsorted | 16 | 64 | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | Binary (1.0 μs) | 1.01x | +| plateau | unsorted | 16 | 256 | 4.6 μs | 4.6 μs | 4.6 μs | 4.5 μs | 4.6 μs | 4.5 μs | 4.6 μs | InterpSearch (4.5 μs) | 1.00x | +| plateau | unsorted | 16 | 1024 | 18.3 μs | 18.3 μs | 18.3 μs | 18.2 μs | 18.3 μs | 18.3 μs | 18.4 μs | InterpSearch (18.2 μs) | 1.00x | +| plateau | unsorted | 16 | 4096 | 74.4 μs | 74.5 μs | 74.4 μs | 74.0 μs | 74.5 μs | 74.2 μs | 74.5 μs | InterpSearch (74.0 μs) | 1.00x | +| plateau | unsorted | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 49 ns | ExpFromLeft (50 ns) | 1.20x | +| plateau | unsorted | 64 | 4 | 100 ns | 110 ns | 110 ns | 110 ns | 110 ns | 120 ns | 90 ns | Linear (100 ns) | 1.20x | +| plateau | unsorted | 64 | 16 | 300 ns | 290 ns | 300 ns | 290 ns | 300 ns | 310 ns | 280 ns | InterpSearch (290 ns) | 1.07x | +| plateau | unsorted | 64 | 64 | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | InterpSearch (1.4 μs) | 1.01x | +| plateau | unsorted | 64 | 256 | 5.6 μs | 5.7 μs | 5.7 μs | 5.7 μs | 5.7 μs | 5.7 μs | 5.7 μs | Linear (5.6 μs) | 1.01x | +| plateau | unsorted | 64 | 1024 | 22.8 μs | 22.6 μs | 22.7 μs | 22.7 μs | 22.8 μs | 23.1 μs | 22.8 μs | Gallop (22.6 μs) | 1.02x | +| plateau | unsorted | 64 | 4096 | 89.8 μs | 90.0 μs | 89.9 μs | 90.0 μs | 89.8 μs | 89.7 μs | 89.3 μs | Binary (89.8 μs) | 1.00x | +| plateau | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | unsorted | 256 | 4 | 120 ns | 120 ns | 130 ns | 130 ns | 130 ns | 140 ns | 110 ns | Gallop (120 ns) | 1.17x | +| plateau | unsorted | 256 | 16 | 390 ns | 390 ns | 380 ns | 380 ns | 390 ns | 400 ns | 360 ns | InterpSearch (380 ns) | 1.05x | +| plateau | unsorted | 256 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | InterpSearch (1.6 μs) | 1.01x | +| plateau | unsorted | 256 | 256 | 6.5 μs | 6.5 μs | 6.5 μs | 6.5 μs | 6.5 μs | 6.5 μs | 6.5 μs | InterpSearch (6.5 μs) | 1.00x | +| plateau | unsorted | 256 | 1024 | 27.0 μs | 27.1 μs | 27.1 μs | 27.1 μs | 27.1 μs | 27.1 μs | 26.8 μs | Linear (27.0 μs) | 1.00x | +| plateau | unsorted | 256 | 4096 | 108.6 μs | 108.7 μs | 108.6 μs | 111.7 μs | 111.9 μs | 111.9 μs | 108.1 μs | Linear (108.6 μs) | 1.03x | +| plateau | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| plateau | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| plateau | unsorted | 1024 | 16 | 480 ns | 480 ns | 470 ns | 470 ns | 480 ns | 479 ns | 460 ns | InterpSearch (470 ns) | 1.02x | +| plateau | unsorted | 1024 | 64 | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | Gallop (2.0 μs) | 1.02x | +| plateau | unsorted | 1024 | 256 | 8.4 μs | 8.2 μs | 8.3 μs | 8.2 μs | 8.3 μs | 8.3 μs | 8.4 μs | InterpSearch (8.2 μs) | 1.02x | +| plateau | unsorted | 1024 | 1024 | 32.3 μs | 32.4 μs | 32.5 μs | 32.4 μs | 32.5 μs | 32.3 μs | 32.4 μs | Linear (32.3 μs) | 1.00x | +| plateau | unsorted | 1024 | 4096 | 130.2 μs | 130.5 μs | 131.5 μs | 129.4 μs | 130.0 μs | 129.9 μs | 130.3 μs | InterpSearch (129.4 μs) | 1.00x | +| plateau | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | unsorted | 4096 | 4 | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 150 ns | InterpSearch (160 ns) | 1.00x | +| plateau | unsorted | 4096 | 16 | 560 ns | 540 ns | 550 ns | 550 ns | 550 ns | 550 ns | 540 ns | Gallop (540 ns) | 1.02x | +| plateau | unsorted | 4096 | 64 | 2.3 μs | 2.4 μs | 2.4 μs | 2.4 μs | 2.4 μs | 2.4 μs | 2.3 μs | Linear (2.3 μs) | 1.03x | +| plateau | unsorted | 4096 | 256 | 9.5 μs | 9.4 μs | 9.5 μs | 9.5 μs | 9.5 μs | 9.5 μs | 9.4 μs | Gallop (9.4 μs) | 1.00x | +| plateau | unsorted | 4096 | 1024 | 36.6 μs | 36.6 μs | 36.6 μs | 36.6 μs | 36.5 μs | 36.5 μs | 36.6 μs | Binary (36.5 μs) | 1.00x | +| plateau | unsorted | 4096 | 4096 | 148.7 μs | 147.9 μs | 147.8 μs | 148.7 μs | 148.1 μs | 148.8 μs | 148.3 μs | ExpFromLeft (147.8 μs) | 1.01x | +| plateau | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| plateau | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 210 ns | 179 ns | 180 ns | 170 ns | ExpFromLeft (170 ns) | 1.06x | +| plateau | unsorted | 16384 | 16 | 630 ns | 630 ns | 630 ns | 630 ns | 640 ns | 650 ns | 630 ns | InterpSearch (630 ns) | 1.03x | +| plateau | unsorted | 16384 | 64 | 2.6 μs | 2.5 μs | 2.5 μs | 2.5 μs | 2.6 μs | 2.6 μs | 2.5 μs | InterpSearch (2.5 μs) | 1.01x | +| plateau | unsorted | 16384 | 256 | 10.5 μs | 10.5 μs | 10.6 μs | 10.6 μs | 10.6 μs | 10.6 μs | 10.4 μs | Linear (10.5 μs) | 1.01x | +| plateau | unsorted | 16384 | 1024 | 41.8 μs | 41.9 μs | 41.8 μs | 42.0 μs | 42.1 μs | 41.8 μs | 41.9 μs | Linear (41.8 μs) | 1.00x | +| plateau | unsorted | 16384 | 4096 | 168.3 μs | 168.2 μs | 168.2 μs | 168.2 μs | 168.2 μs | 168.2 μs | 167.4 μs | Binary (168.2 μs) | 1.00x | +| plateau | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| plateau | unsorted | 65536 | 4 | 200 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | +| plateau | unsorted | 65536 | 16 | 730 ns | 730 ns | 720 ns | 720 ns | 740 ns | 740 ns | 720 ns | InterpSearch (720 ns) | 1.03x | +| plateau | unsorted | 65536 | 64 | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | InterpSearch (2.9 μs) | 1.01x | +| plateau | unsorted | 65536 | 256 | 12.0 μs | 12.0 μs | 12.1 μs | 12.0 μs | 12.0 μs | 12.0 μs | 12.0 μs | Binary (12.0 μs) | 1.00x | +| plateau | unsorted | 65536 | 1024 | 47.8 μs | 48.0 μs | 48.0 μs | 47.9 μs | 47.8 μs | 47.9 μs | 47.9 μs | Linear (47.8 μs) | 1.00x | +| plateau | unsorted | 65536 | 4096 | 194.3 μs | 194.5 μs | 193.9 μs | 193.8 μs | 194.1 μs | 194.3 μs | 193.7 μs | InterpSearch (193.8 μs) | 1.00x | +| bimodal | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 90 ns | 170 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| bimodal | sorted_uniform | 16 | 16 | 190 ns | 280 ns | 240 ns | 570 ns | 230 ns | 200 ns | 180 ns | Linear (190 ns) | 1.05x | +| bimodal | sorted_uniform | 16 | 64 | 570 ns | 950 ns | 750 ns | 2.2 μs | 840 ns | 600 ns | 710 ns | Linear (570 ns) | 1.05x | +| bimodal | sorted_uniform | 16 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 8.6 μs | 3.1 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.02x | +| bimodal | sorted_uniform | 16 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 33.6 μs | 12.0 μs | 7.9 μs | 9.9 μs | Linear (7.9 μs) | 1.00x | +| bimodal | sorted_uniform | 16 | 4096 | 31.0 μs | 55.1 μs | 42.3 μs | 132.4 μs | 47.5 μs | 31.0 μs | 41.1 μs | Linear (31.0 μs) | 1.00x | +| bimodal | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | sorted_uniform | 64 | 4 | 120 ns | 120 ns | 120 ns | 180 ns | 110 ns | 130 ns | 90 ns | Binary (110 ns) | 1.18x | +| bimodal | sorted_uniform | 64 | 16 | 190 ns | 290 ns | 220 ns | 640 ns | 320 ns | 210 ns | 280 ns | Linear (190 ns) | 1.11x | +| bimodal | sorted_uniform | 64 | 64 | 650 ns | 980 ns | 770 ns | 2.5 μs | 1.1 μs | 680 ns | 940 ns | Linear (650 ns) | 1.05x | +| bimodal | sorted_uniform | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 10.7 μs | 4.4 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | +| bimodal | sorted_uniform | 64 | 1024 | 7.9 μs | 14.1 μs | 10.7 μs | 42.1 μs | 17.3 μs | 7.9 μs | 15.0 μs | Linear (7.9 μs) | 1.00x | +| bimodal | sorted_uniform | 64 | 4096 | 31.9 μs | 55.9 μs | 43.0 μs | 164.1 μs | 67.5 μs | 31.9 μs | 58.4 μs | Linear (31.9 μs) | 1.00x | +| bimodal | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | sorted_uniform | 256 | 4 | 80 ns | 100 ns | 100 ns | 250 ns | 120 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | +| bimodal | sorted_uniform | 256 | 16 | 500 ns | 320 ns | 260 ns | 760 ns | 390 ns | 280 ns | 350 ns | ExpFromLeft (260 ns) | 1.08x | +| bimodal | sorted_uniform | 256 | 64 | 930 ns | 1.1 μs | 860 ns | 3.1 μs | 1.4 μs | 940 ns | 1.2 μs | ExpFromLeft (860 ns) | 1.09x | +| bimodal | sorted_uniform | 256 | 256 | 2.5 μs | 3.8 μs | 2.9 μs | 12.9 μs | 5.5 μs | 2.5 μs | 5.0 μs | Linear (2.5 μs) | 1.01x | +| bimodal | sorted_uniform | 256 | 1024 | 8.2 μs | 14.4 μs | 10.8 μs | 57.7 μs | 22.9 μs | 8.2 μs | 20.7 μs | Linear (8.2 μs) | 1.00x | +| bimodal | sorted_uniform | 256 | 4096 | 31.9 μs | 57.1 μs | 43.5 μs | 212.3 μs | 89.4 μs | 31.9 μs | 80.2 μs | Linear (31.9 μs) | 1.00x | +| bimodal | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | sorted_uniform | 1024 | 4 | 520 ns | 140 ns | 130 ns | 290 ns | 140 ns | 170 ns | 130 ns | ExpFromLeft (130 ns) | 1.31x | +| bimodal | sorted_uniform | 1024 | 16 | 1.2 μs | 380 ns | 310 ns | 1.0 μs | 460 ns | 330 ns | 430 ns | ExpFromLeft (310 ns) | 1.06x | +| bimodal | sorted_uniform | 1024 | 64 | 2.0 μs | 1.2 μs | 970 ns | 3.8 μs | 1.7 μs | 1.0 μs | 1.5 μs | ExpFromLeft (970 ns) | 1.05x | +| bimodal | sorted_uniform | 1024 | 256 | 3.7 μs | 4.3 μs | 3.3 μs | 15.7 μs | 6.8 μs | 3.7 μs | 6.1 μs | ExpFromLeft (3.3 μs) | 1.14x | +| bimodal | sorted_uniform | 1024 | 1024 | 9.7 μs | 15.7 μs | 11.6 μs | 79.7 μs | 28.0 μs | 9.8 μs | 25.7 μs | Linear (9.7 μs) | 1.01x | +| bimodal | sorted_uniform | 1024 | 4096 | 33.5 μs | 58.3 μs | 44.0 μs | 324.0 μs | 118.6 μs | 33.3 μs | 113.4 μs | Linear (33.5 μs) | 1.00x | +| bimodal | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (70 ns) | 0.86x | +| bimodal | sorted_uniform | 4096 | 4 | 90 ns | 110 ns | 120 ns | 309 ns | 160 ns | 130 ns | 140 ns | Linear (90 ns) | 1.44x | +| bimodal | sorted_uniform | 4096 | 16 | 1.9 μs | 400 ns | 310 ns | 1.1 μs | 540 ns | 330 ns | 490 ns | ExpFromLeft (310 ns) | 1.06x | +| bimodal | sorted_uniform | 4096 | 64 | 6.2 μs | 1.4 μs | 1.1 μs | 4.4 μs | 2.0 μs | 1.1 μs | 1.8 μs | ExpFromLeft (1.1 μs) | 1.04x | +| bimodal | sorted_uniform | 4096 | 256 | 8.4 μs | 4.6 μs | 3.5 μs | 18.4 μs | 7.9 μs | 3.7 μs | 7.2 μs | ExpFromLeft (3.5 μs) | 1.03x | +| bimodal | sorted_uniform | 4096 | 1024 | 15.0 μs | 16.8 μs | 12.7 μs | 109.1 μs | 33.9 μs | 15.3 μs | 30.0 μs | ExpFromLeft (12.7 μs) | 1.20x | +| bimodal | sorted_uniform | 4096 | 4096 | 39.4 μs | 63.7 μs | 47.7 μs | 452.0 μs | 163.7 μs | 40.2 μs | 147.5 μs | Linear (39.4 μs) | 1.02x | +| bimodal | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | sorted_uniform | 16384 | 4 | 4.6 μs | 200 ns | 180 ns | 370 ns | 180 ns | 200 ns | 170 ns | ExpFromLeft (180 ns) | 1.11x | +| bimodal | sorted_uniform | 16384 | 16 | 18.5 μs | 550 ns | 430 ns | 1.3 μs | 610 ns | 450 ns | 560 ns | ExpFromLeft (430 ns) | 1.05x | +| bimodal | sorted_uniform | 16384 | 64 | 20.5 μs | 1.5 μs | 1.2 μs | 5.2 μs | 2.3 μs | 1.2 μs | 2.1 μs | ExpFromLeft (1.2 μs) | 1.03x | +| bimodal | sorted_uniform | 16384 | 256 | 26.6 μs | 5.1 μs | 3.9 μs | 21.7 μs | 9.2 μs | 4.1 μs | 8.5 μs | ExpFromLeft (3.9 μs) | 1.03x | +| bimodal | sorted_uniform | 16384 | 1024 | 35.0 μs | 19.1 μs | 14.6 μs | 140.4 μs | 38.4 μs | 15.0 μs | 35.7 μs | ExpFromLeft (14.6 μs) | 1.03x | +| bimodal | sorted_uniform | 16384 | 4096 | 63.6 μs | 71.5 μs | 56.6 μs | 571.5 μs | 206.6 μs | 63.3 μs | 199.3 μs | ExpFromLeft (56.6 μs) | 1.12x | +| bimodal | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 79 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (79 ns) | 1.01x | +| bimodal | sorted_uniform | 65536 | 4 | 100 ns | 120 ns | 110 ns | 400 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| bimodal | sorted_uniform | 65536 | 16 | 46.0 μs | 370 ns | 300 ns | 1.5 μs | 680 ns | 320 ns | 640 ns | ExpFromLeft (300 ns) | 1.07x | +| bimodal | sorted_uniform | 65536 | 64 | 90.2 μs | 1.7 μs | 1.3 μs | 5.7 μs | 2.6 μs | 1.3 μs | 2.5 μs | ExpFromLeft (1.3 μs) | 1.03x | +| bimodal | sorted_uniform | 65536 | 256 | 95.1 μs | 6.0 μs | 4.6 μs | 26.8 μs | 10.8 μs | 4.6 μs | 9.9 μs | ExpFromLeft (4.6 μs) | 0.99x | +| bimodal | sorted_uniform | 65536 | 1024 | 107.1 μs | 21.4 μs | 16.8 μs | 189.8 μs | 43.2 μs | 17.0 μs | 41.2 μs | ExpFromLeft (16.8 μs) | 1.01x | +| bimodal | sorted_uniform | 65536 | 4096 | 136.7 μs | 88.7 μs | 67.5 μs | 730.4 μs | 251.0 μs | 66.9 μs | 251.5 μs | ExpFromLeft (67.5 μs) | 0.99x | +| bimodal | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | sorted_dense_burst | 16 | 4 | 80 ns | 90 ns | 90 ns | 160 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| bimodal | sorted_dense_burst | 16 | 16 | 170 ns | 270 ns | 220 ns | 570 ns | 230 ns | 190 ns | 190 ns | Linear (170 ns) | 1.12x | +| bimodal | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 720 ns | 2.2 μs | 790 ns | 570 ns | 649 ns | Linear (550 ns) | 1.04x | +| bimodal | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.4 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.01x | +| bimodal | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 33.1 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.01x | +| bimodal | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.8 μs | 42.0 μs | 130.4 μs | 47.0 μs | 32.9 μs | 38.5 μs | Linear (30.8 μs) | 1.07x | +| bimodal | sorted_dense_burst | 64 | 1 | 50 ns | 90 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 90 ns | 190 ns | 110 ns | 110 ns | 80 ns | Linear (80 ns) | 1.38x | +| bimodal | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 220 ns | 670 ns | 310 ns | 200 ns | 270 ns | Linear (170 ns) | 1.18x | +| bimodal | sorted_dense_burst | 64 | 64 | 550 ns | 930 ns | 730 ns | 2.6 μs | 1.1 μs | 580 ns | 910 ns | Linear (550 ns) | 1.05x | +| bimodal | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 10.8 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | +| bimodal | sorted_dense_burst | 64 | 1024 | 8.3 μs | 13.9 μs | 10.5 μs | 41.6 μs | 17.1 μs | 7.8 μs | 14.1 μs | Linear (8.3 μs) | 0.94x | +| bimodal | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.4 μs | 41.9 μs | 162.9 μs | 66.6 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | sorted_dense_burst | 256 | 4 | 80 ns | 100 ns | 100 ns | 200 ns | 120 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | +| bimodal | sorted_dense_burst | 256 | 16 | 180 ns | 280 ns | 230 ns | 780 ns | 380 ns | 250 ns | 350 ns | Linear (180 ns) | 1.39x | +| bimodal | sorted_dense_burst | 256 | 64 | 550 ns | 930 ns | 730 ns | 3.2 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | +| bimodal | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 12.9 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| bimodal | sorted_dense_burst | 256 | 1024 | 7.8 μs | 13.9 μs | 10.6 μs | 56.1 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | +| bimodal | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 205.3 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | sorted_dense_burst | 1024 | 4 | 100 ns | 100 ns | 110 ns | 290 ns | 140 ns | 130 ns | 120 ns | Gallop (100 ns) | 1.30x | +| bimodal | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 250 ns | 999 ns | 460 ns | 250 ns | 420 ns | Linear (180 ns) | 1.39x | +| bimodal | sorted_dense_burst | 1024 | 64 | 560 ns | 939 ns | 730 ns | 3.9 μs | 1.7 μs | 790 ns | 1.5 μs | Linear (560 ns) | 1.41x | +| bimodal | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.1 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | +| bimodal | sorted_dense_burst | 1024 | 1024 | 8.3 μs | 14.0 μs | 10.6 μs | 78.8 μs | 26.3 μs | 7.8 μs | 24.0 μs | Linear (8.3 μs) | 0.94x | +| bimodal | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 312.8 μs | 105.5 μs | 30.9 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | sorted_dense_burst | 4096 | 4 | 100 ns | 110 ns | 110 ns | 400 ns | 200 ns | 130 ns | 150 ns | Linear (100 ns) | 1.30x | +| bimodal | sorted_dense_burst | 4096 | 16 | 180 ns | 290 ns | 260 ns | 1.1 μs | 520 ns | 270 ns | 489 ns | Linear (180 ns) | 1.50x | +| bimodal | sorted_dense_burst | 4096 | 64 | 560 ns | 950 ns | 750 ns | 4.3 μs | 2.0 μs | 780 ns | 1.8 μs | Linear (560 ns) | 1.39x | +| bimodal | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 19.0 μs | 7.8 μs | 2.8 μs | 7.2 μs | Linear (2.0 μs) | 1.40x | +| bimodal | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 14.0 μs | 10.4 μs | 101.8 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | +| bimodal | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 56.0 μs | 41.8 μs | 441.0 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 360 ns | 179 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | +| bimodal | sorted_dense_burst | 16384 | 16 | 200 ns | 290 ns | 240 ns | 1.3 μs | 610 ns | 270 ns | 560 ns | Linear (200 ns) | 1.35x | +| bimodal | sorted_dense_burst | 16384 | 64 | 570 ns | 950 ns | 750 ns | 5.1 μs | 2.3 μs | 790 ns | 2.1 μs | Linear (570 ns) | 1.39x | +| bimodal | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 22.3 μs | 9.0 μs | 2.8 μs | 8.4 μs | Linear (2.0 μs) | 1.41x | +| bimodal | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 136.3 μs | 36.0 μs | 11.0 μs | 33.4 μs | Linear (7.8 μs) | 1.41x | +| bimodal | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.7 μs | 42.0 μs | 556.4 μs | 144.2 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| bimodal | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 370 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| bimodal | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 250 ns | 1.5 μs | 690 ns | 260 ns | 640 ns | Linear (190 ns) | 1.37x | +| bimodal | sorted_dense_burst | 65536 | 64 | 780 ns | 960 ns | 750 ns | 5.9 μs | 2.6 μs | 820 ns | 2.4 μs | ExpFromLeft (750 ns) | 1.09x | +| bimodal | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 24.8 μs | 10.2 μs | 2.8 μs | 9.5 μs | Linear (2.0 μs) | 1.42x | +| bimodal | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 181.4 μs | 40.8 μs | 11.0 μs | 38.2 μs | Linear (7.8 μs) | 1.41x | +| bimodal | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 707.9 μs | 163.2 μs | 43.7 μs | 152.6 μs | Linear (30.8 μs) | 1.42x | +| bimodal | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | sorted_near_start | 16 | 4 | 90 ns | 100 ns | 100 ns | 160 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | +| bimodal | sorted_near_start | 16 | 16 | 180 ns | 280 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | +| bimodal | sorted_near_start | 16 | 64 | 570 ns | 960 ns | 740 ns | 1.8 μs | 810 ns | 590 ns | 690 ns | Linear (570 ns) | 1.04x | +| bimodal | sorted_near_start | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 6.8 μs | 3.0 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.01x | +| bimodal | sorted_near_start | 16 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 27.2 μs | 11.9 μs | 7.8 μs | 10.1 μs | Linear (7.8 μs) | 1.00x | +| bimodal | sorted_near_start | 16 | 4096 | 30.9 μs | 55.7 μs | 42.1 μs | 107.6 μs | 47.6 μs | 30.9 μs | 40.2 μs | Linear (30.9 μs) | 1.00x | +| bimodal | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 50 ns | 69 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| bimodal | sorted_near_start | 64 | 4 | 130 ns | 110 ns | 110 ns | 200 ns | 130 ns | 120 ns | 90 ns | ExpFromLeft (110 ns) | 1.09x | +| bimodal | sorted_near_start | 64 | 16 | 220 ns | 280 ns | 230 ns | 520 ns | 320 ns | 240 ns | 280 ns | Linear (220 ns) | 1.09x | +| bimodal | sorted_near_start | 64 | 64 | 600 ns | 960 ns | 750 ns | 1.8 μs | 1.1 μs | 630 ns | 1.0 μs | Linear (600 ns) | 1.05x | +| bimodal | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.1 μs | 4.2 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | +| bimodal | sorted_near_start | 64 | 1024 | 7.9 μs | 14.1 μs | 10.7 μs | 28.1 μs | 16.6 μs | 7.9 μs | 14.9 μs | Linear (7.9 μs) | 1.00x | +| bimodal | sorted_near_start | 64 | 4096 | 31.0 μs | 55.9 μs | 42.1 μs | 113.3 μs | 66.4 μs | 31.0 μs | 59.9 μs | Linear (31.0 μs) | 1.00x | +| bimodal | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | sorted_near_start | 256 | 4 | 360 ns | 150 ns | 130 ns | 210 ns | 130 ns | 150 ns | 110 ns | ExpFromLeft (130 ns) | 1.15x | +| bimodal | sorted_near_start | 256 | 16 | 470 ns | 320 ns | 260 ns | 630 ns | 450 ns | 270 ns | 390 ns | ExpFromLeft (260 ns) | 1.04x | +| bimodal | sorted_near_start | 256 | 64 | 930 ns | 1.1 μs | 830 ns | 2.4 μs | 1.5 μs | 1.0 μs | 1.4 μs | ExpFromLeft (830 ns) | 1.20x | +| bimodal | sorted_near_start | 256 | 256 | 2.4 μs | 3.8 μs | 3.0 μs | 9.5 μs | 5.6 μs | 2.5 μs | 5.1 μs | Linear (2.4 μs) | 1.02x | +| bimodal | sorted_near_start | 256 | 1024 | 8.8 μs | 14.4 μs | 10.9 μs | 36.9 μs | 21.7 μs | 8.4 μs | 19.8 μs | Linear (8.8 μs) | 0.96x | +| bimodal | sorted_near_start | 256 | 4096 | 31.6 μs | 56.3 μs | 42.6 μs | 149.5 μs | 86.2 μs | 31.7 μs | 78.7 μs | Linear (31.6 μs) | 1.00x | +| bimodal | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 90 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| bimodal | sorted_near_start | 1024 | 4 | 820 ns | 160 ns | 160 ns | 240 ns | 140 ns | 180 ns | 120 ns | Binary (140 ns) | 1.29x | +| bimodal | sorted_near_start | 1024 | 16 | 950 ns | 410 ns | 310 ns | 800 ns | 460 ns | 340 ns | 430 ns | ExpFromLeft (310 ns) | 1.10x | +| bimodal | sorted_near_start | 1024 | 64 | 1.8 μs | 1.1 μs | 810 ns | 3.1 μs | 2.0 μs | 850 ns | 1.8 μs | ExpFromLeft (810 ns) | 1.05x | +| bimodal | sorted_near_start | 1024 | 256 | 3.3 μs | 4.0 μs | 3.0 μs | 12.4 μs | 7.3 μs | 3.4 μs | 6.8 μs | ExpFromLeft (3.0 μs) | 1.10x | +| bimodal | sorted_near_start | 1024 | 1024 | 10.3 μs | 15.2 μs | 11.8 μs | 47.6 μs | 27.0 μs | 10.3 μs | 25.2 μs | Linear (10.3 μs) | 1.00x | +| bimodal | sorted_near_start | 1024 | 4096 | 33.6 μs | 57.4 μs | 43.8 μs | 189.3 μs | 105.5 μs | 33.6 μs | 98.5 μs | Linear (33.6 μs) | 1.00x | +| bimodal | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 69 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (69 ns) | 1.01x | +| bimodal | sorted_near_start | 4096 | 4 | 5.7 μs | 200 ns | 180 ns | 250 ns | 160 ns | 200 ns | 150 ns | Binary (160 ns) | 1.25x | +| bimodal | sorted_near_start | 4096 | 16 | 3.1 μs | 450 ns | 370 ns | 880 ns | 570 ns | 380 ns | 530 ns | ExpFromLeft (370 ns) | 1.03x | +| bimodal | sorted_near_start | 4096 | 64 | 3.5 μs | 1.3 μs | 920 ns | 3.6 μs | 2.6 μs | 960 ns | 2.5 μs | ExpFromLeft (920 ns) | 1.04x | +| bimodal | sorted_near_start | 4096 | 256 | 5.9 μs | 4.3 μs | 3.0 μs | 14.5 μs | 10.7 μs | 3.1 μs | 9.7 μs | ExpFromLeft (3.0 μs) | 1.03x | +| bimodal | sorted_near_start | 4096 | 1024 | 15.5 μs | 17.1 μs | 13.0 μs | 60.1 μs | 38.7 μs | 15.3 μs | 34.8 μs | ExpFromLeft (13.0 μs) | 1.18x | +| bimodal | sorted_near_start | 4096 | 4096 | 41.5 μs | 60.7 μs | 46.9 μs | 236.7 μs | 137.5 μs | 41.6 μs | 123.7 μs | Linear (41.5 μs) | 1.00x | +| bimodal | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 70 ns | 100 ns | 70 ns | 80 ns | 69 ns | ExpFromLeft (70 ns) | 1.14x | +| bimodal | sorted_near_start | 16384 | 4 | 11.5 μs | 220 ns | 180 ns | 290 ns | 180 ns | 210 ns | 170 ns | ExpFromLeft (180 ns) | 1.17x | +| bimodal | sorted_near_start | 16384 | 16 | 17.9 μs | 649 ns | 500 ns | 989 ns | 600 ns | 510 ns | 560 ns | ExpFromLeft (500 ns) | 1.02x | +| bimodal | sorted_near_start | 16384 | 64 | 12.1 μs | 1.8 μs | 1.3 μs | 4.1 μs | 3.0 μs | 1.3 μs | 2.8 μs | ExpFromLeft (1.3 μs) | 1.03x | +| bimodal | sorted_near_start | 16384 | 256 | 13.7 μs | 5.1 μs | 3.9 μs | 17.3 μs | 16.2 μs | 3.9 μs | 15.3 μs | ExpFromLeft (3.9 μs) | 1.00x | +| bimodal | sorted_near_start | 16384 | 1024 | 30.8 μs | 18.0 μs | 12.7 μs | 78.3 μs | 69.2 μs | 13.2 μs | 62.2 μs | ExpFromLeft (12.7 μs) | 1.04x | +| bimodal | sorted_near_start | 16384 | 4096 | 64.5 μs | 69.7 μs | 54.5 μs | 332.8 μs | 223.2 μs | 64.4 μs | 202.5 μs | ExpFromLeft (54.5 μs) | 1.18x | +| bimodal | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| bimodal | sorted_near_start | 65536 | 4 | 45.4 μs | 280 ns | 220 ns | 340 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | +| bimodal | sorted_near_start | 65536 | 16 | 46.9 μs | 720 ns | 550 ns | 1.2 μs | 690 ns | 580 ns | 690 ns | ExpFromLeft (550 ns) | 1.05x | +| bimodal | sorted_near_start | 65536 | 64 | 91.7 μs | 2.4 μs | 1.8 μs | 4.7 μs | 3.4 μs | 1.8 μs | 3.2 μs | ExpFromLeft (1.8 μs) | 1.01x | +| bimodal | sorted_near_start | 65536 | 256 | 76.7 μs | 7.6 μs | 6.6 μs | 20.2 μs | 19.7 μs | 5.1 μs | 18.7 μs | ExpFromLeft (6.6 μs) | 0.78x | +| bimodal | sorted_near_start | 65536 | 1024 | 102.3 μs | 23.6 μs | 16.1 μs | 109.6 μs | 84.7 μs | 16.8 μs | 78.7 μs | ExpFromLeft (16.1 μs) | 1.04x | +| bimodal | sorted_near_start | 65536 | 4096 | 149.5 μs | 96.5 μs | 76.4 μs | 465.1 μs | 281.7 μs | 76.3 μs | 241.3 μs | ExpFromLeft (76.4 μs) | 1.00x | +| bimodal | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | sorted_arithmetic | 16 | 4 | 110 ns | 120 ns | 120 ns | 160 ns | 100 ns | 120 ns | 80 ns | Binary (100 ns) | 1.20x | +| bimodal | sorted_arithmetic | 16 | 16 | 190 ns | 280 ns | 220 ns | 540 ns | 240 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | +| bimodal | sorted_arithmetic | 16 | 64 | 570 ns | 960 ns | 740 ns | 2.1 μs | 800 ns | 600 ns | 660 ns | Linear (570 ns) | 1.05x | +| bimodal | sorted_arithmetic | 16 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 8.7 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | +| bimodal | sorted_arithmetic | 16 | 1024 | 8.0 μs | 14.2 μs | 10.8 μs | 33.5 μs | 12.0 μs | 8.0 μs | 9.9 μs | Linear (8.0 μs) | 1.00x | +| bimodal | sorted_arithmetic | 16 | 4096 | 31.1 μs | 55.7 μs | 42.3 μs | 131.7 μs | 47.6 μs | 44.5 μs | 44.9 μs | Linear (31.1 μs) | 1.43x | +| bimodal | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| bimodal | sorted_arithmetic | 64 | 4 | 160 ns | 140 ns | 120 ns | 170 ns | 110 ns | 140 ns | 90 ns | Binary (110 ns) | 1.27x | +| bimodal | sorted_arithmetic | 64 | 16 | 250 ns | 320 ns | 260 ns | 650 ns | 330 ns | 270 ns | 270 ns | Linear (250 ns) | 1.08x | +| bimodal | sorted_arithmetic | 64 | 64 | 650 ns | 1.0 μs | 830 ns | 2.5 μs | 1.1 μs | 700 ns | 940 ns | Linear (650 ns) | 1.08x | +| bimodal | sorted_arithmetic | 64 | 256 | 2.1 μs | 3.7 μs | 2.7 μs | 10.5 μs | 4.4 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | +| bimodal | sorted_arithmetic | 64 | 1024 | 7.9 μs | 14.3 μs | 10.8 μs | 42.4 μs | 17.5 μs | 8.0 μs | 15.2 μs | Linear (7.9 μs) | 1.01x | +| bimodal | sorted_arithmetic | 64 | 4096 | 32.0 μs | 56.4 μs | 43.0 μs | 163.8 μs | 67.6 μs | 32.0 μs | 58.3 μs | Linear (32.0 μs) | 1.00x | +| bimodal | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | sorted_arithmetic | 256 | 4 | 490 ns | 150 ns | 140 ns | 190 ns | 130 ns | 160 ns | 110 ns | Binary (130 ns) | 1.23x | +| bimodal | sorted_arithmetic | 256 | 16 | 530 ns | 370 ns | 300 ns | 780 ns | 400 ns | 320 ns | 350 ns | ExpFromLeft (300 ns) | 1.07x | +| bimodal | sorted_arithmetic | 256 | 64 | 929 ns | 1.2 μs | 920 ns | 3.1 μs | 1.4 μs | 950 ns | 1.2 μs | ExpFromLeft (920 ns) | 1.03x | +| bimodal | sorted_arithmetic | 256 | 256 | 2.5 μs | 4.0 μs | 3.0 μs | 12.8 μs | 5.4 μs | 2.5 μs | 4.8 μs | Linear (2.5 μs) | 1.02x | +| bimodal | sorted_arithmetic | 256 | 1024 | 11.6 μs | 14.6 μs | 10.7 μs | 59.6 μs | 22.6 μs | 8.2 μs | 20.3 μs | ExpFromLeft (10.7 μs) | 0.77x | +| bimodal | sorted_arithmetic | 256 | 4096 | 32.0 μs | 57.9 μs | 43.5 μs | 212.7 μs | 89.7 μs | 32.0 μs | 81.0 μs | Linear (32.0 μs) | 1.00x | +| bimodal | sorted_arithmetic | 1024 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | +| bimodal | sorted_arithmetic | 1024 | 4 | 1.6 μs | 180 ns | 150 ns | 210 ns | 150 ns | 190 ns | 130 ns | ExpFromLeft (150 ns) | 1.27x | +| bimodal | sorted_arithmetic | 1024 | 16 | 1.7 μs | 400 ns | 320 ns | 920 ns | 480 ns | 350 ns | 430 ns | ExpFromLeft (320 ns) | 1.09x | +| bimodal | sorted_arithmetic | 1024 | 64 | 2.3 μs | 1.3 μs | 1.0 μs | 3.7 μs | 1.7 μs | 1.1 μs | 1.6 μs | ExpFromLeft (1.0 μs) | 1.04x | +| bimodal | sorted_arithmetic | 1024 | 256 | 3.7 μs | 4.5 μs | 3.4 μs | 16.0 μs | 6.6 μs | 3.7 μs | 6.1 μs | ExpFromLeft (3.4 μs) | 1.10x | +| bimodal | sorted_arithmetic | 1024 | 1024 | 9.7 μs | 15.9 μs | 12.0 μs | 89.3 μs | 26.7 μs | 9.8 μs | 24.5 μs | Linear (9.7 μs) | 1.00x | +| bimodal | sorted_arithmetic | 1024 | 4096 | 32.7 μs | 59.0 μs | 43.3 μs | 340.3 μs | 125.8 μs | 33.5 μs | 116.7 μs | Linear (32.7 μs) | 1.03x | +| bimodal | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | InterpSearch (70 ns) | 0.86x | +| bimodal | sorted_arithmetic | 4096 | 4 | 5.9 μs | 200 ns | 170 ns | 230 ns | 170 ns | 200 ns | 140 ns | ExpFromLeft (170 ns) | 1.18x | +| bimodal | sorted_arithmetic | 4096 | 16 | 5.9 μs | 440 ns | 340 ns | 1.1 μs | 540 ns | 390 ns | 500 ns | ExpFromLeft (340 ns) | 1.15x | +| bimodal | sorted_arithmetic | 4096 | 64 | 6.8 μs | 1.4 μs | 1.1 μs | 4.3 μs | 2.0 μs | 1.1 μs | 1.8 μs | ExpFromLeft (1.1 μs) | 1.06x | +| bimodal | sorted_arithmetic | 4096 | 256 | 8.9 μs | 4.9 μs | 3.8 μs | 18.6 μs | 7.8 μs | 3.9 μs | 7.2 μs | ExpFromLeft (3.8 μs) | 1.03x | +| bimodal | sorted_arithmetic | 4096 | 1024 | 15.3 μs | 17.5 μs | 13.3 μs | 112.8 μs | 32.3 μs | 15.2 μs | 30.6 μs | ExpFromLeft (13.3 μs) | 1.14x | +| bimodal | sorted_arithmetic | 4096 | 4096 | 39.9 μs | 64.3 μs | 49.4 μs | 487.6 μs | 173.5 μs | 39.8 μs | 165.3 μs | Linear (39.9 μs) | 1.00x | +| bimodal | sorted_arithmetic | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| bimodal | sorted_arithmetic | 16384 | 4 | 26.4 μs | 240 ns | 190 ns | 260 ns | 180 ns | 280 ns | 170 ns | Binary (180 ns) | 1.56x | +| bimodal | sorted_arithmetic | 16384 | 16 | 22.8 μs | 480 ns | 370 ns | 1.2 μs | 620 ns | 420 ns | 580 ns | ExpFromLeft (370 ns) | 1.14x | +| bimodal | sorted_arithmetic | 16384 | 64 | 24.8 μs | 1.6 μs | 1.2 μs | 5.1 μs | 2.3 μs | 1.2 μs | 2.1 μs | ExpFromLeft (1.2 μs) | 1.05x | +| bimodal | sorted_arithmetic | 16384 | 256 | 26.9 μs | 5.5 μs | 4.1 μs | 22.4 μs | 9.2 μs | 4.2 μs | 8.6 μs | ExpFromLeft (4.1 μs) | 1.03x | +| bimodal | sorted_arithmetic | 16384 | 1024 | 35.4 μs | 19.7 μs | 14.9 μs | 150.1 μs | 37.2 μs | 15.4 μs | 35.2 μs | ExpFromLeft (14.9 μs) | 1.03x | +| bimodal | sorted_arithmetic | 16384 | 4096 | 78.7 μs | 88.3 μs | 55.3 μs | 585.1 μs | 213.1 μs | 68.6 μs | 207.7 μs | ExpFromLeft (55.3 μs) | 1.24x | +| bimodal | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| bimodal | sorted_arithmetic | 65536 | 4 | 90.8 μs | 250 ns | 210 ns | 270 ns | 200 ns | 240 ns | 190 ns | Binary (200 ns) | 1.20x | +| bimodal | sorted_arithmetic | 65536 | 16 | 92.9 μs | 540 ns | 420 ns | 1.4 μs | 700 ns | 450 ns | 650 ns | ExpFromLeft (420 ns) | 1.07x | +| bimodal | sorted_arithmetic | 65536 | 64 | 96.1 μs | 1.7 μs | 1.3 μs | 5.8 μs | 2.6 μs | 1.3 μs | 2.5 μs | ExpFromLeft (1.3 μs) | 1.02x | +| bimodal | sorted_arithmetic | 65536 | 256 | 99.3 μs | 6.0 μs | 4.4 μs | 25.2 μs | 10.6 μs | 4.5 μs | 9.8 μs | ExpFromLeft (4.4 μs) | 1.03x | +| bimodal | sorted_arithmetic | 65536 | 1024 | 108.3 μs | 22.2 μs | 16.6 μs | 195.5 μs | 42.4 μs | 16.9 μs | 40.6 μs | ExpFromLeft (16.6 μs) | 1.02x | +| bimodal | sorted_arithmetic | 65536 | 4096 | 139.6 μs | 84.7 μs | 65.7 μs | 710.7 μs | 257.7 μs | 64.5 μs | 259.7 μs | ExpFromLeft (65.7 μs) | 0.98x | +| bimodal | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 110 ns | 160 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | +| bimodal | sorted_geometric | 16 | 16 | 190 ns | 280 ns | 220 ns | 540 ns | 220 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | +| bimodal | sorted_geometric | 16 | 64 | 580 ns | 950 ns | 750 ns | 2.2 μs | 800 ns | 610 ns | 660 ns | Linear (580 ns) | 1.05x | +| bimodal | sorted_geometric | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 8.7 μs | 3.1 μs | 2.1 μs | 2.5 μs | Linear (2.1 μs) | 1.02x | +| bimodal | sorted_geometric | 16 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 33.4 μs | 12.1 μs | 8.0 μs | 10.0 μs | Linear (7.9 μs) | 1.01x | +| bimodal | sorted_geometric | 16 | 4096 | 31.1 μs | 55.3 μs | 42.3 μs | 130.8 μs | 47.3 μs | 31.1 μs | 39.1 μs | Linear (31.1 μs) | 1.00x | +| bimodal | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| bimodal | sorted_geometric | 64 | 4 | 170 ns | 130 ns | 120 ns | 170 ns | 110 ns | 150 ns | 100 ns | Binary (110 ns) | 1.36x | +| bimodal | sorted_geometric | 64 | 16 | 250 ns | 320 ns | 280 ns | 650 ns | 330 ns | 280 ns | 270 ns | Linear (250 ns) | 1.12x | +| bimodal | sorted_geometric | 64 | 64 | 660 ns | 1.0 μs | 790 ns | 2.6 μs | 1.1 μs | 660 ns | 950 ns | Linear (660 ns) | 1.00x | +| bimodal | sorted_geometric | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 10.8 μs | 4.6 μs | 2.1 μs | 4.0 μs | Linear (2.1 μs) | 1.01x | +| bimodal | sorted_geometric | 64 | 1024 | 8.2 μs | 14.3 μs | 10.9 μs | 42.8 μs | 17.4 μs | 8.2 μs | 15.1 μs | Linear (8.2 μs) | 1.00x | +| bimodal | sorted_geometric | 64 | 4096 | 31.6 μs | 55.9 μs | 42.9 μs | 165.3 μs | 67.3 μs | 31.6 μs | 59.2 μs | Linear (31.6 μs) | 1.00x | +| bimodal | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 59 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (59 ns) | 1.02x | +| bimodal | sorted_geometric | 256 | 4 | 480 ns | 160 ns | 120 ns | 190 ns | 130 ns | 160 ns | 110 ns | ExpFromLeft (120 ns) | 1.33x | +| bimodal | sorted_geometric | 256 | 16 | 560 ns | 380 ns | 310 ns | 770 ns | 410 ns | 320 ns | 350 ns | ExpFromLeft (310 ns) | 1.03x | +| bimodal | sorted_geometric | 256 | 64 | 940 ns | 1.2 μs | 939 ns | 3.2 μs | 1.4 μs | 1.0 μs | 1.3 μs | ExpFromLeft (939 ns) | 1.09x | +| bimodal | sorted_geometric | 256 | 256 | 2.4 μs | 3.9 μs | 2.9 μs | 13.3 μs | 5.8 μs | 2.4 μs | 5.2 μs | Linear (2.4 μs) | 1.00x | +| bimodal | sorted_geometric | 256 | 1024 | 8.2 μs | 14.6 μs | 11.0 μs | 58.0 μs | 23.1 μs | 8.2 μs | 20.9 μs | Linear (8.2 μs) | 1.00x | +| bimodal | sorted_geometric | 256 | 4096 | 33.1 μs | 57.3 μs | 44.0 μs | 214.8 μs | 89.3 μs | 33.2 μs | 80.1 μs | Linear (33.1 μs) | 1.00x | +| bimodal | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | +| bimodal | sorted_geometric | 1024 | 4 | 1.6 μs | 180 ns | 150 ns | 210 ns | 150 ns | 180 ns | 130 ns | ExpFromLeft (150 ns) | 1.20x | +| bimodal | sorted_geometric | 1024 | 16 | 1.8 μs | 450 ns | 360 ns | 910 ns | 480 ns | 370 ns | 420 ns | ExpFromLeft (360 ns) | 1.03x | +| bimodal | sorted_geometric | 1024 | 64 | 2.5 μs | 1.6 μs | 1.4 μs | 3.8 μs | 1.8 μs | 1.4 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.01x | +| bimodal | sorted_geometric | 1024 | 256 | 3.7 μs | 4.6 μs | 3.5 μs | 15.8 μs | 6.7 μs | 3.6 μs | 6.1 μs | ExpFromLeft (3.5 μs) | 1.03x | +| bimodal | sorted_geometric | 1024 | 1024 | 9.4 μs | 15.7 μs | 11.6 μs | 82.8 μs | 29.6 μs | 9.6 μs | 26.8 μs | Linear (9.4 μs) | 1.02x | +| bimodal | sorted_geometric | 1024 | 4096 | 34.7 μs | 60.1 μs | 45.9 μs | 328.2 μs | 127.2 μs | 35.1 μs | 122.4 μs | Linear (34.7 μs) | 1.01x | +| bimodal | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| bimodal | sorted_geometric | 4096 | 4 | 6.0 μs | 200 ns | 150 ns | 230 ns | 160 ns | 190 ns | 150 ns | ExpFromLeft (150 ns) | 1.27x | +| bimodal | sorted_geometric | 4096 | 16 | 6.3 μs | 500 ns | 370 ns | 1.1 μs | 550 ns | 399 ns | 510 ns | ExpFromLeft (370 ns) | 1.08x | +| bimodal | sorted_geometric | 4096 | 64 | 7.6 μs | 1.8 μs | 1.3 μs | 4.4 μs | 2.0 μs | 1.3 μs | 1.8 μs | ExpFromLeft (1.3 μs) | 0.99x | +| bimodal | sorted_geometric | 4096 | 256 | 9.0 μs | 5.3 μs | 4.1 μs | 18.6 μs | 7.9 μs | 4.2 μs | 7.4 μs | ExpFromLeft (4.1 μs) | 1.02x | +| bimodal | sorted_geometric | 4096 | 1024 | 15.2 μs | 18.3 μs | 13.9 μs | 111.4 μs | 36.6 μs | 14.6 μs | 34.5 μs | ExpFromLeft (13.9 μs) | 1.05x | +| bimodal | sorted_geometric | 4096 | 4096 | 39.7 μs | 65.2 μs | 48.0 μs | 473.1 μs | 195.0 μs | 39.2 μs | 179.4 μs | Linear (39.7 μs) | 0.99x | +| bimodal | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| bimodal | sorted_geometric | 16384 | 4 | 23.4 μs | 230 ns | 170 ns | 250 ns | 180 ns | 200 ns | 170 ns | ExpFromLeft (170 ns) | 1.18x | +| bimodal | sorted_geometric | 16384 | 16 | 23.2 μs | 560 ns | 400 ns | 1.2 μs | 620 ns | 440 ns | 580 ns | ExpFromLeft (400 ns) | 1.10x | +| bimodal | sorted_geometric | 16384 | 64 | 24.7 μs | 1.8 μs | 1.4 μs | 5.0 μs | 2.3 μs | 1.4 μs | 2.1 μs | ExpFromLeft (1.4 μs) | 1.00x | +| bimodal | sorted_geometric | 16384 | 256 | 27.9 μs | 6.2 μs | 4.7 μs | 21.4 μs | 9.3 μs | 4.9 μs | 8.7 μs | ExpFromLeft (4.7 μs) | 1.03x | +| bimodal | sorted_geometric | 16384 | 1024 | 36.8 μs | 21.5 μs | 16.2 μs | 146.3 μs | 43.9 μs | 16.8 μs | 42.4 μs | ExpFromLeft (16.2 μs) | 1.04x | +| bimodal | sorted_geometric | 16384 | 4096 | 65.0 μs | 79.7 μs | 61.5 μs | 582.8 μs | 249.9 μs | 60.4 μs | 244.3 μs | ExpFromLeft (61.5 μs) | 0.98x | +| bimodal | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| bimodal | sorted_geometric | 65536 | 4 | 93.3 μs | 250 ns | 210 ns | 260 ns | 200 ns | 240 ns | 180 ns | Binary (200 ns) | 1.20x | +| bimodal | sorted_geometric | 65536 | 16 | 94.6 μs | 630 ns | 480 ns | 1.4 μs | 710 ns | 490 ns | 650 ns | ExpFromLeft (480 ns) | 1.02x | +| bimodal | sorted_geometric | 65536 | 64 | 95.0 μs | 2.1 μs | 1.6 μs | 5.8 μs | 2.6 μs | 1.6 μs | 2.5 μs | ExpFromLeft (1.6 μs) | 1.03x | +| bimodal | sorted_geometric | 65536 | 256 | 99.5 μs | 7.0 μs | 5.3 μs | 26.4 μs | 10.9 μs | 5.4 μs | 10.2 μs | ExpFromLeft (5.3 μs) | 1.02x | +| bimodal | sorted_geometric | 65536 | 1024 | 109.8 μs | 25.9 μs | 19.7 μs | 192.0 μs | 50.6 μs | 20.4 μs | 52.5 μs | ExpFromLeft (19.7 μs) | 1.03x | +| bimodal | sorted_geometric | 65536 | 4096 | 149.4 μs | 104.0 μs | 81.0 μs | 739.1 μs | 299.0 μs | 76.0 μs | 295.3 μs | ExpFromLeft (81.0 μs) | 0.94x | +| bimodal | sorted_bimodal | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | sorted_bimodal | 16 | 4 | 80 ns | 100 ns | 90 ns | 170 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| bimodal | sorted_bimodal | 16 | 16 | 190 ns | 270 ns | 210 ns | 589 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | +| bimodal | sorted_bimodal | 16 | 64 | 560 ns | 990 ns | 770 ns | 2.2 μs | 920 ns | 580 ns | 790 ns | Linear (560 ns) | 1.04x | +| bimodal | sorted_bimodal | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 8.7 μs | 3.2 μs | 2.3 μs | 2.7 μs | Linear (2.2 μs) | 1.01x | +| bimodal | sorted_bimodal | 16 | 1024 | 8.1 μs | 14.1 μs | 10.8 μs | 33.7 μs | 12.1 μs | 8.0 μs | 10.3 μs | Linear (8.1 μs) | 1.00x | +| bimodal | sorted_bimodal | 16 | 4096 | 31.0 μs | 55.1 μs | 42.3 μs | 132.7 μs | 47.5 μs | 31.1 μs | 40.1 μs | Linear (31.0 μs) | 1.00x | +| bimodal | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| bimodal | sorted_bimodal | 64 | 4 | 140 ns | 130 ns | 140 ns | 200 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | +| bimodal | sorted_bimodal | 64 | 16 | 230 ns | 350 ns | 260 ns | 710 ns | 300 ns | 260 ns | 270 ns | Linear (230 ns) | 1.13x | +| bimodal | sorted_bimodal | 64 | 64 | 630 ns | 1.0 μs | 760 ns | 2.6 μs | 1.3 μs | 660 ns | 1.3 μs | Linear (630 ns) | 1.05x | +| bimodal | sorted_bimodal | 64 | 256 | 2.2 μs | 4.0 μs | 3.0 μs | 10.8 μs | 5.0 μs | 2.3 μs | 4.6 μs | Linear (2.2 μs) | 1.01x | +| bimodal | sorted_bimodal | 64 | 1024 | 9.0 μs | 14.8 μs | 11.6 μs | 43.1 μs | 17.5 μs | 9.0 μs | 15.7 μs | Linear (9.0 μs) | 1.00x | +| bimodal | sorted_bimodal | 64 | 4096 | 32.2 μs | 56.0 μs | 43.2 μs | 166.6 μs | 67.4 μs | 32.1 μs | 59.9 μs | Linear (32.2 μs) | 1.00x | +| bimodal | sorted_bimodal | 256 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 70 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | sorted_bimodal | 256 | 4 | 280 ns | 160 ns | 140 ns | 240 ns | 120 ns | 160 ns | 110 ns | Binary (120 ns) | 1.33x | +| bimodal | sorted_bimodal | 256 | 16 | 500 ns | 450 ns | 370 ns | 830 ns | 370 ns | 390 ns | 340 ns | ExpFromLeft (370 ns) | 1.05x | +| bimodal | sorted_bimodal | 256 | 64 | 910 ns | 1.4 μs | 1.0 μs | 3.2 μs | 1.6 μs | 920 ns | 1.5 μs | Linear (910 ns) | 1.01x | +| bimodal | sorted_bimodal | 256 | 256 | 2.4 μs | 4.1 μs | 2.9 μs | 13.2 μs | 6.8 μs | 2.4 μs | 6.5 μs | Linear (2.4 μs) | 1.01x | +| bimodal | sorted_bimodal | 256 | 1024 | 9.6 μs | 16.7 μs | 12.6 μs | 54.3 μs | 25.2 μs | 9.6 μs | 23.3 μs | Linear (9.6 μs) | 1.00x | +| bimodal | sorted_bimodal | 256 | 4096 | 36.0 μs | 59.2 μs | 46.3 μs | 209.0 μs | 90.6 μs | 36.1 μs | 82.9 μs | Linear (36.0 μs) | 1.00x | +| bimodal | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | sorted_bimodal | 1024 | 4 | 1.3 μs | 210 ns | 180 ns | 270 ns | 140 ns | 260 ns | 120 ns | Binary (140 ns) | 1.86x | +| bimodal | sorted_bimodal | 1024 | 16 | 1.7 μs | 610 ns | 460 ns | 939 ns | 450 ns | 490 ns | 420 ns | Binary (450 ns) | 1.09x | +| bimodal | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.6 μs | 1.3 μs | 3.7 μs | 1.9 μs | 1.3 μs | 1.8 μs | ExpFromLeft (1.3 μs) | 1.03x | +| bimodal | sorted_bimodal | 1024 | 256 | 3.7 μs | 5.1 μs | 3.8 μs | 15.9 μs | 8.2 μs | 3.5 μs | 7.7 μs | Linear (3.7 μs) | 0.96x | +| bimodal | sorted_bimodal | 1024 | 1024 | 13.4 μs | 21.8 μs | 16.6 μs | 75.3 μs | 44.2 μs | 10.5 μs | 42.6 μs | Linear (13.4 μs) | 0.79x | +| bimodal | sorted_bimodal | 1024 | 4096 | 43.6 μs | 69.0 μs | 54.2 μs | 284.5 μs | 164.4 μs | 43.4 μs | 161.0 μs | Linear (43.6 μs) | 1.00x | +| bimodal | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | sorted_bimodal | 4096 | 4 | 2.7 μs | 220 ns | 180 ns | 320 ns | 170 ns | 210 ns | 150 ns | Binary (170 ns) | 1.24x | +| bimodal | sorted_bimodal | 4096 | 16 | 6.5 μs | 740 ns | 570 ns | 1.1 μs | 530 ns | 580 ns | 490 ns | Binary (530 ns) | 1.09x | +| bimodal | sorted_bimodal | 4096 | 64 | 7.4 μs | 2.3 μs | 1.8 μs | 4.3 μs | 2.0 μs | 1.8 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.01x | +| bimodal | sorted_bimodal | 4096 | 256 | 8.8 μs | 6.9 μs | 5.2 μs | 18.2 μs | 11.3 μs | 5.3 μs | 10.3 μs | ExpFromLeft (5.2 μs) | 1.02x | +| bimodal | sorted_bimodal | 4096 | 1024 | 16.1 μs | 24.0 μs | 17.9 μs | 97.4 μs | 88.5 μs | 15.4 μs | 83.4 μs | Linear (16.1 μs) | 0.95x | +| bimodal | sorted_bimodal | 4096 | 4096 | 77.7 μs | 100.0 μs | 79.2 μs | 415.1 μs | 279.4 μs | 73.0 μs | 273.3 μs | Linear (77.7 μs) | 0.94x | +| bimodal | sorted_bimodal | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | sorted_bimodal | 16384 | 4 | 16.7 μs | 260 ns | 220 ns | 350 ns | 190 ns | 250 ns | 170 ns | Binary (190 ns) | 1.32x | +| bimodal | sorted_bimodal | 16384 | 16 | 23.0 μs | 880 ns | 660 ns | 1.3 μs | 600 ns | 670 ns | 550 ns | Binary (600 ns) | 1.12x | +| bimodal | sorted_bimodal | 16384 | 64 | 24.2 μs | 3.0 μs | 2.3 μs | 5.0 μs | 2.4 μs | 2.3 μs | 2.3 μs | ExpFromLeft (2.3 μs) | 1.00x | +| bimodal | sorted_bimodal | 16384 | 256 | 32.1 μs | 10.0 μs | 7.5 μs | 22.1 μs | 13.8 μs | 7.3 μs | 13.9 μs | ExpFromLeft (7.5 μs) | 0.97x | +| bimodal | sorted_bimodal | 16384 | 1024 | 41.1 μs | 35.2 μs | 25.7 μs | 132.9 μs | 124.0 μs | 25.2 μs | 123.8 μs | ExpFromLeft (25.7 μs) | 0.98x | +| bimodal | sorted_bimodal | 16384 | 4096 | 115.1 μs | 161.4 μs | 120.2 μs | 542.9 μs | 390.5 μs | 112.8 μs | 384.1 μs | Linear (115.1 μs) | 0.98x | +| bimodal | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| bimodal | sorted_bimodal | 65536 | 4 | 85.1 μs | 300 ns | 250 ns | 380 ns | 200 ns | 280 ns | 180 ns | Binary (200 ns) | 1.40x | +| bimodal | sorted_bimodal | 65536 | 16 | 64.6 μs | 920 ns | 690 ns | 1.5 μs | 720 ns | 700 ns | 680 ns | ExpFromLeft (690 ns) | 1.01x | +| bimodal | sorted_bimodal | 65536 | 64 | 89.8 μs | 3.6 μs | 2.6 μs | 5.9 μs | 3.0 μs | 2.6 μs | 2.8 μs | ExpFromLeft (2.6 μs) | 1.02x | +| bimodal | sorted_bimodal | 65536 | 256 | 101.1 μs | 12.6 μs | 9.6 μs | 26.9 μs | 19.5 μs | 9.7 μs | 17.7 μs | ExpFromLeft (9.6 μs) | 1.01x | +| bimodal | sorted_bimodal | 65536 | 1024 | 116.6 μs | 59.8 μs | 43.0 μs | 182.1 μs | 155.1 μs | 39.4 μs | 161.8 μs | ExpFromLeft (43.0 μs) | 0.92x | +| bimodal | sorted_bimodal | 65536 | 4096 | 196.6 μs | 250.0 μs | 199.5 μs | 702.2 μs | 487.5 μs | 201.9 μs | 480.8 μs | Linear (196.6 μs) | 1.03x | +| bimodal | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 170 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| bimodal | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 200 ns | 580 ns | 220 ns | 200 ns | 180 ns | Linear (170 ns) | 1.18x | +| bimodal | sorted_repeated | 16 | 64 | 550 ns | 930 ns | 700 ns | 2.1 μs | 790 ns | 570 ns | 640 ns | Linear (550 ns) | 1.04x | +| bimodal | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 8.5 μs | 3.0 μs | 2.0 μs | 2.7 μs | Linear (2.0 μs) | 1.01x | +| bimodal | sorted_repeated | 16 | 1024 | 7.7 μs | 13.9 μs | 9.8 μs | 33.8 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.01x | +| bimodal | sorted_repeated | 16 | 4096 | 30.8 μs | 55.5 μs | 39.2 μs | 135.2 μs | 47.3 μs | 30.8 μs | 39.7 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_repeated | 64 | 1 | 70 ns | 50 ns | 60 ns | 80 ns | 60 ns | 70 ns | 50 ns | Gallop (50 ns) | 1.40x | +| bimodal | sorted_repeated | 64 | 4 | 80 ns | 90 ns | 90 ns | 210 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| bimodal | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 200 ns | 760 ns | 310 ns | 200 ns | 260 ns | Linear (170 ns) | 1.18x | +| bimodal | sorted_repeated | 64 | 64 | 550 ns | 930 ns | 700 ns | 2.9 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | +| bimodal | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 11.2 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | +| bimodal | sorted_repeated | 64 | 1024 | 7.7 μs | 14.0 μs | 9.8 μs | 44.6 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | +| bimodal | sorted_repeated | 64 | 4096 | 30.8 μs | 55.6 μs | 39.2 μs | 179.1 μs | 66.6 μs | 30.9 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 80 ns | 120 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | +| bimodal | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 100 ns | 260 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| bimodal | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 930 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| bimodal | sorted_repeated | 256 | 64 | 550 ns | 930 ns | 710 ns | 3.5 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | +| bimodal | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 14.0 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.01x | +| bimodal | sorted_repeated | 256 | 1024 | 7.7 μs | 14.0 μs | 9.8 μs | 55.9 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.00x | +| bimodal | sorted_repeated | 256 | 4096 | 30.8 μs | 55.6 μs | 39.3 μs | 222.7 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | sorted_repeated | 1024 | 4 | 90 ns | 110 ns | 100 ns | 290 ns | 140 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | +| bimodal | sorted_repeated | 1024 | 16 | 230 ns | 440 ns | 250 ns | 1.1 μs | 470 ns | 240 ns | 410 ns | Linear (230 ns) | 1.04x | +| bimodal | sorted_repeated | 1024 | 64 | 560 ns | 940 ns | 700 ns | 4.2 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| bimodal | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 16.3 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | +| bimodal | sorted_repeated | 1024 | 1024 | 7.8 μs | 14.0 μs | 9.9 μs | 65.2 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.8 μs) | 1.00x | +| bimodal | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.6 μs | 39.3 μs | 260.4 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | sorted_repeated | 4096 | 4 | 100 ns | 109 ns | 110 ns | 350 ns | 160 ns | 120 ns | 150 ns | Linear (100 ns) | 1.20x | +| bimodal | sorted_repeated | 4096 | 16 | 190 ns | 280 ns | 230 ns | 1.2 μs | 540 ns | 210 ns | 490 ns | Linear (190 ns) | 1.11x | +| bimodal | sorted_repeated | 4096 | 64 | 560 ns | 950 ns | 710 ns | 4.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | +| bimodal | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 19.1 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | +| bimodal | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.9 μs | 10.0 μs | 76.0 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.01x | +| bimodal | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.5 μs | 39.4 μs | 300.6 μs | 127.4 μs | 44.3 μs | 113.3 μs | Linear (30.8 μs) | 1.44x | +| bimodal | sorted_repeated | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | sorted_repeated | 16384 | 4 | 100 ns | 120 ns | 110 ns | 380 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | +| bimodal | sorted_repeated | 16384 | 16 | 190 ns | 290 ns | 230 ns | 1.4 μs | 610 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | +| bimodal | sorted_repeated | 16384 | 64 | 570 ns | 950 ns | 710 ns | 5.4 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | +| bimodal | sorted_repeated | 16384 | 256 | 2.0 μs | 3.6 μs | 2.6 μs | 21.4 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | +| bimodal | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.9 μs | 9.9 μs | 85.7 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | +| bimodal | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.6 μs | 39.6 μs | 342.5 μs | 144.1 μs | 30.9 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | +| bimodal | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | +| bimodal | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 430 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | +| bimodal | sorted_repeated | 65536 | 16 | 190 ns | 290 ns | 230 ns | 1.6 μs | 670 ns | 210 ns | 639 ns | Linear (190 ns) | 1.11x | +| bimodal | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 710 ns | 6.1 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| bimodal | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 24.2 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.02x | +| bimodal | sorted_repeated | 65536 | 1024 | 7.8 μs | 14.0 μs | 9.9 μs | 96.6 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.00x | +| bimodal | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.5 μs | 39.4 μs | 387.7 μs | 163.2 μs | 30.9 μs | 152.4 μs | Linear (30.8 μs) | 1.00x | +| bimodal | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| bimodal | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 90 ns | 90 ns | 100 ns | 70 ns | InterpSearch (90 ns) | 1.11x | +| bimodal | unsorted | 16 | 16 | 210 ns | 200 ns | 200 ns | 190 ns | 210 ns | 210 ns | 190 ns | InterpSearch (190 ns) | 1.11x | +| bimodal | unsorted | 16 | 64 | 820 ns | 800 ns | 810 ns | 810 ns | 820 ns | 820 ns | 790 ns | Gallop (800 ns) | 1.02x | +| bimodal | unsorted | 16 | 256 | 3.4 μs | 3.4 μs | 3.4 μs | 3.4 μs | 3.4 μs | 3.4 μs | 3.3 μs | ExpFromLeft (3.4 μs) | 1.00x | +| bimodal | unsorted | 16 | 1024 | 13.9 μs | 13.9 μs | 13.9 μs | 13.9 μs | 13.9 μs | 13.9 μs | 13.8 μs | InterpSearch (13.9 μs) | 1.00x | +| bimodal | unsorted | 16 | 4096 | 57.0 μs | 57.2 μs | 57.2 μs | 57.2 μs | 57.6 μs | 60.7 μs | 60.9 μs | Linear (57.0 μs) | 1.06x | +| bimodal | unsorted | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | +| bimodal | unsorted | 64 | 4 | 100 ns | 110 ns | 110 ns | 100 ns | 110 ns | 120 ns | 90 ns | InterpSearch (100 ns) | 1.20x | +| bimodal | unsorted | 64 | 16 | 290 ns | 290 ns | 300 ns | 290 ns | 290 ns | 300 ns | 260 ns | InterpSearch (290 ns) | 1.03x | +| bimodal | unsorted | 64 | 64 | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.1 μs | InterpSearch (1.2 μs) | 1.02x | +| bimodal | unsorted | 64 | 256 | 5.4 μs | 5.4 μs | 5.4 μs | 5.4 μs | 5.5 μs | 5.5 μs | 5.4 μs | InterpSearch (5.4 μs) | 1.02x | +| bimodal | unsorted | 64 | 1024 | 21.7 μs | 21.7 μs | 21.7 μs | 21.7 μs | 21.7 μs | 21.7 μs | 21.4 μs | InterpSearch (21.7 μs) | 1.00x | +| bimodal | unsorted | 64 | 4096 | 86.7 μs | 86.3 μs | 86.3 μs | 86.1 μs | 86.2 μs | 86.3 μs | 85.8 μs | InterpSearch (86.1 μs) | 1.00x | +| bimodal | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| bimodal | unsorted | 256 | 4 | 120 ns | 110 ns | 120 ns | 120 ns | 120 ns | 130 ns | 110 ns | Gallop (110 ns) | 1.18x | +| bimodal | unsorted | 256 | 16 | 430 ns | 440 ns | 430 ns | 430 ns | 430 ns | 450 ns | 410 ns | InterpSearch (430 ns) | 1.05x | +| bimodal | unsorted | 256 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | Gallop (1.6 μs) | 1.01x | +| bimodal | unsorted | 256 | 256 | 6.9 μs | 6.9 μs | 6.9 μs | 6.9 μs | 6.9 μs | 6.9 μs | 6.8 μs | Binary (6.9 μs) | 1.01x | +| bimodal | unsorted | 256 | 1024 | 28.1 μs | 28.1 μs | 28.1 μs | 28.1 μs | 28.1 μs | 28.1 μs | 27.9 μs | Binary (28.1 μs) | 1.00x | +| bimodal | unsorted | 256 | 4096 | 113.6 μs | 113.7 μs | 113.5 μs | 113.5 μs | 113.6 μs | 112.5 μs | 113.3 μs | ExpFromLeft (113.5 μs) | 0.99x | +| bimodal | unsorted | 1024 | 1 | 70 ns | 60 ns | 70 ns | 90 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | +| bimodal | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| bimodal | unsorted | 1024 | 16 | 430 ns | 430 ns | 420 ns | 440 ns | 420 ns | 440 ns | 420 ns | ExpFromLeft (420 ns) | 1.05x | +| bimodal | unsorted | 1024 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | Binary (1.6 μs) | 1.01x | +| bimodal | unsorted | 1024 | 256 | 7.9 μs | 7.9 μs | 7.9 μs | 8.0 μs | 7.9 μs | 7.9 μs | 7.9 μs | Gallop (7.9 μs) | 1.01x | +| bimodal | unsorted | 1024 | 1024 | 34.3 μs | 34.4 μs | 34.4 μs | 34.4 μs | 34.4 μs | 34.4 μs | 34.2 μs | Linear (34.3 μs) | 1.00x | +| bimodal | unsorted | 1024 | 4096 | 142.0 μs | 142.5 μs | 142.4 μs | 141.6 μs | 142.1 μs | 142.0 μs | 142.3 μs | InterpSearch (141.6 μs) | 1.00x | +| bimodal | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | +| bimodal | unsorted | 4096 | 4 | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 140 ns | InterpSearch (160 ns) | 1.00x | +| bimodal | unsorted | 4096 | 16 | 510 ns | 490 ns | 510 ns | 500 ns | 500 ns | 510 ns | 480 ns | Gallop (490 ns) | 1.04x | +| bimodal | unsorted | 4096 | 64 | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | InterpSearch (2.1 μs) | 1.01x | +| bimodal | unsorted | 4096 | 256 | 8.7 μs | 8.7 μs | 8.7 μs | 8.7 μs | 8.7 μs | 8.7 μs | 8.6 μs | Gallop (8.7 μs) | 1.00x | +| bimodal | unsorted | 4096 | 1024 | 38.3 μs | 38.4 μs | 38.4 μs | 38.3 μs | 38.4 μs | 38.4 μs | 38.3 μs | InterpSearch (38.3 μs) | 1.00x | +| bimodal | unsorted | 4096 | 4096 | 171.2 μs | 170.3 μs | 169.6 μs | 169.3 μs | 169.5 μs | 169.1 μs | 171.6 μs | InterpSearch (169.3 μs) | 1.00x | +| bimodal | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 120 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | +| bimodal | unsorted | 16384 | 4 | 170 ns | 170 ns | 170 ns | 170 ns | 180 ns | 170 ns | 170 ns | InterpSearch (170 ns) | 1.00x | +| bimodal | unsorted | 16384 | 16 | 640 ns | 650 ns | 650 ns | 640 ns | 650 ns | 660 ns | 650 ns | InterpSearch (640 ns) | 1.03x | +| bimodal | unsorted | 16384 | 64 | 2.7 μs | 2.7 μs | 2.7 μs | 2.8 μs | 2.7 μs | 2.7 μs | 2.8 μs | ExpFromLeft (2.7 μs) | 1.01x | +| bimodal | unsorted | 16384 | 256 | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | Binary (10.9 μs) | 1.00x | +| bimodal | unsorted | 16384 | 1024 | 46.1 μs | 45.9 μs | 46.0 μs | 46.0 μs | 46.0 μs | 46.2 μs | 46.3 μs | Gallop (45.9 μs) | 1.00x | +| bimodal | unsorted | 16384 | 4096 | 220.6 μs | 218.2 μs | 217.0 μs | 216.5 μs | 216.3 μs | 216.1 μs | 220.1 μs | Binary (216.3 μs) | 1.00x | +| bimodal | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | +| bimodal | unsorted | 65536 | 4 | 190 ns | 190 ns | 190 ns | 200 ns | 190 ns | 200 ns | 180 ns | ExpFromLeft (190 ns) | 1.05x | +| bimodal | unsorted | 65536 | 16 | 700 ns | 700 ns | 700 ns | 700 ns | 700 ns | 710 ns | 700 ns | InterpSearch (700 ns) | 1.01x | +| bimodal | unsorted | 65536 | 64 | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.8 μs | 2.8 μs | ExpFromLeft (2.7 μs) | 1.01x | +| bimodal | unsorted | 65536 | 256 | 11.1 μs | 11.1 μs | 11.2 μs | 11.2 μs | 11.2 μs | 11.2 μs | 11.2 μs | Linear (11.1 μs) | 1.01x | +| bimodal | unsorted | 65536 | 1024 | 54.9 μs | 54.8 μs | 54.7 μs | 54.7 μs | 54.6 μs | 54.5 μs | 55.5 μs | Binary (54.6 μs) | 1.00x | +| bimodal | unsorted | 65536 | 4096 | 270.2 μs | 266.2 μs | 264.6 μs | 263.2 μs | 262.5 μs | 262.1 μs | 269.0 μs | Binary (262.5 μs) | 1.00x | +| near_linear | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| near_linear | sorted_uniform | 16 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 90 ns | 100 ns | 90 ns | Binary (90 ns) | 1.11x | +| near_linear | sorted_uniform | 16 | 16 | 290 ns | 380 ns | 280 ns | 670 ns | 290 ns | 210 ns | 200 ns | ExpFromLeft (280 ns) | 0.75x | +| near_linear | sorted_uniform | 16 | 64 | 750 ns | 1.0 μs | 960 ns | 2.6 μs | 940 ns | 600 ns | 850 ns | Linear (750 ns) | 0.80x | +| near_linear | sorted_uniform | 16 | 256 | 2.3 μs | 3.9 μs | 2.9 μs | 8.0 μs | 3.3 μs | 2.3 μs | 2.9 μs | Linear (2.3 μs) | 1.02x | +| near_linear | sorted_uniform | 16 | 1024 | 8.1 μs | 14.7 μs | 10.8 μs | 28.9 μs | 12.4 μs | 8.2 μs | 10.4 μs | Linear (8.1 μs) | 1.01x | +| near_linear | sorted_uniform | 16 | 4096 | 31.5 μs | 58.1 μs | 42.4 μs | 109.2 μs | 48.0 μs | 31.1 μs | 40.8 μs | Linear (31.5 μs) | 0.99x | +| near_linear | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| near_linear | sorted_uniform | 64 | 4 | 140 ns | 140 ns | 120 ns | 150 ns | 110 ns | 120 ns | 90 ns | Binary (110 ns) | 1.09x | +| near_linear | sorted_uniform | 64 | 16 | 260 ns | 350 ns | 280 ns | 520 ns | 300 ns | 280 ns | 270 ns | Linear (260 ns) | 1.08x | +| near_linear | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 750 ns | 2.0 μs | 1.4 μs | 660 ns | 1.3 μs | Linear (630 ns) | 1.05x | +| near_linear | sorted_uniform | 64 | 256 | 2.2 μs | 4.1 μs | 3.1 μs | 9.1 μs | 5.3 μs | 2.2 μs | 4.8 μs | Linear (2.2 μs) | 1.00x | +| near_linear | sorted_uniform | 64 | 1024 | 9.2 μs | 14.9 μs | 11.7 μs | 31.0 μs | 17.8 μs | 9.2 μs | 16.0 μs | Linear (9.2 μs) | 1.00x | +| near_linear | sorted_uniform | 64 | 4096 | 32.1 μs | 56.6 μs | 43.2 μs | 112.4 μs | 67.1 μs | 32.1 μs | 60.3 μs | Linear (32.1 μs) | 1.00x | +| near_linear | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_uniform | 256 | 4 | 330 ns | 170 ns | 150 ns | 150 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | +| near_linear | sorted_uniform | 256 | 16 | 480 ns | 450 ns | 380 ns | 460 ns | 410 ns | 380 ns | 370 ns | ExpFromLeft (380 ns) | 1.00x | +| near_linear | sorted_uniform | 256 | 64 | 910 ns | 1.3 μs | 980 ns | 2.0 μs | 1.6 μs | 930 ns | 1.4 μs | Linear (910 ns) | 1.02x | +| near_linear | sorted_uniform | 256 | 256 | 2.5 μs | 4.1 μs | 2.8 μs | 9.0 μs | 7.3 μs | 2.5 μs | 6.8 μs | Linear (2.5 μs) | 1.03x | +| near_linear | sorted_uniform | 256 | 1024 | 10.1 μs | 17.5 μs | 13.5 μs | 38.7 μs | 26.2 μs | 10.2 μs | 24.8 μs | Linear (10.1 μs) | 1.01x | +| near_linear | sorted_uniform | 256 | 4096 | 36.6 μs | 59.6 μs | 46.7 μs | 125.0 μs | 90.5 μs | 36.7 μs | 83.9 μs | Linear (36.6 μs) | 1.00x | +| near_linear | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_uniform | 1024 | 4 | 210 ns | 150 ns | 140 ns | 150 ns | 140 ns | 190 ns | 130 ns | ExpFromLeft (140 ns) | 1.36x | +| near_linear | sorted_uniform | 1024 | 16 | 1.8 μs | 580 ns | 470 ns | 520 ns | 450 ns | 580 ns | 399 ns | Binary (450 ns) | 1.29x | +| near_linear | sorted_uniform | 1024 | 64 | 2.0 μs | 1.8 μs | 1.3 μs | 2.0 μs | 1.7 μs | 2.1 μs | 1.6 μs | ExpFromLeft (1.3 μs) | 1.61x | +| near_linear | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.8 μs | 8.7 μs | 7.8 μs | 3.6 μs | 7.4 μs | Linear (3.6 μs) | 0.99x | +| near_linear | sorted_uniform | 1024 | 1024 | 10.2 μs | 17.4 μs | 12.2 μs | 39.0 μs | 57.0 μs | 10.6 μs | 56.6 μs | Linear (10.2 μs) | 1.04x | +| near_linear | sorted_uniform | 1024 | 4096 | 48.4 μs | 72.7 μs | 57.7 μs | 154.5 μs | 194.2 μs | 48.6 μs | 191.3 μs | Linear (48.4 μs) | 1.00x | +| near_linear | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_uniform | 4096 | 4 | 4.5 μs | 230 ns | 190 ns | 150 ns | 170 ns | 190 ns | 150 ns | InterpSearch (150 ns) | 1.27x | +| near_linear | sorted_uniform | 4096 | 16 | 6.0 μs | 710 ns | 540 ns | 490 ns | 510 ns | 560 ns | 480 ns | InterpSearch (490 ns) | 1.14x | +| near_linear | sorted_uniform | 4096 | 64 | 7.4 μs | 2.3 μs | 1.8 μs | 1.9 μs | 2.1 μs | 2.1 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.19x | +| near_linear | sorted_uniform | 4096 | 256 | 8.4 μs | 7.1 μs | 5.4 μs | 9.0 μs | 10.0 μs | 9.6 μs | 10.3 μs | ExpFromLeft (5.4 μs) | 1.76x | +| near_linear | sorted_uniform | 4096 | 1024 | 16.1 μs | 23.8 μs | 17.4 μs | 38.3 μs | 96.1 μs | 14.9 μs | 93.8 μs | Linear (16.1 μs) | 0.93x | +| near_linear | sorted_uniform | 4096 | 4096 | 66.3 μs | 107.8 μs | 82.1 μs | 168.7 μs | 299.9 μs | 67.9 μs | 295.4 μs | Linear (66.3 μs) | 1.02x | +| near_linear | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_uniform | 16384 | 4 | 13.7 μs | 250 ns | 200 ns | 150 ns | 180 ns | 190 ns | 160 ns | InterpSearch (150 ns) | 1.27x | +| near_linear | sorted_uniform | 16384 | 16 | 22.0 μs | 890 ns | 660 ns | 530 ns | 620 ns | 570 ns | 560 ns | InterpSearch (530 ns) | 1.08x | +| near_linear | sorted_uniform | 16384 | 64 | 24.0 μs | 2.9 μs | 2.2 μs | 2.0 μs | 2.4 μs | 2.1 μs | 2.3 μs | InterpSearch (2.0 μs) | 1.07x | +| near_linear | sorted_uniform | 16384 | 256 | 28.6 μs | 9.5 μs | 7.2 μs | 9.4 μs | 13.1 μs | 9.8 μs | 13.1 μs | ExpFromLeft (7.2 μs) | 1.36x | +| near_linear | sorted_uniform | 16384 | 1024 | 40.8 μs | 34.4 μs | 26.2 μs | 39.7 μs | 126.4 μs | 40.7 μs | 125.5 μs | ExpFromLeft (26.2 μs) | 1.55x | +| near_linear | sorted_uniform | 16384 | 4096 | 113.3 μs | 160.2 μs | 120.0 μs | 164.0 μs | 400.1 μs | 110.8 μs | 399.8 μs | Linear (113.3 μs) | 0.98x | +| near_linear | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | sorted_uniform | 65536 | 4 | 63.1 μs | 300 ns | 240 ns | 150 ns | 200 ns | 200 ns | 180 ns | InterpSearch (150 ns) | 1.33x | +| near_linear | sorted_uniform | 65536 | 16 | 89.4 μs | 1.1 μs | 770 ns | 470 ns | 690 ns | 549 ns | 650 ns | InterpSearch (470 ns) | 1.17x | +| near_linear | sorted_uniform | 65536 | 64 | 93.3 μs | 3.6 μs | 2.7 μs | 2.0 μs | 2.9 μs | 2.2 μs | 2.7 μs | InterpSearch (2.0 μs) | 1.07x | +| near_linear | sorted_uniform | 65536 | 256 | 100.4 μs | 12.6 μs | 9.5 μs | 9.5 μs | 16.6 μs | 10.0 μs | 16.8 μs | ExpFromLeft (9.5 μs) | 1.05x | +| near_linear | sorted_uniform | 65536 | 1024 | 119.6 μs | 61.2 μs | 42.6 μs | 40.8 μs | 157.1 μs | 42.5 μs | 162.9 μs | InterpSearch (40.8 μs) | 1.04x | +| near_linear | sorted_uniform | 65536 | 4096 | 192.9 μs | 250.6 μs | 199.5 μs | 164.0 μs | 494.3 μs | 170.6 μs | 493.4 μs | InterpSearch (164.0 μs) | 1.04x | +| near_linear | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| near_linear | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| near_linear | sorted_dense_burst | 16 | 16 | 170 ns | 340 ns | 230 ns | 490 ns | 230 ns | 180 ns | 190 ns | Linear (170 ns) | 1.06x | +| near_linear | sorted_dense_burst | 16 | 64 | 540 ns | 930 ns | 730 ns | 1.8 μs | 790 ns | 580 ns | 780 ns | Linear (540 ns) | 1.07x | +| near_linear | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 3.0 μs | 2.0 μs | 3.0 μs | Linear (2.0 μs) | 1.01x | +| near_linear | sorted_dense_burst | 16 | 1024 | 7.7 μs | 14.0 μs | 10.5 μs | 27.6 μs | 11.8 μs | 7.8 μs | 12.3 μs | Linear (7.7 μs) | 1.00x | +| near_linear | sorted_dense_burst | 16 | 4096 | 30.8 μs | 55.6 μs | 41.9 μs | 109.0 μs | 47.3 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| near_linear | sorted_dense_burst | 64 | 4 | 90 ns | 90 ns | 90 ns | 150 ns | 100 ns | 110 ns | 90 ns | ExpFromLeft (90 ns) | 1.22x | +| near_linear | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 220 ns | 500 ns | 310 ns | 190 ns | 260 ns | Linear (170 ns) | 1.12x | +| near_linear | sorted_dense_burst | 64 | 64 | 680 ns | 1.2 μs | 730 ns | 1.8 μs | 1.1 μs | 579 ns | 929 ns | Linear (680 ns) | 0.85x | +| near_linear | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | +| near_linear | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.9 μs | 10.6 μs | 27.4 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | +| near_linear | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 108.7 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 110 ns | 150 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | +| near_linear | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 510 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| near_linear | sorted_dense_burst | 256 | 64 | 760 ns | 1.2 μs | 940 ns | 2.0 μs | 1.4 μs | 780 ns | 1.2 μs | Linear (760 ns) | 1.03x | +| near_linear | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| near_linear | sorted_dense_burst | 256 | 1024 | 7.8 μs | 14.0 μs | 10.5 μs | 27.3 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | +| near_linear | sorted_dense_burst | 256 | 4096 | 44.3 μs | 73.8 μs | 55.8 μs | 119.8 μs | 88.3 μs | 44.3 μs | 76.5 μs | Linear (44.3 μs) | 1.00x | +| near_linear | sorted_dense_burst | 1024 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_dense_burst | 1024 | 4 | 90 ns | 110 ns | 100 ns | 140 ns | 140 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | +| near_linear | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 250 ns | 490 ns | 450 ns | 220 ns | 410 ns | Linear (180 ns) | 1.22x | +| near_linear | sorted_dense_burst | 1024 | 64 | 560 ns | 930 ns | 740 ns | 1.8 μs | 1.7 μs | 589 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| near_linear | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | +| near_linear | sorted_dense_burst | 1024 | 1024 | 7.7 μs | 13.9 μs | 10.5 μs | 27.3 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.01x | +| near_linear | sorted_dense_burst | 1024 | 4096 | 31.3 μs | 55.5 μs | 42.1 μs | 109.1 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (31.3 μs) | 0.98x | +| near_linear | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_dense_burst | 4096 | 4 | 90 ns | 120 ns | 110 ns | 150 ns | 160 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | +| near_linear | sorted_dense_burst | 4096 | 16 | 180 ns | 280 ns | 240 ns | 510 ns | 530 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | +| near_linear | sorted_dense_burst | 4096 | 64 | 770 ns | 1.2 μs | 950 ns | 2.0 μs | 2.1 μs | 780 ns | 1.8 μs | Linear (770 ns) | 1.01x | +| near_linear | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 6.9 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| near_linear | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 13.9 μs | 10.6 μs | 27.5 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 0.99x | +| near_linear | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.6 μs | 41.9 μs | 109.1 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_dense_burst | 16384 | 4 | 99 ns | 110 ns | 110 ns | 150 ns | 180 ns | 130 ns | 160 ns | Linear (99 ns) | 1.31x | +| near_linear | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 510 ns | 610 ns | 210 ns | 570 ns | Linear (190 ns) | 1.11x | +| near_linear | sorted_dense_burst | 16384 | 64 | 560 ns | 950 ns | 740 ns | 1.8 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | +| near_linear | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | +| near_linear | sorted_dense_burst | 16384 | 1024 | 7.7 μs | 14.0 μs | 10.5 μs | 27.4 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.7 μs) | 1.01x | +| near_linear | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 108.9 μs | 143.9 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 120 ns | 150 ns | 200 ns | 129 ns | 190 ns | Linear (100 ns) | 1.29x | +| near_linear | sorted_dense_burst | 65536 | 16 | 190 ns | 299 ns | 250 ns | 500 ns | 690 ns | 220 ns | 630 ns | Linear (190 ns) | 1.16x | +| near_linear | sorted_dense_burst | 65536 | 64 | 570 ns | 949 ns | 750 ns | 1.9 μs | 2.6 μs | 610 ns | 2.4 μs | Linear (570 ns) | 1.07x | +| near_linear | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.2 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | +| near_linear | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 28.4 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.00x | +| near_linear | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.0 μs | 113.7 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| near_linear | sorted_near_start | 16 | 4 | 90 ns | 110 ns | 110 ns | 150 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | +| near_linear | sorted_near_start | 16 | 16 | 180 ns | 290 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | +| near_linear | sorted_near_start | 16 | 64 | 579 ns | 970 ns | 770 ns | 1.8 μs | 840 ns | 600 ns | 710 ns | Linear (579 ns) | 1.04x | +| near_linear | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 3.1 μs | 2.0 μs | 2.7 μs | Linear (2.0 μs) | 1.01x | +| near_linear | sorted_near_start | 16 | 1024 | 7.9 μs | 14.2 μs | 10.8 μs | 27.3 μs | 12.2 μs | 7.9 μs | 10.3 μs | Linear (7.9 μs) | 1.00x | +| near_linear | sorted_near_start | 16 | 4096 | 31.1 μs | 55.6 μs | 42.2 μs | 106.9 μs | 47.9 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | +| near_linear | sorted_near_start | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (60 ns) | 0.83x | +| near_linear | sorted_near_start | 64 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 100 ns | 120 ns | 90 ns | Binary (100 ns) | 1.20x | +| near_linear | sorted_near_start | 64 | 16 | 250 ns | 310 ns | 240 ns | 460 ns | 320 ns | 270 ns | 290 ns | ExpFromLeft (240 ns) | 1.12x | +| near_linear | sorted_near_start | 64 | 64 | 680 ns | 1.0 μs | 819 ns | 1.8 μs | 1.1 μs | 730 ns | 980 ns | Linear (680 ns) | 1.07x | +| near_linear | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.3 μs | 2.3 μs | 3.8 μs | Linear (2.1 μs) | 1.07x | +| near_linear | sorted_near_start | 64 | 1024 | 7.9 μs | 14.1 μs | 10.6 μs | 27.9 μs | 17.1 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.00x | +| near_linear | sorted_near_start | 64 | 4096 | 31.8 μs | 56.5 μs | 42.8 μs | 111.0 μs | 67.2 μs | 31.8 μs | 60.4 μs | Linear (31.8 μs) | 1.00x | +| near_linear | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_near_start | 256 | 4 | 300 ns | 150 ns | 120 ns | 150 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | +| near_linear | sorted_near_start | 256 | 16 | 540 ns | 340 ns | 260 ns | 490 ns | 400 ns | 290 ns | 360 ns | ExpFromLeft (260 ns) | 1.12x | +| near_linear | sorted_near_start | 256 | 64 | 869 ns | 1.1 μs | 870 ns | 1.9 μs | 1.6 μs | 910 ns | 1.4 μs | Linear (869 ns) | 1.05x | +| near_linear | sorted_near_start | 256 | 256 | 2.5 μs | 4.0 μs | 3.1 μs | 7.5 μs | 5.7 μs | 2.7 μs | 5.2 μs | Linear (2.5 μs) | 1.04x | +| near_linear | sorted_near_start | 256 | 1024 | 8.4 μs | 14.6 μs | 11.0 μs | 28.6 μs | 22.3 μs | 8.4 μs | 20.4 μs | Linear (8.4 μs) | 1.00x | +| near_linear | sorted_near_start | 256 | 4096 | 31.8 μs | 56.9 μs | 42.5 μs | 114.1 μs | 89.4 μs | 31.6 μs | 82.2 μs | Linear (31.8 μs) | 0.99x | +| near_linear | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| near_linear | sorted_near_start | 1024 | 4 | 450 ns | 160 ns | 150 ns | 150 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | +| near_linear | sorted_near_start | 1024 | 16 | 1.2 μs | 400 ns | 320 ns | 470 ns | 490 ns | 330 ns | 440 ns | ExpFromLeft (320 ns) | 1.03x | +| near_linear | sorted_near_start | 1024 | 64 | 2.1 μs | 1.2 μs | 900 ns | 1.9 μs | 2.0 μs | 940 ns | 1.9 μs | ExpFromLeft (900 ns) | 1.04x | +| near_linear | sorted_near_start | 1024 | 256 | 3.8 μs | 4.7 μs | 3.5 μs | 8.9 μs | 7.6 μs | 3.8 μs | 7.0 μs | ExpFromLeft (3.5 μs) | 1.07x | +| near_linear | sorted_near_start | 1024 | 1024 | 10.6 μs | 15.8 μs | 12.3 μs | 30.7 μs | 27.6 μs | 10.6 μs | 25.7 μs | Linear (10.6 μs) | 1.00x | +| near_linear | sorted_near_start | 1024 | 4096 | 33.8 μs | 58.7 μs | 44.4 μs | 115.6 μs | 111.1 μs | 33.9 μs | 105.2 μs | Linear (33.8 μs) | 1.00x | +| near_linear | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_near_start | 4096 | 4 | 3.4 μs | 200 ns | 170 ns | 140 ns | 160 ns | 180 ns | 150 ns | InterpSearch (140 ns) | 1.29x | +| near_linear | sorted_near_start | 4096 | 16 | 2.1 μs | 499 ns | 390 ns | 470 ns | 550 ns | 420 ns | 520 ns | ExpFromLeft (390 ns) | 1.08x | +| near_linear | sorted_near_start | 4096 | 64 | 6.1 μs | 1.7 μs | 1.4 μs | 2.1 μs | 2.4 μs | 1.4 μs | 2.4 μs | ExpFromLeft (1.4 μs) | 1.01x | +| near_linear | sorted_near_start | 4096 | 256 | 7.9 μs | 4.8 μs | 3.4 μs | 8.9 μs | 11.4 μs | 3.4 μs | 10.6 μs | ExpFromLeft (3.4 μs) | 1.01x | +| near_linear | sorted_near_start | 4096 | 1024 | 16.7 μs | 19.1 μs | 14.5 μs | 37.2 μs | 43.4 μs | 16.3 μs | 37.7 μs | ExpFromLeft (14.5 μs) | 1.13x | +| near_linear | sorted_near_start | 4096 | 4096 | 42.6 μs | 63.4 μs | 49.2 μs | 123.8 μs | 155.6 μs | 42.6 μs | 141.5 μs | Linear (42.6 μs) | 1.00x | +| near_linear | sorted_near_start | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_near_start | 16384 | 4 | 6.1 μs | 200 ns | 170 ns | 150 ns | 180 ns | 200 ns | 160 ns | InterpSearch (150 ns) | 1.33x | +| near_linear | sorted_near_start | 16384 | 16 | 9.1 μs | 610 ns | 490 ns | 470 ns | 660 ns | 510 ns | 620 ns | InterpSearch (470 ns) | 1.09x | +| near_linear | sorted_near_start | 16384 | 64 | 23.5 μs | 2.0 μs | 1.5 μs | 1.9 μs | 3.0 μs | 1.5 μs | 2.7 μs | ExpFromLeft (1.5 μs) | 1.02x | +| near_linear | sorted_near_start | 16384 | 256 | 26.0 μs | 6.1 μs | 4.2 μs | 8.8 μs | 18.1 μs | 4.4 μs | 17.0 μs | ExpFromLeft (4.2 μs) | 1.03x | +| near_linear | sorted_near_start | 16384 | 1024 | 34.4 μs | 21.1 μs | 14.8 μs | 38.5 μs | 76.7 μs | 14.9 μs | 70.1 μs | ExpFromLeft (14.8 μs) | 1.00x | +| near_linear | sorted_near_start | 16384 | 4096 | 73.3 μs | 78.8 μs | 61.6 μs | 149.3 μs | 257.9 μs | 73.6 μs | 242.2 μs | ExpFromLeft (61.6 μs) | 1.20x | +| near_linear | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | sorted_near_start | 65536 | 4 | 48.2 μs | 260 ns | 209 ns | 150 ns | 200 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | +| near_linear | sorted_near_start | 65536 | 16 | 40.4 μs | 790 ns | 600 ns | 470 ns | 670 ns | 620 ns | 630 ns | InterpSearch (470 ns) | 1.32x | +| near_linear | sorted_near_start | 65536 | 64 | 81.9 μs | 2.5 μs | 1.9 μs | 1.9 μs | 3.6 μs | 1.9 μs | 3.4 μs | ExpFromLeft (1.9 μs) | 1.01x | +| near_linear | sorted_near_start | 65536 | 256 | 95.0 μs | 7.8 μs | 5.7 μs | 9.1 μs | 20.2 μs | 5.8 μs | 20.0 μs | ExpFromLeft (5.7 μs) | 1.02x | +| near_linear | sorted_near_start | 65536 | 1024 | 102.2 μs | 27.7 μs | 20.1 μs | 38.5 μs | 93.8 μs | 19.1 μs | 88.6 μs | ExpFromLeft (20.1 μs) | 0.95x | +| near_linear | sorted_near_start | 65536 | 4096 | 156.3 μs | 120.2 μs | 94.1 μs | 159.9 μs | 322.1 μs | 91.9 μs | 299.4 μs | ExpFromLeft (94.1 μs) | 0.98x | +| near_linear | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 40 ns | ExpFromLeft (50 ns) | 1.20x | +| near_linear | sorted_arithmetic | 16 | 4 | 100 ns | 120 ns | 120 ns | 140 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | +| near_linear | sorted_arithmetic | 16 | 16 | 190 ns | 310 ns | 250 ns | 480 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | +| near_linear | sorted_arithmetic | 16 | 64 | 630 ns | 1.0 μs | 780 ns | 1.8 μs | 980 ns | 650 ns | 870 ns | Linear (630 ns) | 1.03x | +| near_linear | sorted_arithmetic | 16 | 256 | 2.0 μs | 3.8 μs | 2.7 μs | 7.8 μs | 3.2 μs | 2.1 μs | 2.8 μs | Linear (2.0 μs) | 1.01x | +| near_linear | sorted_arithmetic | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 28.2 μs | 12.2 μs | 8.2 μs | 10.4 μs | Linear (8.1 μs) | 1.01x | +| near_linear | sorted_arithmetic | 16 | 4096 | 31.1 μs | 55.4 μs | 42.0 μs | 109.5 μs | 48.1 μs | 31.1 μs | 40.8 μs | Linear (31.1 μs) | 1.00x | +| near_linear | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | +| near_linear | sorted_arithmetic | 64 | 4 | 170 ns | 150 ns | 130 ns | 140 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | +| near_linear | sorted_arithmetic | 64 | 16 | 270 ns | 430 ns | 340 ns | 500 ns | 300 ns | 310 ns | 250 ns | Linear (270 ns) | 1.15x | +| near_linear | sorted_arithmetic | 64 | 64 | 670 ns | 1.1 μs | 740 ns | 1.7 μs | 1.1 μs | 690 ns | 990 ns | Linear (670 ns) | 1.03x | +| near_linear | sorted_arithmetic | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 6.9 μs | 5.2 μs | 2.2 μs | 4.9 μs | Linear (2.1 μs) | 1.01x | +| near_linear | sorted_arithmetic | 64 | 1024 | 8.2 μs | 14.9 μs | 11.7 μs | 31.3 μs | 17.7 μs | 8.2 μs | 16.0 μs | Linear (8.2 μs) | 1.01x | +| near_linear | sorted_arithmetic | 64 | 4096 | 32.3 μs | 56.4 μs | 42.0 μs | 112.9 μs | 67.1 μs | 32.2 μs | 60.3 μs | Linear (32.3 μs) | 1.00x | +| near_linear | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_arithmetic | 256 | 4 | 460 ns | 180 ns | 150 ns | 140 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | +| near_linear | sorted_arithmetic | 256 | 16 | 570 ns | 550 ns | 440 ns | 470 ns | 370 ns | 470 ns | 340 ns | Binary (370 ns) | 1.27x | +| near_linear | sorted_arithmetic | 256 | 64 | 990 ns | 1.6 μs | 1.2 μs | 1.9 μs | 1.4 μs | 1.0 μs | 1.3 μs | Linear (990 ns) | 1.03x | +| near_linear | sorted_arithmetic | 256 | 256 | 2.4 μs | 4.2 μs | 2.7 μs | 6.5 μs | 5.5 μs | 2.5 μs | 5.8 μs | Linear (2.4 μs) | 1.02x | +| near_linear | sorted_arithmetic | 256 | 1024 | 8.3 μs | 14.6 μs | 10.6 μs | 27.4 μs | 26.8 μs | 8.3 μs | 25.3 μs | Linear (8.3 μs) | 1.00x | +| near_linear | sorted_arithmetic | 256 | 4096 | 31.6 μs | 59.5 μs | 46.4 μs | 125.0 μs | 90.5 μs | 31.6 μs | 83.3 μs | Linear (31.6 μs) | 1.00x | +| near_linear | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_arithmetic | 1024 | 4 | 1.6 μs | 210 ns | 170 ns | 140 ns | 140 ns | 180 ns | 130 ns | InterpSearch (140 ns) | 1.29x | +| near_linear | sorted_arithmetic | 1024 | 16 | 1.7 μs | 680 ns | 520 ns | 500 ns | 450 ns | 550 ns | 409 ns | Binary (450 ns) | 1.22x | +| near_linear | sorted_arithmetic | 1024 | 64 | 2.1 μs | 2.1 μs | 1.7 μs | 1.8 μs | 1.7 μs | 2.0 μs | 1.6 μs | Binary (1.7 μs) | 1.20x | +| near_linear | sorted_arithmetic | 1024 | 256 | 3.6 μs | 6.2 μs | 4.7 μs | 7.0 μs | 7.9 μs | 3.6 μs | 7.8 μs | Linear (3.6 μs) | 1.01x | +| near_linear | sorted_arithmetic | 1024 | 1024 | 9.5 μs | 16.4 μs | 10.6 μs | 26.0 μs | 95.2 μs | 9.5 μs | 93.5 μs | Linear (9.5 μs) | 1.00x | +| near_linear | sorted_arithmetic | 1024 | 4096 | 32.8 μs | 58.2 μs | 42.2 μs | 108.9 μs | 200.3 μs | 32.8 μs | 193.0 μs | Linear (32.8 μs) | 1.00x | +| near_linear | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 69 ns | 60 ns | 70 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | +| near_linear | sorted_arithmetic | 4096 | 4 | 6.0 μs | 250 ns | 200 ns | 140 ns | 160 ns | 190 ns | 150 ns | InterpSearch (140 ns) | 1.36x | +| near_linear | sorted_arithmetic | 4096 | 16 | 6.4 μs | 820 ns | 580 ns | 470 ns | 530 ns | 530 ns | 480 ns | InterpSearch (470 ns) | 1.13x | +| near_linear | sorted_arithmetic | 4096 | 64 | 6.4 μs | 2.7 μs | 2.0 μs | 1.7 μs | 2.0 μs | 1.8 μs | 1.9 μs | InterpSearch (1.7 μs) | 1.10x | +| near_linear | sorted_arithmetic | 4096 | 256 | 8.2 μs | 8.4 μs | 6.2 μs | 7.7 μs | 8.3 μs | 8.2 μs | 8.0 μs | ExpFromLeft (6.2 μs) | 1.34x | +| near_linear | sorted_arithmetic | 4096 | 1024 | 14.0 μs | 24.5 μs | 18.4 μs | 27.5 μs | 85.3 μs | 13.8 μs | 74.4 μs | Linear (14.0 μs) | 0.99x | +| near_linear | sorted_arithmetic | 4096 | 4096 | 37.8 μs | 65.7 μs | 41.9 μs | 103.6 μs | 312.5 μs | 37.9 μs | 309.4 μs | Linear (37.8 μs) | 1.00x | +| near_linear | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_arithmetic | 16384 | 4 | 23.4 μs | 280 ns | 220 ns | 140 ns | 190 ns | 190 ns | 170 ns | InterpSearch (140 ns) | 1.36x | +| near_linear | sorted_arithmetic | 16384 | 16 | 23.8 μs | 1.0 μs | 680 ns | 480 ns | 600 ns | 560 ns | 570 ns | InterpSearch (480 ns) | 1.17x | +| near_linear | sorted_arithmetic | 16384 | 64 | 25.2 μs | 3.3 μs | 2.1 μs | 1.9 μs | 2.3 μs | 2.1 μs | 2.2 μs | InterpSearch (1.9 μs) | 1.10x | +| near_linear | sorted_arithmetic | 16384 | 256 | 26.7 μs | 10.5 μs | 7.8 μs | 7.0 μs | 13.9 μs | 7.6 μs | 13.8 μs | InterpSearch (7.0 μs) | 1.10x | +| near_linear | sorted_arithmetic | 16384 | 1024 | 31.6 μs | 32.7 μs | 24.5 μs | 28.2 μs | 109.3 μs | 30.9 μs | 105.1 μs | ExpFromLeft (24.5 μs) | 1.26x | +| near_linear | sorted_arithmetic | 16384 | 4096 | 55.6 μs | 97.6 μs | 73.3 μs | 109.2 μs | 394.2 μs | 55.2 μs | 397.5 μs | Linear (55.6 μs) | 0.99x | +| near_linear | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_arithmetic | 65536 | 4 | 93.2 μs | 320 ns | 250 ns | 140 ns | 210 ns | 190 ns | 180 ns | InterpSearch (140 ns) | 1.36x | +| near_linear | sorted_arithmetic | 65536 | 16 | 93.8 μs | 1.1 μs | 799 ns | 470 ns | 690 ns | 530 ns | 660 ns | InterpSearch (470 ns) | 1.13x | +| near_linear | sorted_arithmetic | 65536 | 64 | 95.7 μs | 3.9 μs | 2.8 μs | 1.9 μs | 2.7 μs | 2.0 μs | 2.6 μs | InterpSearch (1.9 μs) | 1.09x | +| near_linear | sorted_arithmetic | 65536 | 256 | 101.7 μs | 12.8 μs | 8.8 μs | 6.5 μs | 11.2 μs | 7.1 μs | 11.7 μs | InterpSearch (6.5 μs) | 1.08x | +| near_linear | sorted_arithmetic | 65536 | 1024 | 104.3 μs | 43.4 μs | 32.5 μs | 30.7 μs | 115.2 μs | 32.6 μs | 115.5 μs | InterpSearch (30.7 μs) | 1.06x | +| near_linear | sorted_arithmetic | 65536 | 4096 | 128.2 μs | 130.3 μs | 97.6 μs | 110.2 μs | 409.9 μs | 117.9 μs | 402.5 μs | ExpFromLeft (97.6 μs) | 1.21x | +| near_linear | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| near_linear | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 120 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | +| near_linear | sorted_geometric | 16 | 16 | 190 ns | 300 ns | 220 ns | 460 ns | 230 ns | 210 ns | 180 ns | Linear (190 ns) | 1.11x | +| near_linear | sorted_geometric | 16 | 64 | 560 ns | 1.0 μs | 750 ns | 1.9 μs | 990 ns | 590 ns | 860 ns | Linear (560 ns) | 1.05x | +| near_linear | sorted_geometric | 16 | 256 | 3.0 μs | 4.9 μs | 3.7 μs | 8.3 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (3.0 μs) | 0.76x | +| near_linear | sorted_geometric | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 28.2 μs | 12.2 μs | 8.1 μs | 10.1 μs | Linear (8.1 μs) | 1.00x | +| near_linear | sorted_geometric | 16 | 4096 | 31.1 μs | 56.0 μs | 42.3 μs | 108.9 μs | 47.1 μs | 31.1 μs | 40.2 μs | Linear (31.1 μs) | 1.00x | +| near_linear | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| near_linear | sorted_geometric | 64 | 4 | 170 ns | 150 ns | 140 ns | 150 ns | 110 ns | 140 ns | 100 ns | Binary (110 ns) | 1.27x | +| near_linear | sorted_geometric | 64 | 16 | 260 ns | 370 ns | 300 ns | 470 ns | 300 ns | 280 ns | 270 ns | Linear (260 ns) | 1.08x | +| near_linear | sorted_geometric | 64 | 64 | 630 ns | 1.1 μs | 730 ns | 2.0 μs | 1.3 μs | 660 ns | 1.1 μs | Linear (630 ns) | 1.05x | +| near_linear | sorted_geometric | 64 | 256 | 2.3 μs | 4.0 μs | 3.1 μs | 8.4 μs | 5.3 μs | 2.4 μs | 4.8 μs | Linear (2.3 μs) | 1.01x | +| near_linear | sorted_geometric | 64 | 1024 | 9.0 μs | 14.9 μs | 11.6 μs | 30.8 μs | 17.7 μs | 9.1 μs | 16.0 μs | Linear (9.0 μs) | 1.01x | +| near_linear | sorted_geometric | 64 | 4096 | 32.2 μs | 56.5 μs | 43.2 μs | 112.8 μs | 66.9 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | +| near_linear | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_geometric | 256 | 4 | 490 ns | 180 ns | 150 ns | 150 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | +| near_linear | sorted_geometric | 256 | 16 | 530 ns | 490 ns | 390 ns | 470 ns | 380 ns | 400 ns | 340 ns | Binary (380 ns) | 1.05x | +| near_linear | sorted_geometric | 256 | 64 | 920 ns | 1.4 μs | 990 ns | 1.9 μs | 1.4 μs | 930 ns | 1.2 μs | Linear (920 ns) | 1.01x | +| near_linear | sorted_geometric | 256 | 256 | 2.5 μs | 4.6 μs | 3.0 μs | 8.0 μs | 6.7 μs | 2.5 μs | 6.2 μs | Linear (2.5 μs) | 1.00x | +| near_linear | sorted_geometric | 256 | 1024 | 9.7 μs | 16.3 μs | 12.4 μs | 32.6 μs | 27.8 μs | 9.7 μs | 26.1 μs | Linear (9.7 μs) | 1.00x | +| near_linear | sorted_geometric | 256 | 4096 | 35.3 μs | 58.9 μs | 45.6 μs | 119.3 μs | 90.8 μs | 35.3 μs | 83.7 μs | Linear (35.3 μs) | 1.00x | +| near_linear | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_geometric | 1024 | 4 | 1.8 μs | 210 ns | 170 ns | 150 ns | 140 ns | 190 ns | 120 ns | Binary (140 ns) | 1.36x | +| near_linear | sorted_geometric | 1024 | 16 | 1.8 μs | 620 ns | 500 ns | 500 ns | 450 ns | 520 ns | 410 ns | Binary (450 ns) | 1.16x | +| near_linear | sorted_geometric | 1024 | 64 | 2.1 μs | 1.9 μs | 1.4 μs | 2.0 μs | 1.7 μs | 1.5 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.03x | +| near_linear | sorted_geometric | 1024 | 256 | 3.7 μs | 5.7 μs | 4.0 μs | 8.8 μs | 7.7 μs | 3.7 μs | 7.6 μs | Linear (3.7 μs) | 1.00x | +| near_linear | sorted_geometric | 1024 | 1024 | 10.8 μs | 18.6 μs | 12.3 μs | 33.2 μs | 65.5 μs | 10.7 μs | 62.3 μs | Linear (10.8 μs) | 0.99x | +| near_linear | sorted_geometric | 1024 | 4096 | 38.6 μs | 63.1 μs | 48.0 μs | 120.3 μs | 192.1 μs | 38.6 μs | 192.2 μs | Linear (38.6 μs) | 1.00x | +| near_linear | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_geometric | 4096 | 4 | 6.0 μs | 240 ns | 190 ns | 150 ns | 160 ns | 190 ns | 150 ns | InterpSearch (150 ns) | 1.27x | +| near_linear | sorted_geometric | 4096 | 16 | 6.4 μs | 770 ns | 580 ns | 470 ns | 530 ns | 600 ns | 480 ns | InterpSearch (470 ns) | 1.28x | +| near_linear | sorted_geometric | 4096 | 64 | 7.4 μs | 2.5 μs | 1.8 μs | 2.0 μs | 2.0 μs | 1.9 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.02x | +| near_linear | sorted_geometric | 4096 | 256 | 8.7 μs | 7.5 μs | 5.7 μs | 9.0 μs | 10.7 μs | 5.8 μs | 10.3 μs | ExpFromLeft (5.7 μs) | 1.02x | +| near_linear | sorted_geometric | 4096 | 1024 | 15.8 μs | 24.1 μs | 17.1 μs | 33.1 μs | 94.1 μs | 15.8 μs | 86.8 μs | Linear (15.8 μs) | 1.00x | +| near_linear | sorted_geometric | 4096 | 4096 | 44.4 μs | 73.8 μs | 50.1 μs | 125.6 μs | 310.9 μs | 44.7 μs | 301.9 μs | Linear (44.4 μs) | 1.01x | +| near_linear | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_geometric | 16384 | 4 | 23.4 μs | 270 ns | 210 ns | 150 ns | 180 ns | 190 ns | 170 ns | InterpSearch (150 ns) | 1.27x | +| near_linear | sorted_geometric | 16384 | 16 | 23.8 μs | 920 ns | 690 ns | 480 ns | 600 ns | 710 ns | 560 ns | InterpSearch (480 ns) | 1.48x | +| near_linear | sorted_geometric | 16384 | 64 | 25.5 μs | 3.2 μs | 2.3 μs | 2.0 μs | 2.4 μs | 2.3 μs | 2.2 μs | InterpSearch (2.0 μs) | 1.18x | +| near_linear | sorted_geometric | 16384 | 256 | 29.9 μs | 10.1 μs | 7.4 μs | 8.9 μs | 13.3 μs | 7.6 μs | 12.8 μs | ExpFromLeft (7.4 μs) | 1.02x | +| near_linear | sorted_geometric | 16384 | 1024 | 36.2 μs | 31.9 μs | 24.7 μs | 36.0 μs | 123.1 μs | 24.8 μs | 121.6 μs | ExpFromLeft (24.7 μs) | 1.00x | +| near_linear | sorted_geometric | 16384 | 4096 | 66.4 μs | 98.4 μs | 69.6 μs | 130.8 μs | 408.2 μs | 66.7 μs | 410.6 μs | Linear (66.4 μs) | 1.01x | +| near_linear | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | +| near_linear | sorted_geometric | 65536 | 4 | 93.1 μs | 310 ns | 250 ns | 150 ns | 200 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | +| near_linear | sorted_geometric | 65536 | 16 | 93.6 μs | 1.1 μs | 810 ns | 470 ns | 690 ns | 820 ns | 650 ns | InterpSearch (470 ns) | 1.74x | +| near_linear | sorted_geometric | 65536 | 64 | 95.4 μs | 3.7 μs | 2.7 μs | 2.1 μs | 2.9 μs | 2.8 μs | 2.6 μs | InterpSearch (2.1 μs) | 1.33x | +| near_linear | sorted_geometric | 65536 | 256 | 101.8 μs | 13.4 μs | 10.0 μs | 9.6 μs | 17.5 μs | 9.7 μs | 17.3 μs | InterpSearch (9.6 μs) | 1.01x | +| near_linear | sorted_geometric | 65536 | 1024 | 117.6 μs | 48.0 μs | 36.9 μs | 39.0 μs | 153.7 μs | 35.4 μs | 158.3 μs | ExpFromLeft (36.9 μs) | 0.96x | +| near_linear | sorted_geometric | 65536 | 4096 | 147.5 μs | 134.0 μs | 102.3 μs | 132.2 μs | 501.4 μs | 103.1 μs | 503.5 μs | ExpFromLeft (102.3 μs) | 1.01x | +| near_linear | sorted_bimodal | 16 | 1 | 50 ns | 50 ns | 50 ns | 69 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| near_linear | sorted_bimodal | 16 | 4 | 100 ns | 120 ns | 100 ns | 150 ns | 100 ns | 110 ns | 80 ns | ExpFromLeft (100 ns) | 1.10x | +| near_linear | sorted_bimodal | 16 | 16 | 190 ns | 280 ns | 220 ns | 460 ns | 240 ns | 210 ns | 200 ns | Linear (190 ns) | 1.11x | +| near_linear | sorted_bimodal | 16 | 64 | 630 ns | 970 ns | 800 ns | 1.9 μs | 880 ns | 640 ns | 750 ns | Linear (630 ns) | 1.02x | +| near_linear | sorted_bimodal | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 6.9 μs | 3.2 μs | 2.2 μs | 2.8 μs | Linear (2.1 μs) | 1.02x | +| near_linear | sorted_bimodal | 16 | 1024 | 7.9 μs | 13.5 μs | 10.7 μs | 26.9 μs | 12.7 μs | 7.8 μs | 10.9 μs | Linear (7.9 μs) | 1.00x | +| near_linear | sorted_bimodal | 16 | 4096 | 30.9 μs | 53.7 μs | 42.1 μs | 107.3 μs | 50.2 μs | 31.0 μs | 43.4 μs | Linear (30.9 μs) | 1.00x | +| near_linear | sorted_bimodal | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| near_linear | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 110 ns | 150 ns | 110 ns | 140 ns | 90 ns | ExpFromLeft (110 ns) | 1.27x | +| near_linear | sorted_bimodal | 64 | 16 | 260 ns | 300 ns | 240 ns | 460 ns | 310 ns | 290 ns | 290 ns | ExpFromLeft (240 ns) | 1.21x | +| near_linear | sorted_bimodal | 64 | 64 | 630 ns | 980 ns | 750 ns | 1.9 μs | 1.3 μs | 660 ns | 1.2 μs | Linear (630 ns) | 1.05x | +| near_linear | sorted_bimodal | 64 | 256 | 2.3 μs | 3.7 μs | 2.9 μs | 7.6 μs | 4.5 μs | 2.3 μs | 4.0 μs | Linear (2.3 μs) | 1.01x | +| near_linear | sorted_bimodal | 64 | 1024 | 8.2 μs | 14.1 μs | 10.8 μs | 28.0 μs | 17.0 μs | 8.2 μs | 15.2 μs | Linear (8.2 μs) | 1.00x | +| near_linear | sorted_bimodal | 64 | 4096 | 31.1 μs | 55.3 μs | 42.3 μs | 109.3 μs | 66.8 μs | 31.2 μs | 60.2 μs | Linear (31.1 μs) | 1.00x | +| near_linear | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_bimodal | 256 | 4 | 450 ns | 160 ns | 130 ns | 150 ns | 130 ns | 160 ns | 110 ns | ExpFromLeft (130 ns) | 1.23x | +| near_linear | sorted_bimodal | 256 | 16 | 530 ns | 360 ns | 290 ns | 490 ns | 440 ns | 310 ns | 420 ns | ExpFromLeft (290 ns) | 1.07x | +| near_linear | sorted_bimodal | 256 | 64 | 920 ns | 1.1 μs | 760 ns | 2.0 μs | 1.8 μs | 960 ns | 1.7 μs | ExpFromLeft (760 ns) | 1.26x | +| near_linear | sorted_bimodal | 256 | 256 | 2.6 μs | 4.2 μs | 3.2 μs | 8.6 μs | 6.3 μs | 2.6 μs | 5.8 μs | Linear (2.6 μs) | 1.01x | +| near_linear | sorted_bimodal | 256 | 1024 | 9.2 μs | 14.8 μs | 11.5 μs | 30.9 μs | 22.6 μs | 9.1 μs | 20.6 μs | Linear (9.2 μs) | 1.00x | +| near_linear | sorted_bimodal | 256 | 4096 | 32.2 μs | 56.5 μs | 43.0 μs | 112.1 μs | 86.6 μs | 32.2 μs | 79.5 μs | Linear (32.2 μs) | 1.00x | +| near_linear | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | sorted_bimodal | 1024 | 4 | 1.5 μs | 180 ns | 160 ns | 150 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | +| near_linear | sorted_bimodal | 1024 | 16 | 1.7 μs | 460 ns | 390 ns | 470 ns | 460 ns | 390 ns | 410 ns | ExpFromLeft (390 ns) | 1.00x | +| near_linear | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 960 ns | 2.0 μs | 1.9 μs | 1.0 μs | 1.8 μs | ExpFromLeft (960 ns) | 1.05x | +| near_linear | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.1 μs | 2.8 μs | 8.8 μs | 8.4 μs | 3.5 μs | 8.0 μs | ExpFromLeft (2.8 μs) | 1.25x | +| near_linear | sorted_bimodal | 1024 | 1024 | 11.8 μs | 17.2 μs | 13.5 μs | 37.0 μs | 30.7 μs | 11.6 μs | 29.1 μs | Linear (11.8 μs) | 0.99x | +| near_linear | sorted_bimodal | 1024 | 4096 | 36.6 μs | 58.8 μs | 45.8 μs | 122.3 μs | 109.0 μs | 36.6 μs | 102.1 μs | Linear (36.6 μs) | 1.00x | +| near_linear | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_bimodal | 4096 | 4 | 5.2 μs | 200 ns | 170 ns | 150 ns | 170 ns | 200 ns | 140 ns | InterpSearch (150 ns) | 1.33x | +| near_linear | sorted_bimodal | 4096 | 16 | 6.2 μs | 620 ns | 480 ns | 460 ns | 520 ns | 520 ns | 490 ns | InterpSearch (460 ns) | 1.13x | +| near_linear | sorted_bimodal | 4096 | 64 | 6.6 μs | 1.7 μs | 1.3 μs | 2.0 μs | 2.2 μs | 1.4 μs | 2.0 μs | ExpFromLeft (1.3 μs) | 1.02x | +| near_linear | sorted_bimodal | 4096 | 256 | 7.8 μs | 5.3 μs | 3.6 μs | 8.9 μs | 11.6 μs | 4.9 μs | 10.2 μs | ExpFromLeft (3.6 μs) | 1.35x | +| near_linear | sorted_bimodal | 4096 | 1024 | 14.7 μs | 17.8 μs | 12.4 μs | 39.5 μs | 60.8 μs | 14.5 μs | 56.1 μs | ExpFromLeft (12.4 μs) | 1.17x | +| near_linear | sorted_bimodal | 4096 | 4096 | 51.4 μs | 70.2 μs | 55.8 μs | 151.1 μs | 181.7 μs | 51.5 μs | 168.1 μs | Linear (51.4 μs) | 1.00x | +| near_linear | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_bimodal | 16384 | 4 | 22.8 μs | 260 ns | 210 ns | 150 ns | 180 ns | 190 ns | 170 ns | InterpSearch (150 ns) | 1.27x | +| near_linear | sorted_bimodal | 16384 | 16 | 23.5 μs | 750 ns | 570 ns | 470 ns | 600 ns | 600 ns | 570 ns | InterpSearch (470 ns) | 1.28x | +| near_linear | sorted_bimodal | 16384 | 64 | 24.7 μs | 2.2 μs | 1.7 μs | 1.9 μs | 2.7 μs | 1.7 μs | 2.5 μs | ExpFromLeft (1.7 μs) | 1.02x | +| near_linear | sorted_bimodal | 16384 | 256 | 26.2 μs | 6.8 μs | 5.0 μs | 9.0 μs | 15.1 μs | 5.0 μs | 14.2 μs | ExpFromLeft (5.0 μs) | 1.01x | +| near_linear | sorted_bimodal | 16384 | 1024 | 33.7 μs | 22.3 μs | 16.1 μs | 38.1 μs | 90.3 μs | 15.7 μs | 87.0 μs | ExpFromLeft (16.1 μs) | 0.97x | +| near_linear | sorted_bimodal | 16384 | 4096 | 75.4 μs | 91.9 μs | 67.2 μs | 160.3 μs | 273.8 μs | 77.6 μs | 263.7 μs | ExpFromLeft (67.2 μs) | 1.16x | +| near_linear | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | sorted_bimodal | 65536 | 4 | 83.9 μs | 270 ns | 220 ns | 150 ns | 200 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | +| near_linear | sorted_bimodal | 65536 | 16 | 92.7 μs | 900 ns | 660 ns | 460 ns | 660 ns | 690 ns | 640 ns | InterpSearch (460 ns) | 1.50x | +| near_linear | sorted_bimodal | 65536 | 64 | 94.6 μs | 2.9 μs | 2.2 μs | 2.0 μs | 3.0 μs | 2.2 μs | 2.8 μs | InterpSearch (2.0 μs) | 1.12x | +| near_linear | sorted_bimodal | 65536 | 256 | 99.5 μs | 9.4 μs | 7.0 μs | 9.2 μs | 18.6 μs | 6.9 μs | 17.5 μs | ExpFromLeft (7.0 μs) | 0.99x | +| near_linear | sorted_bimodal | 65536 | 1024 | 108.7 μs | 33.2 μs | 24.4 μs | 39.1 μs | 115.0 μs | 22.6 μs | 115.4 μs | ExpFromLeft (24.4 μs) | 0.93x | +| near_linear | sorted_bimodal | 65536 | 4096 | 183.9 μs | 147.1 μs | 110.2 μs | 160.7 μs | 349.4 μs | 108.6 μs | 351.9 μs | ExpFromLeft (110.2 μs) | 0.99x | +| near_linear | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | +| near_linear | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | +| near_linear | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 200 ns | 460 ns | 230 ns | 190 ns | 190 ns | Linear (170 ns) | 1.12x | +| near_linear | sorted_repeated | 16 | 64 | 550 ns | 930 ns | 690 ns | 1.7 μs | 790 ns | 570 ns | 670 ns | Linear (550 ns) | 1.04x | +| near_linear | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.6 μs | 3.0 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.00x | +| near_linear | sorted_repeated | 16 | 1024 | 7.7 μs | 13.9 μs | 9.9 μs | 25.9 μs | 11.8 μs | 7.8 μs | 9.9 μs | Linear (7.7 μs) | 1.00x | +| near_linear | sorted_repeated | 16 | 4096 | 30.8 μs | 55.5 μs | 39.3 μs | 103.4 μs | 47.3 μs | 30.8 μs | 41.0 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| near_linear | sorted_repeated | 64 | 4 | 80 ns | 110 ns | 90 ns | 140 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | +| near_linear | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 230 ns | 460 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | +| near_linear | sorted_repeated | 64 | 64 | 690 ns | 930 ns | 710 ns | 1.7 μs | 1.1 μs | 580 ns | 910 ns | Linear (690 ns) | 0.84x | +| near_linear | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | +| near_linear | sorted_repeated | 64 | 1024 | 7.7 μs | 13.9 μs | 9.9 μs | 26.0 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | +| near_linear | sorted_repeated | 64 | 4096 | 30.8 μs | 55.5 μs | 39.4 μs | 103.5 μs | 66.6 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 80 ns | 80 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | +| near_linear | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 90 ns | 140 ns | 130 ns | 110 ns | 110 ns | ExpFromLeft (90 ns) | 1.22x | +| near_linear | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 459 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | +| near_linear | sorted_repeated | 256 | 64 | 550 ns | 940 ns | 710 ns | 1.7 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | +| near_linear | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | +| near_linear | sorted_repeated | 256 | 1024 | 7.7 μs | 14.0 μs | 9.9 μs | 25.9 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.7 μs) | 1.00x | +| near_linear | sorted_repeated | 256 | 4096 | 30.8 μs | 55.6 μs | 39.4 μs | 103.5 μs | 85.9 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| near_linear | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | +| near_linear | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 220 ns | 450 ns | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | +| near_linear | sorted_repeated | 1024 | 64 | 560 ns | 940 ns | 700 ns | 1.7 μs | 1.7 μs | 589 ns | 1.5 μs | Linear (560 ns) | 1.05x | +| near_linear | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | +| near_linear | sorted_repeated | 1024 | 1024 | 7.7 μs | 14.0 μs | 10.0 μs | 25.9 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.00x | +| near_linear | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.6 μs | 39.2 μs | 103.4 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 140 ns | 160 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | +| near_linear | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 450 ns | 520 ns | 210 ns | 610 ns | Linear (180 ns) | 1.17x | +| near_linear | sorted_repeated | 4096 | 64 | 570 ns | 940 ns | 700 ns | 1.7 μs | 2.0 μs | 600 ns | 1.8 μs | Linear (570 ns) | 1.05x | +| near_linear | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | +| near_linear | sorted_repeated | 4096 | 1024 | 7.8 μs | 14.0 μs | 9.9 μs | 25.9 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | +| near_linear | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.5 μs | 39.3 μs | 103.4 μs | 124.6 μs | 30.8 μs | 114.1 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | sorted_repeated | 16384 | 4 | 90 ns | 110 ns | 110 ns | 140 ns | 180 ns | 120 ns | 170 ns | Linear (90 ns) | 1.33x | +| near_linear | sorted_repeated | 16384 | 16 | 240 ns | 360 ns | 260 ns | 499 ns | 620 ns | 250 ns | 570 ns | Linear (240 ns) | 1.04x | +| near_linear | sorted_repeated | 16384 | 64 | 560 ns | 939 ns | 710 ns | 1.7 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | +| near_linear | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | +| near_linear | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.9 μs | 10.0 μs | 26.0 μs | 36.1 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | +| near_linear | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.6 μs | 39.6 μs | 103.5 μs | 144.1 μs | 30.9 μs | 133.7 μs | Linear (30.8 μs) | 1.00x | +| near_linear | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 150 ns | 200 ns | 120 ns | 180 ns | Linear (100 ns) | 1.20x | +| near_linear | sorted_repeated | 65536 | 16 | 240 ns | 360 ns | 260 ns | 500 ns | 680 ns | 260 ns | 640 ns | Linear (240 ns) | 1.08x | +| near_linear | sorted_repeated | 65536 | 64 | 570 ns | 960 ns | 710 ns | 1.7 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | +| near_linear | sorted_repeated | 65536 | 256 | 2.0 μs | 3.6 μs | 2.6 μs | 6.5 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | +| near_linear | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.9 μs | 10.0 μs | 25.9 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.01x | +| near_linear | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.5 μs | 39.1 μs | 103.5 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | +| near_linear | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | +| near_linear | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 80 ns | 90 ns | 100 ns | 70 ns | InterpSearch (80 ns) | 1.25x | +| near_linear | unsorted | 16 | 16 | 200 ns | 210 ns | 210 ns | 220 ns | 210 ns | 220 ns | 190 ns | Linear (200 ns) | 1.10x | +| near_linear | unsorted | 16 | 64 | 719 ns | 730 ns | 730 ns | 720 ns | 730 ns | 740 ns | 740 ns | Linear (719 ns) | 1.03x | +| near_linear | unsorted | 16 | 256 | 3.2 μs | 3.0 μs | 3.0 μs | 3.0 μs | 3.0 μs | 3.0 μs | 3.0 μs | InterpSearch (3.0 μs) | 1.01x | +| near_linear | unsorted | 16 | 1024 | 21.5 μs | 21.5 μs | 21.4 μs | 21.3 μs | 21.3 μs | 21.4 μs | 22.6 μs | Binary (21.3 μs) | 1.00x | +| near_linear | unsorted | 16 | 4096 | 145.3 μs | 142.7 μs | 141.6 μs | 140.3 μs | 140.3 μs | 139.8 μs | 144.4 μs | InterpSearch (140.3 μs) | 1.00x | +| near_linear | unsorted | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | +| near_linear | unsorted | 64 | 4 | 110 ns | 110 ns | 110 ns | 120 ns | 110 ns | 120 ns | 90 ns | ExpFromLeft (110 ns) | 1.09x | +| near_linear | unsorted | 64 | 16 | 280 ns | 280 ns | 270 ns | 280 ns | 280 ns | 290 ns | 270 ns | ExpFromLeft (270 ns) | 1.07x | +| near_linear | unsorted | 64 | 64 | 1.1 μs | 1.0 μs | 1.1 μs | 1.0 μs | 1.0 μs | 1.1 μs | 1.1 μs | InterpSearch (1.0 μs) | 1.02x | +| near_linear | unsorted | 64 | 256 | 5.7 μs | 5.6 μs | 5.5 μs | 5.6 μs | 5.5 μs | 5.5 μs | 5.7 μs | ExpFromLeft (5.5 μs) | 1.00x | +| near_linear | unsorted | 64 | 1024 | 39.0 μs | 37.9 μs | 37.6 μs | 37.2 μs | 37.2 μs | 36.9 μs | 38.9 μs | Binary (37.2 μs) | 0.99x | +| near_linear | unsorted | 64 | 4096 | 224.3 μs | 223.3 μs | 222.5 μs | 222.1 μs | 224.0 μs | 224.3 μs | 226.6 μs | InterpSearch (222.1 μs) | 1.01x | +| near_linear | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | +| near_linear | unsorted | 256 | 4 | 130 ns | 120 ns | 120 ns | 120 ns | 130 ns | 130 ns | 109 ns | InterpSearch (120 ns) | 1.08x | +| near_linear | unsorted | 256 | 16 | 350 ns | 350 ns | 350 ns | 350 ns | 350 ns | 360 ns | 340 ns | InterpSearch (350 ns) | 1.03x | +| near_linear | unsorted | 256 | 64 | 1.3 μs | 1.3 μs | 1.3 μs | 1.3 μs | 1.3 μs | 1.3 μs | 1.3 μs | Gallop (1.3 μs) | 1.00x | +| near_linear | unsorted | 256 | 256 | 6.9 μs | 6.9 μs | 6.9 μs | 6.9 μs | 6.8 μs | 6.8 μs | 7.0 μs | Binary (6.8 μs) | 1.00x | +| near_linear | unsorted | 256 | 1024 | 53.2 μs | 51.9 μs | 51.2 μs | 51.1 μs | 50.5 μs | 50.3 μs | 51.3 μs | Binary (50.5 μs) | 1.00x | +| near_linear | unsorted | 256 | 4096 | 309.3 μs | 310.4 μs | 307.7 μs | 306.2 μs | 306.6 μs | 303.6 μs | 306.2 μs | InterpSearch (306.2 μs) | 0.99x | +| near_linear | unsorted | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | +| near_linear | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | +| near_linear | unsorted | 1024 | 16 | 420 ns | 430 ns | 430 ns | 420 ns | 420 ns | 440 ns | 420 ns | InterpSearch (420 ns) | 1.05x | +| near_linear | unsorted | 1024 | 64 | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | InterpSearch (1.7 μs) | 1.00x | +| near_linear | unsorted | 1024 | 256 | 7.5 μs | 7.4 μs | 7.4 μs | 7.2 μs | 7.2 μs | 7.3 μs | 7.6 μs | Binary (7.2 μs) | 1.02x | +| near_linear | unsorted | 1024 | 1024 | 78.8 μs | 76.4 μs | 74.7 μs | 74.5 μs | 74.3 μs | 73.7 μs | 77.3 μs | Binary (74.3 μs) | 0.99x | +| near_linear | unsorted | 1024 | 4096 | 412.1 μs | 412.4 μs | 412.6 μs | 411.3 μs | 412.0 μs | 411.7 μs | 408.2 μs | InterpSearch (411.3 μs) | 1.00x | +| near_linear | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | unsorted | 4096 | 4 | 150 ns | 160 ns | 160 ns | 160 ns | 160 ns | 170 ns | 150 ns | Linear (150 ns) | 1.13x | +| near_linear | unsorted | 4096 | 16 | 510 ns | 490 ns | 490 ns | 500 ns | 490 ns | 510 ns | 480 ns | ExpFromLeft (490 ns) | 1.04x | +| near_linear | unsorted | 4096 | 64 | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | Binary (1.9 μs) | 1.01x | +| near_linear | unsorted | 4096 | 256 | 9.3 μs | 9.1 μs | 9.0 μs | 9.0 μs | 9.0 μs | 9.0 μs | 10.7 μs | ExpFromLeft (9.0 μs) | 1.00x | +| near_linear | unsorted | 4096 | 1024 | 98.2 μs | 95.9 μs | 94.3 μs | 94.4 μs | 93.9 μs | 93.8 μs | 98.0 μs | Binary (93.9 μs) | 1.00x | +| near_linear | unsorted | 4096 | 4096 | 498.2 μs | 498.8 μs | 498.2 μs | 498.2 μs | 498.0 μs | 496.9 μs | 498.7 μs | Binary (498.0 μs) | 1.00x | +| near_linear | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | +| near_linear | unsorted | 16384 | 4 | 13.0 μs | 250 ns | 200 ns | 150 ns | 180 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | +| near_linear | unsorted | 16384 | 16 | 580 ns | 570 ns | 580 ns | 570 ns | 589 ns | 580 ns | 560 ns | InterpSearch (570 ns) | 1.02x | +| near_linear | unsorted | 16384 | 64 | 2.4 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.4 μs | Gallop (2.3 μs) | 1.01x | +| near_linear | unsorted | 16384 | 256 | 10.7 μs | 10.7 μs | 10.6 μs | 10.6 μs | 10.5 μs | 10.4 μs | 13.7 μs | Binary (10.5 μs) | 1.00x | +| near_linear | unsorted | 16384 | 1024 | 140.7 μs | 137.1 μs | 134.5 μs | 134.4 μs | 133.2 μs | 134.3 μs | 141.5 μs | Binary (133.2 μs) | 1.01x | +| near_linear | unsorted | 16384 | 4096 | 663.3 μs | 665.1 μs | 663.5 μs | 662.9 μs | 663.9 μs | 662.9 μs | 668.2 μs | InterpSearch (662.9 μs) | 1.00x | +| near_linear | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | +| near_linear | unsorted | 65536 | 4 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | +| near_linear | unsorted | 65536 | 16 | 670 ns | 670 ns | 660 ns | 670 ns | 680 ns | 680 ns | 640 ns | ExpFromLeft (660 ns) | 1.03x | +| near_linear | unsorted | 65536 | 64 | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.6 μs | 2.7 μs | 2.7 μs | Binary (2.6 μs) | 1.02x | +| near_linear | unsorted | 65536 | 256 | 14.0 μs | 13.6 μs | 13.3 μs | 13.2 μs | 13.2 μs | 13.2 μs | 18.4 μs | InterpSearch (13.2 μs) | 1.00x | +| near_linear | unsorted | 65536 | 1024 | 187.8 μs | 184.1 μs | 184.1 μs | 184.8 μs | 182.7 μs | 182.6 μs | 185.2 μs | Binary (182.7 μs) | 1.00x | +| near_linear | unsorted | 65536 | 4096 | 842.3 μs | 843.1 μs | 842.4 μs | 844.3 μs | 844.3 μs | 840.7 μs | 841.2 μs | Linear (842.3 μs) | 1.00x | + +**Auto verdict over 3920 cells**: 3289 within 20% of best, 545 worse than 20% slowdown, 86 effectively-faster-than-best. diff --git a/bench/strategies.jl b/bench/strategies.jl index 40d54d3..ee27efe 100644 --- a/bench/strategies.jl +++ b/bench/strategies.jl @@ -136,6 +136,7 @@ end # Arithmetic progression covering the full range of t. function queries_arithmetic(t::Vector, m::Integer) + m <= 1 && return [(first(t) + last(t)) / 2] return collect(range(first(t), last(t); length = m)) end @@ -416,6 +417,186 @@ function sweep_extreme() return (sparse = res_sparse, dense = res_dense) end +""" + sweep_tune_gap_linear_vs_exp() + +Empirical crossover between `LinearScan` and `ExpFromLeft` as a function of +the gap between consecutive query results. Runs at a fixed large `n` on +uniform data (so per-segment work is dominated by the per-query inner-loop +overhead, not by data-shape effects), sweeping `m` so the average gap covers +0..256. We're looking for the largest gap at which LinearScan still wins. +""" +function sweep_tune_gap_linear_vs_exp() + n = 4096 + t = knots_uniform(n) + println("\n## Tune: LinearScan vs ExpFromLeft crossover (n=$n, uniform)\n") + println("| gap (≈n/m) | m | Linear | ExpFromLeft | winner | margin |") + println("|---|---|---|---|---|---|") + pairs = [ + (gap, max(1, n ÷ gap)) for gap in (1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256) + ] + for (gap_target, m) in pairs + q = queries_uniform(t, m) + t_lin = bench_batch(LinearScan(), t, q) + t_exp = bench_batch(ExpFromLeft(), t, q) + winner = t_lin <= t_exp ? "Linear" : "ExpFromLeft" + margin = abs(t_lin - t_exp) / min(t_lin, t_exp) + @printf( + "| %d | %d | %s | %s | %s | %.0f%% |\n", + gap_target, m, format_ns(t_lin), format_ns(t_exp), + winner, 100 * margin + ) + end + return +end + +""" + sweep_tune_gap_exp_vs_interp() + +Empirical crossover between `ExpFromLeft` and `InterpolationSearch` on +uniform data, where InterpolationSearch's per-query O(1) advantage is +maximum. Sweeps `m` from sparse to dense at fixed `n`. +""" +function sweep_tune_gap_exp_vs_interp() + n = 65_536 + t = knots_uniform(n) + println("\n## Tune: ExpFromLeft vs InterpolationSearch crossover (n=$n, uniform)\n") + println("| gap (≈n/m) | m | ExpFromLeft | InterpSearch | winner | margin |") + println("|---|---|---|---|---|---|") + pairs = [ + (gap, max(1, n ÷ gap)) for gap in + (8, 16, 24, 32, 48, 64, 96, 128, 256, 512, 1024, 4096, 16_384, 65_536) + ] + for (gap_target, m) in pairs + q = queries_uniform(t, m) + t_exp = bench_batch(ExpFromLeft(), t, q) + t_int = bench_batch(InterpolationSearch(), t, q) + winner = t_exp <= t_int ? "ExpFromLeft" : "InterpSearch" + margin = abs(t_exp - t_int) / min(t_exp, t_int) + @printf( + "| %d | %d | %s | %s | %s | %.0f%% |\n", + gap_target, m, format_ns(t_exp), format_ns(t_int), + winner, 100 * margin + ) + end + return +end + +""" + sweep_tune_n_for_interp() + +How does the InterpolationSearch break-even shift with `n`? Fix `m=16`, +vary `n`, compare InterpolationSearch vs ExpFromLeft. Useful for picking +`_AUTO_INTERP_MIN_N`. +""" +function sweep_tune_n_for_interp() + println("\n## Tune: minimum n at which InterpolationSearch wins (uniform, m=16)\n") + println("| n | gap | ExpFromLeft | InterpSearch | winner | margin |") + println("|---|---|---|---|---|---|") + m = 16 + for n in (32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16_384, 65_536, 262_144) + t = knots_uniform(n) + q = queries_uniform(t, m) + t_exp = bench_batch(ExpFromLeft(), t, q) + t_int = bench_batch(InterpolationSearch(), t, q) + gap = n ÷ m + winner = t_exp <= t_int ? "ExpFromLeft" : "InterpSearch" + margin = abs(t_exp - t_int) / min(t_exp, t_int) + @printf( + "| %d | %d | %s | %s | %s | %.0f%% |\n", + n, gap, format_ns(t_exp), format_ns(t_int), + winner, 100 * margin + ) + end + return +end + +""" + sweep_tune_m_for_interp() + +How does the break-even shift with `m`? Fix `n=65_536` (large), vary `m`, +compare InterpolationSearch vs ExpFromLeft. Useful for picking +`_AUTO_INTERP_MIN_M`. +""" +function sweep_tune_m_for_interp() + println("\n## Tune: minimum m at which InterpolationSearch wins (uniform, n=65536)\n") + println("| m | gap | ExpFromLeft | InterpSearch | winner | margin |") + println("|---|---|---|---|---|---|") + n = 65_536 + t = knots_uniform(n) + for m in (1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 64, 128, 256, 1024, 4096) + q = queries_uniform(t, m) + t_exp = bench_batch(ExpFromLeft(), t, q) + t_int = bench_batch(InterpolationSearch(), t, q) + gap = n ÷ max(1, m) + winner = t_exp <= t_int ? "ExpFromLeft" : "InterpSearch" + margin = abs(t_exp - t_int) / min(t_exp, t_int) + @printf( + "| %d | %d | %s | %s | %s | %.0f%% |\n", + m, gap, format_ns(t_exp), format_ns(t_int), + winner, 100 * margin + ) + end + return +end + +""" + sweep_tune_interp_on_nonlinear() + +Worst case for InterpolationSearch — measure how badly it loses on each +non-linear spacing. This bounds the downside risk of accidentally picking +InterpolationSearch when the linearity probe gives a false positive. +""" +function sweep_tune_interp_on_nonlinear() + println("\n## Tune: InterpolationSearch downside on non-linear data (m=256)\n") + println("| spacing | n | ExpFromLeft | InterpSearch | InterpSearch slowdown |") + println("|---|---|---|---|---|") + m = 256 + nonlinear = ( + :log => knots_log, :random => knots_random, + :two_scale => knots_two_scale, :power2 => knots_power2, + :sqrt => knots_sqrt, :plateau => knots_plateau, + :bimodal => knots_bimodal, + ) + for (sp_name, sp_fn) in nonlinear + for n in (1024, 16_384, 262_144) + t = sp_fn(n) + q = queries_uniform(t, m) + t_exp = bench_batch(ExpFromLeft(), t, q) + t_int = bench_batch(InterpolationSearch(), t, q) + slowdown = t_int / t_exp + @printf( + "| %s | %d | %s | %s | %.2fx |\n", + sp_name, n, format_ns(t_exp), format_ns(t_int), slowdown + ) + end + end + return +end + +# Comprehensive validation sweep — many cells with smaller per-cell sample +# counts. Use this once Auto's thresholds are tuned to check that the +# heuristic is in fact picking well across the parameter space. +function sweep_validate() + return run_sweep( + title = "Validation sweep (many cells)", + ns = (16, 64, 256, 1024, 4096, 16_384, 65_536), + ms = (1, 4, 16, 64, 256, 1024, 4096), + spacings = ALL_KNOT_SPACINGS, + query_patterns = ALL_QUERY_PATTERNS, + strategies = STRATEGIES, + ) +end + +function tune_all() + sweep_tune_gap_linear_vs_exp() + sweep_tune_gap_exp_vs_interp() + sweep_tune_n_for_interp() + sweep_tune_m_for_interp() + sweep_tune_interp_on_nonlinear() + return +end + if abspath(PROGRAM_FILE) == @__FILE__ mode = get(ENV, "MODE", "fast") if mode == "full" @@ -428,6 +609,10 @@ if abspath(PROGRAM_FILE) == @__FILE__ sweep_pattern() elseif mode == "extreme" sweep_extreme() + elseif mode == "tune" + tune_all() + elseif mode == "validate" + sweep_validate() else fast_sweep() end diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index b53c887..f24d38c 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -354,26 +354,39 @@ const _AUTO_BATCH_LINEAR_GAP = 4 # beat ExpFromLeft by ~2× on uniformly-spaced data. The sampled-linearity # check below is O(1) — 5 fixed probes — so it's cheap enough to run inside # Auto when there's a real chance of unlocking InterpolationSearch. -const _AUTO_INTERP_MIN_GAP = 64 +const _AUTO_INTERP_MIN_GAP = 8 const _AUTO_INTERP_MIN_N = 1024 const _AUTO_INTERP_MIN_M = 2 -const _AUTO_LINEAR_REL_TOLERANCE = 0.05 - -# Sampled linearity check: probes v[1], v[n/4], v[n/2], v[3n/4], v[n] and -# tests whether the interior points sit close to the straight line between -# the endpoints. Cost is ~12 ns regardless of n. Used by Auto to decide -# whether to gamble on InterpolationSearch. +const _AUTO_LINEAR_REL_TOLERANCE = 1.0e-3 + +# Sampled linearity check: probes v[1], v[k*n/10] for k = 1..9, v[n] and +# tests whether all interior points sit within `_AUTO_LINEAR_REL_TOLERANCE` +# (default 0.1%) of the straight line between v[1] and v[n]. The tight +# tolerance reliably distinguishes truly-uniform data from random/sorted +# data even at large n (where the order-statistic variance ≈ 1/sqrt(n) +# would fool a looser check). +# +# Cost is ~25 ns regardless of n — 11 reads + 9 comparisons. Used by Auto +# to decide whether to gamble on InterpolationSearch. +# +# InterpolationSearch's downside on non-linear data is large (4-14× slower +# than ExpFromLeft on log/plateau/two-scale spacings), so we err on the +# side of rejecting borderline cases. Truly uniform data — exact ranges, +# evenly-spaced grids, and small-amplitude jittered data — passes; sorted +# random data is rejected at all `n` tested up to ~10⁶. @inline function _sampled_looks_linear(v::AbstractVector{<:Number}) n = length(v) - n < 5 && return true + n < 11 && return false @inbounds begin v1, vn = v[1], v[n] span = vn - v1 (iszero(span) || !isfinite(span)) && return false - for k in (n >> 2, n >> 1, (3 * n) >> 2) - kk = max(1, min(n, k)) - expected = v1 + (kk - 1) / (n - 1) * span - rel_err = abs(v[kk] - expected) / abs(span) + abs_span = abs(span) + nm1 = n - 1 + for k in 1:9 + kk = 1 + (k * nm1) ÷ 10 + expected = v1 + (kk - 1) / nm1 * span + rel_err = abs(v[kk] - expected) / abs_span rel_err > _AUTO_LINEAR_REL_TOLERANCE && return false end end @@ -383,6 +396,9 @@ end # Non-numeric eltype: can't sample, never picks InterpolationSearch. @inline _sampled_looks_linear(::AbstractVector) = false +# AbstractRange is definitionally uniform — accept without sampling. +@inline _sampled_looks_linear(::AbstractRange) = true + # Strategy: BinaryBracket — ignore any hint. Base.searchsortedlast( ::BinaryBracket, v::AbstractVector, x; @@ -649,30 +665,56 @@ end if m == 0 return BinaryBracket() end - gap = _estimate_avg_gap(v, queries, m) + gap, _ = _estimate_avg_gap(v, queries, m) return gap <= _AUTO_BATCH_LINEAR_GAP ? LinearScan() : ExpFromLeft() end +# Returns `(gap, skewed)`: the estimated average step in `v`'s index space +# between consecutive query results, plus a flag that's true when the +# queries' distribution is non-uniform within their span. The skew flag is +# what lets Auto reject InterpolationSearch even when the gap is large: +# `ExpFromLeft` from `prev_idx` wins on skewed queries because consecutive +# queries land in the same neighbourhood, regardless of `v` being linear. @inline function _estimate_avg_gap( v::AbstractVector{<:Number}, queries::AbstractVector{<:Number}, m::Integer ) n = length(v) - n <= 1 && return 0 + n <= 1 && return (0, false) @inbounds span_v = v[end] - v[1] if iszero(span_v) || !isfinite(span_v) - return n ÷ max(1, m) + return (n ÷ max(1, m), false) end @inbounds span_q = queries[end] - queries[1] + # Skew detection on small `m` is too noisy — for `m ≈ 4` random uniform + # samples, the median routinely sits 30 %+ off the linear midpoint by + # chance. Gate on `m ≥ 10` where the statistical variance is well below + # the 20 % threshold. + skewed = false + if m >= 10 + @inbounds mid_q = queries[firstindex(queries) + m ÷ 2] + @inbounds expected_mid = ( + queries[firstindex(queries)] + + queries[lastindex(queries)] + ) / 2 + if !iszero(span_q) && + abs(mid_q - expected_mid) > 0.2 * abs(span_q) + skewed = true + end + end + if skewed + return (n ÷ max(1, m), true) + end ratio = span_q / span_v # Clamp ratio: queries may extend outside v's range (extrapolation). ratio = clamp(ratio, zero(ratio), one(ratio)) - return floor(Int, n * ratio / max(1, m)) + return (floor(Int, n * ratio / max(1, m)), false) end -# Non-numeric eltypes: no span subtraction possible, fall back to length ratio. +# Non-numeric eltypes: no span subtraction possible, fall back to length ratio +# and assume queries are roughly uniform (no skew detection possible). @inline _estimate_avg_gap( v::AbstractVector, ::AbstractVector, m::Integer -) = length(v) ÷ max(1, m) +) = (length(v) ÷ max(1, m), false) function Base.searchsortedlast( ::Auto, v::AbstractVector, x, hint::Integer; @@ -851,7 +893,7 @@ function _searchsortedlast_batched!( if !issorted(queries; order = order) return _searchsortedlast_unsorted_loop!(idx_out, v, queries, order) end - gap = _estimate_avg_gap(v, queries, m) + gap, skewed = _estimate_avg_gap(v, queries, m) # Manually dispatch on the picked strategy so each branch is concrete. if gap <= _AUTO_BATCH_LINEAR_GAP return _searchsortedlast_sorted_loop!( @@ -859,8 +901,12 @@ function _searchsortedlast_batched!( ) end # Sparse-on-large-linear: InterpolationSearch wins ~2× over ExpFromLeft - # on uniformly-spaced data. Sampled check is ~12 ns. - if gap >= _AUTO_INTERP_MIN_GAP && + # on uniformly-spaced data — but only when queries are *also* spread + # roughly uniformly within their span. For skewed (clustered) queries, + # `ExpFromLeft` from `prev_idx` wins even on linear v because the next + # query's true index is close to the previous one's. + if !skewed && + gap >= _AUTO_INTERP_MIN_GAP && length(v) >= _AUTO_INTERP_MIN_N && m >= _AUTO_INTERP_MIN_M && _sampled_looks_linear(v) @@ -898,13 +944,14 @@ function _searchsortedfirst_batched!( if !issorted(queries; order = order) return _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) end - gap = _estimate_avg_gap(v, queries, m) + gap, skewed = _estimate_avg_gap(v, queries, m) if gap <= _AUTO_BATCH_LINEAR_GAP return _searchsortedfirst_sorted_loop!( idx_out, v, queries, LinearScan(), order ) end - if gap >= _AUTO_INTERP_MIN_GAP && + if !skewed && + gap >= _AUTO_INTERP_MIN_GAP && length(v) >= _AUTO_INTERP_MIN_N && m >= _AUTO_INTERP_MIN_M && _sampled_looks_linear(v) From e6afad55908f600e3017650bf0d663cd5a4d818e Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 17 May 2026 10:18:44 -0400 Subject: [PATCH 05/16] Fix CI: rename strat -> strategy, add StableRNGs compat, docs entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three small CI fixes from the FFF #65 run: - `bench/strategies.jl`: rename loop variable `strat` to `strategy` so the typo check stops flagging it as `start` / `strata`. - `Project.toml`: add `StableRNGs = "1"` to `[compat]` — Aqua's `test_deps_compat` requires every test-extras dep to have a compat bound. - `docs/src/index.md`: add `@docs` entries for the new public symbols (`searchsortedlast!`, `searchsortedfirst!`, plus the strategy types `SearchStrategy` / `LinearScan` / `BracketGallop` / `ExpFromLeft` / `InterpolationSearch` / `BinaryBracket` / `GuesserHint` / `Auto`) so Documenter's cross-reference resolver finds them and the `missing_docs` check passes. Tests: 26929 / 26929 still passing locally. Co-Authored-By: Chris Rackauckas --- Project.toml | 1 + bench/strategies.jl | 4 ++-- docs/src/index.md | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index 70468b9..60ec715 100644 --- a/Project.toml +++ b/Project.toml @@ -10,6 +10,7 @@ PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" Pkg = "1.10" PrecompileTools = "1" SafeTestsets = "0.1" +StableRNGs = "1" Test = "1.10" julia = "1.10" diff --git a/bench/strategies.jl b/bench/strategies.jl index ee27efe..9c790cd 100644 --- a/bench/strategies.jl +++ b/bench/strategies.jl @@ -274,8 +274,8 @@ function run_sweep(; title, ns, ms, spacings, query_patterns, strategies) for m in ms q = qp_fn(t, m) results = Dict{String, Float64}() - for (name, strat) in strategies - results[name] = bench_batch(strat, t, q) + for (name, strategy) in strategies + results[name] = bench_batch(strategy, t, q) end results["base"] = bench_base(t, q) best_name, best_t = "", Inf diff --git a/docs/src/index.md b/docs/src/index.md index f516303..6e392ee 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -24,6 +24,21 @@ FindFirstFunctions.searchsortedfirstexp FindFirstFunctions.searchsortedfirstvec FindFirstFunctions.searchsortedlastvec FindFirstFunctions.findfirstsortedequal +FindFirstFunctions.searchsortedfirst! +FindFirstFunctions.searchsortedlast! +``` + +## Sorted-search strategies + +```@docs +FindFirstFunctions.SearchStrategy +FindFirstFunctions.LinearScan +FindFirstFunctions.BracketGallop +FindFirstFunctions.ExpFromLeft +FindFirstFunctions.InterpolationSearch +FindFirstFunctions.BinaryBracket +FindFirstFunctions.GuesserHint +FindFirstFunctions.Auto ``` ## Contributing From cebc780497e6d4b29f7328739223a5e6a724aad3 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 05:30:04 -0400 Subject: [PATCH 06/16] FFF 2.0: drop legacy single-purpose dispatches, keep only strategy API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 1.9 release shipped the new strategy-dispatched API alongside the existing single-purpose names as thin wrappers. Cleaner long-term shape is a single canonical API, so 2.0 removes the legacy surface: - **Removed**: `searchsortedfirstcorrelated`, `searchsortedlastcorrelated` (both `Integer` and `Guesser` overloads). - **Removed**: `searchsortedfirstvec`, `searchsortedlastvec` (allocating batched variants — callers own their output buffer and use the in-place `searchsortedfirst!` / `searchsortedlast!`). - **Made internal**: `searchsortedfirstexp` and `bracketstrictlymontonic`. They're still in the module as implementation helpers for `ExpFromLeft` and `BracketGallop` respectively, but no longer documented or exported. - **Kept (documented public)**: `searchsortedfirst!` / `searchsortedlast!`, `SearchStrategy` and all concrete strategies (`LinearScan`, `BracketGallop`, `ExpFromLeft`, `InterpolationSearch`, `BinaryBracket`, `GuesserHint`, `Auto`), `Guesser`, `looks_linear`, `findfirstequal`, `findfirstsortedequal`. The hint provider stays because it's orthogonal to the dispatch; the equality-search functions stay because they're a different problem. Migration for downstream callers: | old | 2.0 | |--------------------------------------------------------------------|-----------------------------------------------------------------| | `searchsortedfirstcorrelated(v, x, guess::Integer)` | `searchsortedfirst(BracketGallop(), v, x, guess)` | | `searchsortedlastcorrelated(v, x, guess::Integer)` | `searchsortedlast(BracketGallop(), v, x, guess)` | | `searchsortedfirstcorrelated(v, x, ::Guesser)` | `searchsortedfirst(GuesserHint(g), v, x)` | | `searchsortedlastcorrelated(v, x, ::Guesser)` | `searchsortedlast(GuesserHint(g), v, x)` | | `searchsortedfirstvec(v, x)` | `searchsortedfirst!(buf, v, x)` (caller-owned `buf`) | | `searchsortedlastvec(v, x)` | `searchsortedlast!(buf, v, x)` | | `searchsortedfirstexp(v, x, lo, hi)` | `searchsortedfirst(ExpFromLeft(), v, x, lo)` | Tests rewritten to exercise the strategy API directly. Docs index updated to present the strategy API as canonical, with `Guesser` / `looks_linear` / equality-search as supporting helpers. `Project.toml` bumped to `2.0.0`. Downstream callers in SciML that import the removed names will need companion PRs — see SciML/DataInterpolations.jl#529 for the first one. Co-Authored-By: Chris Rackauckas --- Project.toml | 2 +- bench/Project.toml | 8 - bench/results.md | 266 --- bench/results_focused.md | 571 ------ bench/results_tune.md | 103 - bench/results_validate.md | 3927 ------------------------------------- bench/strategies.jl | 619 ------ docs/src/index.md | 46 +- src/FindFirstFunctions.jl | 219 +-- test/runtests.jl | 198 +- 10 files changed, 140 insertions(+), 5819 deletions(-) delete mode 100644 bench/Project.toml delete mode 100644 bench/results.md delete mode 100644 bench/results_focused.md delete mode 100644 bench/results_tune.md delete mode 100644 bench/results_validate.md delete mode 100644 bench/strategies.jl diff --git a/Project.toml b/Project.toml index 60ec715..655dfb1 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "FindFirstFunctions" uuid = "64ca27bc-2ba2-4a57-88aa-44e436879224" -version = "1.9.0" +version = "2.0.0" authors = ["Chris Elrod and contributors"] [deps] diff --git a/bench/Project.toml b/bench/Project.toml deleted file mode 100644 index 145279d..0000000 --- a/bench/Project.toml +++ /dev/null @@ -1,8 +0,0 @@ -[deps] -BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" -FindFirstFunctions = "64ca27bc-2ba2-4a57-88aa-44e436879224" -Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" -StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" - -[sources] -FindFirstFunctions = {path = ".."} diff --git a/bench/results.md b/bench/results.md deleted file mode 100644 index 2fb577e..0000000 --- a/bench/results.md +++ /dev/null @@ -1,266 +0,0 @@ -# `bench/strategies.jl` results — fast sweep - -Captured 2026-05-17 on Julia 1.10.11, run via -`julia --project=bench bench/strategies.jl`. 240 cells, 20 samples each, -`BenchmarkTools.minimum`. - -The companion artifacts are: - -- `bench/results_focused.md` — spacing/pattern/ratio/extreme sub-sweeps -- `bench/results_validate.md` — large 3920-cell validation sweep -- `bench/results_tune.md` — empirical crossover measurements that drive - the `Auto` thresholds (LinearScan↔ExpFromLeft, ExpFromLeft↔InterpSearch, - min-n / min-m for InterpSearch, and the InterpSearch downside on - non-linear data) - -`Auto` verdict on this sweep: **221 / 240 (92 %) within 20 % of best**. -Aggregate verdict across all sweeps (4 692 cells total): -**3 988 (85 %) within 20 % of best**; **only 1 cell exceeds 2 ×** (and that -one cell is a 180 ns absolute difference at `m = 4`). - -## Fast sweep - -| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | -|---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| uniform | sorted_uniform | 64 | 10 | 180 ns | 220 ns | 190 ns | 310 ns | 200 ns | 190 ns | 180 ns | Linear (180 ns) | 1.06x | -| uniform | sorted_uniform | 64 | 256 | 2.1 μs | 4.2 μs | 3.0 μs | 9.0 μs | 4.2 μs | 2.2 μs | 4.8 μs | Linear (2.1 μs) | 1.01x | -| uniform | sorted_uniform | 64 | 4096 | 32.2 μs | 56.4 μs | 43.5 μs | 113.3 μs | 68.8 μs | 32.2 μs | 60.3 μs | Linear (32.2 μs) | 1.00x | -| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| uniform | sorted_uniform | 1024 | 10 | 1.7 μs | 410 ns | 330 ns | 320 ns | 290 ns | 370 ns | 270 ns | Binary (290 ns) | 1.28x | -| uniform | sorted_uniform | 1024 | 256 | 3.6 μs | 5.2 μs | 3.8 μs | 9.2 μs | 7.1 μs | 3.8 μs | 7.3 μs | Linear (3.6 μs) | 1.06x | -| uniform | sorted_uniform | 1024 | 4096 | 49.0 μs | 72.7 μs | 57.5 μs | 151.6 μs | 227.8 μs | 48.7 μs | 183.2 μs | Linear (49.0 μs) | 0.99x | -| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | -| uniform | sorted_uniform | 65536 | 10 | 81.6 μs | 750 ns | 500 ns | 310 ns | 430 ns | 379 ns | 410 ns | InterpSearch (310 ns) | 1.22x | -| uniform | sorted_uniform | 65536 | 256 | 100.9 μs | 12.7 μs | 9.1 μs | 9.3 μs | 14.2 μs | 9.7 μs | 17.2 μs | ExpFromLeft (9.1 μs) | 1.07x | -| uniform | sorted_uniform | 65536 | 4096 | 200.1 μs | 251.4 μs | 205.7 μs | 166.2 μs | 489.8 μs | 173.2 μs | 493.1 μs | InterpSearch (166.2 μs) | 1.04x | -| uniform | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Linear (50 ns) | 1.00x | -| uniform | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 310 ns | 200 ns | 140 ns | 170 ns | Linear (130 ns) | 1.08x | -| uniform | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 109.8 μs | 67.9 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| uniform | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 310 ns | 310 ns | 150 ns | 270 ns | Linear (130 ns) | 1.15x | -| uniform | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 109.7 μs | 106.9 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 310 ns | 450 ns | 170 ns | 410 ns | Linear (150 ns) | 1.13x | -| uniform | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.3 μs | 2.1 μs | 9.6 μs | Linear (2.0 μs) | 1.02x | -| uniform | sorted_dense_burst | 65536 | 4096 | 30.9 μs | 55.5 μs | 42.3 μs | 109.6 μs | 164.5 μs | 30.8 μs | 152.4 μs | Linear (30.9 μs) | 1.00x | -| uniform | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| uniform | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 170 ns | 330 ns | 200 ns | 190 ns | 180 ns | ExpFromLeft (170 ns) | 1.12x | -| uniform | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.3 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.06x | -| uniform | sorted_near_start | 64 | 4096 | 31.7 μs | 56.6 μs | 43.4 μs | 111.6 μs | 67.4 μs | 31.8 μs | 60.6 μs | Linear (31.7 μs) | 1.00x | -| uniform | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_near_start | 1024 | 10 | 1.4 μs | 300 ns | 230 ns | 310 ns | 290 ns | 260 ns | 270 ns | ExpFromLeft (230 ns) | 1.13x | -| uniform | sorted_near_start | 1024 | 256 | 3.8 μs | 4.7 μs | 3.5 μs | 8.7 μs | 6.8 μs | 3.7 μs | 7.0 μs | ExpFromLeft (3.5 μs) | 1.05x | -| uniform | sorted_near_start | 1024 | 4096 | 33.6 μs | 58.6 μs | 44.6 μs | 117.5 μs | 111.6 μs | 33.8 μs | 106.3 μs | Linear (33.6 μs) | 1.00x | -| uniform | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_near_start | 65536 | 10 | 36.5 μs | 520 ns | 400 ns | 300 ns | 430 ns | 440 ns | 430 ns | InterpSearch (300 ns) | 1.47x | -| uniform | sorted_near_start | 65536 | 256 | 95.9 μs | 8.0 μs | 5.7 μs | 9.0 μs | 11.9 μs | 5.9 μs | 19.9 μs | ExpFromLeft (5.7 μs) | 1.03x | -| uniform | sorted_near_start | 65536 | 4096 | 157.0 μs | 120.9 μs | 98.0 μs | 162.6 μs | 379.6 μs | 96.9 μs | 301.5 μs | ExpFromLeft (98.0 μs) | 0.99x | -| uniform | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | unsorted | 64 | 10 | 190 ns | 180 ns | 180 ns | 180 ns | 190 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | -| uniform | unsorted | 64 | 256 | 6.1 μs | 6.0 μs | 6.0 μs | 5.9 μs | 6.0 μs | 6.0 μs | 5.8 μs | InterpSearch (5.9 μs) | 1.01x | -| uniform | unsorted | 64 | 4096 | 230.8 μs | 230.3 μs | 229.0 μs | 229.3 μs | 227.0 μs | 226.9 μs | 224.7 μs | Binary (227.0 μs) | 1.00x | -| uniform | unsorted | 1024 | 1 | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| uniform | unsorted | 1024 | 10 | 270 ns | 280 ns | 280 ns | 280 ns | 290 ns | 290 ns | 270 ns | Linear (270 ns) | 1.07x | -| uniform | unsorted | 1024 | 256 | 8.5 μs | 8.1 μs | 8.1 μs | 8.1 μs | 8.0 μs | 8.1 μs | 8.0 μs | Binary (8.0 μs) | 1.00x | -| uniform | unsorted | 1024 | 4096 | 412.4 μs | 410.2 μs | 411.5 μs | 408.8 μs | 410.6 μs | 411.7 μs | 412.4 μs | InterpSearch (408.8 μs) | 1.01x | -| uniform | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | unsorted | 65536 | 10 | 420 ns | 430 ns | 430 ns | 420 ns | 430 ns | 440 ns | 410 ns | InterpSearch (420 ns) | 1.05x | -| uniform | unsorted | 65536 | 256 | 15.1 μs | 14.6 μs | 14.5 μs | 14.3 μs | 14.5 μs | 14.4 μs | 17.1 μs | InterpSearch (14.3 μs) | 1.00x | -| uniform | unsorted | 65536 | 4096 | 854.7 μs | 851.6 μs | 849.7 μs | 853.0 μs | 852.6 μs | 852.9 μs | 857.9 μs | ExpFromLeft (849.7 μs) | 1.00x | -| log | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| log | sorted_uniform | 64 | 10 | 170 ns | 220 ns | 190 ns | 440 ns | 200 ns | 220 ns | 180 ns | Linear (170 ns) | 1.29x | -| log | sorted_uniform | 64 | 256 | 2.3 μs | 3.8 μs | 3.0 μs | 11.3 μs | 4.5 μs | 2.4 μs | 4.2 μs | Linear (2.3 μs) | 1.01x | -| log | sorted_uniform | 64 | 4096 | 31.7 μs | 55.6 μs | 43.2 μs | 170.7 μs | 69.1 μs | 31.7 μs | 60.6 μs | Linear (31.7 μs) | 1.00x | -| log | sorted_uniform | 1024 | 1 | 60 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_uniform | 1024 | 10 | 470 ns | 330 ns | 260 ns | 670 ns | 290 ns | 300 ns | 270 ns | ExpFromLeft (260 ns) | 1.15x | -| log | sorted_uniform | 1024 | 256 | 3.2 μs | 4.6 μs | 3.2 μs | 16.3 μs | 7.1 μs | 3.3 μs | 8.1 μs | ExpFromLeft (3.2 μs) | 1.03x | -| log | sorted_uniform | 1024 | 4096 | 38.5 μs | 62.7 μs | 48.7 μs | 286.3 μs | 170.3 μs | 38.7 μs | 124.9 μs | Linear (38.5 μs) | 1.00x | -| log | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_uniform | 65536 | 10 | 19.6 μs | 580 ns | 440 ns | 910 ns | 440 ns | 470 ns | 410 ns | ExpFromLeft (440 ns) | 1.07x | -| log | sorted_uniform | 65536 | 256 | 89.7 μs | 10.3 μs | 7.7 μs | 25.5 μs | 13.5 μs | 7.7 μs | 17.6 μs | ExpFromLeft (7.7 μs) | 1.01x | -| log | sorted_uniform | 65536 | 4096 | 183.7 μs | 198.8 μs | 154.0 μs | 657.0 μs | 438.3 μs | 153.8 μs | 418.9 μs | ExpFromLeft (154.0 μs) | 1.00x | -| log | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| log | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 490 ns | 200 ns | 140 ns | 170 ns | Linear (130 ns) | 1.08x | -| log | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.2 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | -| log | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.4 μs | 42.3 μs | 176.7 μs | 68.0 μs | 32.9 μs | 60.7 μs | Linear (30.8 μs) | 1.07x | -| log | sorted_dense_burst | 1024 | 1 | 60 ns | 70 ns | 70 ns | 100 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| log | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 680 ns | 310 ns | 149 ns | 270 ns | Linear (130 ns) | 1.15x | -| log | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.2 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.00x | -| log | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.6 μs | 42.3 μs | 259.1 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 989 ns | 450 ns | 170 ns | 420 ns | Linear (150 ns) | 1.13x | -| log | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.1 μs | 10.3 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.00x | -| log | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.4 μs | 384.3 μs | 164.5 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| log | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 160 ns | 330 ns | 200 ns | 199 ns | 170 ns | ExpFromLeft (160 ns) | 1.24x | -| log | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.3 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | -| log | sorted_near_start | 64 | 4096 | 31.2 μs | 55.8 μs | 42.8 μs | 116.7 μs | 67.6 μs | 33.2 μs | 59.9 μs | Linear (31.2 μs) | 1.06x | -| log | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_near_start | 1024 | 10 | 1.2 μs | 300 ns | 230 ns | 480 ns | 300 ns | 280 ns | 270 ns | ExpFromLeft (230 ns) | 1.22x | -| log | sorted_near_start | 1024 | 256 | 3.8 μs | 4.5 μs | 3.4 μs | 12.2 μs | 6.8 μs | 3.8 μs | 7.0 μs | ExpFromLeft (3.4 μs) | 1.13x | -| log | sorted_near_start | 1024 | 4096 | 33.5 μs | 58.0 μs | 44.0 μs | 191.1 μs | 110.4 μs | 33.6 μs | 102.9 μs | Linear (33.5 μs) | 1.00x | -| log | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_near_start | 65536 | 10 | 61.2 μs | 550 ns | 420 ns | 800 ns | 440 ns | 450 ns | 410 ns | ExpFromLeft (420 ns) | 1.07x | -| log | sorted_near_start | 65536 | 256 | 93.7 μs | 7.7 μs | 5.6 μs | 20.7 μs | 12.2 μs | 6.0 μs | 19.5 μs | ExpFromLeft (5.6 μs) | 1.05x | -| log | sorted_near_start | 65536 | 4096 | 159.8 μs | 112.2 μs | 88.8 μs | 497.8 μs | 369.6 μs | 89.5 μs | 293.0 μs | ExpFromLeft (88.8 μs) | 1.01x | -| log | unsorted | 64 | 1 | 60 ns | 50 ns | 60 ns | 90 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| log | unsorted | 64 | 10 | 190 ns | 190 ns | 190 ns | 180 ns | 190 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | -| log | unsorted | 64 | 256 | 4.9 μs | 5.1 μs | 5.0 μs | 4.9 μs | 4.9 μs | 5.0 μs | 5.1 μs | Linear (4.9 μs) | 1.03x | -| log | unsorted | 64 | 4096 | 169.8 μs | 169.8 μs | 174.5 μs | 167.8 μs | 167.1 μs | 167.6 μs | 172.2 μs | Binary (167.1 μs) | 1.00x | -| log | unsorted | 1024 | 1 | 60 ns | 70 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | unsorted | 1024 | 10 | 280 ns | 280 ns | 270 ns | 270 ns | 290 ns | 290 ns | 260 ns | InterpSearch (270 ns) | 1.07x | -| log | unsorted | 1024 | 256 | 9.9 μs | 9.8 μs | 9.8 μs | 9.7 μs | 9.7 μs | 9.5 μs | 9.6 μs | InterpSearch (9.7 μs) | 0.98x | -| log | unsorted | 1024 | 4096 | 350.5 μs | 349.2 μs | 347.7 μs | 344.9 μs | 342.0 μs | 343.8 μs | 344.6 μs | Binary (342.0 μs) | 1.01x | -| log | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | unsorted | 65536 | 10 | 420 ns | 420 ns | 420 ns | 420 ns | 420 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | -| log | unsorted | 65536 | 256 | 17.8 μs | 17.6 μs | 17.3 μs | 17.4 μs | 17.4 μs | 17.5 μs | 19.2 μs | ExpFromLeft (17.3 μs) | 1.02x | -| log | unsorted | 65536 | 4096 | 705.9 μs | 703.7 μs | 703.3 μs | 704.5 μs | 705.5 μs | 705.9 μs | 707.2 μs | ExpFromLeft (703.3 μs) | 1.00x | -| jittered | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 60 ns | 60 ns | 50 ns | 50 ns | 50 ns | Binary (50 ns) | 1.00x | -| jittered | sorted_uniform | 64 | 10 | 180 ns | 230 ns | 180 ns | 310 ns | 210 ns | 210 ns | 180 ns | ExpFromLeft (180 ns) | 1.17x | -| jittered | sorted_uniform | 64 | 256 | 2.2 μs | 4.2 μs | 3.2 μs | 9.1 μs | 4.3 μs | 2.2 μs | 5.0 μs | Linear (2.2 μs) | 1.02x | -| jittered | sorted_uniform | 64 | 4096 | 32.2 μs | 56.2 μs | 43.5 μs | 113.6 μs | 68.7 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | -| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_uniform | 1024 | 10 | 1.5 μs | 380 ns | 290 ns | 340 ns | 300 ns | 400 ns | 270 ns | ExpFromLeft (290 ns) | 1.38x | -| jittered | sorted_uniform | 1024 | 256 | 3.6 μs | 5.5 μs | 3.8 μs | 9.1 μs | 7.4 μs | 3.7 μs | 7.6 μs | Linear (3.6 μs) | 1.02x | -| jittered | sorted_uniform | 1024 | 4096 | 48.5 μs | 72.8 μs | 57.9 μs | 152.2 μs | 233.2 μs | 48.2 μs | 181.6 μs | Linear (48.5 μs) | 0.99x | -| jittered | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_uniform | 65536 | 10 | 58.7 μs | 670 ns | 480 ns | 310 ns | 440 ns | 370 ns | 410 ns | InterpSearch (310 ns) | 1.19x | -| jittered | sorted_uniform | 65536 | 256 | 99.7 μs | 12.7 μs | 9.6 μs | 9.7 μs | 13.2 μs | 10.2 μs | 16.6 μs | ExpFromLeft (9.6 μs) | 1.07x | -| jittered | sorted_uniform | 65536 | 4096 | 201.7 μs | 253.6 μs | 206.0 μs | 164.3 μs | 490.9 μs | 171.4 μs | 497.2 μs | InterpSearch (164.3 μs) | 1.04x | -| jittered | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| jittered | sorted_dense_burst | 64 | 10 | 120 ns | 180 ns | 150 ns | 320 ns | 200 ns | 140 ns | 170 ns | Linear (120 ns) | 1.17x | -| jittered | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.00x | -| jittered | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.4 μs | 42.3 μs | 110.0 μs | 67.9 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| jittered | sorted_dense_burst | 1024 | 10 | 130 ns | 190 ns | 160 ns | 310 ns | 310 ns | 150 ns | 270 ns | Linear (130 ns) | 1.15x | -| jittered | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.00x | -| jittered | sorted_dense_burst | 1024 | 4096 | 31.3 μs | 55.7 μs | 42.3 μs | 109.8 μs | 106.7 μs | 30.8 μs | 95.8 μs | Linear (31.3 μs) | 0.98x | -| jittered | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_dense_burst | 65536 | 10 | 150 ns | 200 ns | 170 ns | 310 ns | 450 ns | 160 ns | 420 ns | Linear (150 ns) | 1.07x | -| jittered | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.3 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | -| jittered | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 109.6 μs | 164.5 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| jittered | sorted_near_start | 64 | 10 | 200 ns | 200 ns | 160 ns | 330 ns | 200 ns | 190 ns | 170 ns | ExpFromLeft (160 ns) | 1.19x | -| jittered | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | -| jittered | sorted_near_start | 64 | 4096 | 31.8 μs | 56.6 μs | 43.4 μs | 111.1 μs | 68.8 μs | 31.8 μs | 60.4 μs | Linear (31.8 μs) | 1.00x | -| jittered | sorted_near_start | 1024 | 1 | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| jittered | sorted_near_start | 1024 | 10 | 720 ns | 290 ns | 240 ns | 310 ns | 290 ns | 270 ns | 260 ns | ExpFromLeft (240 ns) | 1.12x | -| jittered | sorted_near_start | 1024 | 256 | 3.8 μs | 4.6 μs | 3.6 μs | 9.1 μs | 6.7 μs | 3.8 μs | 7.1 μs | ExpFromLeft (3.6 μs) | 1.04x | -| jittered | sorted_near_start | 1024 | 4096 | 33.7 μs | 58.4 μs | 44.5 μs | 116.9 μs | 111.0 μs | 34.2 μs | 104.4 μs | Linear (33.7 μs) | 1.01x | -| jittered | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_near_start | 65536 | 10 | 80.0 μs | 540 ns | 410 ns | 300 ns | 430 ns | 440 ns | 440 ns | InterpSearch (300 ns) | 1.47x | -| jittered | sorted_near_start | 65536 | 256 | 93.3 μs | 7.9 μs | 5.9 μs | 9.0 μs | 11.9 μs | 5.9 μs | 19.8 μs | ExpFromLeft (5.9 μs) | 0.99x | -| jittered | sorted_near_start | 65536 | 4096 | 157.2 μs | 120.1 μs | 95.8 μs | 159.2 μs | 375.8 μs | 94.3 μs | 301.1 μs | ExpFromLeft (95.8 μs) | 0.98x | -| jittered | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Linear (50 ns) | 1.00x | -| jittered | unsorted | 64 | 10 | 190 ns | 180 ns | 190 ns | 180 ns | 200 ns | 200 ns | 180 ns | InterpSearch (180 ns) | 1.11x | -| jittered | unsorted | 64 | 256 | 5.3 μs | 5.2 μs | 5.2 μs | 5.2 μs | 5.1 μs | 5.1 μs | 5.3 μs | Binary (5.1 μs) | 1.00x | -| jittered | unsorted | 64 | 4096 | 231.3 μs | 228.1 μs | 228.5 μs | 228.5 μs | 228.2 μs | 228.1 μs | 226.8 μs | Gallop (228.1 μs) | 1.00x | -| jittered | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| jittered | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 280 ns | 300 ns | 300 ns | 270 ns | InterpSearch (280 ns) | 1.07x | -| jittered | unsorted | 1024 | 256 | 8.5 μs | 8.3 μs | 8.2 μs | 8.3 μs | 8.1 μs | 8.1 μs | 8.0 μs | Binary (8.1 μs) | 1.00x | -| jittered | unsorted | 1024 | 4096 | 414.1 μs | 411.7 μs | 413.0 μs | 411.2 μs | 412.2 μs | 412.8 μs | 408.3 μs | InterpSearch (411.2 μs) | 1.00x | -| jittered | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | unsorted | 65536 | 10 | 420 ns | 420 ns | 420 ns | 420 ns | 430 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | -| jittered | unsorted | 65536 | 256 | 14.8 μs | 14.5 μs | 14.4 μs | 14.3 μs | 14.3 μs | 14.2 μs | 17.5 μs | Binary (14.3 μs) | 1.00x | -| jittered | unsorted | 65536 | 4096 | 850.3 μs | 847.7 μs | 848.3 μs | 849.4 μs | 848.5 μs | 848.4 μs | 859.1 μs | Gallop (847.7 μs) | 1.00x | -| random | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 60 ns | 60 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| random | sorted_uniform | 64 | 10 | 190 ns | 230 ns | 190 ns | 380 ns | 200 ns | 240 ns | 180 ns | ExpFromLeft (190 ns) | 1.26x | -| random | sorted_uniform | 64 | 256 | 2.2 μs | 4.0 μs | 3.1 μs | 8.7 μs | 4.3 μs | 2.2 μs | 4.5 μs | Linear (2.2 μs) | 1.02x | -| random | sorted_uniform | 64 | 4096 | 32.2 μs | 56.5 μs | 43.5 μs | 127.6 μs | 68.3 μs | 32.2 μs | 60.0 μs | Linear (32.2 μs) | 1.00x | -| random | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 70 ns | 90 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| random | sorted_uniform | 1024 | 10 | 1.7 μs | 410 ns | 320 ns | 410 ns | 290 ns | 360 ns | 270 ns | Binary (290 ns) | 1.24x | -| random | sorted_uniform | 1024 | 256 | 3.6 μs | 5.3 μs | 3.8 μs | 10.3 μs | 7.1 μs | 3.7 μs | 7.8 μs | Linear (3.6 μs) | 1.02x | -| random | sorted_uniform | 1024 | 4096 | 45.3 μs | 70.2 μs | 55.7 μs | 188.4 μs | 206.8 μs | 44.5 μs | 159.7 μs | Linear (45.3 μs) | 0.98x | -| random | sorted_uniform | 65536 | 1 | 80 ns | 79 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | Gallop (79 ns) | 1.01x | -| random | sorted_uniform | 65536 | 10 | 55.6 μs | 660 ns | 490 ns | 560 ns | 440 ns | 510 ns | 420 ns | Binary (440 ns) | 1.16x | -| random | sorted_uniform | 65536 | 256 | 100.7 μs | 12.5 μs | 9.8 μs | 15.3 μs | 13.9 μs | 10.0 μs | 16.0 μs | ExpFromLeft (9.8 μs) | 1.02x | -| random | sorted_uniform | 65536 | 4096 | 195.2 μs | 251.3 μs | 202.9 μs | 365.8 μs | 491.4 μs | 204.3 μs | 489.8 μs | Linear (195.2 μs) | 1.05x | -| random | sorted_dense_burst | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 50 ns | 50 ns | 50 ns | Binary (50 ns) | 1.00x | -| random | sorted_dense_burst | 64 | 10 | 120 ns | 180 ns | 150 ns | 360 ns | 200 ns | 140 ns | 170 ns | Linear (120 ns) | 1.17x | -| random | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 7.9 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.94x | -| random | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.4 μs | 42.3 μs | 125.3 μs | 68.0 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_dense_burst | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_dense_burst | 1024 | 10 | 140 ns | 190 ns | 160 ns | 480 ns | 310 ns | 170 ns | 270 ns | Linear (140 ns) | 1.21x | -| random | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.1 μs | 6.8 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| random | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 175.6 μs | 106.8 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | -| random | sorted_dense_burst | 65536 | 10 | 140 ns | 200 ns | 170 ns | 670 ns | 450 ns | 160 ns | 420 ns | Linear (140 ns) | 1.14x | -| random | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 15.3 μs | 10.3 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | -| random | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.4 μs | 241.5 μs | 164.5 μs | 30.9 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| random | sorted_near_start | 64 | 10 | 200 ns | 200 ns | 170 ns | 330 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (170 ns) | 1.18x | -| random | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.8 μs | 4.2 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | -| random | sorted_near_start | 64 | 4096 | 31.5 μs | 56.2 μs | 42.9 μs | 122.8 μs | 67.5 μs | 31.4 μs | 60.8 μs | Linear (31.5 μs) | 1.00x | -| random | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_near_start | 1024 | 10 | 730 ns | 280 ns | 210 ns | 410 ns | 290 ns | 240 ns | 310 ns | ExpFromLeft (210 ns) | 1.14x | -| random | sorted_near_start | 1024 | 256 | 4.0 μs | 4.5 μs | 3.4 μs | 10.2 μs | 6.9 μs | 3.9 μs | 6.9 μs | ExpFromLeft (3.4 μs) | 1.13x | -| random | sorted_near_start | 1024 | 4096 | 33.5 μs | 58.4 μs | 44.6 μs | 150.8 μs | 112.3 μs | 33.9 μs | 103.2 μs | Linear (33.5 μs) | 1.01x | -| random | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| random | sorted_near_start | 65536 | 10 | 42.4 μs | 510 ns | 400 ns | 500 ns | 440 ns | 420 ns | 440 ns | ExpFromLeft (400 ns) | 1.05x | -| random | sorted_near_start | 65536 | 256 | 96.4 μs | 7.7 μs | 6.0 μs | 11.5 μs | 11.6 μs | 5.9 μs | 19.8 μs | ExpFromLeft (6.0 μs) | 0.99x | -| random | sorted_near_start | 65536 | 4096 | 160.3 μs | 129.1 μs | 107.3 μs | 254.2 μs | 362.5 μs | 107.7 μs | 288.0 μs | ExpFromLeft (107.3 μs) | 1.00x | -| random | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Linear (50 ns) | 1.20x | -| random | unsorted | 64 | 10 | 180 ns | 190 ns | 190 ns | 190 ns | 189 ns | 200 ns | 180 ns | Linear (180 ns) | 1.11x | -| random | unsorted | 64 | 256 | 7.3 μs | 7.2 μs | 7.2 μs | 7.1 μs | 7.1 μs | 7.1 μs | 6.7 μs | Binary (7.1 μs) | 1.00x | -| random | unsorted | 64 | 4096 | 210.3 μs | 208.5 μs | 207.1 μs | 209.0 μs | 207.2 μs | 207.9 μs | 206.5 μs | ExpFromLeft (207.1 μs) | 1.00x | -| random | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 279 ns | 280 ns | 290 ns | 270 ns | InterpSearch (279 ns) | 1.04x | -| random | unsorted | 1024 | 256 | 8.7 μs | 8.4 μs | 8.4 μs | 8.3 μs | 8.1 μs | 8.3 μs | 8.1 μs | Binary (8.1 μs) | 1.03x | -| random | unsorted | 1024 | 4096 | 385.2 μs | 378.6 μs | 378.0 μs | 377.1 μs | 377.1 μs | 378.6 μs | 377.0 μs | Binary (377.1 μs) | 1.00x | -| random | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| random | unsorted | 65536 | 10 | 430 ns | 430 ns | 420 ns | 450 ns | 440 ns | 450 ns | 430 ns | ExpFromLeft (420 ns) | 1.07x | -| random | unsorted | 65536 | 256 | 15.4 μs | 14.5 μs | 14.3 μs | 14.3 μs | 14.3 μs | 14.3 μs | 18.3 μs | ExpFromLeft (14.3 μs) | 1.00x | -| random | unsorted | 65536 | 4096 | 856.5 μs | 856.0 μs | 857.6 μs | 856.5 μs | 855.9 μs | 856.1 μs | 859.9 μs | Binary (855.9 μs) | 1.00x | -| two_scale | sorted_uniform | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| two_scale | sorted_uniform | 64 | 10 | 170 ns | 220 ns | 170 ns | 410 ns | 210 ns | 200 ns | 180 ns | ExpFromLeft (170 ns) | 1.18x | -| two_scale | sorted_uniform | 64 | 256 | 2.4 μs | 3.9 μs | 3.1 μs | 11.4 μs | 4.5 μs | 2.4 μs | 4.0 μs | Linear (2.4 μs) | 1.01x | -| two_scale | sorted_uniform | 64 | 4096 | 31.5 μs | 55.7 μs | 43.0 μs | 167.0 μs | 68.9 μs | 31.5 μs | 59.3 μs | Linear (31.5 μs) | 1.00x | -| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_uniform | 1024 | 10 | 570 ns | 360 ns | 290 ns | 620 ns | 300 ns | 330 ns | 270 ns | ExpFromLeft (290 ns) | 1.14x | -| two_scale | sorted_uniform | 1024 | 256 | 2.9 μs | 4.6 μs | 3.2 μs | 15.9 μs | 7.2 μs | 2.9 μs | 8.0 μs | Linear (2.9 μs) | 1.00x | -| two_scale | sorted_uniform | 1024 | 4096 | 40.0 μs | 63.7 μs | 50.5 μs | 290.0 μs | 159.9 μs | 40.1 μs | 110.2 μs | Linear (40.0 μs) | 1.00x | -| two_scale | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_uniform | 65536 | 10 | 45.8 μs | 630 ns | 470 ns | 910 ns | 430 ns | 500 ns | 410 ns | Binary (430 ns) | 1.16x | -| two_scale | sorted_uniform | 65536 | 256 | 60.2 μs | 11.5 μs | 8.4 μs | 27.5 μs | 14.1 μs | 8.5 μs | 16.6 μs | ExpFromLeft (8.4 μs) | 1.01x | -| two_scale | sorted_uniform | 65536 | 4096 | 191.1 μs | 203.3 μs | 161.6 μs | 684.5 μs | 442.5 μs | 162.1 μs | 420.6 μs | ExpFromLeft (161.6 μs) | 1.00x | -| two_scale | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| two_scale | sorted_dense_burst | 64 | 10 | 130 ns | 180 ns | 150 ns | 480 ns | 200 ns | 160 ns | 160 ns | Linear (130 ns) | 1.23x | -| two_scale | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.5 μs | 4.3 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.00x | -| two_scale | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.6 μs | 42.3 μs | 180.3 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 1024 | 1 | 70 ns | 70 ns | 80 ns | 100 ns | 70 ns | 60 ns | 60 ns | Binary (70 ns) | 0.86x | -| two_scale | sorted_dense_burst | 1024 | 10 | 140 ns | 220 ns | 180 ns | 720 ns | 310 ns | 150 ns | 280 ns | Linear (140 ns) | 1.07x | -| two_scale | sorted_dense_burst | 1024 | 256 | 2.2 μs | 4.3 μs | 3.1 μs | 17.2 μs | 6.7 μs | 2.0 μs | 5.9 μs | Linear (2.2 μs) | 0.92x | -| two_scale | sorted_dense_burst | 1024 | 4096 | 33.8 μs | 67.8 μs | 49.2 μs | 274.8 μs | 107.4 μs | 30.9 μs | 95.7 μs | Linear (33.8 μs) | 0.91x | -| two_scale | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_dense_burst | 65536 | 10 | 170 ns | 240 ns | 199 ns | 1.0 μs | 450 ns | 220 ns | 420 ns | Linear (170 ns) | 1.29x | -| two_scale | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.3 μs | 10.3 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.00x | -| two_scale | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.3 μs | 391.1 μs | 164.5 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_near_start | 64 | 1 | 50 ns | 60 ns | 60 ns | 70 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| two_scale | sorted_near_start | 64 | 10 | 190 ns | 200 ns | 170 ns | 330 ns | 200 ns | 200 ns | 180 ns | ExpFromLeft (170 ns) | 1.18x | -| two_scale | sorted_near_start | 64 | 256 | 2.2 μs | 3.6 μs | 2.8 μs | 7.1 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.2 μs) | 0.96x | -| two_scale | sorted_near_start | 64 | 4096 | 31.5 μs | 56.1 μs | 42.9 μs | 113.5 μs | 67.6 μs | 31.5 μs | 60.1 μs | Linear (31.5 μs) | 1.00x | -| two_scale | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 89 ns | 60 ns | 70 ns | 60 ns | Binary (60 ns) | 1.17x | -| two_scale | sorted_near_start | 1024 | 10 | 1.3 μs | 280 ns | 240 ns | 460 ns | 290 ns | 270 ns | 280 ns | ExpFromLeft (240 ns) | 1.12x | -| two_scale | sorted_near_start | 1024 | 256 | 3.7 μs | 4.4 μs | 3.2 μs | 11.5 μs | 6.8 μs | 3.7 μs | 6.8 μs | ExpFromLeft (3.2 μs) | 1.15x | -| two_scale | sorted_near_start | 1024 | 4096 | 34.1 μs | 57.8 μs | 44.0 μs | 179.8 μs | 110.1 μs | 33.7 μs | 102.6 μs | Linear (34.1 μs) | 0.99x | -| two_scale | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_near_start | 65536 | 10 | 61.9 μs | 540 ns | 410 ns | 790 ns | 440 ns | 440 ns | 450 ns | ExpFromLeft (410 ns) | 1.07x | -| two_scale | sorted_near_start | 65536 | 256 | 96.1 μs | 7.8 μs | 6.0 μs | 20.6 μs | 11.9 μs | 5.8 μs | 19.0 μs | ExpFromLeft (6.0 μs) | 0.96x | -| two_scale | sorted_near_start | 65536 | 4096 | 162.5 μs | 121.7 μs | 98.1 μs | 479.2 μs | 359.9 μs | 102.8 μs | 286.0 μs | ExpFromLeft (98.1 μs) | 1.05x | -| two_scale | unsorted | 64 | 1 | 50 ns | 60 ns | 60 ns | 80 ns | 50 ns | 60 ns | 50 ns | Binary (50 ns) | 1.20x | -| two_scale | unsorted | 64 | 10 | 180 ns | 190 ns | 180 ns | 190 ns | 200 ns | 210 ns | 190 ns | ExpFromLeft (180 ns) | 1.17x | -| two_scale | unsorted | 64 | 256 | 6.3 μs | 6.2 μs | 6.3 μs | 6.2 μs | 6.2 μs | 6.3 μs | 6.0 μs | Gallop (6.2 μs) | 1.03x | -| two_scale | unsorted | 64 | 4096 | 181.2 μs | 181.8 μs | 182.2 μs | 179.6 μs | 178.3 μs | 177.1 μs | 173.5 μs | Binary (178.3 μs) | 0.99x | -| two_scale | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 90 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| two_scale | unsorted | 1024 | 10 | 280 ns | 280 ns | 280 ns | 270 ns | 290 ns | 290 ns | 270 ns | InterpSearch (270 ns) | 1.07x | -| two_scale | unsorted | 1024 | 256 | 10.1 μs | 10.0 μs | 9.9 μs | 9.9 μs | 9.6 μs | 9.7 μs | 9.4 μs | Binary (9.6 μs) | 1.02x | -| two_scale | unsorted | 1024 | 4096 | 345.9 μs | 344.6 μs | 343.2 μs | 339.2 μs | 337.2 μs | 339.0 μs | 340.1 μs | Binary (337.2 μs) | 1.01x | -| two_scale | unsorted | 65536 | 1 | 80 ns | 80 ns | 70 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| two_scale | unsorted | 65536 | 10 | 420 ns | 420 ns | 430 ns | 420 ns | 440 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | -| two_scale | unsorted | 65536 | 256 | 16.0 μs | 15.8 μs | 15.8 μs | 15.7 μs | 15.6 μs | 15.7 μs | 18.8 μs | Binary (15.6 μs) | 1.00x | -| two_scale | unsorted | 65536 | 4096 | 751.6 μs | 752.4 μs | 752.7 μs | 750.5 μs | 751.6 μs | 752.3 μs | 756.8 μs | InterpSearch (750.5 μs) | 1.00x | - -**Auto verdict over 240 cells**: 221 within 20% of best, 14 worse than 20% slowdown, 5 effectively-faster-than-best. diff --git a/bench/results_focused.md b/bench/results_focused.md deleted file mode 100644 index f5240ae..0000000 --- a/bench/results_focused.md +++ /dev/null @@ -1,571 +0,0 @@ - -## Spacing variety (n=4096, m=512, sorted_uniform) - -| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | -|---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 4096 | 512 | 10.4 μs | 12.5 μs | 9.2 μs | 19.1 μs | 23.5 μs | 9.3 μs | 24.6 μs | ExpFromLeft (9.2 μs) | 1.01x | -| log | sorted_uniform | 4096 | 512 | 10.2 μs | 10.5 μs | 7.4 μs | 39.8 μs | 21.9 μs | 8.0 μs | 23.9 μs | ExpFromLeft (7.4 μs) | 1.07x | -| jittered | sorted_uniform | 4096 | 512 | 10.2 μs | 12.2 μs | 9.3 μs | 18.7 μs | 25.8 μs | 9.2 μs | 29.3 μs | ExpFromLeft (9.3 μs) | 0.99x | -| random | sorted_uniform | 4096 | 512 | 10.0 μs | 12.1 μs | 9.0 μs | 22.8 μs | 24.9 μs | 9.4 μs | 27.9 μs | ExpFromLeft (9.0 μs) | 1.05x | -| two_scale | sorted_uniform | 4096 | 512 | 7.1 μs | 10.4 μs | 7.6 μs | 42.4 μs | 23.1 μs | 8.2 μs | 26.4 μs | Linear (7.1 μs) | 1.16x | -| power2 | sorted_uniform | 4096 | 512 | 10.1 μs | 12.0 μs | 9.1 μs | 39.0 μs | 25.8 μs | 9.4 μs | 28.9 μs | ExpFromLeft (9.1 μs) | 1.04x | -| sqrt | sorted_uniform | 4096 | 512 | 10.1 μs | 12.1 μs | 9.1 μs | 36.3 μs | 23.3 μs | 9.5 μs | 27.0 μs | ExpFromLeft (9.1 μs) | 1.04x | -| plateau | sorted_uniform | 4096 | 512 | 6.0 μs | 7.0 μs | 5.4 μs | 40.0 μs | 15.8 μs | 5.6 μs | 14.6 μs | ExpFromLeft (5.4 μs) | 1.04x | -| bimodal | sorted_uniform | 4096 | 512 | 11.3 μs | 8.8 μs | 6.8 μs | 42.1 μs | 16.1 μs | 7.0 μs | 14.7 μs | ExpFromLeft (6.8 μs) | 1.02x | -| near_linear | sorted_uniform | 4096 | 512 | 10.4 μs | 12.6 μs | 9.4 μs | 18.7 μs | 26.0 μs | 9.3 μs | 29.6 μs | ExpFromLeft (9.4 μs) | 0.99x | - -**Auto verdict over 10 cells**: 10 within 20% of best, 0 worse than 20% slowdown, 0 effectively-faster-than-best. - -## Query patterns (n=4096, m=512, uniform) - -| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | -|---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 4096 | 512 | 10.3 μs | 12.4 μs | 9.2 μs | 19.2 μs | 24.6 μs | 9.2 μs | 25.4 μs | ExpFromLeft (9.2 μs) | 1.00x | -| uniform | sorted_dense_burst | 4096 | 512 | 3.9 μs | 6.9 μs | 5.3 μs | 13.8 μs | 15.8 μs | 3.9 μs | 14.3 μs | Linear (3.9 μs) | 1.00x | -| uniform | sorted_near_start | 4096 | 512 | 10.7 μs | 9.5 μs | 6.7 μs | 18.7 μs | 17.3 μs | 6.9 μs | 20.6 μs | ExpFromLeft (6.7 μs) | 1.04x | -| uniform | sorted_arithmetic | 4096 | 512 | 10.6 μs | 13.5 μs | 11.6 μs | 14.1 μs | 23.4 μs | 15.2 μs | 28.7 μs | Linear (10.6 μs) | 1.43x | -| uniform | sorted_geometric | 4096 | 512 | 11.5 μs | 13.5 μs | 9.8 μs | 17.7 μs | 27.1 μs | 10.0 μs | 28.5 μs | ExpFromLeft (9.8 μs) | 1.02x | -| uniform | sorted_bimodal | 4096 | 512 | 9.2 μs | 9.1 μs | 6.2 μs | 18.6 μs | 20.8 μs | 6.6 μs | 25.1 μs | ExpFromLeft (6.2 μs) | 1.06x | -| uniform | sorted_repeated | 4096 | 512 | 3.9 μs | 6.9 μs | 5.0 μs | 13.1 μs | 15.8 μs | 3.9 μs | 14.3 μs | Linear (3.9 μs) | 1.01x | -| uniform | unsorted | 4096 | 512 | 34.5 μs | 32.5 μs | 31.9 μs | 31.1 μs | 31.1 μs | 31.3 μs | 32.6 μs | Binary (31.1 μs) | 1.01x | - -**Auto verdict over 8 cells**: 7 within 20% of best, 1 worse than 20% slowdown, 0 effectively-faster-than-best. - -## n/m crossover (uniform, sorted_uniform) - -| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | -|---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_uniform | 16 | 4 | 90 ns | 100 ns | 90 ns | 160 ns | 90 ns | 110 ns | 80 ns | ExpFromLeft (90 ns) | 1.22x | -| uniform | sorted_uniform | 16 | 16 | 200 ns | 290 ns | 210 ns | 490 ns | 220 ns | 220 ns | 190 ns | Linear (200 ns) | 1.10x | -| uniform | sorted_uniform | 16 | 64 | 550 ns | 960 ns | 730 ns | 1.9 μs | 960 ns | 580 ns | 689 ns | Linear (550 ns) | 1.05x | -| uniform | sorted_uniform | 16 | 256 | 2.3 μs | 3.7 μs | 3.0 μs | 7.7 μs | 3.4 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 0.99x | -| uniform | sorted_uniform | 16 | 1024 | 7.9 μs | 13.8 μs | 11.2 μs | 28.5 μs | 12.3 μs | 7.9 μs | 10.4 μs | Linear (7.9 μs) | 1.00x | -| uniform | sorted_uniform | 16 | 4096 | 30.3 μs | 54.3 μs | 43.9 μs | 110.9 μs | 48.1 μs | 30.3 μs | 40.8 μs | Linear (30.3 μs) | 1.00x | -| uniform | sorted_uniform | 16 | 16384 | 120.0 μs | 217.0 μs | 174.8 μs | 441.5 μs | 190.7 μs | 120.0 μs | 162.0 μs | Linear (120.0 μs) | 1.00x | -| uniform | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 50 ns | 50 ns | 50 ns | Binary (50 ns) | 1.00x | -| uniform | sorted_uniform | 64 | 4 | 140 ns | 140 ns | 130 ns | 160 ns | 100 ns | 150 ns | 100 ns | Binary (100 ns) | 1.50x | -| uniform | sorted_uniform | 64 | 16 | 240 ns | 350 ns | 270 ns | 490 ns | 330 ns | 280 ns | 260 ns | Linear (240 ns) | 1.17x | -| uniform | sorted_uniform | 64 | 64 | 620 ns | 1.1 μs | 790 ns | 2.2 μs | 1.4 μs | 640 ns | 960 ns | Linear (620 ns) | 1.03x | -| uniform | sorted_uniform | 64 | 256 | 2.2 μs | 4.2 μs | 3.2 μs | 9.0 μs | 5.3 μs | 2.2 μs | 3.7 μs | Linear (2.2 μs) | 1.01x | -| uniform | sorted_uniform | 64 | 1024 | 9.0 μs | 14.7 μs | 12.0 μs | 30.9 μs | 17.7 μs | 8.9 μs | 15.9 μs | Linear (9.0 μs) | 0.99x | -| uniform | sorted_uniform | 64 | 4096 | 31.4 μs | 55.6 μs | 44.7 μs | 113.4 μs | 67.3 μs | 31.4 μs | 60.1 μs | Linear (31.4 μs) | 1.00x | -| uniform | sorted_uniform | 64 | 16384 | 121.1 μs | 219.1 μs | 175.7 μs | 445.4 μs | 266.2 μs | 121.2 μs | 237.2 μs | Linear (121.1 μs) | 1.00x | -| uniform | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_uniform | 256 | 4 | 350 ns | 160 ns | 150 ns | 160 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | -| uniform | sorted_uniform | 256 | 16 | 520 ns | 460 ns | 380 ns | 500 ns | 380 ns | 400 ns | 330 ns | ExpFromLeft (380 ns) | 1.05x | -| uniform | sorted_uniform | 256 | 64 | 890 ns | 1.4 μs | 1.0 μs | 2.1 μs | 1.5 μs | 930 ns | 1.2 μs | Linear (890 ns) | 1.04x | -| uniform | sorted_uniform | 256 | 256 | 2.4 μs | 4.1 μs | 3.0 μs | 9.1 μs | 7.3 μs | 2.4 μs | 5.1 μs | Linear (2.4 μs) | 1.00x | -| uniform | sorted_uniform | 256 | 1024 | 9.7 μs | 17.8 μs | 14.0 μs | 37.2 μs | 26.9 μs | 9.8 μs | 24.7 μs | Linear (9.7 μs) | 1.01x | -| uniform | sorted_uniform | 256 | 4096 | 35.7 μs | 58.9 μs | 48.1 μs | 123.8 μs | 91.6 μs | 35.7 μs | 121.0 μs | Linear (35.7 μs) | 1.00x | -| uniform | sorted_uniform | 256 | 16384 | 125.5 μs | 222.7 μs | 178.9 μs | 454.2 μs | 347.4 μs | 125.5 μs | 354.1 μs | Linear (125.5 μs) | 1.00x | -| uniform | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_uniform | 1024 | 4 | 1.1 μs | 190 ns | 170 ns | 150 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| uniform | sorted_uniform | 1024 | 16 | 1.7 μs | 570 ns | 480 ns | 510 ns | 440 ns | 560 ns | 410 ns | Binary (440 ns) | 1.27x | -| uniform | sorted_uniform | 1024 | 64 | 2.0 μs | 1.8 μs | 1.4 μs | 2.0 μs | 1.7 μs | 2.2 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.55x | -| uniform | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.9 μs | 8.9 μs | 8.1 μs | 3.5 μs | 7.2 μs | Linear (3.6 μs) | 0.96x | -| uniform | sorted_uniform | 1024 | 1024 | 9.7 μs | 17.8 μs | 12.8 μs | 39.5 μs | 58.0 μs | 9.7 μs | 69.9 μs | Linear (9.7 μs) | 0.99x | -| uniform | sorted_uniform | 1024 | 4096 | 46.8 μs | 73.0 μs | 58.8 μs | 151.8 μs | 199.6 μs | 46.8 μs | 226.4 μs | Linear (46.8 μs) | 1.00x | -| uniform | sorted_uniform | 1024 | 16384 | 143.2 μs | 236.2 μs | 191.7 μs | 494.1 μs | 515.7 μs | 142.8 μs | 555.3 μs | Linear (143.2 μs) | 1.00x | -| uniform | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_uniform | 4096 | 4 | 2.3 μs | 220 ns | 180 ns | 160 ns | 160 ns | 200 ns | 140 ns | InterpSearch (160 ns) | 1.25x | -| uniform | sorted_uniform | 4096 | 16 | 6.0 μs | 750 ns | 560 ns | 489 ns | 520 ns | 539 ns | 490 ns | InterpSearch (489 ns) | 1.10x | -| uniform | sorted_uniform | 4096 | 64 | 7.3 μs | 2.3 μs | 1.8 μs | 2.0 μs | 2.0 μs | 2.1 μs | 1.8 μs | ExpFromLeft (1.8 μs) | 1.21x | -| uniform | sorted_uniform | 4096 | 256 | 8.4 μs | 7.2 μs | 5.4 μs | 9.1 μs | 10.2 μs | 9.6 μs | 9.2 μs | ExpFromLeft (5.4 μs) | 1.77x | -| uniform | sorted_uniform | 4096 | 1024 | 15.1 μs | 23.2 μs | 17.6 μs | 39.0 μs | 94.1 μs | 14.9 μs | 90.5 μs | Linear (15.1 μs) | 0.99x | -| uniform | sorted_uniform | 4096 | 4096 | 62.6 μs | 95.3 μs | 74.1 μs | 163.1 μs | 302.0 μs | 62.5 μs | 296.1 μs | Linear (62.6 μs) | 1.00x | -| uniform | sorted_uniform | 4096 | 16384 | 199.8 μs | 293.6 μs | 242.1 μs | 606.7 μs | 762.5 μs | 200.2 μs | 863.9 μs | Linear (199.8 μs) | 1.00x | -| uniform | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_uniform | 16384 | 4 | 17.8 μs | 280 ns | 230 ns | 160 ns | 180 ns | 200 ns | 160 ns | InterpSearch (160 ns) | 1.25x | -| uniform | sorted_uniform | 16384 | 16 | 19.1 μs | 860 ns | 650 ns | 540 ns | 600 ns | 590 ns | 560 ns | InterpSearch (540 ns) | 1.09x | -| uniform | sorted_uniform | 16384 | 64 | 24.8 μs | 2.9 μs | 2.2 μs | 2.0 μs | 2.3 μs | 2.1 μs | 2.2 μs | InterpSearch (2.0 μs) | 1.05x | -| uniform | sorted_uniform | 16384 | 256 | 29.0 μs | 9.8 μs | 7.3 μs | 9.3 μs | 12.0 μs | 9.7 μs | 11.0 μs | ExpFromLeft (7.3 μs) | 1.34x | -| uniform | sorted_uniform | 16384 | 1024 | 38.5 μs | 36.7 μs | 27.6 μs | 40.3 μs | 127.3 μs | 41.8 μs | 121.4 μs | ExpFromLeft (27.6 μs) | 1.52x | -| uniform | sorted_uniform | 16384 | 4096 | 108.9 μs | 161.1 μs | 123.0 μs | 162.8 μs | 392.7 μs | 106.8 μs | 392.4 μs | Linear (108.9 μs) | 0.98x | -| uniform | sorted_uniform | 16384 | 16384 | 360.3 μs | 452.0 μs | 375.1 μs | 653.1 μs | 1.11 ms | 360.9 μs | 1.26 ms | Linear (360.3 μs) | 1.00x | -| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_uniform | 65536 | 4 | 21.6 μs | 270 ns | 220 ns | 150 ns | 200 ns | 200 ns | 180 ns | InterpSearch (150 ns) | 1.33x | -| uniform | sorted_uniform | 65536 | 16 | 83.3 μs | 1.0 μs | 770 ns | 490 ns | 700 ns | 540 ns | 650 ns | InterpSearch (490 ns) | 1.10x | -| uniform | sorted_uniform | 65536 | 64 | 94.4 μs | 3.6 μs | 2.7 μs | 2.2 μs | 2.9 μs | 2.3 μs | 2.6 μs | InterpSearch (2.2 μs) | 1.06x | -| uniform | sorted_uniform | 65536 | 256 | 100.7 μs | 12.6 μs | 9.9 μs | 9.2 μs | 16.1 μs | 9.7 μs | 13.6 μs | InterpSearch (9.2 μs) | 1.05x | -| uniform | sorted_uniform | 65536 | 1024 | 119.4 μs | 61.5 μs | 43.2 μs | 41.4 μs | 158.9 μs | 42.9 μs | 156.8 μs | InterpSearch (41.4 μs) | 1.04x | -| uniform | sorted_uniform | 65536 | 4096 | 190.9 μs | 257.0 μs | 203.0 μs | 166.4 μs | 494.8 μs | 173.3 μs | 488.9 μs | InterpSearch (166.4 μs) | 1.04x | -| uniform | sorted_uniform | 65536 | 16384 | 518.5 μs | 715.7 μs | 555.9 μs | 656.8 μs | 1.46 ms | 515.4 μs | 1.58 ms | Linear (518.5 μs) | 0.99x | -| uniform | sorted_uniform | 262144 | 1 | 90 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_uniform | 262144 | 4 | 153.4 μs | 330 ns | 270 ns | 170 ns | 220 ns | 200 ns | 200 ns | InterpSearch (170 ns) | 1.18x | -| uniform | sorted_uniform | 262144 | 16 | 332.3 μs | 1.2 μs | 850 ns | 540 ns | 810 ns | 590 ns | 770 ns | InterpSearch (540 ns) | 1.09x | -| uniform | sorted_uniform | 262144 | 64 | 360.7 μs | 4.2 μs | 3.1 μs | 2.2 μs | 3.5 μs | 2.3 μs | 3.3 μs | InterpSearch (2.2 μs) | 1.04x | -| uniform | sorted_uniform | 262144 | 256 | 380.8 μs | 14.6 μs | 11.2 μs | 9.8 μs | 19.3 μs | 10.3 μs | 19.9 μs | InterpSearch (9.8 μs) | 1.05x | -| uniform | sorted_uniform | 262144 | 1024 | 406.1 μs | 132.3 μs | 98.0 μs | 43.1 μs | 207.8 μs | 44.8 μs | 207.6 μs | InterpSearch (43.1 μs) | 1.04x | -| uniform | sorted_uniform | 262144 | 4096 | 481.7 μs | 388.1 μs | 330.2 μs | 177.7 μs | 646.4 μs | 183.7 μs | 657.6 μs | InterpSearch (177.7 μs) | 1.03x | -| uniform | sorted_uniform | 262144 | 16384 | 812.8 μs | 1.07 ms | 889.5 μs | 674.6 μs | 1.84 ms | 697.9 μs | 1.97 ms | InterpSearch (674.6 μs) | 1.03x | - -**Auto verdict over 64 cells**: 51 within 20% of best, 13 worse than 20% slowdown, 0 effectively-faster-than-best. - -### Super-sparse cases (small m on large n) - -## Super sparse - -| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | -|---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 1024 | 1 | 60 ns | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| uniform | sorted_uniform | 1024 | 4 | 500 ns | 160 ns | 140 ns | 150 ns | 140 ns | 200 ns | 130 ns | ExpFromLeft (140 ns) | 1.43x | -| uniform | sorted_uniform | 1024 | 16 | 1.6 μs | 570 ns | 470 ns | 500 ns | 450 ns | 480 ns | 409 ns | Binary (450 ns) | 1.07x | -| uniform | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_uniform | 16384 | 4 | 8.9 μs | 240 ns | 190 ns | 150 ns | 170 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | -| uniform | sorted_uniform | 16384 | 16 | 22.9 μs | 880 ns | 650 ns | 520 ns | 610 ns | 590 ns | 560 ns | InterpSearch (520 ns) | 1.13x | -| uniform | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_uniform | 262144 | 4 | 251.7 μs | 350 ns | 260 ns | 150 ns | 210 ns | 200 ns | 200 ns | InterpSearch (150 ns) | 1.33x | -| uniform | sorted_uniform | 262144 | 16 | 369.6 μs | 1.2 μs | 890 ns | 470 ns | 810 ns | 550 ns | 780 ns | InterpSearch (470 ns) | 1.17x | -| uniform | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | -| uniform | unsorted | 1024 | 4 | 130 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | Linear (130 ns) | 1.15x | -| uniform | unsorted | 1024 | 16 | 450 ns | 450 ns | 450 ns | 450 ns | 460 ns | 460 ns | 450 ns | InterpSearch (450 ns) | 1.02x | -| uniform | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 60 ns | 80 ns | 70 ns | 70 ns | InterpSearch (60 ns) | 1.17x | -| uniform | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 180 ns | 180 ns | 190 ns | 170 ns | Gallop (170 ns) | 1.12x | -| uniform | unsorted | 16384 | 16 | 560 ns | 570 ns | 570 ns | 570 ns | 570 ns | 580 ns | 550 ns | Linear (560 ns) | 1.04x | -| uniform | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 210 ns | 220 ns | 220 ns | 200 ns | InterpSearch (210 ns) | 1.05x | -| uniform | unsorted | 262144 | 16 | 760 ns | 760 ns | 760 ns | 770 ns | 760 ns | 760 ns | 740 ns | ExpFromLeft (760 ns) | 1.00x | -| log | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | -| log | sorted_uniform | 1024 | 4 | 200 ns | 150 ns | 130 ns | 300 ns | 140 ns | 160 ns | 130 ns | ExpFromLeft (130 ns) | 1.23x | -| log | sorted_uniform | 1024 | 16 | 1.2 μs | 490 ns | 379 ns | 980 ns | 450 ns | 400 ns | 420 ns | ExpFromLeft (379 ns) | 1.06x | -| log | sorted_uniform | 16384 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_uniform | 16384 | 4 | 2.2 μs | 210 ns | 170 ns | 350 ns | 180 ns | 200 ns | 160 ns | ExpFromLeft (170 ns) | 1.18x | -| log | sorted_uniform | 16384 | 16 | 14.5 μs | 770 ns | 570 ns | 1.3 μs | 600 ns | 590 ns | 600 ns | ExpFromLeft (570 ns) | 1.04x | -| log | sorted_uniform | 262144 | 1 | 90 ns | 90 ns | 80 ns | 140 ns | 80 ns | 90 ns | 80 ns | ExpFromLeft (80 ns) | 1.12x | -| log | sorted_uniform | 262144 | 4 | 321.5 μs | 340 ns | 260 ns | 420 ns | 220 ns | 300 ns | 200 ns | Binary (220 ns) | 1.36x | -| log | sorted_uniform | 262144 | 16 | 176.3 μs | 1.1 μs | 790 ns | 1.7 μs | 810 ns | 800 ns | 820 ns | ExpFromLeft (790 ns) | 1.01x | -| log | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 100 ns | 60 ns | 70 ns | 60 ns | Binary (60 ns) | 1.17x | -| log | unsorted | 1024 | 4 | 130 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | Linear (130 ns) | 1.15x | -| log | unsorted | 1024 | 16 | 410 ns | 420 ns | 410 ns | 420 ns | 420 ns | 440 ns | 420 ns | ExpFromLeft (410 ns) | 1.07x | -| log | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 120 ns | 70 ns | 70 ns | 60 ns | Binary (70 ns) | 1.00x | -| log | unsorted | 16384 | 4 | 170 ns | 180 ns | 170 ns | 170 ns | 170 ns | 180 ns | 160 ns | InterpSearch (170 ns) | 1.06x | -| log | unsorted | 16384 | 16 | 620 ns | 630 ns | 620 ns | 620 ns | 630 ns | 630 ns | 610 ns | InterpSearch (620 ns) | 1.02x | -| log | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 140 ns | 90 ns | 80 ns | 80 ns | Gallop (80 ns) | 1.00x | -| log | unsorted | 262144 | 4 | 210 ns | 220 ns | 210 ns | 210 ns | 210 ns | 220 ns | 200 ns | InterpSearch (210 ns) | 1.05x | -| log | unsorted | 262144 | 16 | 770 ns | 770 ns | 780 ns | 780 ns | 780 ns | 800 ns | 710 ns | Gallop (770 ns) | 1.04x | -| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| jittered | sorted_uniform | 1024 | 4 | 920 ns | 190 ns | 170 ns | 150 ns | 150 ns | 200 ns | 130 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_uniform | 1024 | 16 | 1.9 μs | 610 ns | 470 ns | 470 ns | 460 ns | 559 ns | 420 ns | Binary (460 ns) | 1.22x | -| jittered | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 60 ns | 80 ns | 70 ns | 70 ns | InterpSearch (60 ns) | 1.17x | -| jittered | sorted_uniform | 16384 | 4 | 18.7 μs | 250 ns | 200 ns | 150 ns | 170 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_uniform | 16384 | 16 | 21.2 μs | 870 ns | 660 ns | 460 ns | 590 ns | 540 ns | 550 ns | InterpSearch (460 ns) | 1.17x | -| jittered | sorted_uniform | 262144 | 1 | 90 ns | 80 ns | 90 ns | 70 ns | 90 ns | 80 ns | 80 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_uniform | 262144 | 4 | 316.0 μs | 310 ns | 240 ns | 150 ns | 220 ns | 200 ns | 210 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_uniform | 262144 | 16 | 340.2 μs | 1.2 μs | 870 ns | 500 ns | 800 ns | 580 ns | 790 ns | InterpSearch (500 ns) | 1.16x | -| jittered | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | -| jittered | unsorted | 1024 | 4 | 130 ns | 140 ns | 130 ns | 140 ns | 140 ns | 140 ns | 130 ns | ExpFromLeft (130 ns) | 1.08x | -| jittered | unsorted | 1024 | 16 | 420 ns | 429 ns | 420 ns | 420 ns | 420 ns | 430 ns | 400 ns | InterpSearch (420 ns) | 1.02x | -| jittered | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | unsorted | 16384 | 4 | 170 ns | 170 ns | 180 ns | 180 ns | 170 ns | 190 ns | 170 ns | Binary (170 ns) | 1.12x | -| jittered | unsorted | 16384 | 16 | 570 ns | 570 ns | 570 ns | 570 ns | 570 ns | 580 ns | 550 ns | InterpSearch (570 ns) | 1.02x | -| jittered | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 80 ns | InterpSearch (60 ns) | 1.33x | -| jittered | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 210 ns | 220 ns | 220 ns | 210 ns | InterpSearch (210 ns) | 1.05x | -| jittered | unsorted | 262144 | 16 | 780 ns | 850 ns | 790 ns | 800 ns | 800 ns | 810 ns | 780 ns | Linear (780 ns) | 1.04x | -| random | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_uniform | 1024 | 4 | 930 ns | 180 ns | 160 ns | 200 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | -| random | sorted_uniform | 1024 | 16 | 1.8 μs | 600 ns | 470 ns | 640 ns | 460 ns | 490 ns | 420 ns | Binary (460 ns) | 1.07x | -| random | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_uniform | 16384 | 4 | 16.4 μs | 250 ns | 190 ns | 210 ns | 180 ns | 230 ns | 170 ns | Binary (180 ns) | 1.28x | -| random | sorted_uniform | 16384 | 16 | 19.8 μs | 890 ns | 670 ns | 700 ns | 600 ns | 680 ns | 600 ns | Binary (600 ns) | 1.13x | -| random | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 90 ns | 80 ns | ExpFromLeft (80 ns) | 1.12x | -| random | sorted_uniform | 262144 | 4 | 226.2 μs | 340 ns | 270 ns | 250 ns | 220 ns | 300 ns | 210 ns | Binary (220 ns) | 1.36x | -| random | sorted_uniform | 262144 | 16 | 275.5 μs | 1.2 μs | 850 ns | 860 ns | 830 ns | 940 ns | 780 ns | Binary (830 ns) | 1.13x | -| random | unsorted | 1024 | 1 | 60 ns | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| random | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 150 ns | 140 ns | 150 ns | 130 ns | ExpFromLeft (140 ns) | 1.07x | -| random | unsorted | 1024 | 16 | 410 ns | 410 ns | 420 ns | 420 ns | 420 ns | 430 ns | 410 ns | Gallop (410 ns) | 1.05x | -| random | unsorted | 16384 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| random | unsorted | 16384 | 4 | 170 ns | 170 ns | 170 ns | 170 ns | 180 ns | 190 ns | 170 ns | InterpSearch (170 ns) | 1.12x | -| random | unsorted | 16384 | 16 | 580 ns | 580 ns | 580 ns | 580 ns | 570 ns | 590 ns | 560 ns | Binary (570 ns) | 1.04x | -| random | unsorted | 262144 | 1 | 80 ns | 80 ns | 80 ns | 100 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| random | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 210 ns | 210 ns | 220 ns | 210 ns | InterpSearch (210 ns) | 1.05x | -| random | unsorted | 262144 | 16 | 810 ns | 820 ns | 800 ns | 810 ns | 810 ns | 820 ns | 800 ns | ExpFromLeft (800 ns) | 1.02x | -| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| two_scale | sorted_uniform | 1024 | 4 | 570 ns | 170 ns | 140 ns | 270 ns | 150 ns | 170 ns | 130 ns | ExpFromLeft (140 ns) | 1.21x | -| two_scale | sorted_uniform | 1024 | 16 | 1.0 μs | 540 ns | 420 ns | 990 ns | 450 ns | 450 ns | 410 ns | ExpFromLeft (420 ns) | 1.07x | -| two_scale | sorted_uniform | 16384 | 1 | 70 ns | 80 ns | 70 ns | 120 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| two_scale | sorted_uniform | 16384 | 4 | 9.5 μs | 250 ns | 190 ns | 360 ns | 180 ns | 220 ns | 160 ns | Binary (180 ns) | 1.22x | -| two_scale | sorted_uniform | 16384 | 16 | 9.9 μs | 780 ns | 580 ns | 1.4 μs | 609 ns | 630 ns | 570 ns | ExpFromLeft (580 ns) | 1.09x | -| two_scale | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 150 ns | 80 ns | 90 ns | 70 ns | ExpFromLeft (80 ns) | 1.12x | -| two_scale | sorted_uniform | 262144 | 4 | 153.9 μs | 330 ns | 250 ns | 440 ns | 220 ns | 290 ns | 210 ns | Binary (220 ns) | 1.32x | -| two_scale | sorted_uniform | 262144 | 16 | 170.9 μs | 1.1 μs | 810 ns | 1.7 μs | 820 ns | 840 ns | 780 ns | ExpFromLeft (810 ns) | 1.04x | -| two_scale | unsorted | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | -| two_scale | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 120 ns | InterpSearch (140 ns) | 1.07x | -| two_scale | unsorted | 1024 | 16 | 420 ns | 430 ns | 430 ns | 420 ns | 430 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | -| two_scale | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| two_scale | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 170 ns | 180 ns | 190 ns | 170 ns | InterpSearch (170 ns) | 1.12x | -| two_scale | unsorted | 16384 | 16 | 579 ns | 580 ns | 580 ns | 580 ns | 590 ns | 590 ns | 580 ns | Linear (579 ns) | 1.02x | -| two_scale | unsorted | 262144 | 1 | 90 ns | 80 ns | 90 ns | 120 ns | 80 ns | 90 ns | 80 ns | Binary (80 ns) | 1.12x | -| two_scale | unsorted | 262144 | 4 | 220 ns | 210 ns | 220 ns | 210 ns | 220 ns | 230 ns | 200 ns | InterpSearch (210 ns) | 1.10x | -| two_scale | unsorted | 262144 | 16 | 790 ns | 780 ns | 800 ns | 790 ns | 790 ns | 790 ns | 780 ns | Gallop (780 ns) | 1.01x | -| power2 | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | -| power2 | sorted_uniform | 1024 | 4 | 1.1 μs | 190 ns | 160 ns | 260 ns | 150 ns | 190 ns | 130 ns | Binary (150 ns) | 1.27x | -| power2 | sorted_uniform | 1024 | 16 | 1.7 μs | 580 ns | 470 ns | 930 ns | 450 ns | 490 ns | 420 ns | Binary (450 ns) | 1.09x | -| power2 | sorted_uniform | 16384 | 1 | 70 ns | 80 ns | 70 ns | 120 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_uniform | 16384 | 4 | 11.1 μs | 250 ns | 210 ns | 350 ns | 170 ns | 230 ns | 160 ns | Binary (170 ns) | 1.35x | -| power2 | sorted_uniform | 16384 | 16 | 22.5 μs | 840 ns | 630 ns | 1.3 μs | 609 ns | 670 ns | 630 ns | Binary (609 ns) | 1.10x | -| power2 | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 90 ns | 90 ns | 80 ns | ExpFromLeft (80 ns) | 1.12x | -| power2 | sorted_uniform | 262144 | 4 | 264.8 μs | 340 ns | 260 ns | 440 ns | 220 ns | 290 ns | 200 ns | Binary (220 ns) | 1.32x | -| power2 | sorted_uniform | 262144 | 16 | 342.8 μs | 1.3 μs | 910 ns | 1.7 μs | 840 ns | 960 ns | 800 ns | Binary (840 ns) | 1.14x | -| power2 | unsorted | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| power2 | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| power2 | unsorted | 1024 | 16 | 420 ns | 420 ns | 430 ns | 410 ns | 430 ns | 430 ns | 450 ns | InterpSearch (410 ns) | 1.05x | -| power2 | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | unsorted | 16384 | 4 | 170 ns | 180 ns | 180 ns | 180 ns | 180 ns | 190 ns | 170 ns | Linear (170 ns) | 1.12x | -| power2 | unsorted | 16384 | 16 | 570 ns | 570 ns | 580 ns | 580 ns | 580 ns | 600 ns | 570 ns | Gallop (570 ns) | 1.05x | -| power2 | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 140 ns | 80 ns | 90 ns | 80 ns | Binary (80 ns) | 1.12x | -| power2 | unsorted | 262144 | 4 | 230 ns | 210 ns | 210 ns | 220 ns | 220 ns | 230 ns | 210 ns | ExpFromLeft (210 ns) | 1.10x | -| power2 | unsorted | 262144 | 16 | 760 ns | 770 ns | 780 ns | 780 ns | 790 ns | 770 ns | 770 ns | Linear (760 ns) | 1.01x | -| sqrt | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| sqrt | sorted_uniform | 1024 | 4 | 1.5 μs | 190 ns | 160 ns | 260 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | -| sqrt | sorted_uniform | 1024 | 16 | 1.5 μs | 560 ns | 450 ns | 940 ns | 450 ns | 470 ns | 410 ns | ExpFromLeft (450 ns) | 1.04x | -| sqrt | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 80 ns | 110 ns | 70 ns | 80 ns | 70 ns | Binary (70 ns) | 1.14x | -| sqrt | sorted_uniform | 16384 | 4 | 12.8 μs | 260 ns | 210 ns | 340 ns | 180 ns | 240 ns | 160 ns | Binary (180 ns) | 1.33x | -| sqrt | sorted_uniform | 16384 | 16 | 24.6 μs | 790 ns | 610 ns | 1.2 μs | 590 ns | 640 ns | 560 ns | Binary (590 ns) | 1.08x | -| sqrt | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | sorted_uniform | 262144 | 4 | 310.7 μs | 340 ns | 270 ns | 440 ns | 220 ns | 300 ns | 200 ns | Binary (220 ns) | 1.36x | -| sqrt | sorted_uniform | 262144 | 16 | 386.2 μs | 1.2 μs | 900 ns | 1.6 μs | 810 ns | 920 ns | 760 ns | Binary (810 ns) | 1.14x | -| sqrt | unsorted | 1024 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| sqrt | unsorted | 1024 | 16 | 430 ns | 420 ns | 430 ns | 420 ns | 430 ns | 430 ns | 410 ns | InterpSearch (420 ns) | 1.02x | -| sqrt | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 120 ns | 80 ns | 70 ns | 60 ns | Gallop (70 ns) | 1.00x | -| sqrt | unsorted | 16384 | 4 | 180 ns | 180 ns | 170 ns | 180 ns | 180 ns | 190 ns | 170 ns | ExpFromLeft (170 ns) | 1.12x | -| sqrt | unsorted | 16384 | 16 | 580 ns | 580 ns | 580 ns | 580 ns | 580 ns | 590 ns | 560 ns | InterpSearch (580 ns) | 1.02x | -| sqrt | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 140 ns | 80 ns | 90 ns | 70 ns | Binary (80 ns) | 1.12x | -| sqrt | unsorted | 262144 | 4 | 243.2 μs | 320 ns | 250 ns | 449 ns | 220 ns | 290 ns | 210 ns | Binary (220 ns) | 1.32x | -| sqrt | unsorted | 262144 | 16 | 790 ns | 810 ns | 790 ns | 780 ns | 780 ns | 800 ns | 770 ns | InterpSearch (780 ns) | 1.03x | -| plateau | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| plateau | sorted_uniform | 1024 | 4 | 90 ns | 100 ns | 90 ns | 270 ns | 150 ns | 120 ns | 130 ns | ExpFromLeft (90 ns) | 1.33x | -| plateau | sorted_uniform | 1024 | 16 | 690 ns | 310 ns | 250 ns | 930 ns | 470 ns | 270 ns | 450 ns | ExpFromLeft (250 ns) | 1.08x | -| plateau | sorted_uniform | 16384 | 1 | 80 ns | 80 ns | 70 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| plateau | sorted_uniform | 16384 | 4 | 7.7 μs | 170 ns | 140 ns | 350 ns | 180 ns | 160 ns | 150 ns | ExpFromLeft (140 ns) | 1.14x | -| plateau | sorted_uniform | 16384 | 16 | 8.1 μs | 340 ns | 270 ns | 1.3 μs | 630 ns | 300 ns | 590 ns | ExpFromLeft (270 ns) | 1.11x | -| plateau | sorted_uniform | 262144 | 1 | 80 ns | 90 ns | 80 ns | 130 ns | 80 ns | 90 ns | 70 ns | ExpFromLeft (80 ns) | 1.12x | -| plateau | sorted_uniform | 262144 | 4 | 119.2 μs | 200 ns | 170 ns | 430 ns | 220 ns | 210 ns | 210 ns | ExpFromLeft (170 ns) | 1.24x | -| plateau | sorted_uniform | 262144 | 16 | 120.9 μs | 370 ns | 290 ns | 1.6 μs | 770 ns | 320 ns | 760 ns | ExpFromLeft (290 ns) | 1.10x | -| plateau | unsorted | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| plateau | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 150 ns | 120 ns | InterpSearch (140 ns) | 1.07x | -| plateau | unsorted | 1024 | 16 | 480 ns | 480 ns | 480 ns | 480 ns | 490 ns | 490 ns | 460 ns | InterpSearch (480 ns) | 1.02x | -| plateau | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| plateau | unsorted | 16384 | 4 | 7.9 μs | 160 ns | 140 ns | 360 ns | 180 ns | 170 ns | 170 ns | ExpFromLeft (140 ns) | 1.21x | -| plateau | unsorted | 16384 | 16 | 640 ns | 640 ns | 650 ns | 660 ns | 650 ns | 649 ns | 640 ns | Gallop (640 ns) | 1.01x | -| plateau | unsorted | 262144 | 1 | 90 ns | 80 ns | 90 ns | 140 ns | 90 ns | 90 ns | 80 ns | Gallop (80 ns) | 1.12x | -| plateau | unsorted | 262144 | 4 | 220 ns | 220 ns | 220 ns | 220 ns | 220 ns | 230 ns | 210 ns | InterpSearch (220 ns) | 1.05x | -| plateau | unsorted | 262144 | 16 | 840 ns | 840 ns | 840 ns | 850 ns | 840 ns | 850 ns | 830 ns | ExpFromLeft (840 ns) | 1.01x | -| bimodal | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 70 ns | 59 ns | ExpFromLeft (60 ns) | 1.17x | -| bimodal | sorted_uniform | 1024 | 4 | 80 ns | 100 ns | 90 ns | 270 ns | 140 ns | 120 ns | 130 ns | Linear (80 ns) | 1.50x | -| bimodal | sorted_uniform | 1024 | 16 | 780 ns | 350 ns | 270 ns | 940 ns | 470 ns | 300 ns | 420 ns | ExpFromLeft (270 ns) | 1.11x | -| bimodal | sorted_uniform | 16384 | 1 | 80 ns | 80 ns | 70 ns | 110 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| bimodal | sorted_uniform | 16384 | 4 | 90 ns | 110 ns | 100 ns | 370 ns | 180 ns | 130 ns | 170 ns | Linear (90 ns) | 1.44x | -| bimodal | sorted_uniform | 16384 | 16 | 16.8 μs | 560 ns | 390 ns | 1.3 μs | 630 ns | 420 ns | 580 ns | ExpFromLeft (390 ns) | 1.08x | -| bimodal | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 90 ns | 140 ns | 90 ns | 90 ns | 80 ns | Gallop (80 ns) | 1.12x | -| bimodal | sorted_uniform | 262144 | 4 | 60.1 μs | 200 ns | 160 ns | 450 ns | 220 ns | 190 ns | 200 ns | ExpFromLeft (160 ns) | 1.19x | -| bimodal | sorted_uniform | 262144 | 16 | 302.6 μs | 659 ns | 490 ns | 1.6 μs | 790 ns | 520 ns | 740 ns | ExpFromLeft (490 ns) | 1.06x | -| bimodal | unsorted | 1024 | 1 | 60 ns | 60 ns | 70 ns | 90 ns | 60 ns | 70 ns | 60 ns | Binary (60 ns) | 1.17x | -| bimodal | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| bimodal | unsorted | 1024 | 16 | 460 ns | 470 ns | 470 ns | 470 ns | 480 ns | 480 ns | 460 ns | Linear (460 ns) | 1.04x | -| bimodal | unsorted | 16384 | 1 | 70 ns | 70 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | unsorted | 16384 | 4 | 100 ns | 130 ns | 100 ns | 350 ns | 180 ns | 120 ns | 170 ns | ExpFromLeft (100 ns) | 1.20x | -| bimodal | unsorted | 16384 | 16 | 599 ns | 590 ns | 599 ns | 600 ns | 600 ns | 610 ns | 580 ns | Gallop (590 ns) | 1.03x | -| bimodal | unsorted | 262144 | 1 | 80 ns | 80 ns | 90 ns | 120 ns | 90 ns | 90 ns | 80 ns | Gallop (80 ns) | 1.12x | -| bimodal | unsorted | 262144 | 4 | 210 ns | 210 ns | 210 ns | 210 ns | 200 ns | 220 ns | 200 ns | Binary (200 ns) | 1.10x | -| bimodal | unsorted | 262144 | 16 | 750 ns | 770 ns | 770 ns | 770 ns | 770 ns | 770 ns | 750 ns | Linear (750 ns) | 1.03x | -| near_linear | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | 70 ns | 50 ns | InterpSearch (60 ns) | 1.17x | -| near_linear | sorted_uniform | 1024 | 4 | 1.6 μs | 220 ns | 170 ns | 150 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| near_linear | sorted_uniform | 1024 | 16 | 1.8 μs | 620 ns | 490 ns | 480 ns | 460 ns | 550 ns | 410 ns | Binary (460 ns) | 1.20x | -| near_linear | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | sorted_uniform | 16384 | 4 | 4.1 μs | 240 ns | 200 ns | 160 ns | 180 ns | 200 ns | 170 ns | InterpSearch (160 ns) | 1.25x | -| near_linear | sorted_uniform | 16384 | 16 | 22.2 μs | 870 ns | 670 ns | 470 ns | 610 ns | 550 ns | 560 ns | InterpSearch (470 ns) | 1.17x | -| near_linear | sorted_uniform | 262144 | 1 | 80 ns | 80 ns | 90 ns | 70 ns | 90 ns | 90 ns | 80 ns | InterpSearch (70 ns) | 1.29x | -| near_linear | sorted_uniform | 262144 | 4 | 235.2 μs | 340 ns | 260 ns | 150 ns | 220 ns | 210 ns | 210 ns | InterpSearch (150 ns) | 1.40x | -| near_linear | sorted_uniform | 262144 | 16 | 366.2 μs | 1.2 μs | 860 ns | 500 ns | 820 ns | 580 ns | 770 ns | InterpSearch (500 ns) | 1.16x | -| near_linear | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| near_linear | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| near_linear | unsorted | 1024 | 16 | 420 ns | 420 ns | 420 ns | 430 ns | 430 ns | 430 ns | 400 ns | ExpFromLeft (420 ns) | 1.02x | -| near_linear | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | unsorted | 16384 | 4 | 180 ns | 170 ns | 190 ns | 180 ns | 180 ns | 190 ns | 170 ns | Gallop (170 ns) | 1.12x | -| near_linear | unsorted | 16384 | 16 | 570 ns | 580 ns | 590 ns | 570 ns | 590 ns | 590 ns | 560 ns | InterpSearch (570 ns) | 1.04x | -| near_linear | unsorted | 262144 | 1 | 90 ns | 80 ns | 80 ns | 60 ns | 80 ns | 90 ns | 70 ns | InterpSearch (60 ns) | 1.50x | -| near_linear | unsorted | 262144 | 4 | 220 ns | 220 ns | 210 ns | 220 ns | 220 ns | 230 ns | 210 ns | ExpFromLeft (210 ns) | 1.10x | -| near_linear | unsorted | 262144 | 16 | 810 ns | 780 ns | 800 ns | 800 ns | 800 ns | 800 ns | 820 ns | Gallop (780 ns) | 1.03x | - -**Auto verdict over 180 cells**: 147 within 20% of best, 33 worse than 20% slowdown, 0 effectively-faster-than-best. - -### Super-dense cases (m ≫ n) - -## Super dense - -| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | -|---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 64 | 1024 | 8.9 μs | 15.5 μs | 12.0 μs | 30.8 μs | 18.1 μs | 9.1 μs | 16.2 μs | Linear (8.9 μs) | 1.02x | -| uniform | sorted_uniform | 64 | 4096 | 31.1 μs | 59.2 μs | 44.7 μs | 112.7 μs | 68.6 μs | 32.1 μs | 60.5 μs | Linear (31.1 μs) | 1.03x | -| uniform | sorted_uniform | 64 | 16384 | 117.7 μs | 222.1 μs | 175.5 μs | 441.4 μs | 270.8 μs | 124.2 μs | 237.2 μs | Linear (117.7 μs) | 1.05x | -| uniform | sorted_uniform | 256 | 1024 | 9.9 μs | 18.1 μs | 13.9 μs | 37.5 μs | 29.8 μs | 10.3 μs | 25.0 μs | Linear (9.9 μs) | 1.05x | -| uniform | sorted_uniform | 256 | 4096 | 35.0 μs | 59.7 μs | 48.1 μs | 122.7 μs | 125.7 μs | 36.6 μs | 84.1 μs | Linear (35.0 μs) | 1.05x | -| uniform | sorted_uniform | 256 | 16384 | 121.8 μs | 226.6 μs | 178.9 μs | 452.0 μs | 388.0 μs | 128.8 μs | 318.0 μs | Linear (121.8 μs) | 1.06x | -| uniform | sorted_uniform | 1024 | 1024 | 9.6 μs | 18.1 μs | 13.1 μs | 38.9 μs | 74.4 μs | 9.9 μs | 55.3 μs | Linear (9.6 μs) | 1.03x | -| uniform | sorted_uniform | 1024 | 4096 | 46.7 μs | 73.1 μs | 58.4 μs | 149.1 μs | 236.1 μs | 48.3 μs | 189.4 μs | Linear (46.7 μs) | 1.03x | -| uniform | sorted_uniform | 1024 | 16384 | 140.2 μs | 238.9 μs | 192.8 μs | 491.8 μs | 591.2 μs | 144.6 μs | 484.7 μs | Linear (140.2 μs) | 1.03x | -| uniform | sorted_dense_burst | 64 | 1024 | 7.4 μs | 13.9 μs | 10.9 μs | 27.6 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.06x | -| uniform | sorted_dense_burst | 64 | 4096 | 29.1 μs | 55.5 μs | 43.6 μs | 109.6 μs | 67.9 μs | 31.0 μs | 56.7 μs | Linear (29.1 μs) | 1.06x | -| uniform | sorted_dense_burst | 64 | 16384 | 117.0 μs | 221.6 μs | 174.2 μs | 438.9 μs | 271.8 μs | 123.3 μs | 227.1 μs | Linear (117.0 μs) | 1.05x | -| uniform | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.0 μs | 11.1 μs | 27.4 μs | 21.8 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | -| uniform | sorted_dense_burst | 256 | 4096 | 29.3 μs | 55.5 μs | 43.6 μs | 109.9 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (29.3 μs) | 1.05x | -| uniform | sorted_dense_burst | 256 | 16384 | 116.4 μs | 222.1 μs | 174.1 μs | 439.0 μs | 349.2 μs | 122.9 μs | 305.7 μs | Linear (116.4 μs) | 1.06x | -| uniform | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 27.6 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | -| uniform | sorted_dense_burst | 1024 | 4096 | 29.3 μs | 55.7 μs | 43.5 μs | 109.7 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.3 μs) | 1.05x | -| uniform | sorted_dense_burst | 1024 | 16384 | 116.4 μs | 222.2 μs | 174.2 μs | 438.9 μs | 427.5 μs | 123.1 μs | 383.1 μs | Linear (116.4 μs) | 1.06x | -| uniform | unsorted | 64 | 1024 | 42.6 μs | 41.9 μs | 39.4 μs | 39.2 μs | 39.3 μs | 39.2 μs | 38.4 μs | InterpSearch (39.2 μs) | 1.00x | -| uniform | unsorted | 64 | 4096 | 233.4 μs | 229.2 μs | 230.4 μs | 229.8 μs | 230.5 μs | 229.4 μs | 228.6 μs | Gallop (229.2 μs) | 1.00x | -| uniform | unsorted | 64 | 16384 | 981.8 μs | 979.7 μs | 979.0 μs | 980.4 μs | 980.2 μs | 976.8 μs | 972.9 μs | ExpFromLeft (979.0 μs) | 1.00x | -| uniform | unsorted | 256 | 1024 | 58.6 μs | 57.3 μs | 55.8 μs | 54.9 μs | 54.6 μs | 54.5 μs | 53.6 μs | Binary (54.6 μs) | 1.00x | -| uniform | unsorted | 256 | 4096 | 314.8 μs | 314.3 μs | 311.6 μs | 310.4 μs | 311.1 μs | 309.9 μs | 306.7 μs | InterpSearch (310.4 μs) | 1.00x | -| uniform | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.29 ms | 1.30 ms | 1.29 ms | Binary (1.29 ms) | 1.00x | -| uniform | unsorted | 1024 | 1024 | 84.0 μs | 83.1 μs | 79.4 μs | 78.9 μs | 81.3 μs | 78.7 μs | 80.3 μs | InterpSearch (78.9 μs) | 1.00x | -| uniform | unsorted | 1024 | 4096 | 408.7 μs | 405.9 μs | 406.1 μs | 406.0 μs | 405.3 μs | 405.4 μs | 409.3 μs | Binary (405.3 μs) | 1.00x | -| uniform | unsorted | 1024 | 16384 | 1.69 ms | 1.68 ms | 1.68 ms | 1.68 ms | 1.67 ms | 1.67 ms | 1.69 ms | Binary (1.67 ms) | 1.00x | -| log | sorted_uniform | 64 | 1024 | 8.0 μs | 14.4 μs | 11.4 μs | 43.7 μs | 17.6 μs | 8.4 μs | 15.8 μs | Linear (8.0 μs) | 1.05x | -| log | sorted_uniform | 64 | 4096 | 30.0 μs | 55.6 μs | 44.4 μs | 170.5 μs | 69.1 μs | 31.5 μs | 60.9 μs | Linear (30.0 μs) | 1.05x | -| log | sorted_uniform | 64 | 16384 | 117.4 μs | 221.2 μs | 175.4 μs | 676.6 μs | 275.0 μs | 124.0 μs | 240.8 μs | Linear (117.4 μs) | 1.06x | -| log | sorted_uniform | 256 | 1024 | 9.0 μs | 15.6 μs | 12.2 μs | 57.8 μs | 23.1 μs | 9.4 μs | 21.3 μs | Linear (9.0 μs) | 1.05x | -| log | sorted_uniform | 256 | 4096 | 31.8 μs | 58.4 μs | 45.8 μs | 223.8 μs | 91.5 μs | 33.2 μs | 81.4 μs | Linear (31.8 μs) | 1.05x | -| log | sorted_uniform | 256 | 16384 | 120.1 μs | 226.7 μs | 177.5 μs | 869.6 μs | 363.0 μs | 126.8 μs | 319.4 μs | Linear (120.1 μs) | 1.06x | -| log | sorted_uniform | 1024 | 1024 | 10.3 μs | 17.6 μs | 13.4 μs | 69.8 μs | 39.6 μs | 10.6 μs | 32.6 μs | Linear (10.3 μs) | 1.02x | -| log | sorted_uniform | 1024 | 4096 | 36.9 μs | 62.4 μs | 49.6 μs | 282.8 μs | 167.3 μs | 38.7 μs | 124.1 μs | Linear (36.9 μs) | 1.05x | -| log | sorted_uniform | 1024 | 16384 | 128.5 μs | 233.0 μs | 184.4 μs | 1.06 ms | 532.4 μs | 134.3 μs | 448.1 μs | Linear (128.5 μs) | 1.04x | -| log | sorted_dense_burst | 64 | 1024 | 7.3 μs | 14.0 μs | 10.9 μs | 44.8 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.3 μs) | 1.06x | -| log | sorted_dense_burst | 64 | 4096 | 29.3 μs | 55.5 μs | 44.3 μs | 179.1 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.3 μs) | 1.05x | -| log | sorted_dense_burst | 64 | 16384 | 116.3 μs | 221.8 μs | 177.1 μs | 716.5 μs | 273.6 μs | 122.9 μs | 227.2 μs | Linear (116.3 μs) | 1.06x | -| log | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 55.4 μs | 21.8 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | -| log | sorted_dense_burst | 256 | 4096 | 29.3 μs | 55.5 μs | 44.3 μs | 221.9 μs | 87.3 μs | 30.8 μs | 76.5 μs | Linear (29.3 μs) | 1.05x | -| log | sorted_dense_burst | 256 | 16384 | 116.4 μs | 222.2 μs | 173.8 μs | 887.9 μs | 349.3 μs | 123.0 μs | 305.8 μs | Linear (116.4 μs) | 1.06x | -| log | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.9 μs | 11.0 μs | 65.1 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | -| log | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 73.8 μs | 55.8 μs | 259.2 μs | 106.8 μs | 30.8 μs | 94.6 μs | Linear (29.2 μs) | 1.06x | -| log | sorted_dense_burst | 1024 | 16384 | 116.4 μs | 222.2 μs | 174.1 μs | 1.04 ms | 427.4 μs | 122.9 μs | 383.3 μs | Linear (116.4 μs) | 1.06x | -| log | unsorted | 64 | 1024 | 35.1 μs | 34.7 μs | 34.7 μs | 34.7 μs | 34.2 μs | 34.3 μs | 31.5 μs | Binary (34.2 μs) | 1.00x | -| log | unsorted | 64 | 4096 | 179.5 μs | 178.4 μs | 178.2 μs | 178.0 μs | 178.0 μs | 177.8 μs | 176.1 μs | Binary (178.0 μs) | 1.00x | -| log | unsorted | 64 | 16384 | 757.7 μs | 758.2 μs | 757.7 μs | 758.2 μs | 758.1 μs | 757.4 μs | 736.3 μs | ExpFromLeft (757.7 μs) | 1.00x | -| log | unsorted | 256 | 1024 | 50.7 μs | 50.4 μs | 49.3 μs | 49.5 μs | 49.4 μs | 49.6 μs | 47.1 μs | ExpFromLeft (49.3 μs) | 1.01x | -| log | unsorted | 256 | 4096 | 260.6 μs | 257.4 μs | 256.7 μs | 257.7 μs | 257.5 μs | 256.4 μs | 256.8 μs | ExpFromLeft (256.7 μs) | 1.00x | -| log | unsorted | 256 | 16384 | 1.09 ms | 1.09 ms | 1.09 ms | 1.09 ms | 1.09 ms | 1.09 ms | 1.06 ms | Binary (1.09 ms) | 1.00x | -| log | unsorted | 1024 | 1024 | 72.8 μs | 72.0 μs | 71.6 μs | 70.2 μs | 70.0 μs | 69.8 μs | 69.5 μs | Binary (70.0 μs) | 1.00x | -| log | unsorted | 1024 | 4096 | 350.4 μs | 348.8 μs | 349.1 μs | 348.6 μs | 348.5 μs | 349.3 μs | 347.2 μs | Binary (348.5 μs) | 1.00x | -| log | unsorted | 1024 | 16384 | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.42 ms | 1.41 ms | Binary (1.42 ms) | 1.00x | -| jittered | sorted_uniform | 64 | 1024 | 8.8 μs | 14.9 μs | 12.1 μs | 31.3 μs | 17.9 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | -| jittered | sorted_uniform | 64 | 4096 | 30.5 μs | 56.6 μs | 44.7 μs | 115.5 μs | 68.6 μs | 32.1 μs | 60.2 μs | Linear (30.5 μs) | 1.05x | -| jittered | sorted_uniform | 64 | 16384 | 117.7 μs | 222.7 μs | 175.6 μs | 454.8 μs | 270.9 μs | 124.2 μs | 237.0 μs | Linear (117.7 μs) | 1.06x | -| jittered | sorted_uniform | 256 | 1024 | 10.0 μs | 17.9 μs | 13.8 μs | 37.5 μs | 27.5 μs | 10.3 μs | 25.4 μs | Linear (10.0 μs) | 1.03x | -| jittered | sorted_uniform | 256 | 4096 | 34.8 μs | 59.7 μs | 48.1 μs | 123.4 μs | 126.2 μs | 36.1 μs | 84.0 μs | Linear (34.8 μs) | 1.04x | -| jittered | sorted_uniform | 256 | 16384 | 122.1 μs | 226.4 μs | 179.0 μs | 453.8 μs | 386.8 μs | 128.4 μs | 316.2 μs | Linear (122.1 μs) | 1.05x | -| jittered | sorted_uniform | 1024 | 1024 | 10.0 μs | 18.2 μs | 12.6 μs | 38.9 μs | 71.0 μs | 10.1 μs | 52.8 μs | Linear (10.0 μs) | 1.00x | -| jittered | sorted_uniform | 1024 | 4096 | 47.8 μs | 74.6 μs | 58.7 μs | 150.9 μs | 237.4 μs | 47.2 μs | 190.7 μs | Linear (47.8 μs) | 0.99x | -| jittered | sorted_uniform | 1024 | 16384 | 140.2 μs | 242.6 μs | 192.4 μs | 503.6 μs | 591.7 μs | 146.7 μs | 483.4 μs | Linear (140.2 μs) | 1.05x | -| jittered | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 27.6 μs | 17.0 μs | 7.8 μs | 14.1 μs | Linear (7.4 μs) | 1.06x | -| jittered | sorted_dense_burst | 64 | 4096 | 29.3 μs | 55.5 μs | 43.5 μs | 110.5 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.3 μs) | 1.05x | -| jittered | sorted_dense_burst | 64 | 16384 | 116.5 μs | 221.7 μs | 173.8 μs | 441.6 μs | 271.8 μs | 123.1 μs | 227.1 μs | Linear (116.5 μs) | 1.06x | -| jittered | sorted_dense_burst | 256 | 1024 | 7.5 μs | 14.6 μs | 11.0 μs | 27.9 μs | 22.0 μs | 7.9 μs | 19.4 μs | Linear (7.5 μs) | 1.05x | -| jittered | sorted_dense_burst | 256 | 4096 | 29.6 μs | 56.0 μs | 43.6 μs | 109.1 μs | 87.3 μs | 30.8 μs | 76.3 μs | Linear (29.6 μs) | 1.04x | -| jittered | sorted_dense_burst | 256 | 16384 | 116.3 μs | 226.7 μs | 174.3 μs | 436.2 μs | 349.2 μs | 123.0 μs | 305.7 μs | Linear (116.3 μs) | 1.06x | -| jittered | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 29.3 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.06x | -| jittered | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 55.6 μs | 44.3 μs | 117.2 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.2 μs) | 1.05x | -| jittered | sorted_dense_burst | 1024 | 16384 | 116.3 μs | 222.9 μs | 174.0 μs | 468.5 μs | 427.3 μs | 122.9 μs | 383.4 μs | Linear (116.3 μs) | 1.06x | -| jittered | unsorted | 64 | 1024 | 42.6 μs | 40.9 μs | 41.2 μs | 39.9 μs | 40.5 μs | 40.0 μs | 37.8 μs | InterpSearch (39.9 μs) | 1.00x | -| jittered | unsorted | 64 | 4096 | 231.9 μs | 232.9 μs | 229.2 μs | 228.3 μs | 227.3 μs | 228.6 μs | 223.7 μs | Binary (227.3 μs) | 1.01x | -| jittered | unsorted | 64 | 16384 | 981.5 μs | 982.2 μs | 980.1 μs | 980.1 μs | 979.3 μs | 977.9 μs | 967.9 μs | Binary (979.3 μs) | 1.00x | -| jittered | unsorted | 256 | 1024 | 56.9 μs | 55.4 μs | 52.7 μs | 52.5 μs | 52.1 μs | 52.2 μs | 52.7 μs | Binary (52.1 μs) | 1.00x | -| jittered | unsorted | 256 | 4096 | 316.5 μs | 314.4 μs | 312.4 μs | 313.2 μs | 312.7 μs | 313.2 μs | 307.4 μs | ExpFromLeft (312.4 μs) | 1.00x | -| jittered | unsorted | 256 | 16384 | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.30 ms | 1.29 ms | ExpFromLeft (1.30 ms) | 1.00x | -| jittered | unsorted | 1024 | 1024 | 84.6 μs | 81.3 μs | 79.0 μs | 77.8 μs | 77.3 μs | 76.8 μs | 77.5 μs | Binary (77.3 μs) | 0.99x | -| jittered | unsorted | 1024 | 4096 | 408.7 μs | 407.2 μs | 406.0 μs | 404.5 μs | 405.0 μs | 406.3 μs | 411.1 μs | InterpSearch (404.5 μs) | 1.00x | -| jittered | unsorted | 1024 | 16384 | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.69 ms | InterpSearch (1.67 ms) | 1.00x | -| random | sorted_uniform | 64 | 1024 | 8.8 μs | 14.8 μs | 12.0 μs | 33.4 μs | 17.6 μs | 9.1 μs | 15.9 μs | Linear (8.8 μs) | 1.04x | -| random | sorted_uniform | 64 | 4096 | 30.5 μs | 55.9 μs | 44.7 μs | 126.2 μs | 68.5 μs | 32.1 μs | 60.2 μs | Linear (30.5 μs) | 1.05x | -| random | sorted_uniform | 64 | 16384 | 117.6 μs | 220.5 μs | 175.5 μs | 495.9 μs | 271.4 μs | 124.2 μs | 237.2 μs | Linear (117.6 μs) | 1.06x | -| random | sorted_uniform | 256 | 1024 | 9.1 μs | 16.9 μs | 13.3 μs | 42.3 μs | 24.1 μs | 9.4 μs | 23.3 μs | Linear (9.1 μs) | 1.03x | -| random | sorted_uniform | 256 | 4096 | 34.4 μs | 59.2 μs | 47.8 μs | 155.0 μs | 99.7 μs | 35.7 μs | 83.5 μs | Linear (34.4 μs) | 1.04x | -| random | sorted_uniform | 256 | 16384 | 122.0 μs | 223.9 μs | 179.0 μs | 590.1 μs | 383.6 μs | 128.3 μs | 316.7 μs | Linear (122.0 μs) | 1.05x | -| random | sorted_uniform | 1024 | 1024 | 10.0 μs | 18.0 μs | 12.3 μs | 45.8 μs | 58.5 μs | 10.5 μs | 42.2 μs | Linear (10.0 μs) | 1.05x | -| random | sorted_uniform | 1024 | 4096 | 42.9 μs | 70.0 μs | 55.9 μs | 184.7 μs | 212.0 μs | 43.5 μs | 166.4 μs | Linear (42.9 μs) | 1.01x | -| random | sorted_uniform | 1024 | 16384 | 138.2 μs | 237.2 μs | 191.5 μs | 666.2 μs | 568.5 μs | 143.4 μs | 480.1 μs | Linear (138.2 μs) | 1.04x | -| random | sorted_dense_burst | 64 | 1024 | 7.4 μs | 13.7 μs | 10.9 μs | 29.5 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.4 μs) | 1.05x | -| random | sorted_dense_burst | 64 | 4096 | 29.2 μs | 54.9 μs | 43.5 μs | 116.8 μs | 67.9 μs | 30.8 μs | 56.7 μs | Linear (29.2 μs) | 1.05x | -| random | sorted_dense_burst | 64 | 16384 | 116.2 μs | 219.2 μs | 173.9 μs | 467.9 μs | 271.8 μs | 122.9 μs | 227.1 μs | Linear (116.2 μs) | 1.06x | -| random | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 31.7 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | -| random | sorted_dense_burst | 256 | 4096 | 29.2 μs | 55.6 μs | 43.2 μs | 125.6 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (29.2 μs) | 1.05x | -| random | sorted_dense_burst | 256 | 16384 | 116.3 μs | 222.2 μs | 174.0 μs | 502.1 μs | 349.2 μs | 122.8 μs | 306.1 μs | Linear (116.3 μs) | 1.06x | -| random | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 44.4 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.06x | -| random | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 55.5 μs | 43.6 μs | 180.0 μs | 124.2 μs | 46.0 μs | 111.1 μs | Linear (29.2 μs) | 1.58x | -| random | sorted_dense_burst | 1024 | 16384 | 177.7 μs | 304.6 μs | 232.0 μs | 718.8 μs | 427.2 μs | 122.8 μs | 383.2 μs | Linear (177.7 μs) | 0.69x | -| random | unsorted | 64 | 1024 | 36.5 μs | 35.1 μs | 35.2 μs | 34.8 μs | 35.1 μs | 34.8 μs | 33.5 μs | InterpSearch (34.8 μs) | 1.00x | -| random | unsorted | 64 | 4096 | 203.7 μs | 202.6 μs | 201.8 μs | 202.4 μs | 202.8 μs | 201.4 μs | 200.6 μs | ExpFromLeft (201.8 μs) | 1.00x | -| random | unsorted | 64 | 16384 | 870.0 μs | 869.4 μs | 869.6 μs | 868.7 μs | 871.1 μs | 870.2 μs | 842.5 μs | InterpSearch (868.7 μs) | 1.00x | -| random | unsorted | 256 | 1024 | 55.6 μs | 53.3 μs | 52.6 μs | 52.2 μs | 52.1 μs | 52.1 μs | 49.4 μs | Binary (52.1 μs) | 1.00x | -| random | unsorted | 256 | 4096 | 279.9 μs | 278.9 μs | 278.6 μs | 279.1 μs | 278.4 μs | 278.0 μs | 277.1 μs | Binary (278.4 μs) | 1.00x | -| random | unsorted | 256 | 16384 | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.16 ms | 1.15 ms | Binary (1.16 ms) | 1.00x | -| random | unsorted | 1024 | 1024 | 77.1 μs | 75.2 μs | 74.3 μs | 73.7 μs | 73.0 μs | 72.1 μs | 76.2 μs | Binary (73.0 μs) | 0.99x | -| random | unsorted | 1024 | 4096 | 382.1 μs | 380.1 μs | 380.0 μs | 378.0 μs | 377.9 μs | 380.0 μs | 381.3 μs | Binary (377.9 μs) | 1.01x | -| random | unsorted | 1024 | 16384 | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | 1.55 ms | Linear (1.55 ms) | 1.00x | -| two_scale | sorted_uniform | 64 | 1024 | 8.0 μs | 14.4 μs | 11.4 μs | 42.2 μs | 17.8 μs | 8.4 μs | 15.2 μs | Linear (8.0 μs) | 1.06x | -| two_scale | sorted_uniform | 64 | 4096 | 30.2 μs | 58.7 μs | 44.4 μs | 159.4 μs | 68.8 μs | 31.4 μs | 59.1 μs | Linear (30.2 μs) | 1.04x | -| two_scale | sorted_uniform | 64 | 16384 | 116.9 μs | 222.2 μs | 175.6 μs | 630.9 μs | 273.6 μs | 125.4 μs | 236.2 μs | Linear (116.9 μs) | 1.07x | -| two_scale | sorted_uniform | 256 | 1024 | 9.5 μs | 15.7 μs | 12.7 μs | 56.4 μs | 23.4 μs | 9.9 μs | 21.3 μs | Linear (9.5 μs) | 1.05x | -| two_scale | sorted_uniform | 256 | 4096 | 32.1 μs | 57.1 μs | 45.9 μs | 211.8 μs | 90.0 μs | 33.5 μs | 80.6 μs | Linear (32.1 μs) | 1.04x | -| two_scale | sorted_uniform | 256 | 16384 | 119.2 μs | 222.0 μs | 176.8 μs | 820.4 μs | 353.5 μs | 127.4 μs | 313.8 μs | Linear (119.2 μs) | 1.07x | -| two_scale | sorted_uniform | 1024 | 1024 | 9.9 μs | 17.2 μs | 12.6 μs | 70.6 μs | 45.4 μs | 10.3 μs | 32.5 μs | Linear (9.9 μs) | 1.05x | -| two_scale | sorted_uniform | 1024 | 4096 | 38.6 μs | 63.7 μs | 51.6 μs | 292.3 μs | 162.3 μs | 40.7 μs | 114.1 μs | Linear (38.6 μs) | 1.05x | -| two_scale | sorted_uniform | 1024 | 16384 | 128.3 μs | 239.5 μs | 183.7 μs | 1.04 ms | 501.3 μs | 136.3 μs | 412.6 μs | Linear (128.3 μs) | 1.06x | -| two_scale | sorted_dense_burst | 64 | 1024 | 7.5 μs | 14.6 μs | 10.9 μs | 47.0 μs | 17.3 μs | 7.8 μs | 14.5 μs | Linear (7.5 μs) | 1.05x | -| two_scale | sorted_dense_burst | 64 | 4096 | 29.1 μs | 54.8 μs | 43.5 μs | 186.4 μs | 67.9 μs | 30.8 μs | 56.9 μs | Linear (29.1 μs) | 1.06x | -| two_scale | sorted_dense_burst | 64 | 16384 | 116.7 μs | 219.2 μs | 173.5 μs | 748.9 μs | 271.5 μs | 123.0 μs | 226.9 μs | Linear (116.7 μs) | 1.05x | -| two_scale | sorted_dense_burst | 256 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 55.9 μs | 21.8 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.05x | -| two_scale | sorted_dense_burst | 256 | 4096 | 29.2 μs | 55.0 μs | 43.6 μs | 224.2 μs | 87.2 μs | 30.8 μs | 76.5 μs | Linear (29.2 μs) | 1.05x | -| two_scale | sorted_dense_burst | 256 | 16384 | 116.2 μs | 219.7 μs | 174.3 μs | 896.0 μs | 349.3 μs | 122.9 μs | 305.9 μs | Linear (116.2 μs) | 1.06x | -| two_scale | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 65.6 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.05x | -| two_scale | sorted_dense_burst | 1024 | 4096 | 29.1 μs | 54.9 μs | 44.3 μs | 261.1 μs | 107.2 μs | 31.3 μs | 96.8 μs | Linear (29.1 μs) | 1.08x | -| two_scale | sorted_dense_burst | 1024 | 16384 | 117.0 μs | 219.6 μs | 174.2 μs | 1.04 ms | 427.6 μs | 124.9 μs | 383.2 μs | Linear (117.0 μs) | 1.07x | -| two_scale | unsorted | 64 | 1024 | 45.1 μs | 44.4 μs | 44.5 μs | 44.7 μs | 44.8 μs | 44.9 μs | 41.2 μs | Gallop (44.4 μs) | 1.01x | -| two_scale | unsorted | 64 | 4096 | 199.8 μs | 200.3 μs | 198.9 μs | 198.4 μs | 199.5 μs | 199.0 μs | 182.5 μs | InterpSearch (198.4 μs) | 1.00x | -| two_scale | unsorted | 64 | 16384 | 830.1 μs | 837.8 μs | 836.1 μs | 836.5 μs | 835.5 μs | 840.0 μs | 764.3 μs | Linear (830.1 μs) | 1.01x | -| two_scale | unsorted | 256 | 1024 | 54.1 μs | 52.9 μs | 53.4 μs | 53.2 μs | 53.2 μs | 53.1 μs | 51.5 μs | Gallop (52.9 μs) | 1.00x | -| two_scale | unsorted | 256 | 4096 | 256.1 μs | 256.1 μs | 255.3 μs | 255.1 μs | 255.1 μs | 255.2 μs | 251.2 μs | InterpSearch (255.1 μs) | 1.00x | -| two_scale | unsorted | 256 | 16384 | 1.07 ms | 1.06 ms | 1.06 ms | 1.07 ms | 1.06 ms | 1.07 ms | 1.03 ms | Gallop (1.06 ms) | 1.00x | -| two_scale | unsorted | 1024 | 1024 | 74.2 μs | 71.0 μs | 70.6 μs | 70.8 μs | 70.7 μs | 70.6 μs | 70.1 μs | ExpFromLeft (70.6 μs) | 1.00x | -| two_scale | unsorted | 1024 | 4096 | 348.7 μs | 347.2 μs | 347.2 μs | 345.7 μs | 344.6 μs | 345.8 μs | 344.5 μs | Binary (344.6 μs) | 1.00x | -| two_scale | unsorted | 1024 | 16384 | 1.43 ms | 1.43 ms | 1.43 ms | 1.42 ms | 1.42 ms | 1.43 ms | 1.41 ms | Binary (1.42 ms) | 1.00x | -| power2 | sorted_uniform | 64 | 1024 | 8.4 μs | 14.7 μs | 11.9 μs | 41.5 μs | 17.8 μs | 8.8 μs | 15.9 μs | Linear (8.4 μs) | 1.05x | -| power2 | sorted_uniform | 64 | 4096 | 30.4 μs | 55.9 μs | 44.7 μs | 159.0 μs | 69.8 μs | 32.0 μs | 60.1 μs | Linear (30.4 μs) | 1.05x | -| power2 | sorted_uniform | 64 | 16384 | 117.7 μs | 219.7 μs | 175.6 μs | 626.1 μs | 272.2 μs | 124.1 μs | 237.0 μs | Linear (117.7 μs) | 1.05x | -| power2 | sorted_uniform | 256 | 1024 | 9.8 μs | 16.6 μs | 12.9 μs | 53.9 μs | 25.5 μs | 10.0 μs | 24.2 μs | Linear (9.8 μs) | 1.03x | -| power2 | sorted_uniform | 256 | 4096 | 34.0 μs | 58.9 μs | 47.5 μs | 203.0 μs | 113.9 μs | 35.2 μs | 83.4 μs | Linear (34.0 μs) | 1.03x | -| power2 | sorted_uniform | 256 | 16384 | 121.7 μs | 223.8 μs | 178.8 μs | 780.2 μs | 392.7 μs | 129.5 μs | 317.5 μs | Linear (121.7 μs) | 1.06x | -| power2 | sorted_uniform | 1024 | 1024 | 10.2 μs | 17.7 μs | 12.7 μs | 65.6 μs | 64.7 μs | 10.7 μs | 48.2 μs | Linear (10.2 μs) | 1.06x | -| power2 | sorted_uniform | 1024 | 4096 | 42.8 μs | 69.9 μs | 54.5 μs | 267.5 μs | 224.0 μs | 44.8 μs | 173.6 μs | Linear (42.8 μs) | 1.05x | -| power2 | sorted_uniform | 1024 | 16384 | 136.1 μs | 235.9 μs | 190.4 μs | 979.4 μs | 581.3 μs | 141.3 μs | 477.3 μs | Linear (136.1 μs) | 1.04x | -| power2 | sorted_dense_burst | 64 | 1024 | 7.4 μs | 14.6 μs | 11.1 μs | 43.4 μs | 17.0 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | -| power2 | sorted_dense_burst | 64 | 4096 | 29.1 μs | 54.8 μs | 44.3 μs | 173.3 μs | 69.2 μs | 31.2 μs | 57.9 μs | Linear (29.1 μs) | 1.07x | -| power2 | sorted_dense_burst | 64 | 16384 | 116.2 μs | 219.2 μs | 173.8 μs | 693.7 μs | 271.6 μs | 122.8 μs | 227.2 μs | Linear (116.2 μs) | 1.06x | -| power2 | sorted_dense_burst | 256 | 1024 | 11.1 μs | 18.5 μs | 11.1 μs | 53.9 μs | 21.9 μs | 7.8 μs | 19.1 μs | ExpFromLeft (11.1 μs) | 0.70x | -| power2 | sorted_dense_burst | 256 | 4096 | 29.1 μs | 58.3 μs | 43.5 μs | 215.6 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (29.1 μs) | 1.06x | -| power2 | sorted_dense_burst | 256 | 16384 | 116.3 μs | 219.6 μs | 174.3 μs | 860.2 μs | 349.1 μs | 122.9 μs | 309.6 μs | Linear (116.3 μs) | 1.06x | -| power2 | sorted_dense_burst | 1024 | 1024 | 11.1 μs | 18.5 μs | 11.1 μs | 63.5 μs | 26.7 μs | 7.8 μs | 24.0 μs | ExpFromLeft (11.1 μs) | 0.70x | -| power2 | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 55.6 μs | 44.3 μs | 254.1 μs | 106.7 μs | 30.9 μs | 95.8 μs | Linear (29.2 μs) | 1.06x | -| power2 | sorted_dense_burst | 1024 | 16384 | 116.4 μs | 222.5 μs | 177.1 μs | 1.02 ms | 427.3 μs | 122.9 μs | 386.9 μs | Linear (116.4 μs) | 1.06x | -| power2 | unsorted | 64 | 1024 | 40.7 μs | 39.7 μs | 39.7 μs | 39.2 μs | 39.3 μs | 39.2 μs | 37.4 μs | InterpSearch (39.2 μs) | 1.00x | -| power2 | unsorted | 64 | 4096 | 221.0 μs | 217.6 μs | 216.0 μs | 216.8 μs | 215.4 μs | 215.1 μs | 212.1 μs | Binary (215.4 μs) | 1.00x | -| power2 | unsorted | 64 | 16384 | 916.4 μs | 914.6 μs | 915.9 μs | 914.2 μs | 915.0 μs | 915.5 μs | 913.8 μs | InterpSearch (914.2 μs) | 1.00x | -| power2 | unsorted | 256 | 1024 | 52.9 μs | 51.7 μs | 51.8 μs | 51.1 μs | 51.3 μs | 50.9 μs | 49.8 μs | InterpSearch (51.1 μs) | 1.00x | -| power2 | unsorted | 256 | 4096 | 302.8 μs | 299.6 μs | 299.1 μs | 297.0 μs | 294.5 μs | 298.6 μs | 298.0 μs | Binary (294.5 μs) | 1.01x | -| power2 | unsorted | 256 | 16384 | 1.24 ms | 1.24 ms | 1.24 ms | 1.24 ms | 1.23 ms | 1.24 ms | 1.23 ms | Binary (1.23 ms) | 1.01x | -| power2 | unsorted | 1024 | 1024 | 81.6 μs | 76.1 μs | 75.2 μs | 74.6 μs | 74.1 μs | 74.0 μs | 73.7 μs | Binary (74.1 μs) | 1.00x | -| power2 | unsorted | 1024 | 4096 | 392.3 μs | 391.4 μs | 390.7 μs | 388.0 μs | 390.6 μs | 390.0 μs | 390.9 μs | InterpSearch (388.0 μs) | 1.01x | -| power2 | unsorted | 1024 | 16384 | 1.59 ms | 1.60 ms | 1.60 ms | 1.59 ms | 1.59 ms | 1.59 ms | 1.60 ms | InterpSearch (1.59 ms) | 1.00x | -| sqrt | sorted_uniform | 64 | 1024 | 8.8 μs | 15.0 μs | 12.2 μs | 41.1 μs | 17.6 μs | 9.3 μs | 16.1 μs | Linear (8.8 μs) | 1.06x | -| sqrt | sorted_uniform | 64 | 4096 | 30.5 μs | 56.6 μs | 44.8 μs | 157.7 μs | 68.4 μs | 32.1 μs | 60.5 μs | Linear (30.5 μs) | 1.05x | -| sqrt | sorted_uniform | 64 | 16384 | 117.7 μs | 222.5 μs | 175.2 μs | 626.7 μs | 273.4 μs | 124.1 μs | 240.2 μs | Linear (117.7 μs) | 1.05x | -| sqrt | sorted_uniform | 256 | 1024 | 9.2 μs | 17.4 μs | 12.8 μs | 53.5 μs | 25.6 μs | 9.7 μs | 24.1 μs | Linear (9.2 μs) | 1.05x | -| sqrt | sorted_uniform | 256 | 4096 | 35.0 μs | 60.3 μs | 48.1 μs | 206.3 μs | 124.5 μs | 36.1 μs | 83.9 μs | Linear (35.0 μs) | 1.03x | -| sqrt | sorted_uniform | 256 | 16384 | 123.7 μs | 227.1 μs | 179.0 μs | 790.9 μs | 392.9 μs | 128.4 μs | 317.6 μs | Linear (123.7 μs) | 1.04x | -| sqrt | sorted_uniform | 1024 | 1024 | 10.7 μs | 18.2 μs | 12.8 μs | 64.7 μs | 59.8 μs | 10.7 μs | 45.8 μs | Linear (10.7 μs) | 1.00x | -| sqrt | sorted_uniform | 1024 | 4096 | 43.4 μs | 70.5 μs | 55.2 μs | 261.5 μs | 223.9 μs | 44.2 μs | 183.1 μs | Linear (43.4 μs) | 1.02x | -| sqrt | sorted_uniform | 1024 | 16384 | 139.2 μs | 237.4 μs | 191.6 μs | 966.5 μs | 588.2 μs | 144.8 μs | 488.2 μs | Linear (139.2 μs) | 1.04x | -| sqrt | sorted_dense_burst | 64 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 40.2 μs | 17.3 μs | 7.8 μs | 14.5 μs | Linear (7.4 μs) | 1.05x | -| sqrt | sorted_dense_burst | 64 | 4096 | 29.1 μs | 54.8 μs | 43.7 μs | 161.0 μs | 67.9 μs | 30.9 μs | 56.8 μs | Linear (29.1 μs) | 1.06x | -| sqrt | sorted_dense_burst | 64 | 16384 | 116.5 μs | 219.2 μs | 174.2 μs | 641.2 μs | 271.8 μs | 124.9 μs | 227.1 μs | Linear (116.5 μs) | 1.07x | -| sqrt | sorted_dense_burst | 256 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 50.4 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | -| sqrt | sorted_dense_burst | 256 | 4096 | 29.1 μs | 55.0 μs | 43.6 μs | 199.6 μs | 87.6 μs | 30.8 μs | 76.4 μs | Linear (29.1 μs) | 1.06x | -| sqrt | sorted_dense_burst | 256 | 16384 | 116.3 μs | 219.7 μs | 174.5 μs | 799.8 μs | 349.4 μs | 122.9 μs | 305.8 μs | Linear (116.3 μs) | 1.06x | -| sqrt | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 60.1 μs | 26.8 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.06x | -| sqrt | sorted_dense_burst | 1024 | 4096 | 29.3 μs | 55.0 μs | 43.6 μs | 240.6 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.3 μs) | 1.05x | -| sqrt | sorted_dense_burst | 1024 | 16384 | 116.3 μs | 232.9 μs | 173.9 μs | 963.5 μs | 429.0 μs | 124.9 μs | 383.1 μs | Linear (116.3 μs) | 1.07x | -| sqrt | unsorted | 64 | 1024 | 43.9 μs | 42.9 μs | 42.2 μs | 41.7 μs | 41.8 μs | 41.8 μs | 40.0 μs | InterpSearch (41.7 μs) | 1.00x | -| sqrt | unsorted | 64 | 4096 | 211.6 μs | 212.6 μs | 211.6 μs | 210.1 μs | 210.2 μs | 209.6 μs | 207.3 μs | InterpSearch (210.1 μs) | 1.00x | -| sqrt | unsorted | 64 | 16384 | 909.1 μs | 908.2 μs | 909.8 μs | 904.5 μs | 906.9 μs | 907.1 μs | 885.0 μs | InterpSearch (904.5 μs) | 1.00x | -| sqrt | unsorted | 256 | 1024 | 52.2 μs | 52.0 μs | 50.4 μs | 50.6 μs | 50.0 μs | 49.8 μs | 49.0 μs | Binary (50.0 μs) | 1.00x | -| sqrt | unsorted | 256 | 4096 | 290.0 μs | 288.4 μs | 287.8 μs | 284.3 μs | 281.2 μs | 284.2 μs | 281.4 μs | Binary (281.2 μs) | 1.01x | -| sqrt | unsorted | 256 | 16384 | 1.20 ms | 1.20 ms | 1.20 ms | 1.20 ms | 1.20 ms | 1.20 ms | 1.18 ms | ExpFromLeft (1.20 ms) | 1.01x | -| sqrt | unsorted | 1024 | 1024 | 74.3 μs | 71.3 μs | 70.1 μs | 69.9 μs | 69.5 μs | 69.3 μs | 71.7 μs | Binary (69.5 μs) | 1.00x | -| sqrt | unsorted | 1024 | 4096 | 379.5 μs | 375.1 μs | 375.2 μs | 374.3 μs | 375.4 μs | 374.1 μs | 377.7 μs | InterpSearch (374.3 μs) | 1.00x | -| sqrt | unsorted | 1024 | 16384 | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.54 ms | 1.55 ms | Gallop (1.54 ms) | 1.00x | -| plateau | sorted_uniform | 64 | 1024 | 7.9 μs | 14.7 μs | 11.0 μs | 39.4 μs | 17.0 μs | 7.8 μs | 14.7 μs | Linear (7.9 μs) | 0.99x | -| plateau | sorted_uniform | 64 | 4096 | 29.2 μs | 55.0 μs | 43.7 μs | 152.8 μs | 67.8 μs | 44.4 μs | 64.0 μs | Linear (29.2 μs) | 1.52x | -| plateau | sorted_uniform | 64 | 16384 | 116.6 μs | 219.7 μs | 174.0 μs | 606.6 μs | 274.9 μs | 123.1 μs | 234.7 μs | Linear (116.6 μs) | 1.06x | -| plateau | sorted_uniform | 256 | 1024 | 7.5 μs | 13.8 μs | 11.0 μs | 53.5 μs | 21.9 μs | 11.1 μs | 19.8 μs | Linear (7.5 μs) | 1.48x | -| plateau | sorted_uniform | 256 | 4096 | 29.8 μs | 58.4 μs | 43.5 μs | 194.1 μs | 87.4 μs | 30.9 μs | 78.4 μs | Linear (29.8 μs) | 1.04x | -| plateau | sorted_uniform | 256 | 16384 | 116.4 μs | 219.7 μs | 174.5 μs | 753.4 μs | 349.6 μs | 123.1 μs | 313.5 μs | Linear (116.4 μs) | 1.06x | -| plateau | sorted_uniform | 1024 | 1024 | 7.9 μs | 13.9 μs | 11.0 μs | 73.6 μs | 26.6 μs | 8.3 μs | 24.3 μs | Linear (7.9 μs) | 1.05x | -| plateau | sorted_uniform | 1024 | 4096 | 29.7 μs | 55.0 μs | 43.7 μs | 292.0 μs | 106.1 μs | 31.3 μs | 97.2 μs | Linear (29.7 μs) | 1.06x | -| plateau | sorted_uniform | 1024 | 16384 | 116.8 μs | 219.8 μs | 174.1 μs | 982.9 μs | 424.1 μs | 123.3 μs | 389.0 μs | Linear (116.8 μs) | 1.06x | -| plateau | sorted_dense_burst | 64 | 1024 | 7.4 μs | 13.8 μs | 10.3 μs | 40.1 μs | 17.1 μs | 7.8 μs | 14.3 μs | Linear (7.4 μs) | 1.05x | -| plateau | sorted_dense_burst | 64 | 4096 | 29.1 μs | 54.8 μs | 41.3 μs | 160.1 μs | 68.0 μs | 30.8 μs | 57.1 μs | Linear (29.1 μs) | 1.06x | -| plateau | sorted_dense_burst | 64 | 16384 | 116.5 μs | 219.2 μs | 164.9 μs | 640.2 μs | 272.5 μs | 122.8 μs | 228.6 μs | Linear (116.5 μs) | 1.05x | -| plateau | sorted_dense_burst | 256 | 1024 | 7.4 μs | 13.8 μs | 10.3 μs | 49.6 μs | 21.8 μs | 7.8 μs | 19.6 μs | Linear (7.4 μs) | 1.06x | -| plateau | sorted_dense_burst | 256 | 4096 | 29.3 μs | 55.0 μs | 41.3 μs | 197.6 μs | 87.0 μs | 30.9 μs | 78.2 μs | Linear (29.3 μs) | 1.06x | -| plateau | sorted_dense_burst | 256 | 16384 | 116.3 μs | 220.0 μs | 165.0 μs | 790.1 μs | 347.9 μs | 123.6 μs | 312.3 μs | Linear (116.3 μs) | 1.06x | -| plateau | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.8 μs | 10.4 μs | 60.6 μs | 26.7 μs | 7.8 μs | 24.2 μs | Linear (7.4 μs) | 1.05x | -| plateau | sorted_dense_burst | 1024 | 4096 | 29.1 μs | 55.0 μs | 41.3 μs | 242.2 μs | 106.6 μs | 30.9 μs | 96.8 μs | Linear (29.1 μs) | 1.06x | -| plateau | sorted_dense_burst | 1024 | 16384 | 116.3 μs | 219.7 μs | 164.8 μs | 969.5 μs | 426.9 μs | 123.0 μs | 386.8 μs | Linear (116.3 μs) | 1.06x | -| plateau | unsorted | 64 | 1024 | 23.1 μs | 23.2 μs | 23.1 μs | 23.0 μs | 23.3 μs | 23.0 μs | 22.7 μs | InterpSearch (23.0 μs) | 1.00x | -| plateau | unsorted | 64 | 4096 | 91.6 μs | 90.0 μs | 90.1 μs | 91.9 μs | 90.1 μs | 90.0 μs | 89.2 μs | Gallop (90.0 μs) | 1.00x | -| plateau | unsorted | 64 | 16384 | 362.5 μs | 363.0 μs | 360.2 μs | 368.4 μs | 363.0 μs | 360.0 μs | 358.7 μs | ExpFromLeft (360.2 μs) | 1.00x | -| plateau | unsorted | 256 | 1024 | 27.4 μs | 27.1 μs | 27.4 μs | 27.4 μs | 27.4 μs | 27.4 μs | 26.9 μs | Gallop (27.1 μs) | 1.01x | -| plateau | unsorted | 256 | 4096 | 108.5 μs | 108.5 μs | 108.4 μs | 108.5 μs | 108.7 μs | 108.4 μs | 107.6 μs | ExpFromLeft (108.4 μs) | 1.00x | -| plateau | unsorted | 256 | 16384 | 435.5 μs | 435.1 μs | 434.9 μs | 434.9 μs | 435.2 μs | 435.3 μs | 431.4 μs | InterpSearch (434.9 μs) | 1.00x | -| plateau | unsorted | 1024 | 1024 | 31.8 μs | 31.9 μs | 31.9 μs | 31.9 μs | 31.9 μs | 31.9 μs | 32.1 μs | Linear (31.8 μs) | 1.00x | -| plateau | unsorted | 1024 | 4096 | 128.4 μs | 128.0 μs | 128.8 μs | 128.3 μs | 128.2 μs | 128.3 μs | 129.2 μs | Gallop (128.0 μs) | 1.00x | -| plateau | unsorted | 1024 | 16384 | 513.6 μs | 513.8 μs | 513.7 μs | 513.9 μs | 513.6 μs | 513.8 μs | 518.4 μs | Binary (513.6 μs) | 1.00x | -| bimodal | sorted_uniform | 64 | 1024 | 7.5 μs | 14.4 μs | 11.2 μs | 42.7 μs | 17.1 μs | 7.9 μs | 14.9 μs | Linear (7.5 μs) | 1.05x | -| bimodal | sorted_uniform | 64 | 4096 | 30.1 μs | 56.5 μs | 44.4 μs | 163.6 μs | 68.3 μs | 31.7 μs | 58.1 μs | Linear (30.1 μs) | 1.06x | -| bimodal | sorted_uniform | 64 | 16384 | 117.7 μs | 222.5 μs | 175.0 μs | 647.1 μs | 272.2 μs | 124.2 μs | 230.0 μs | Linear (117.7 μs) | 1.06x | -| bimodal | sorted_uniform | 256 | 1024 | 8.1 μs | 14.5 μs | 11.3 μs | 55.3 μs | 22.1 μs | 8.4 μs | 20.6 μs | Linear (8.1 μs) | 1.04x | -| bimodal | sorted_uniform | 256 | 4096 | 30.2 μs | 58.3 μs | 45.2 μs | 211.2 μs | 88.8 μs | 31.8 μs | 80.5 μs | Linear (30.2 μs) | 1.05x | -| bimodal | sorted_uniform | 256 | 16384 | 121.6 μs | 226.5 μs | 178.2 μs | 807.1 μs | 360.7 μs | 127.9 μs | 312.0 μs | Linear (121.6 μs) | 1.05x | -| bimodal | sorted_uniform | 1024 | 1024 | 9.3 μs | 15.5 μs | 12.0 μs | 76.8 μs | 27.1 μs | 9.8 μs | 25.5 μs | Linear (9.3 μs) | 1.05x | -| bimodal | sorted_uniform | 1024 | 4096 | 32.0 μs | 59.4 μs | 45.5 μs | 325.5 μs | 125.7 μs | 33.4 μs | 109.0 μs | Linear (32.0 μs) | 1.04x | -| bimodal | sorted_uniform | 1024 | 16384 | 127.3 μs | 235.4 μs | 184.6 μs | 1.08 ms | 526.3 μs | 134.0 μs | 447.4 μs | Linear (127.3 μs) | 1.05x | -| bimodal | sorted_dense_burst | 64 | 1024 | 7.3 μs | 13.8 μs | 10.9 μs | 42.8 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.3 μs) | 1.06x | -| bimodal | sorted_dense_burst | 64 | 4096 | 29.2 μs | 54.8 μs | 43.6 μs | 167.6 μs | 67.9 μs | 30.8 μs | 56.8 μs | Linear (29.2 μs) | 1.05x | -| bimodal | sorted_dense_burst | 64 | 16384 | 116.3 μs | 219.3 μs | 173.9 μs | 666.1 μs | 271.6 μs | 123.4 μs | 227.4 μs | Linear (116.3 μs) | 1.06x | -| bimodal | sorted_dense_burst | 256 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 55.9 μs | 21.9 μs | 7.8 μs | 19.2 μs | Linear (7.4 μs) | 1.06x | -| bimodal | sorted_dense_burst | 256 | 4096 | 29.2 μs | 55.0 μs | 43.5 μs | 204.1 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (29.2 μs) | 1.06x | -| bimodal | sorted_dense_burst | 256 | 16384 | 116.4 μs | 219.6 μs | 177.0 μs | 799.7 μs | 349.2 μs | 122.8 μs | 305.8 μs | Linear (116.4 μs) | 1.06x | -| bimodal | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 13.8 μs | 10.9 μs | 75.2 μs | 26.7 μs | 7.8 μs | 23.9 μs | Linear (7.4 μs) | 1.06x | -| bimodal | sorted_dense_burst | 1024 | 4096 | 29.2 μs | 55.0 μs | 43.6 μs | 304.7 μs | 106.8 μs | 30.9 μs | 95.7 μs | Linear (29.2 μs) | 1.06x | -| bimodal | sorted_dense_burst | 1024 | 16384 | 116.9 μs | 219.7 μs | 173.9 μs | 1.03 ms | 427.2 μs | 123.0 μs | 383.0 μs | Linear (116.9 μs) | 1.05x | -| bimodal | unsorted | 64 | 1024 | 22.2 μs | 22.3 μs | 21.4 μs | 21.4 μs | 21.5 μs | 21.4 μs | 21.0 μs | ExpFromLeft (21.4 μs) | 1.00x | -| bimodal | unsorted | 64 | 4096 | 88.3 μs | 90.8 μs | 87.9 μs | 87.7 μs | 88.2 μs | 88.0 μs | 86.1 μs | InterpSearch (87.7 μs) | 1.00x | -| bimodal | unsorted | 64 | 16384 | 365.4 μs | 365.1 μs | 365.6 μs | 365.2 μs | 365.2 μs | 365.1 μs | 353.0 μs | Gallop (365.1 μs) | 1.00x | -| bimodal | unsorted | 256 | 1024 | 29.0 μs | 28.7 μs | 28.7 μs | 28.7 μs | 28.8 μs | 28.7 μs | 27.2 μs | ExpFromLeft (28.7 μs) | 1.00x | -| bimodal | unsorted | 256 | 4096 | 119.8 μs | 119.5 μs | 119.6 μs | 119.8 μs | 119.5 μs | 119.5 μs | 112.4 μs | Binary (119.5 μs) | 1.00x | -| bimodal | unsorted | 256 | 16384 | 490.2 μs | 490.4 μs | 490.4 μs | 490.2 μs | 490.4 μs | 493.5 μs | 467.1 μs | Linear (490.2 μs) | 1.01x | -| bimodal | unsorted | 1024 | 1024 | 35.4 μs | 34.7 μs | 34.7 μs | 34.7 μs | 34.6 μs | 34.7 μs | 33.8 μs | Binary (34.6 μs) | 1.00x | -| bimodal | unsorted | 1024 | 4096 | 143.9 μs | 143.6 μs | 143.4 μs | 143.5 μs | 143.4 μs | 143.7 μs | 138.1 μs | ExpFromLeft (143.4 μs) | 1.00x | -| bimodal | unsorted | 1024 | 16384 | 620.9 μs | 618.2 μs | 617.4 μs | 616.5 μs | 616.4 μs | 616.2 μs | 603.8 μs | Binary (616.4 μs) | 1.00x | -| near_linear | sorted_uniform | 64 | 1024 | 8.8 μs | 14.9 μs | 12.0 μs | 30.5 μs | 18.1 μs | 9.2 μs | 16.0 μs | Linear (8.8 μs) | 1.04x | -| near_linear | sorted_uniform | 64 | 4096 | 30.5 μs | 55.9 μs | 44.7 μs | 112.6 μs | 68.5 μs | 32.0 μs | 60.2 μs | Linear (30.5 μs) | 1.05x | -| near_linear | sorted_uniform | 64 | 16384 | 117.6 μs | 220.1 μs | 175.6 μs | 441.2 μs | 270.6 μs | 124.1 μs | 236.6 μs | Linear (117.6 μs) | 1.06x | -| near_linear | sorted_uniform | 256 | 1024 | 9.9 μs | 17.7 μs | 14.1 μs | 37.2 μs | 28.1 μs | 10.3 μs | 25.6 μs | Linear (9.9 μs) | 1.04x | -| near_linear | sorted_uniform | 256 | 4096 | 34.7 μs | 59.3 μs | 48.1 μs | 122.7 μs | 128.1 μs | 36.3 μs | 84.1 μs | Linear (34.7 μs) | 1.05x | -| near_linear | sorted_uniform | 256 | 16384 | 121.8 μs | 223.9 μs | 178.9 μs | 450.9 μs | 386.7 μs | 128.6 μs | 316.6 μs | Linear (121.8 μs) | 1.06x | -| near_linear | sorted_uniform | 1024 | 1024 | 10.4 μs | 17.4 μs | 12.9 μs | 38.6 μs | 70.7 μs | 10.6 μs | 54.4 μs | Linear (10.4 μs) | 1.02x | -| near_linear | sorted_uniform | 1024 | 4096 | 47.1 μs | 73.3 μs | 58.9 μs | 149.9 μs | 236.2 μs | 47.2 μs | 191.7 μs | Linear (47.1 μs) | 1.00x | -| near_linear | sorted_uniform | 1024 | 16384 | 139.4 μs | 237.2 μs | 192.5 μs | 490.9 μs | 590.3 μs | 144.9 μs | 483.9 μs | Linear (139.4 μs) | 1.04x | -| near_linear | sorted_dense_burst | 64 | 1024 | 7.3 μs | 13.9 μs | 10.9 μs | 27.5 μs | 17.0 μs | 7.8 μs | 14.2 μs | Linear (7.3 μs) | 1.06x | -| near_linear | sorted_dense_burst | 64 | 4096 | 29.2 μs | 55.6 μs | 43.5 μs | 109.7 μs | 70.5 μs | 44.3 μs | 56.8 μs | Linear (29.2 μs) | 1.52x | -| near_linear | sorted_dense_burst | 64 | 16384 | 116.4 μs | 222.1 μs | 173.8 μs | 438.8 μs | 271.9 μs | 122.9 μs | 227.2 μs | Linear (116.4 μs) | 1.06x | -| near_linear | sorted_dense_burst | 256 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 27.6 μs | 21.9 μs | 7.8 μs | 19.1 μs | Linear (7.4 μs) | 1.06x | -| near_linear | sorted_dense_burst | 256 | 4096 | 31.2 μs | 55.7 μs | 43.7 μs | 109.6 μs | 87.3 μs | 30.8 μs | 76.4 μs | Linear (31.2 μs) | 0.99x | -| near_linear | sorted_dense_burst | 256 | 16384 | 116.4 μs | 222.3 μs | 174.2 μs | 438.9 μs | 349.2 μs | 122.9 μs | 305.9 μs | Linear (116.4 μs) | 1.06x | -| near_linear | sorted_dense_burst | 1024 | 1024 | 7.4 μs | 14.0 μs | 10.9 μs | 27.4 μs | 26.7 μs | 7.8 μs | 24.0 μs | Linear (7.4 μs) | 1.05x | -| near_linear | sorted_dense_burst | 1024 | 4096 | 29.3 μs | 55.5 μs | 43.5 μs | 109.7 μs | 106.8 μs | 30.8 μs | 95.7 μs | Linear (29.3 μs) | 1.05x | -| near_linear | sorted_dense_burst | 1024 | 16384 | 116.4 μs | 222.3 μs | 173.9 μs | 438.3 μs | 427.3 μs | 123.4 μs | 383.0 μs | Linear (116.4 μs) | 1.06x | -| near_linear | unsorted | 64 | 1024 | 44.2 μs | 41.8 μs | 41.6 μs | 42.8 μs | 41.1 μs | 41.0 μs | 39.7 μs | Binary (41.1 μs) | 1.00x | -| near_linear | unsorted | 64 | 4096 | 232.4 μs | 232.0 μs | 230.3 μs | 229.6 μs | 229.8 μs | 229.6 μs | 227.9 μs | InterpSearch (229.6 μs) | 1.00x | -| near_linear | unsorted | 64 | 16384 | 982.1 μs | 977.6 μs | 978.2 μs | 978.3 μs | 982.8 μs | 980.8 μs | 971.5 μs | Gallop (977.6 μs) | 1.00x | -| near_linear | unsorted | 256 | 1024 | 58.4 μs | 55.6 μs | 53.3 μs | 53.1 μs | 52.8 μs | 52.7 μs | 51.0 μs | Binary (52.8 μs) | 1.00x | -| near_linear | unsorted | 256 | 4096 | 317.0 μs | 312.3 μs | 311.2 μs | 312.5 μs | 310.4 μs | 313.9 μs | 311.2 μs | Binary (310.4 μs) | 1.01x | -| near_linear | unsorted | 256 | 16384 | 1.31 ms | 1.31 ms | 1.31 ms | 1.31 ms | 1.31 ms | 1.31 ms | 1.30 ms | ExpFromLeft (1.31 ms) | 1.00x | -| near_linear | unsorted | 1024 | 1024 | 81.2 μs | 79.0 μs | 77.7 μs | 76.6 μs | 76.3 μs | 76.2 μs | 77.2 μs | Binary (76.3 μs) | 1.00x | -| near_linear | unsorted | 1024 | 4096 | 411.7 μs | 409.2 μs | 409.7 μs | 408.9 μs | 409.0 μs | 408.5 μs | 409.2 μs | InterpSearch (408.9 μs) | 1.00x | -| near_linear | unsorted | 1024 | 16384 | 1.67 ms | 1.68 ms | 1.68 ms | 1.67 ms | 1.67 ms | 1.67 ms | 1.69 ms | Binary (1.67 ms) | 1.00x | - -**Auto verdict over 270 cells**: 263 within 20% of best, 4 worse than 20% slowdown, 3 effectively-faster-than-best. diff --git a/bench/results_tune.md b/bench/results_tune.md deleted file mode 100644 index 331fc72..0000000 --- a/bench/results_tune.md +++ /dev/null @@ -1,103 +0,0 @@ - -## Tune: LinearScan vs ExpFromLeft crossover (n=4096, uniform) - -| gap (≈n/m) | m | Linear | ExpFromLeft | winner | margin | -|---|---|---|---|---|---| -| 1 | 4096 | 66.1 μs | 70.8 μs | Linear | 7% | -| 2 | 2048 | 28.3 μs | 32.5 μs | Linear | 15% | -| 3 | 1365 | 21.0 μs | 22.2 μs | Linear | 6% | -| 4 | 1024 | 15.8 μs | 16.8 μs | Linear | 7% | -| 6 | 682 | 12.5 μs | 12.1 μs | ExpFromLeft | 3% | -| 8 | 512 | 10.7 μs | 9.6 μs | ExpFromLeft | 11% | -| 12 | 341 | 9.4 μs | 6.8 μs | ExpFromLeft | 37% | -| 16 | 256 | 8.5 μs | 5.2 μs | ExpFromLeft | 66% | -| 24 | 170 | 8.1 μs | 3.8 μs | ExpFromLeft | 112% | -| 32 | 128 | 8.2 μs | 3.0 μs | ExpFromLeft | 172% | -| 48 | 85 | 7.5 μs | 2.2 μs | ExpFromLeft | 246% | -| 64 | 64 | 7.3 μs | 1.8 μs | ExpFromLeft | 317% | -| 96 | 42 | 6.8 μs | 1.2 μs | ExpFromLeft | 452% | -| 128 | 32 | 6.5 μs | 970 ns | ExpFromLeft | 575% | -| 192 | 21 | 5.9 μs | 750 ns | ExpFromLeft | 691% | -| 256 | 16 | 5.8 μs | 580 ns | ExpFromLeft | 893% | - -## Tune: ExpFromLeft vs InterpolationSearch crossover (n=65536, uniform) - -| gap (≈n/m) | m | ExpFromLeft | InterpSearch | winner | margin | -|---|---|---|---|---|---| -| 8 | 8192 | 355.6 μs | 324.0 μs | InterpSearch | 10% | -| 16 | 4096 | 209.2 μs | 166.0 μs | InterpSearch | 26% | -| 24 | 2730 | 143.0 μs | 113.3 μs | InterpSearch | 26% | -| 32 | 2048 | 104.2 μs | 84.0 μs | InterpSearch | 24% | -| 48 | 1365 | 61.8 μs | 55.2 μs | InterpSearch | 12% | -| 64 | 1024 | 44.1 μs | 41.2 μs | InterpSearch | 7% | -| 96 | 682 | 27.4 μs | 26.4 μs | InterpSearch | 4% | -| 128 | 512 | 19.7 μs | 20.0 μs | ExpFromLeft | 2% | -| 256 | 256 | 10.2 μs | 9.5 μs | InterpSearch | 7% | -| 512 | 128 | 5.0 μs | 4.6 μs | InterpSearch | 9% | -| 1024 | 64 | 2.7 μs | 2.1 μs | InterpSearch | 29% | -| 4096 | 16 | 790 ns | 490 ns | InterpSearch | 61% | -| 16384 | 4 | 240 ns | 150 ns | InterpSearch | 60% | -| 65536 | 1 | 80 ns | 60 ns | InterpSearch | 33% | - -## Tune: minimum n at which InterpolationSearch wins (uniform, m=16) - -| n | gap | ExpFromLeft | InterpSearch | winner | margin | -|---|---|---|---|---|---| -| 32 | 2 | 250 ns | 470 ns | ExpFromLeft | 88% | -| 64 | 4 | 290 ns | 470 ns | ExpFromLeft | 62% | -| 128 | 8 | 310 ns | 490 ns | ExpFromLeft | 58% | -| 256 | 16 | 380 ns | 500 ns | ExpFromLeft | 32% | -| 512 | 32 | 420 ns | 470 ns | ExpFromLeft | 12% | -| 1024 | 64 | 460 ns | 500 ns | ExpFromLeft | 9% | -| 2048 | 128 | 520 ns | 480 ns | InterpSearch | 8% | -| 4096 | 256 | 560 ns | 470 ns | InterpSearch | 19% | -| 8192 | 512 | 600 ns | 480 ns | InterpSearch | 25% | -| 16384 | 1024 | 650 ns | 460 ns | InterpSearch | 41% | -| 65536 | 4096 | 740 ns | 480 ns | InterpSearch | 54% | -| 262144 | 16384 | 870 ns | 460 ns | InterpSearch | 89% | - -## Tune: minimum m at which InterpolationSearch wins (uniform, n=65536) - -| m | gap | ExpFromLeft | InterpSearch | winner | margin | -|---|---|---|---|---|---| -| 1 | 65536 | 80 ns | 70 ns | InterpSearch | 14% | -| 2 | 32768 | 150 ns | 90 ns | InterpSearch | 67% | -| 3 | 21845 | 180 ns | 120 ns | InterpSearch | 50% | -| 4 | 16384 | 210 ns | 140 ns | InterpSearch | 50% | -| 6 | 10922 | 310 ns | 200 ns | InterpSearch | 55% | -| 8 | 8192 | 430 ns | 240 ns | InterpSearch | 79% | -| 12 | 5461 | 600 ns | 360 ns | InterpSearch | 67% | -| 16 | 4096 | 760 ns | 470 ns | InterpSearch | 62% | -| 24 | 2730 | 1.1 μs | 680 ns | InterpSearch | 59% | -| 32 | 2048 | 1.4 μs | 1.0 μs | InterpSearch | 38% | -| 64 | 1024 | 2.6 μs | 2.0 μs | InterpSearch | 29% | -| 128 | 512 | 4.9 μs | 4.3 μs | InterpSearch | 12% | -| 256 | 256 | 9.4 μs | 9.5 μs | ExpFromLeft | 1% | -| 1024 | 64 | 43.2 μs | 40.9 μs | InterpSearch | 6% | -| 4096 | 16 | 200.7 μs | 165.0 μs | InterpSearch | 22% | - -## Tune: InterpolationSearch downside on non-linear data (m=256) - -| spacing | n | ExpFromLeft | InterpSearch | InterpSearch slowdown | -|---|---|---|---|---| -| log | 1024 | 3.2 μs | 21.4 μs | 6.78x | -| log | 16384 | 6.1 μs | 29.5 μs | 4.81x | -| log | 262144 | 10.3 μs | 44.8 μs | 4.33x | -| random | 1024 | 3.8 μs | 9.7 μs | 2.55x | -| random | 16384 | 7.2 μs | 12.4 μs | 1.71x | -| random | 262144 | 13.1 μs | 19.3 μs | 1.48x | -| two_scale | 1024 | 3.3 μs | 23.3 μs | 7.09x | -| two_scale | 16384 | 6.3 μs | 31.0 μs | 4.94x | -| two_scale | 262144 | 10.9 μs | 46.9 μs | 4.29x | -| power2 | 1024 | 3.6 μs | 22.5 μs | 6.18x | -| power2 | 16384 | 7.0 μs | 31.5 μs | 4.48x | -| power2 | 262144 | 12.4 μs | 48.1 μs | 3.88x | -| sqrt | 1024 | 3.7 μs | 21.1 μs | 5.77x | -| sqrt | 16384 | 7.2 μs | 29.2 μs | 4.06x | -| sqrt | 262144 | 13.2 μs | 46.4 μs | 3.52x | -| plateau | 1024 | 2.7 μs | 22.8 μs | 8.32x | -| plateau | 16384 | 2.8 μs | 29.6 μs | 10.74x | -| plateau | 262144 | 2.8 μs | 39.3 μs | 14.11x | -| bimodal | 1024 | 3.3 μs | 23.6 μs | 7.19x | -| bimodal | 16384 | 4.3 μs | 30.4 μs | 7.10x | -| bimodal | 262144 | 4.6 μs | 42.1 μs | 9.19x | diff --git a/bench/results_validate.md b/bench/results_validate.md deleted file mode 100644 index 9783452..0000000 --- a/bench/results_validate.md +++ /dev/null @@ -1,3927 +0,0 @@ - -## Validation sweep (many cells) - -| spacing | query pattern | n | m | Linear | Gallop | ExpFromLeft | InterpSearch | Binary | Auto | base | best | best/auto | -|---|---|---|---|---|---|---|---|---|---|---|---|---| -| uniform | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 40 ns | ExpFromLeft (50 ns) | 1.20x | -| uniform | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| uniform | sorted_uniform | 16 | 16 | 189 ns | 290 ns | 220 ns | 470 ns | 230 ns | 210 ns | 190 ns | Linear (189 ns) | 1.11x | -| uniform | sorted_uniform | 16 | 64 | 560 ns | 990 ns | 730 ns | 1.9 μs | 990 ns | 590 ns | 860 ns | Linear (560 ns) | 1.05x | -| uniform | sorted_uniform | 16 | 256 | 2.3 μs | 3.7 μs | 3.0 μs | 7.8 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.02x | -| uniform | sorted_uniform | 16 | 1024 | 8.1 μs | 14.1 μs | 10.8 μs | 28.1 μs | 12.2 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 0.99x | -| uniform | sorted_uniform | 16 | 4096 | 31.1 μs | 55.3 μs | 42.3 μs | 109.1 μs | 48.1 μs | 31.1 μs | 40.6 μs | Linear (31.1 μs) | 1.00x | -| uniform | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| uniform | sorted_uniform | 64 | 4 | 120 ns | 130 ns | 120 ns | 150 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | -| uniform | sorted_uniform | 64 | 16 | 260 ns | 350 ns | 280 ns | 470 ns | 300 ns | 270 ns | 270 ns | Linear (260 ns) | 1.04x | -| uniform | sorted_uniform | 64 | 64 | 640 ns | 1.1 μs | 750 ns | 2.1 μs | 1.4 μs | 670 ns | 1.2 μs | Linear (640 ns) | 1.05x | -| uniform | sorted_uniform | 64 | 256 | 2.2 μs | 4.2 μs | 3.1 μs | 8.7 μs | 5.2 μs | 2.2 μs | 4.8 μs | Linear (2.2 μs) | 1.00x | -| uniform | sorted_uniform | 64 | 1024 | 9.2 μs | 14.9 μs | 11.7 μs | 31.4 μs | 17.8 μs | 9.2 μs | 16.0 μs | Linear (9.2 μs) | 1.00x | -| uniform | sorted_uniform | 64 | 4096 | 32.2 μs | 56.4 μs | 43.2 μs | 112.9 μs | 67.4 μs | 32.2 μs | 60.3 μs | Linear (32.2 μs) | 1.00x | -| uniform | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_uniform | 256 | 4 | 170 ns | 140 ns | 120 ns | 150 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | -| uniform | sorted_uniform | 256 | 16 | 520 ns | 460 ns | 370 ns | 460 ns | 370 ns | 400 ns | 340 ns | ExpFromLeft (370 ns) | 1.08x | -| uniform | sorted_uniform | 256 | 64 | 900 ns | 1.3 μs | 1.0 μs | 1.9 μs | 1.6 μs | 940 ns | 1.4 μs | Linear (900 ns) | 1.04x | -| uniform | sorted_uniform | 256 | 256 | 2.4 μs | 4.1 μs | 2.9 μs | 8.8 μs | 7.5 μs | 2.5 μs | 6.9 μs | Linear (2.4 μs) | 1.04x | -| uniform | sorted_uniform | 256 | 1024 | 9.8 μs | 17.9 μs | 13.7 μs | 36.0 μs | 27.3 μs | 9.9 μs | 24.9 μs | Linear (9.8 μs) | 1.01x | -| uniform | sorted_uniform | 256 | 4096 | 36.6 μs | 59.6 μs | 46.6 μs | 125.3 μs | 91.6 μs | 36.5 μs | 83.6 μs | Linear (36.6 μs) | 1.00x | -| uniform | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_uniform | 1024 | 4 | 1.1 μs | 180 ns | 160 ns | 150 ns | 150 ns | 200 ns | 130 ns | InterpSearch (150 ns) | 1.33x | -| uniform | sorted_uniform | 1024 | 16 | 1.7 μs | 600 ns | 470 ns | 460 ns | 440 ns | 530 ns | 400 ns | Binary (440 ns) | 1.20x | -| uniform | sorted_uniform | 1024 | 64 | 2.1 μs | 1.8 μs | 1.4 μs | 2.0 μs | 1.8 μs | 2.2 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.58x | -| uniform | sorted_uniform | 1024 | 256 | 3.5 μs | 5.4 μs | 3.8 μs | 8.8 μs | 7.8 μs | 3.6 μs | 7.5 μs | Linear (3.5 μs) | 1.01x | -| uniform | sorted_uniform | 1024 | 1024 | 10.7 μs | 18.1 μs | 12.2 μs | 38.4 μs | 58.6 μs | 10.4 μs | 54.2 μs | Linear (10.7 μs) | 0.98x | -| uniform | sorted_uniform | 1024 | 4096 | 48.5 μs | 73.1 μs | 57.3 μs | 153.8 μs | 192.6 μs | 48.4 μs | 190.8 μs | Linear (48.5 μs) | 1.00x | -| uniform | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_uniform | 4096 | 4 | 5.4 μs | 240 ns | 210 ns | 150 ns | 160 ns | 190 ns | 140 ns | InterpSearch (150 ns) | 1.27x | -| uniform | sorted_uniform | 4096 | 16 | 4.8 μs | 710 ns | 550 ns | 480 ns | 530 ns | 559 ns | 490 ns | InterpSearch (480 ns) | 1.16x | -| uniform | sorted_uniform | 4096 | 64 | 7.5 μs | 2.3 μs | 1.8 μs | 2.1 μs | 2.0 μs | 2.3 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.29x | -| uniform | sorted_uniform | 4096 | 256 | 8.5 μs | 7.1 μs | 5.4 μs | 9.3 μs | 10.8 μs | 9.6 μs | 9.9 μs | ExpFromLeft (5.4 μs) | 1.77x | -| uniform | sorted_uniform | 4096 | 1024 | 16.8 μs | 23.6 μs | 17.0 μs | 38.5 μs | 97.6 μs | 15.3 μs | 93.0 μs | Linear (16.8 μs) | 0.91x | -| uniform | sorted_uniform | 4096 | 4096 | 66.7 μs | 93.9 μs | 70.7 μs | 160.5 μs | 298.2 μs | 63.0 μs | 291.0 μs | Linear (66.7 μs) | 0.95x | -| uniform | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_uniform | 16384 | 4 | 12.2 μs | 260 ns | 209 ns | 140 ns | 180 ns | 190 ns | 170 ns | InterpSearch (140 ns) | 1.36x | -| uniform | sorted_uniform | 16384 | 16 | 16.7 μs | 850 ns | 640 ns | 470 ns | 600 ns | 530 ns | 540 ns | InterpSearch (470 ns) | 1.13x | -| uniform | sorted_uniform | 16384 | 64 | 24.0 μs | 3.0 μs | 2.3 μs | 2.0 μs | 2.4 μs | 2.3 μs | 2.3 μs | InterpSearch (2.0 μs) | 1.14x | -| uniform | sorted_uniform | 16384 | 256 | 30.4 μs | 9.2 μs | 7.2 μs | 9.2 μs | 13.1 μs | 9.8 μs | 13.7 μs | ExpFromLeft (7.2 μs) | 1.36x | -| uniform | sorted_uniform | 16384 | 1024 | 40.3 μs | 36.7 μs | 26.4 μs | 38.5 μs | 124.0 μs | 40.2 μs | 127.0 μs | ExpFromLeft (26.4 μs) | 1.52x | -| uniform | sorted_uniform | 16384 | 4096 | 114.7 μs | 162.3 μs | 121.8 μs | 160.3 μs | 399.4 μs | 111.0 μs | 392.5 μs | Linear (114.7 μs) | 0.97x | -| uniform | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_uniform | 65536 | 4 | 57.1 μs | 300 ns | 240 ns | 150 ns | 200 ns | 190 ns | 180 ns | InterpSearch (150 ns) | 1.27x | -| uniform | sorted_uniform | 65536 | 16 | 75.7 μs | 1.0 μs | 760 ns | 470 ns | 700 ns | 540 ns | 660 ns | InterpSearch (470 ns) | 1.15x | -| uniform | sorted_uniform | 65536 | 64 | 91.9 μs | 3.6 μs | 2.6 μs | 2.0 μs | 2.8 μs | 2.2 μs | 2.6 μs | InterpSearch (2.0 μs) | 1.08x | -| uniform | sorted_uniform | 65536 | 256 | 101.3 μs | 12.5 μs | 9.7 μs | 9.2 μs | 16.3 μs | 9.7 μs | 16.6 μs | InterpSearch (9.2 μs) | 1.05x | -| uniform | sorted_uniform | 65536 | 1024 | 122.0 μs | 61.1 μs | 44.4 μs | 40.2 μs | 155.6 μs | 42.1 μs | 161.9 μs | InterpSearch (40.2 μs) | 1.05x | -| uniform | sorted_uniform | 65536 | 4096 | 197.8 μs | 251.6 μs | 199.3 μs | 163.8 μs | 488.6 μs | 170.5 μs | 497.6 μs | InterpSearch (163.8 μs) | 1.04x | -| uniform | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 60 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| uniform | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 230 ns | 510 ns | 240 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | -| uniform | sorted_dense_burst | 16 | 64 | 560 ns | 960 ns | 740 ns | 1.8 μs | 800 ns | 580 ns | 680 ns | Linear (560 ns) | 1.04x | -| uniform | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.7 μs | 2.7 μs | 7.0 μs | 3.0 μs | 2.1 μs | 3.3 μs | Linear (2.0 μs) | 1.06x | -| uniform | sorted_dense_burst | 16 | 1024 | 7.8 μs | 14.5 μs | 10.6 μs | 28.0 μs | 12.0 μs | 8.3 μs | 9.9 μs | Linear (7.8 μs) | 1.06x | -| uniform | sorted_dense_burst | 16 | 4096 | 31.2 μs | 58.0 μs | 41.9 μs | 108.0 μs | 47.2 μs | 32.9 μs | 38.5 μs | Linear (31.2 μs) | 1.05x | -| uniform | sorted_dense_burst | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| uniform | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 100 ns | 150 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| uniform | sorted_dense_burst | 64 | 16 | 180 ns | 280 ns | 230 ns | 490 ns | 310 ns | 200 ns | 270 ns | Linear (180 ns) | 1.11x | -| uniform | sorted_dense_burst | 64 | 64 | 550 ns | 940 ns | 730 ns | 1.8 μs | 1.1 μs | 580 ns | 920 ns | Linear (550 ns) | 1.05x | -| uniform | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 6.9 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.95x | -| uniform | sorted_dense_burst | 64 | 1024 | 8.3 μs | 13.8 μs | 10.4 μs | 27.3 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (8.3 μs) | 0.94x | -| uniform | sorted_dense_burst | 64 | 4096 | 32.8 μs | 54.9 μs | 42.1 μs | 108.8 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (32.8 μs) | 0.94x | -| uniform | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 50 ns | InterpSearch (60 ns) | 1.00x | -| uniform | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 130 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| uniform | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 510 ns | 380 ns | 200 ns | 350 ns | Linear (170 ns) | 1.18x | -| uniform | sorted_dense_burst | 256 | 64 | 550 ns | 930 ns | 740 ns | 1.8 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | -| uniform | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 5.4 μs | 2.1 μs | 4.8 μs | Linear (2.0 μs) | 1.08x | -| uniform | sorted_dense_burst | 256 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 27.3 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.01x | -| uniform | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 109.2 μs | 85.8 μs | 32.9 μs | 76.4 μs | Linear (30.8 μs) | 1.07x | -| uniform | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 150 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | -| uniform | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 240 ns | 490 ns | 459 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | -| uniform | sorted_dense_burst | 1024 | 64 | 570 ns | 930 ns | 730 ns | 1.8 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (570 ns) | 1.04x | -| uniform | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 27.4 μs | 26.4 μs | 8.3 μs | 24.0 μs | Linear (7.8 μs) | 1.07x | -| uniform | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 108.5 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_dense_burst | 4096 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 170 ns | 120 ns | 140 ns | Linear (100 ns) | 1.20x | -| uniform | sorted_dense_burst | 4096 | 16 | 190 ns | 290 ns | 240 ns | 490 ns | 540 ns | 210 ns | 480 ns | Linear (190 ns) | 1.11x | -| uniform | sorted_dense_burst | 4096 | 64 | 570 ns | 940 ns | 750 ns | 1.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (570 ns) | 1.04x | -| uniform | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | -| uniform | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 27.3 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | -| uniform | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 108.8 μs | 124.6 μs | 30.8 μs | 114.1 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | -| uniform | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 240 ns | 480 ns | 620 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | -| uniform | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 750 ns | 1.8 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | -| uniform | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | -| uniform | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 27.3 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 0.99x | -| uniform | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 54.9 μs | 42.1 μs | 108.9 μs | 144.2 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 150 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| uniform | sorted_dense_burst | 65536 | 16 | 190 ns | 290 ns | 250 ns | 500 ns | 690 ns | 210 ns | 640 ns | Linear (190 ns) | 1.11x | -| uniform | sorted_dense_burst | 65536 | 64 | 570 ns | 940 ns | 750 ns | 1.8 μs | 2.6 μs | 610 ns | 2.4 μs | Linear (570 ns) | 1.07x | -| uniform | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 27.4 μs | 40.8 μs | 7.8 μs | 38.2 μs | Linear (7.8 μs) | 0.99x | -| uniform | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 41.9 μs | 108.9 μs | 163.2 μs | 30.8 μs | 152.4 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_near_start | 16 | 1 | 50 ns | 60 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_near_start | 16 | 4 | 90 ns | 130 ns | 110 ns | 150 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | -| uniform | sorted_near_start | 16 | 16 | 190 ns | 280 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | -| uniform | sorted_near_start | 16 | 64 | 570 ns | 950 ns | 730 ns | 1.8 μs | 800 ns | 600 ns | 670 ns | Linear (570 ns) | 1.05x | -| uniform | sorted_near_start | 16 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 6.8 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_near_start | 16 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 27.2 μs | 12.2 μs | 8.0 μs | 10.3 μs | Linear (7.9 μs) | 1.01x | -| uniform | sorted_near_start | 16 | 4096 | 31.1 μs | 55.1 μs | 42.3 μs | 106.9 μs | 47.8 μs | 31.1 μs | 40.3 μs | Linear (31.1 μs) | 1.00x | -| uniform | sorted_near_start | 64 | 1 | 60 ns | 60 ns | 50 ns | 69 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_near_start | 64 | 4 | 90 ns | 120 ns | 100 ns | 150 ns | 100 ns | 110 ns | 90 ns | Linear (90 ns) | 1.22x | -| uniform | sorted_near_start | 64 | 16 | 260 ns | 320 ns | 240 ns | 480 ns | 330 ns | 280 ns | 290 ns | ExpFromLeft (240 ns) | 1.17x | -| uniform | sorted_near_start | 64 | 64 | 670 ns | 1.0 μs | 800 ns | 1.8 μs | 1.1 μs | 690 ns | 1.0 μs | Linear (670 ns) | 1.03x | -| uniform | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.0 μs | 4.2 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | -| uniform | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 27.5 μs | 17.2 μs | 7.9 μs | 15.5 μs | Linear (7.9 μs) | 1.00x | -| uniform | sorted_near_start | 64 | 4096 | 31.8 μs | 55.9 μs | 43.0 μs | 110.6 μs | 67.3 μs | 31.8 μs | 60.5 μs | Linear (31.8 μs) | 1.00x | -| uniform | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_near_start | 256 | 4 | 320 ns | 140 ns | 120 ns | 150 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | -| uniform | sorted_near_start | 256 | 16 | 440 ns | 330 ns | 260 ns | 500 ns | 480 ns | 280 ns | 410 ns | ExpFromLeft (260 ns) | 1.08x | -| uniform | sorted_near_start | 256 | 64 | 800 ns | 1.1 μs | 790 ns | 2.1 μs | 1.6 μs | 840 ns | 1.4 μs | ExpFromLeft (790 ns) | 1.06x | -| uniform | sorted_near_start | 256 | 256 | 2.6 μs | 4.0 μs | 3.1 μs | 7.7 μs | 5.6 μs | 2.7 μs | 5.1 μs | Linear (2.6 μs) | 1.03x | -| uniform | sorted_near_start | 256 | 1024 | 8.4 μs | 14.4 μs | 11.0 μs | 29.5 μs | 22.3 μs | 8.4 μs | 20.4 μs | Linear (8.4 μs) | 1.00x | -| uniform | sorted_near_start | 256 | 4096 | 31.6 μs | 56.1 μs | 42.6 μs | 117.8 μs | 89.1 μs | 31.6 μs | 81.6 μs | Linear (31.6 μs) | 1.00x | -| uniform | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 69 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_near_start | 1024 | 4 | 380 ns | 170 ns | 140 ns | 150 ns | 130 ns | 200 ns | 130 ns | Binary (130 ns) | 1.54x | -| uniform | sorted_near_start | 1024 | 16 | 1.1 μs | 390 ns | 310 ns | 490 ns | 500 ns | 330 ns | 470 ns | ExpFromLeft (310 ns) | 1.06x | -| uniform | sorted_near_start | 1024 | 64 | 2.5 μs | 1.2 μs | 900 ns | 2.0 μs | 2.0 μs | 939 ns | 1.8 μs | ExpFromLeft (900 ns) | 1.04x | -| uniform | sorted_near_start | 1024 | 256 | 3.8 μs | 4.6 μs | 3.5 μs | 8.5 μs | 7.7 μs | 3.8 μs | 7.2 μs | ExpFromLeft (3.5 μs) | 1.10x | -| uniform | sorted_near_start | 1024 | 1024 | 10.6 μs | 15.8 μs | 12.3 μs | 31.6 μs | 27.5 μs | 10.4 μs | 25.9 μs | Linear (10.6 μs) | 0.98x | -| uniform | sorted_near_start | 1024 | 4096 | 33.8 μs | 58.1 μs | 44.1 μs | 116.5 μs | 111.0 μs | 34.6 μs | 105.1 μs | Linear (33.8 μs) | 1.02x | -| uniform | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_near_start | 4096 | 4 | 650 ns | 180 ns | 160 ns | 150 ns | 160 ns | 200 ns | 150 ns | InterpSearch (150 ns) | 1.33x | -| uniform | sorted_near_start | 4096 | 16 | 3.9 μs | 550 ns | 450 ns | 470 ns | 530 ns | 460 ns | 480 ns | ExpFromLeft (450 ns) | 1.02x | -| uniform | sorted_near_start | 4096 | 64 | 5.8 μs | 1.5 μs | 1.1 μs | 2.1 μs | 2.4 μs | 1.1 μs | 2.2 μs | ExpFromLeft (1.1 μs) | 1.03x | -| uniform | sorted_near_start | 4096 | 256 | 7.9 μs | 4.6 μs | 3.3 μs | 8.9 μs | 11.1 μs | 3.4 μs | 10.4 μs | ExpFromLeft (3.3 μs) | 1.02x | -| uniform | sorted_near_start | 4096 | 1024 | 16.3 μs | 19.4 μs | 14.7 μs | 36.5 μs | 44.2 μs | 16.4 μs | 38.7 μs | ExpFromLeft (14.7 μs) | 1.11x | -| uniform | sorted_near_start | 4096 | 4096 | 42.8 μs | 63.8 μs | 49.3 μs | 123.8 μs | 156.9 μs | 42.8 μs | 140.6 μs | Linear (42.8 μs) | 1.00x | -| uniform | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 70 ns | 60 ns | 80 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | -| uniform | sorted_near_start | 16384 | 4 | 6.9 μs | 230 ns | 190 ns | 150 ns | 180 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | -| uniform | sorted_near_start | 16384 | 16 | 3.1 μs | 600 ns | 480 ns | 460 ns | 640 ns | 500 ns | 620 ns | InterpSearch (460 ns) | 1.09x | -| uniform | sorted_near_start | 16384 | 64 | 13.5 μs | 1.9 μs | 1.5 μs | 2.0 μs | 3.3 μs | 1.5 μs | 3.0 μs | ExpFromLeft (1.5 μs) | 1.01x | -| uniform | sorted_near_start | 16384 | 256 | 26.3 μs | 6.1 μs | 4.3 μs | 9.0 μs | 17.9 μs | 4.3 μs | 17.0 μs | ExpFromLeft (4.3 μs) | 1.01x | -| uniform | sorted_near_start | 16384 | 1024 | 33.3 μs | 20.9 μs | 14.7 μs | 38.5 μs | 76.7 μs | 14.5 μs | 70.3 μs | ExpFromLeft (14.7 μs) | 0.99x | -| uniform | sorted_near_start | 16384 | 4096 | 73.9 μs | 79.3 μs | 62.5 μs | 149.7 μs | 259.9 μs | 73.4 μs | 242.7 μs | ExpFromLeft (62.5 μs) | 1.17x | -| uniform | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_near_start | 65536 | 4 | 26.4 μs | 260 ns | 220 ns | 140 ns | 200 ns | 190 ns | 190 ns | InterpSearch (140 ns) | 1.36x | -| uniform | sorted_near_start | 65536 | 16 | 74.9 μs | 800 ns | 600 ns | 470 ns | 670 ns | 610 ns | 630 ns | InterpSearch (470 ns) | 1.30x | -| uniform | sorted_near_start | 65536 | 64 | 88.4 μs | 2.5 μs | 1.9 μs | 2.0 μs | 3.8 μs | 1.9 μs | 3.5 μs | ExpFromLeft (1.9 μs) | 1.01x | -| uniform | sorted_near_start | 65536 | 256 | 93.9 μs | 8.1 μs | 5.8 μs | 8.9 μs | 20.9 μs | 5.8 μs | 18.8 μs | ExpFromLeft (5.8 μs) | 0.99x | -| uniform | sorted_near_start | 65536 | 1024 | 102.2 μs | 28.3 μs | 20.2 μs | 38.7 μs | 96.4 μs | 18.9 μs | 88.1 μs | ExpFromLeft (20.2 μs) | 0.94x | -| uniform | sorted_near_start | 65536 | 4096 | 153.3 μs | 120.9 μs | 96.0 μs | 161.4 μs | 324.1 μs | 92.9 μs | 298.4 μs | ExpFromLeft (96.0 μs) | 0.97x | -| uniform | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_arithmetic | 16 | 4 | 100 ns | 130 ns | 120 ns | 140 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | -| uniform | sorted_arithmetic | 16 | 16 | 190 ns | 310 ns | 220 ns | 460 ns | 230 ns | 200 ns | 199 ns | Linear (190 ns) | 1.05x | -| uniform | sorted_arithmetic | 16 | 64 | 650 ns | 1.0 μs | 790 ns | 1.8 μs | 980 ns | 650 ns | 850 ns | Linear (650 ns) | 1.00x | -| uniform | sorted_arithmetic | 16 | 256 | 2.0 μs | 3.8 μs | 2.7 μs | 7.8 μs | 3.3 μs | 2.0 μs | 2.8 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_arithmetic | 16 | 1024 | 8.0 μs | 14.0 μs | 10.8 μs | 28.1 μs | 12.2 μs | 8.1 μs | 10.5 μs | Linear (8.0 μs) | 1.00x | -| uniform | sorted_arithmetic | 16 | 4096 | 31.1 μs | 54.8 μs | 41.9 μs | 109.4 μs | 47.2 μs | 31.1 μs | 41.0 μs | Linear (31.1 μs) | 1.00x | -| uniform | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_arithmetic | 64 | 4 | 170 ns | 150 ns | 130 ns | 150 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | -| uniform | sorted_arithmetic | 64 | 16 | 280 ns | 430 ns | 360 ns | 480 ns | 310 ns | 310 ns | 270 ns | Linear (280 ns) | 1.11x | -| uniform | sorted_arithmetic | 64 | 64 | 660 ns | 1.1 μs | 730 ns | 1.7 μs | 1.1 μs | 690 ns | 960 ns | Linear (660 ns) | 1.05x | -| uniform | sorted_arithmetic | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 6.9 μs | 5.3 μs | 2.2 μs | 4.9 μs | Linear (2.1 μs) | 1.01x | -| uniform | sorted_arithmetic | 64 | 1024 | 8.2 μs | 14.8 μs | 11.7 μs | 31.1 μs | 17.7 μs | 8.2 μs | 16.0 μs | Linear (8.2 μs) | 1.00x | -| uniform | sorted_arithmetic | 64 | 4096 | 32.2 μs | 56.0 μs | 42.1 μs | 112.8 μs | 67.3 μs | 32.2 μs | 60.0 μs | Linear (32.2 μs) | 1.00x | -| uniform | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_arithmetic | 256 | 4 | 460 ns | 180 ns | 150 ns | 140 ns | 130 ns | 170 ns | 120 ns | Binary (130 ns) | 1.31x | -| uniform | sorted_arithmetic | 256 | 16 | 570 ns | 540 ns | 440 ns | 470 ns | 380 ns | 470 ns | 330 ns | Binary (380 ns) | 1.24x | -| uniform | sorted_arithmetic | 256 | 64 | 1.2 μs | 1.8 μs | 1.7 μs | 2.1 μs | 1.5 μs | 1.2 μs | 1.3 μs | Linear (1.2 μs) | 1.01x | -| uniform | sorted_arithmetic | 256 | 256 | 2.4 μs | 4.1 μs | 2.7 μs | 6.5 μs | 5.7 μs | 2.5 μs | 6.2 μs | Linear (2.4 μs) | 1.01x | -| uniform | sorted_arithmetic | 256 | 1024 | 8.3 μs | 14.6 μs | 10.6 μs | 27.3 μs | 26.9 μs | 8.3 μs | 25.5 μs | Linear (8.3 μs) | 1.00x | -| uniform | sorted_arithmetic | 256 | 4096 | 31.5 μs | 59.3 μs | 46.4 μs | 125.4 μs | 90.8 μs | 31.5 μs | 83.4 μs | Linear (31.5 μs) | 1.00x | -| uniform | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_arithmetic | 1024 | 4 | 1.6 μs | 220 ns | 170 ns | 140 ns | 140 ns | 190 ns | 130 ns | InterpSearch (140 ns) | 1.36x | -| uniform | sorted_arithmetic | 1024 | 16 | 1.7 μs | 690 ns | 520 ns | 490 ns | 450 ns | 560 ns | 420 ns | Binary (450 ns) | 1.24x | -| uniform | sorted_arithmetic | 1024 | 64 | 2.4 μs | 2.2 μs | 2.1 μs | 1.8 μs | 1.7 μs | 2.0 μs | 1.7 μs | Binary (1.7 μs) | 1.14x | -| uniform | sorted_arithmetic | 1024 | 256 | 3.5 μs | 6.2 μs | 4.6 μs | 7.1 μs | 7.9 μs | 3.6 μs | 7.5 μs | Linear (3.5 μs) | 1.01x | -| uniform | sorted_arithmetic | 1024 | 1024 | 9.5 μs | 16.4 μs | 10.6 μs | 25.9 μs | 93.1 μs | 9.6 μs | 91.9 μs | Linear (9.5 μs) | 1.01x | -| uniform | sorted_arithmetic | 1024 | 4096 | 32.8 μs | 57.9 μs | 42.2 μs | 109.0 μs | 197.9 μs | 32.8 μs | 194.8 μs | Linear (32.8 μs) | 1.00x | -| uniform | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_arithmetic | 4096 | 4 | 5.8 μs | 240 ns | 200 ns | 140 ns | 160 ns | 190 ns | 150 ns | InterpSearch (140 ns) | 1.36x | -| uniform | sorted_arithmetic | 4096 | 16 | 6.0 μs | 810 ns | 590 ns | 470 ns | 520 ns | 530 ns | 480 ns | InterpSearch (470 ns) | 1.13x | -| uniform | sorted_arithmetic | 4096 | 64 | 6.3 μs | 2.7 μs | 2.0 μs | 1.7 μs | 2.0 μs | 1.9 μs | 1.9 μs | InterpSearch (1.7 μs) | 1.11x | -| uniform | sorted_arithmetic | 4096 | 256 | 8.1 μs | 8.4 μs | 6.1 μs | 7.7 μs | 8.5 μs | 8.3 μs | 7.5 μs | ExpFromLeft (6.1 μs) | 1.37x | -| uniform | sorted_arithmetic | 4096 | 1024 | 13.9 μs | 24.5 μs | 18.4 μs | 27.5 μs | 84.2 μs | 13.9 μs | 76.0 μs | Linear (13.9 μs) | 1.00x | -| uniform | sorted_arithmetic | 4096 | 4096 | 37.7 μs | 65.4 μs | 42.0 μs | 103.3 μs | 319.9 μs | 37.8 μs | 307.8 μs | Linear (37.7 μs) | 1.00x | -| uniform | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_arithmetic | 16384 | 4 | 22.1 μs | 280 ns | 230 ns | 140 ns | 180 ns | 190 ns | 160 ns | InterpSearch (140 ns) | 1.36x | -| uniform | sorted_arithmetic | 16384 | 16 | 23.0 μs | 1.0 μs | 690 ns | 490 ns | 600 ns | 560 ns | 560 ns | InterpSearch (490 ns) | 1.14x | -| uniform | sorted_arithmetic | 16384 | 64 | 24.4 μs | 3.3 μs | 2.2 μs | 1.9 μs | 2.3 μs | 2.1 μs | 2.2 μs | InterpSearch (1.9 μs) | 1.09x | -| uniform | sorted_arithmetic | 16384 | 256 | 25.9 μs | 10.5 μs | 8.0 μs | 7.0 μs | 13.6 μs | 7.6 μs | 13.6 μs | InterpSearch (7.0 μs) | 1.09x | -| uniform | sorted_arithmetic | 16384 | 1024 | 31.6 μs | 32.7 μs | 24.3 μs | 28.2 μs | 107.1 μs | 30.5 μs | 103.5 μs | ExpFromLeft (24.3 μs) | 1.25x | -| uniform | sorted_arithmetic | 16384 | 4096 | 55.2 μs | 97.7 μs | 73.3 μs | 109.3 μs | 396.8 μs | 55.2 μs | 390.4 μs | Linear (55.2 μs) | 1.00x | -| uniform | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_arithmetic | 65536 | 4 | 86.7 μs | 320 ns | 250 ns | 140 ns | 210 ns | 190 ns | 180 ns | InterpSearch (140 ns) | 1.36x | -| uniform | sorted_arithmetic | 65536 | 16 | 87.3 μs | 1.2 μs | 800 ns | 460 ns | 710 ns | 530 ns | 660 ns | InterpSearch (460 ns) | 1.15x | -| uniform | sorted_arithmetic | 65536 | 64 | 89.2 μs | 3.9 μs | 2.8 μs | 1.9 μs | 2.9 μs | 2.0 μs | 2.7 μs | InterpSearch (1.9 μs) | 1.09x | -| uniform | sorted_arithmetic | 65536 | 256 | 96.2 μs | 12.8 μs | 8.8 μs | 6.5 μs | 11.4 μs | 7.0 μs | 12.4 μs | InterpSearch (6.5 μs) | 1.08x | -| uniform | sorted_arithmetic | 65536 | 1024 | 101.0 μs | 43.6 μs | 33.0 μs | 30.7 μs | 117.2 μs | 32.6 μs | 116.0 μs | InterpSearch (30.7 μs) | 1.06x | -| uniform | sorted_arithmetic | 65536 | 4096 | 126.9 μs | 130.2 μs | 97.7 μs | 110.0 μs | 411.9 μs | 117.9 μs | 400.7 μs | ExpFromLeft (97.7 μs) | 1.21x | -| uniform | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| uniform | sorted_geometric | 16 | 16 | 190 ns | 300 ns | 220 ns | 470 ns | 220 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| uniform | sorted_geometric | 16 | 64 | 560 ns | 1.0 μs | 780 ns | 1.9 μs | 960 ns | 590 ns | 860 ns | Linear (560 ns) | 1.05x | -| uniform | sorted_geometric | 16 | 256 | 2.2 μs | 3.7 μs | 3.0 μs | 7.7 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.2 μs) | 1.02x | -| uniform | sorted_geometric | 16 | 1024 | 8.1 μs | 14.1 μs | 10.8 μs | 28.0 μs | 12.1 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | -| uniform | sorted_geometric | 16 | 4096 | 31.1 μs | 55.7 μs | 42.3 μs | 108.9 μs | 47.6 μs | 31.1 μs | 39.9 μs | Linear (31.1 μs) | 1.00x | -| uniform | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| uniform | sorted_geometric | 64 | 4 | 170 ns | 140 ns | 130 ns | 150 ns | 110 ns | 140 ns | 100 ns | Binary (110 ns) | 1.27x | -| uniform | sorted_geometric | 64 | 16 | 270 ns | 380 ns | 290 ns | 470 ns | 310 ns | 280 ns | 270 ns | Linear (270 ns) | 1.04x | -| uniform | sorted_geometric | 64 | 64 | 640 ns | 1.1 μs | 730 ns | 2.0 μs | 1.3 μs | 670 ns | 1.1 μs | Linear (640 ns) | 1.05x | -| uniform | sorted_geometric | 64 | 256 | 2.3 μs | 4.0 μs | 3.0 μs | 8.4 μs | 5.4 μs | 2.3 μs | 4.9 μs | Linear (2.3 μs) | 1.01x | -| uniform | sorted_geometric | 64 | 1024 | 9.0 μs | 14.9 μs | 14.8 μs | 30.8 μs | 17.7 μs | 9.0 μs | 16.0 μs | Linear (9.0 μs) | 1.00x | -| uniform | sorted_geometric | 64 | 4096 | 32.2 μs | 56.6 μs | 43.2 μs | 112.7 μs | 67.1 μs | 32.2 μs | 60.3 μs | Linear (32.2 μs) | 1.00x | -| uniform | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_geometric | 256 | 4 | 480 ns | 170 ns | 140 ns | 150 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | -| uniform | sorted_geometric | 256 | 16 | 550 ns | 480 ns | 390 ns | 470 ns | 380 ns | 400 ns | 350 ns | Binary (380 ns) | 1.05x | -| uniform | sorted_geometric | 256 | 64 | 920 ns | 1.4 μs | 980 ns | 1.9 μs | 1.4 μs | 940 ns | 1.3 μs | Linear (920 ns) | 1.02x | -| uniform | sorted_geometric | 256 | 256 | 2.5 μs | 4.6 μs | 3.0 μs | 8.0 μs | 6.8 μs | 2.5 μs | 6.3 μs | Linear (2.5 μs) | 1.01x | -| uniform | sorted_geometric | 256 | 1024 | 9.7 μs | 16.3 μs | 12.3 μs | 32.6 μs | 27.5 μs | 9.7 μs | 25.9 μs | Linear (9.7 μs) | 1.00x | -| uniform | sorted_geometric | 256 | 4096 | 35.2 μs | 58.8 μs | 45.4 μs | 119.1 μs | 91.5 μs | 35.3 μs | 83.6 μs | Linear (35.2 μs) | 1.00x | -| uniform | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_geometric | 1024 | 4 | 1.6 μs | 200 ns | 180 ns | 150 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | -| uniform | sorted_geometric | 1024 | 16 | 1.8 μs | 620 ns | 480 ns | 510 ns | 450 ns | 510 ns | 410 ns | Binary (450 ns) | 1.13x | -| uniform | sorted_geometric | 1024 | 64 | 2.1 μs | 1.9 μs | 1.4 μs | 2.0 μs | 1.7 μs | 1.5 μs | 1.5 μs | ExpFromLeft (1.4 μs) | 1.03x | -| uniform | sorted_geometric | 1024 | 256 | 3.7 μs | 5.7 μs | 4.0 μs | 8.9 μs | 8.0 μs | 3.7 μs | 8.0 μs | Linear (3.7 μs) | 1.01x | -| uniform | sorted_geometric | 1024 | 1024 | 10.8 μs | 18.6 μs | 12.2 μs | 33.4 μs | 64.9 μs | 10.8 μs | 64.0 μs | Linear (10.8 μs) | 1.00x | -| uniform | sorted_geometric | 1024 | 4096 | 38.5 μs | 63.1 μs | 47.9 μs | 121.0 μs | 194.8 μs | 38.6 μs | 191.9 μs | Linear (38.5 μs) | 1.00x | -| uniform | sorted_geometric | 4096 | 1 | 69 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | Linear (69 ns) | 1.01x | -| uniform | sorted_geometric | 4096 | 4 | 6.0 μs | 240 ns | 190 ns | 150 ns | 160 ns | 190 ns | 150 ns | InterpSearch (150 ns) | 1.27x | -| uniform | sorted_geometric | 4096 | 16 | 6.3 μs | 760 ns | 580 ns | 460 ns | 530 ns | 600 ns | 490 ns | InterpSearch (460 ns) | 1.30x | -| uniform | sorted_geometric | 4096 | 64 | 7.4 μs | 2.5 μs | 1.8 μs | 2.0 μs | 2.0 μs | 1.9 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.02x | -| uniform | sorted_geometric | 4096 | 256 | 8.8 μs | 7.6 μs | 5.7 μs | 8.9 μs | 10.1 μs | 5.8 μs | 10.2 μs | ExpFromLeft (5.7 μs) | 1.01x | -| uniform | sorted_geometric | 4096 | 1024 | 15.9 μs | 24.1 μs | 17.2 μs | 33.7 μs | 96.2 μs | 15.9 μs | 87.1 μs | Linear (15.9 μs) | 1.00x | -| uniform | sorted_geometric | 4096 | 4096 | 44.5 μs | 73.9 μs | 49.9 μs | 124.9 μs | 307.4 μs | 44.5 μs | 299.9 μs | Linear (44.5 μs) | 1.00x | -| uniform | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_geometric | 16384 | 4 | 23.4 μs | 270 ns | 210 ns | 150 ns | 190 ns | 190 ns | 170 ns | InterpSearch (150 ns) | 1.27x | -| uniform | sorted_geometric | 16384 | 16 | 23.9 μs | 920 ns | 700 ns | 470 ns | 610 ns | 710 ns | 560 ns | InterpSearch (470 ns) | 1.51x | -| uniform | sorted_geometric | 16384 | 64 | 25.4 μs | 3.1 μs | 2.3 μs | 2.0 μs | 2.4 μs | 2.4 μs | 2.3 μs | InterpSearch (2.0 μs) | 1.19x | -| uniform | sorted_geometric | 16384 | 256 | 30.0 μs | 10.2 μs | 7.5 μs | 8.9 μs | 13.2 μs | 7.4 μs | 13.0 μs | ExpFromLeft (7.5 μs) | 0.99x | -| uniform | sorted_geometric | 16384 | 1024 | 36.2 μs | 32.0 μs | 24.6 μs | 35.6 μs | 122.5 μs | 25.0 μs | 121.4 μs | ExpFromLeft (24.6 μs) | 1.02x | -| uniform | sorted_geometric | 16384 | 4096 | 66.7 μs | 98.4 μs | 69.6 μs | 130.7 μs | 416.2 μs | 66.7 μs | 409.7 μs | Linear (66.7 μs) | 1.00x | -| uniform | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_geometric | 65536 | 4 | 93.0 μs | 310 ns | 250 ns | 150 ns | 200 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | -| uniform | sorted_geometric | 65536 | 16 | 93.5 μs | 1.1 μs | 810 ns | 470 ns | 690 ns | 830 ns | 650 ns | InterpSearch (470 ns) | 1.77x | -| uniform | sorted_geometric | 65536 | 64 | 95.4 μs | 3.7 μs | 2.8 μs | 2.1 μs | 2.9 μs | 2.8 μs | 2.7 μs | InterpSearch (2.1 μs) | 1.35x | -| uniform | sorted_geometric | 65536 | 256 | 101.9 μs | 13.4 μs | 9.8 μs | 9.6 μs | 17.3 μs | 11.1 μs | 17.7 μs | InterpSearch (9.6 μs) | 1.15x | -| uniform | sorted_geometric | 65536 | 1024 | 117.9 μs | 47.0 μs | 36.8 μs | 39.2 μs | 155.7 μs | 35.4 μs | 156.7 μs | ExpFromLeft (36.8 μs) | 0.96x | -| uniform | sorted_geometric | 65536 | 4096 | 145.8 μs | 133.7 μs | 102.7 μs | 132.3 μs | 501.4 μs | 106.1 μs | 505.0 μs | ExpFromLeft (102.7 μs) | 1.03x | -| uniform | sorted_bimodal | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_bimodal | 16 | 4 | 100 ns | 110 ns | 100 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| uniform | sorted_bimodal | 16 | 16 | 190 ns | 280 ns | 220 ns | 470 ns | 240 ns | 200 ns | 210 ns | Linear (190 ns) | 1.05x | -| uniform | sorted_bimodal | 16 | 64 | 590 ns | 970 ns | 800 ns | 1.9 μs | 880 ns | 620 ns | 760 ns | Linear (590 ns) | 1.05x | -| uniform | sorted_bimodal | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 6.8 μs | 3.2 μs | 2.1 μs | 2.8 μs | Linear (2.1 μs) | 1.02x | -| uniform | sorted_bimodal | 16 | 1024 | 7.8 μs | 13.4 μs | 10.6 μs | 26.9 μs | 12.6 μs | 7.9 μs | 11.0 μs | Linear (7.8 μs) | 1.01x | -| uniform | sorted_bimodal | 16 | 4096 | 30.9 μs | 53.3 μs | 42.1 μs | 107.0 μs | 50.1 μs | 30.9 μs | 43.5 μs | Linear (30.9 μs) | 1.00x | -| uniform | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | InterpSearch (60 ns) | 1.00x | -| uniform | sorted_bimodal | 64 | 4 | 160 ns | 120 ns | 120 ns | 150 ns | 100 ns | 140 ns | 90 ns | Binary (100 ns) | 1.40x | -| uniform | sorted_bimodal | 64 | 16 | 270 ns | 320 ns | 230 ns | 500 ns | 330 ns | 280 ns | 290 ns | ExpFromLeft (230 ns) | 1.22x | -| uniform | sorted_bimodal | 64 | 64 | 630 ns | 1.0 μs | 760 ns | 2.0 μs | 1.3 μs | 660 ns | 1.2 μs | Linear (630 ns) | 1.05x | -| uniform | sorted_bimodal | 64 | 256 | 2.3 μs | 3.7 μs | 2.9 μs | 7.6 μs | 4.4 μs | 2.3 μs | 4.0 μs | Linear (2.3 μs) | 1.01x | -| uniform | sorted_bimodal | 64 | 1024 | 11.4 μs | 18.7 μs | 14.2 μs | 30.6 μs | 18.9 μs | 11.4 μs | 16.4 μs | Linear (11.4 μs) | 1.00x | -| uniform | sorted_bimodal | 64 | 4096 | 31.1 μs | 54.9 μs | 42.3 μs | 108.7 μs | 66.8 μs | 31.1 μs | 59.9 μs | Linear (31.1 μs) | 1.00x | -| uniform | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_bimodal | 256 | 4 | 440 ns | 150 ns | 140 ns | 150 ns | 130 ns | 160 ns | 110 ns | Binary (130 ns) | 1.23x | -| uniform | sorted_bimodal | 256 | 16 | 560 ns | 360 ns | 270 ns | 460 ns | 410 ns | 280 ns | 360 ns | ExpFromLeft (270 ns) | 1.04x | -| uniform | sorted_bimodal | 256 | 64 | 920 ns | 1.1 μs | 760 ns | 2.0 μs | 1.7 μs | 960 ns | 1.6 μs | ExpFromLeft (760 ns) | 1.26x | -| uniform | sorted_bimodal | 256 | 256 | 2.6 μs | 4.1 μs | 3.2 μs | 8.9 μs | 6.4 μs | 2.6 μs | 5.8 μs | Linear (2.6 μs) | 0.99x | -| uniform | sorted_bimodal | 256 | 1024 | 9.2 μs | 14.7 μs | 11.5 μs | 30.5 μs | 22.5 μs | 9.2 μs | 20.7 μs | Linear (9.2 μs) | 1.00x | -| uniform | sorted_bimodal | 256 | 4096 | 32.2 μs | 55.8 μs | 43.1 μs | 112.2 μs | 86.6 μs | 32.2 μs | 78.9 μs | Linear (32.2 μs) | 1.00x | -| uniform | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_bimodal | 1024 | 4 | 1.5 μs | 180 ns | 160 ns | 150 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| uniform | sorted_bimodal | 1024 | 16 | 1.6 μs | 470 ns | 390 ns | 480 ns | 450 ns | 410 ns | 420 ns | ExpFromLeft (390 ns) | 1.05x | -| uniform | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 999 ns | 1.9 μs | 2.0 μs | 1.0 μs | 1.9 μs | ExpFromLeft (999 ns) | 1.02x | -| uniform | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.1 μs | 2.8 μs | 9.1 μs | 8.7 μs | 3.5 μs | 8.1 μs | ExpFromLeft (2.8 μs) | 1.25x | -| uniform | sorted_bimodal | 1024 | 1024 | 11.6 μs | 17.3 μs | 13.7 μs | 37.2 μs | 30.6 μs | 11.6 μs | 28.9 μs | Linear (11.6 μs) | 1.00x | -| uniform | sorted_bimodal | 1024 | 4096 | 36.6 μs | 58.5 μs | 45.8 μs | 122.0 μs | 108.6 μs | 36.5 μs | 102.8 μs | Linear (36.6 μs) | 1.00x | -| uniform | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 69 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (69 ns) | 1.01x | -| uniform | sorted_bimodal | 4096 | 4 | 5.8 μs | 189 ns | 180 ns | 140 ns | 160 ns | 190 ns | 140 ns | InterpSearch (140 ns) | 1.36x | -| uniform | sorted_bimodal | 4096 | 16 | 6.2 μs | 630 ns | 490 ns | 460 ns | 530 ns | 500 ns | 480 ns | InterpSearch (460 ns) | 1.09x | -| uniform | sorted_bimodal | 4096 | 64 | 6.4 μs | 1.8 μs | 1.3 μs | 2.0 μs | 2.2 μs | 1.4 μs | 2.0 μs | ExpFromLeft (1.3 μs) | 1.03x | -| uniform | sorted_bimodal | 4096 | 256 | 8.3 μs | 5.2 μs | 3.7 μs | 9.2 μs | 11.5 μs | 3.7 μs | 10.6 μs | ExpFromLeft (3.7 μs) | 1.01x | -| uniform | sorted_bimodal | 4096 | 1024 | 14.0 μs | 17.6 μs | 12.0 μs | 38.9 μs | 62.2 μs | 14.6 μs | 57.0 μs | ExpFromLeft (12.0 μs) | 1.21x | -| uniform | sorted_bimodal | 4096 | 4096 | 51.3 μs | 69.6 μs | 55.5 μs | 147.3 μs | 185.2 μs | 51.1 μs | 168.0 μs | Linear (51.3 μs) | 1.00x | -| uniform | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_bimodal | 16384 | 4 | 21.8 μs | 250 ns | 210 ns | 150 ns | 180 ns | 200 ns | 160 ns | InterpSearch (150 ns) | 1.33x | -| uniform | sorted_bimodal | 16384 | 16 | 22.9 μs | 740 ns | 560 ns | 490 ns | 630 ns | 590 ns | 560 ns | InterpSearch (490 ns) | 1.20x | -| uniform | sorted_bimodal | 16384 | 64 | 24.2 μs | 2.2 μs | 1.7 μs | 1.9 μs | 2.7 μs | 1.7 μs | 2.5 μs | ExpFromLeft (1.7 μs) | 1.00x | -| uniform | sorted_bimodal | 16384 | 256 | 26.2 μs | 6.9 μs | 5.1 μs | 8.8 μs | 15.9 μs | 5.2 μs | 14.7 μs | ExpFromLeft (5.1 μs) | 1.01x | -| uniform | sorted_bimodal | 16384 | 1024 | 33.4 μs | 22.4 μs | 17.2 μs | 38.6 μs | 90.1 μs | 15.5 μs | 89.5 μs | ExpFromLeft (17.2 μs) | 0.90x | -| uniform | sorted_bimodal | 16384 | 4096 | 79.2 μs | 89.9 μs | 67.6 μs | 159.9 μs | 275.5 μs | 78.3 μs | 265.1 μs | ExpFromLeft (67.6 μs) | 1.16x | -| uniform | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | sorted_bimodal | 65536 | 4 | 83.9 μs | 270 ns | 220 ns | 150 ns | 200 ns | 200 ns | 180 ns | InterpSearch (150 ns) | 1.33x | -| uniform | sorted_bimodal | 65536 | 16 | 87.9 μs | 880 ns | 660 ns | 470 ns | 720 ns | 670 ns | 680 ns | InterpSearch (470 ns) | 1.43x | -| uniform | sorted_bimodal | 65536 | 64 | 91.2 μs | 2.9 μs | 2.2 μs | 2.1 μs | 3.0 μs | 2.2 μs | 2.9 μs | InterpSearch (2.1 μs) | 1.07x | -| uniform | sorted_bimodal | 65536 | 256 | 99.6 μs | 9.1 μs | 6.9 μs | 9.2 μs | 18.8 μs | 6.8 μs | 18.5 μs | ExpFromLeft (6.9 μs) | 1.00x | -| uniform | sorted_bimodal | 65536 | 1024 | 110.0 μs | 33.0 μs | 25.4 μs | 39.9 μs | 109.3 μs | 23.0 μs | 113.2 μs | ExpFromLeft (25.4 μs) | 0.91x | -| uniform | sorted_bimodal | 65536 | 4096 | 186.5 μs | 148.1 μs | 108.6 μs | 160.5 μs | 350.9 μs | 106.9 μs | 351.0 μs | ExpFromLeft (108.6 μs) | 0.98x | -| uniform | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 140 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| uniform | sorted_repeated | 16 | 16 | 180 ns | 270 ns | 200 ns | 460 ns | 230 ns | 190 ns | 220 ns | Linear (180 ns) | 1.06x | -| uniform | sorted_repeated | 16 | 64 | 579 ns | 920 ns | 689 ns | 1.7 μs | 790 ns | 580 ns | 850 ns | Linear (579 ns) | 1.00x | -| uniform | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 3.2 μs | 6.5 μs | 3.0 μs | 2.0 μs | 2.9 μs | Linear (2.0 μs) | 1.02x | -| uniform | sorted_repeated | 16 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 25.9 μs | 11.8 μs | 7.8 μs | 13.1 μs | Linear (7.8 μs) | 1.00x | -| uniform | sorted_repeated | 16 | 4096 | 30.8 μs | 54.8 μs | 39.0 μs | 103.3 μs | 47.2 μs | 30.8 μs | 44.3 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 90 ns | 140 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| uniform | sorted_repeated | 64 | 16 | 170 ns | 280 ns | 200 ns | 460 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | -| uniform | sorted_repeated | 64 | 64 | 550 ns | 920 ns | 700 ns | 1.7 μs | 1.1 μs | 579 ns | 929 ns | Linear (550 ns) | 1.05x | -| uniform | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 25.9 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | -| uniform | sorted_repeated | 64 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 103.3 μs | 66.5 μs | 30.8 μs | 56.6 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_repeated | 256 | 4 | 80 ns | 100 ns | 100 ns | 140 ns | 130 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | -| uniform | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 209 ns | 460 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| uniform | sorted_repeated | 256 | 64 | 550 ns | 930 ns | 690 ns | 1.7 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | -| uniform | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| uniform | sorted_repeated | 256 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 25.8 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.01x | -| uniform | sorted_repeated | 256 | 4096 | 30.8 μs | 55.1 μs | 39.2 μs | 103.7 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 140 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | -| uniform | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 220 ns | 460 ns | 470 ns | 209 ns | 420 ns | Linear (180 ns) | 1.16x | -| uniform | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 1.7 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| uniform | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_repeated | 1024 | 1024 | 11.1 μs | 18.5 μs | 12.8 μs | 28.7 μs | 27.1 μs | 11.2 μs | 23.7 μs | Linear (11.1 μs) | 1.00x | -| uniform | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.1 μs | 39.3 μs | 103.3 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 140 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | -| uniform | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 460 ns | 540 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | -| uniform | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 700 ns | 1.7 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | -| uniform | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.00x | -| uniform | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 25.9 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | -| uniform | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.4 μs | 103.2 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 79 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| uniform | sorted_repeated | 16384 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 190 ns | 120 ns | 170 ns | Linear (100 ns) | 1.20x | -| uniform | sorted_repeated | 16384 | 16 | 190 ns | 300 ns | 230 ns | 460 ns | 609 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | -| uniform | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 710 ns | 1.7 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | -| uniform | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | -| uniform | sorted_repeated | 16384 | 1024 | 11.1 μs | 18.5 μs | 12.8 μs | 28.8 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (11.1 μs) | 0.70x | -| uniform | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.0 μs | 39.6 μs | 103.3 μs | 144.0 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | -| uniform | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | -| uniform | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 150 ns | 190 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| uniform | sorted_repeated | 65536 | 16 | 190 ns | 300 ns | 230 ns | 460 ns | 690 ns | 210 ns | 630 ns | Linear (190 ns) | 1.11x | -| uniform | sorted_repeated | 65536 | 64 | 580 ns | 940 ns | 719 ns | 1.7 μs | 2.6 μs | 610 ns | 2.4 μs | Linear (580 ns) | 1.05x | -| uniform | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.02x | -| uniform | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 25.8 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.01x | -| uniform | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.1 μs | 39.5 μs | 103.3 μs | 163.2 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| uniform | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| uniform | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 90 ns | 100 ns | 100 ns | 80 ns | InterpSearch (90 ns) | 1.11x | -| uniform | unsorted | 16 | 16 | 210 ns | 220 ns | 200 ns | 210 ns | 200 ns | 210 ns | 190 ns | ExpFromLeft (200 ns) | 1.05x | -| uniform | unsorted | 16 | 64 | 820 ns | 800 ns | 810 ns | 820 ns | 890 ns | 899 ns | 839 ns | Gallop (800 ns) | 1.12x | -| uniform | unsorted | 16 | 256 | 3.7 μs | 3.6 μs | 3.6 μs | 3.6 μs | 3.6 μs | 3.6 μs | 3.6 μs | Binary (3.6 μs) | 1.00x | -| uniform | unsorted | 16 | 1024 | 22.5 μs | 22.0 μs | 21.7 μs | 21.9 μs | 21.7 μs | 21.9 μs | 23.1 μs | Binary (21.7 μs) | 1.01x | -| uniform | unsorted | 16 | 4096 | 144.2 μs | 141.1 μs | 140.2 μs | 139.8 μs | 140.0 μs | 138.9 μs | 142.8 μs | InterpSearch (139.8 μs) | 0.99x | -| uniform | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| uniform | unsorted | 64 | 4 | 110 ns | 110 ns | 110 ns | 110 ns | 110 ns | 120 ns | 90 ns | InterpSearch (110 ns) | 1.09x | -| uniform | unsorted | 64 | 16 | 280 ns | 270 ns | 280 ns | 270 ns | 280 ns | 280 ns | 270 ns | InterpSearch (270 ns) | 1.04x | -| uniform | unsorted | 64 | 64 | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.1 μs | ExpFromLeft (1.0 μs) | 1.01x | -| uniform | unsorted | 64 | 256 | 5.6 μs | 5.5 μs | 5.4 μs | 5.4 μs | 5.4 μs | 5.4 μs | 5.6 μs | Binary (5.4 μs) | 1.00x | -| uniform | unsorted | 64 | 1024 | 40.3 μs | 39.8 μs | 38.6 μs | 38.3 μs | 37.9 μs | 38.2 μs | 40.6 μs | Binary (37.9 μs) | 1.01x | -| uniform | unsorted | 64 | 4096 | 226.0 μs | 224.9 μs | 224.7 μs | 225.4 μs | 221.9 μs | 222.8 μs | 226.2 μs | Binary (221.9 μs) | 1.00x | -| uniform | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | unsorted | 256 | 4 | 130 ns | 130 ns | 130 ns | 120 ns | 120 ns | 140 ns | 110 ns | InterpSearch (120 ns) | 1.17x | -| uniform | unsorted | 256 | 16 | 350 ns | 350 ns | 350 ns | 360 ns | 350 ns | 360 ns | 340 ns | ExpFromLeft (350 ns) | 1.03x | -| uniform | unsorted | 256 | 64 | 1.3 μs | 1.2 μs | 1.3 μs | 1.2 μs | 1.2 μs | 1.3 μs | 1.2 μs | Binary (1.2 μs) | 1.02x | -| uniform | unsorted | 256 | 256 | 7.0 μs | 6.8 μs | 6.8 μs | 6.8 μs | 6.8 μs | 6.8 μs | 7.0 μs | InterpSearch (6.8 μs) | 1.00x | -| uniform | unsorted | 256 | 1024 | 54.1 μs | 52.8 μs | 51.6 μs | 51.9 μs | 52.2 μs | 51.9 μs | 55.5 μs | ExpFromLeft (51.6 μs) | 1.00x | -| uniform | unsorted | 256 | 4096 | 313.3 μs | 307.8 μs | 307.0 μs | 305.8 μs | 307.0 μs | 308.6 μs | 309.0 μs | InterpSearch (305.8 μs) | 1.01x | -| uniform | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| uniform | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 139 ns | 140 ns | 150 ns | 130 ns | InterpSearch (139 ns) | 1.08x | -| uniform | unsorted | 1024 | 16 | 430 ns | 430 ns | 480 ns | 480 ns | 480 ns | 490 ns | 450 ns | Gallop (430 ns) | 1.14x | -| uniform | unsorted | 1024 | 64 | 1.9 μs | 1.8 μs | 1.8 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | Binary (1.7 μs) | 1.00x | -| uniform | unsorted | 1024 | 256 | 7.8 μs | 7.5 μs | 7.7 μs | 7.7 μs | 7.7 μs | 7.6 μs | 7.8 μs | Gallop (7.5 μs) | 1.01x | -| uniform | unsorted | 1024 | 1024 | 79.4 μs | 77.7 μs | 76.4 μs | 75.0 μs | 75.0 μs | 74.8 μs | 78.4 μs | Binary (75.0 μs) | 1.00x | -| uniform | unsorted | 1024 | 4096 | 416.5 μs | 415.7 μs | 415.9 μs | 416.7 μs | 414.3 μs | 416.1 μs | 414.4 μs | Binary (414.3 μs) | 1.00x | -| uniform | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| uniform | unsorted | 4096 | 4 | 150 ns | 150 ns | 150 ns | 160 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (150 ns) | 1.13x | -| uniform | unsorted | 4096 | 16 | 490 ns | 500 ns | 490 ns | 500 ns | 490 ns | 510 ns | 490 ns | ExpFromLeft (490 ns) | 1.04x | -| uniform | unsorted | 4096 | 64 | 1.9 μs | 2.0 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | Linear (1.9 μs) | 1.01x | -| uniform | unsorted | 4096 | 256 | 9.7 μs | 9.6 μs | 9.6 μs | 9.5 μs | 9.5 μs | 9.4 μs | 11.7 μs | Binary (9.5 μs) | 1.00x | -| uniform | unsorted | 4096 | 1024 | 100.7 μs | 97.2 μs | 95.9 μs | 94.4 μs | 93.9 μs | 93.4 μs | 99.8 μs | Binary (93.9 μs) | 0.99x | -| uniform | unsorted | 4096 | 4096 | 497.4 μs | 496.2 μs | 495.8 μs | 496.2 μs | 495.6 μs | 492.9 μs | 497.3 μs | Binary (495.6 μs) | 0.99x | -| uniform | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 79 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| uniform | unsorted | 16384 | 4 | 170 ns | 180 ns | 170 ns | 170 ns | 170 ns | 180 ns | 170 ns | InterpSearch (170 ns) | 1.06x | -| uniform | unsorted | 16384 | 16 | 570 ns | 570 ns | 580 ns | 580 ns | 570 ns | 580 ns | 560 ns | Binary (570 ns) | 1.02x | -| uniform | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | InterpSearch (2.3 μs) | 1.01x | -| uniform | unsorted | 16384 | 256 | 11.0 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.8 μs | 12.7 μs | InterpSearch (10.9 μs) | 1.00x | -| uniform | unsorted | 16384 | 1024 | 141.4 μs | 137.6 μs | 135.8 μs | 135.4 μs | 134.5 μs | 133.9 μs | 139.6 μs | Binary (134.5 μs) | 1.00x | -| uniform | unsorted | 16384 | 4096 | 657.2 μs | 654.9 μs | 665.2 μs | 663.9 μs | 664.2 μs | 663.1 μs | 663.5 μs | Gallop (654.9 μs) | 1.01x | -| uniform | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| uniform | unsorted | 65536 | 4 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | -| uniform | unsorted | 65536 | 16 | 670 ns | 700 ns | 680 ns | 670 ns | 680 ns | 690 ns | 660 ns | InterpSearch (670 ns) | 1.03x | -| uniform | unsorted | 65536 | 64 | 2.6 μs | 2.6 μs | 2.6 μs | 2.6 μs | 2.6 μs | 2.6 μs | 2.6 μs | Linear (2.6 μs) | 1.01x | -| uniform | unsorted | 65536 | 256 | 13.6 μs | 13.5 μs | 13.3 μs | 13.3 μs | 13.4 μs | 13.4 μs | 17.7 μs | InterpSearch (13.3 μs) | 1.01x | -| uniform | unsorted | 65536 | 1024 | 188.8 μs | 184.2 μs | 181.7 μs | 181.3 μs | 182.2 μs | 180.9 μs | 186.0 μs | InterpSearch (181.3 μs) | 1.00x | -| uniform | unsorted | 65536 | 4096 | 847.7 μs | 847.3 μs | 849.1 μs | 847.9 μs | 847.3 μs | 842.6 μs | 843.1 μs | Binary (847.3 μs) | 0.99x | -| log | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| log | sorted_uniform | 16 | 4 | 80 ns | 90 ns | 90 ns | 160 ns | 100 ns | 110 ns | 80 ns | Linear (80 ns) | 1.38x | -| log | sorted_uniform | 16 | 16 | 190 ns | 300 ns | 210 ns | 580 ns | 250 ns | 210 ns | 200 ns | Linear (190 ns) | 1.11x | -| log | sorted_uniform | 16 | 64 | 600 ns | 1.0 μs | 780 ns | 2.3 μs | 900 ns | 610 ns | 770 ns | Linear (600 ns) | 1.02x | -| log | sorted_uniform | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 9.1 μs | 3.4 μs | 2.1 μs | 3.0 μs | Linear (2.1 μs) | 1.00x | -| log | sorted_uniform | 16 | 1024 | 8.0 μs | 14.1 μs | 10.7 μs | 35.8 μs | 13.1 μs | 8.0 μs | 11.2 μs | Linear (8.0 μs) | 1.00x | -| log | sorted_uniform | 16 | 4096 | 31.4 μs | 55.9 μs | 41.9 μs | 139.2 μs | 51.1 μs | 31.0 μs | 44.1 μs | Linear (31.4 μs) | 0.99x | -| log | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 59 ns | 110 ns | 70 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| log | sorted_uniform | 64 | 4 | 110 ns | 120 ns | 120 ns | 190 ns | 110 ns | 130 ns | 90 ns | Binary (110 ns) | 1.18x | -| log | sorted_uniform | 64 | 16 | 210 ns | 360 ns | 290 ns | 730 ns | 340 ns | 230 ns | 270 ns | Linear (210 ns) | 1.10x | -| log | sorted_uniform | 64 | 64 | 600 ns | 1.0 μs | 740 ns | 2.7 μs | 1.4 μs | 630 ns | 1.2 μs | Linear (600 ns) | 1.05x | -| log | sorted_uniform | 64 | 256 | 2.3 μs | 3.9 μs | 3.0 μs | 11.4 μs | 4.7 μs | 2.4 μs | 4.4 μs | Linear (2.3 μs) | 1.02x | -| log | sorted_uniform | 64 | 1024 | 8.3 μs | 14.2 μs | 11.1 μs | 43.8 μs | 17.5 μs | 8.3 μs | 15.7 μs | Linear (8.3 μs) | 1.00x | -| log | sorted_uniform | 64 | 4096 | 31.6 μs | 55.1 μs | 42.8 μs | 170.4 μs | 68.2 μs | 31.6 μs | 61.0 μs | Linear (31.6 μs) | 1.00x | -| log | sorted_uniform | 256 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 80 ns | 80 ns | 60 ns | ExpFromLeft (60 ns) | 1.33x | -| log | sorted_uniform | 256 | 4 | 180 ns | 150 ns | 130 ns | 260 ns | 120 ns | 160 ns | 110 ns | Binary (120 ns) | 1.33x | -| log | sorted_uniform | 256 | 16 | 310 ns | 380 ns | 300 ns | 860 ns | 380 ns | 320 ns | 340 ns | ExpFromLeft (300 ns) | 1.07x | -| log | sorted_uniform | 256 | 64 | 820 ns | 1.2 μs | 860 ns | 3.4 μs | 1.7 μs | 820 ns | 1.6 μs | Linear (820 ns) | 1.00x | -| log | sorted_uniform | 256 | 256 | 2.3 μs | 4.3 μs | 3.0 μs | 13.8 μs | 6.5 μs | 2.3 μs | 6.2 μs | Linear (2.3 μs) | 1.00x | -| log | sorted_uniform | 256 | 1024 | 9.3 μs | 15.4 μs | 11.8 μs | 56.3 μs | 24.0 μs | 9.3 μs | 22.0 μs | Linear (9.3 μs) | 1.00x | -| log | sorted_uniform | 256 | 4096 | 33.4 μs | 57.5 μs | 44.3 μs | 217.4 μs | 89.7 μs | 33.5 μs | 82.2 μs | Linear (33.4 μs) | 1.00x | -| log | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 70 ns | 80 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| log | sorted_uniform | 1024 | 4 | 530 ns | 170 ns | 150 ns | 290 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | -| log | sorted_uniform | 1024 | 16 | 620 ns | 440 ns | 370 ns | 1.0 μs | 450 ns | 400 ns | 410 ns | ExpFromLeft (370 ns) | 1.08x | -| log | sorted_uniform | 1024 | 64 | 1.4 μs | 1.4 μs | 1.1 μs | 4.0 μs | 1.8 μs | 1.1 μs | 1.8 μs | ExpFromLeft (1.1 μs) | 1.06x | -| log | sorted_uniform | 1024 | 256 | 3.2 μs | 4.7 μs | 3.3 μs | 16.1 μs | 8.7 μs | 3.2 μs | 7.7 μs | Linear (3.2 μs) | 1.00x | -| log | sorted_uniform | 1024 | 1024 | 10.8 μs | 17.8 μs | 13.1 μs | 71.1 μs | 34.3 μs | 10.7 μs | 32.9 μs | Linear (10.8 μs) | 0.99x | -| log | sorted_uniform | 1024 | 4096 | 38.0 μs | 62.6 μs | 48.2 μs | 290.1 μs | 130.6 μs | 38.3 μs | 125.1 μs | Linear (38.0 μs) | 1.01x | -| log | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| log | sorted_uniform | 4096 | 4 | 960 ns | 190 ns | 160 ns | 310 ns | 160 ns | 190 ns | 150 ns | ExpFromLeft (160 ns) | 1.19x | -| log | sorted_uniform | 4096 | 16 | 2.5 μs | 600 ns | 460 ns | 1.1 μs | 600 ns | 490 ns | 550 ns | ExpFromLeft (460 ns) | 1.07x | -| log | sorted_uniform | 4096 | 64 | 4.3 μs | 1.9 μs | 1.4 μs | 4.6 μs | 2.1 μs | 1.5 μs | 2.0 μs | ExpFromLeft (1.4 μs) | 1.03x | -| log | sorted_uniform | 4096 | 256 | 8.9 μs | 5.9 μs | 4.3 μs | 19.1 μs | 11.2 μs | 4.4 μs | 10.2 μs | ExpFromLeft (4.3 μs) | 1.03x | -| log | sorted_uniform | 4096 | 1024 | 15.8 μs | 20.2 μs | 14.1 μs | 90.7 μs | 67.9 μs | 15.8 μs | 61.5 μs | ExpFromLeft (14.1 μs) | 1.12x | -| log | sorted_uniform | 4096 | 4096 | 53.4 μs | 76.2 μs | 58.6 μs | 400.9 μs | 227.4 μs | 51.9 μs | 218.7 μs | Linear (53.4 μs) | 0.97x | -| log | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 80 ns | 110 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | -| log | sorted_uniform | 16384 | 4 | 4.3 μs | 250 ns | 200 ns | 370 ns | 180 ns | 240 ns | 160 ns | Binary (180 ns) | 1.33x | -| log | sorted_uniform | 16384 | 16 | 11.5 μs | 780 ns | 580 ns | 1.4 μs | 650 ns | 610 ns | 600 ns | ExpFromLeft (580 ns) | 1.05x | -| log | sorted_uniform | 16384 | 64 | 25.3 μs | 2.6 μs | 1.9 μs | 5.3 μs | 2.7 μs | 2.0 μs | 2.5 μs | ExpFromLeft (1.9 μs) | 1.03x | -| log | sorted_uniform | 16384 | 256 | 25.4 μs | 7.7 μs | 5.7 μs | 21.4 μs | 16.1 μs | 5.9 μs | 14.9 μs | ExpFromLeft (5.7 μs) | 1.04x | -| log | sorted_uniform | 16384 | 1024 | 34.7 μs | 27.5 μs | 21.3 μs | 122.2 μs | 102.5 μs | 20.3 μs | 100.8 μs | ExpFromLeft (21.3 μs) | 0.95x | -| log | sorted_uniform | 16384 | 4096 | 90.8 μs | 114.3 μs | 89.3 μs | 515.9 μs | 317.9 μs | 88.8 μs | 313.1 μs | ExpFromLeft (89.3 μs) | 0.99x | -| log | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_uniform | 65536 | 4 | 11.4 μs | 230 ns | 200 ns | 370 ns | 200 ns | 230 ns | 180 ns | ExpFromLeft (200 ns) | 1.15x | -| log | sorted_uniform | 65536 | 16 | 42.8 μs | 930 ns | 700 ns | 1.5 μs | 710 ns | 710 ns | 670 ns | ExpFromLeft (700 ns) | 1.01x | -| log | sorted_uniform | 65536 | 64 | 50.2 μs | 3.2 μs | 2.4 μs | 6.0 μs | 2.9 μs | 2.5 μs | 2.7 μs | ExpFromLeft (2.4 μs) | 1.02x | -| log | sorted_uniform | 65536 | 256 | 81.9 μs | 10.7 μs | 7.7 μs | 26.2 μs | 19.1 μs | 7.8 μs | 18.8 μs | ExpFromLeft (7.7 μs) | 1.02x | -| log | sorted_uniform | 65536 | 1024 | 104.7 μs | 41.9 μs | 31.4 μs | 164.4 μs | 123.1 μs | 30.5 μs | 126.8 μs | ExpFromLeft (31.4 μs) | 0.97x | -| log | sorted_uniform | 65536 | 4096 | 176.6 μs | 198.7 μs | 151.3 μs | 648.8 μs | 412.0 μs | 159.7 μs | 407.1 μs | ExpFromLeft (151.3 μs) | 1.06x | -| log | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 100 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| log | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| log | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 220 ns | 630 ns | 230 ns | 190 ns | 210 ns | Linear (170 ns) | 1.12x | -| log | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 730 ns | 2.3 μs | 790 ns | 570 ns | 750 ns | Linear (550 ns) | 1.04x | -| log | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 9.0 μs | 3.0 μs | 2.1 μs | 2.5 μs | Linear (2.0 μs) | 1.08x | -| log | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 35.9 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.00x | -| log | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.9 μs | 42.0 μs | 142.9 μs | 47.0 μs | 32.9 μs | 38.5 μs | Linear (30.8 μs) | 1.07x | -| log | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| log | sorted_dense_burst | 64 | 4 | 80 ns | 90 ns | 100 ns | 220 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| log | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 230 ns | 759 ns | 300 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | -| log | sorted_dense_burst | 64 | 64 | 550 ns | 920 ns | 730 ns | 2.9 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | -| log | sorted_dense_burst | 64 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 11.3 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.1 μs) | 0.95x | -| log | sorted_dense_burst | 64 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 44.6 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.8 μs) | 1.00x | -| log | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.0 μs | 41.9 μs | 177.9 μs | 66.6 μs | 44.3 μs | 56.7 μs | Linear (30.8 μs) | 1.44x | -| log | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 250 ns | 130 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| log | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 920 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| log | sorted_dense_burst | 256 | 64 | 550 ns | 930 ns | 740 ns | 3.6 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | -| log | sorted_dense_burst | 256 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 14.1 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.1 μs) | 0.95x | -| log | sorted_dense_burst | 256 | 1024 | 8.3 μs | 13.8 μs | 10.5 μs | 55.9 μs | 21.5 μs | 7.8 μs | 19.3 μs | Linear (8.3 μs) | 0.94x | -| log | sorted_dense_burst | 256 | 4096 | 32.8 μs | 54.9 μs | 41.9 μs | 223.1 μs | 85.9 μs | 30.8 μs | 76.5 μs | Linear (32.8 μs) | 0.94x | -| log | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 100 ns | 290 ns | 140 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | -| log | sorted_dense_burst | 1024 | 16 | 180 ns | 290 ns | 240 ns | 1.1 μs | 450 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | -| log | sorted_dense_burst | 1024 | 64 | 560 ns | 930 ns | 740 ns | 4.1 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| log | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.2 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| log | sorted_dense_burst | 1024 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 64.9 μs | 26.4 μs | 8.3 μs | 24.0 μs | Linear (7.7 μs) | 1.07x | -| log | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 41.9 μs | 258.7 μs | 105.4 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| log | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 110 ns | 330 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | -| log | sorted_dense_burst | 4096 | 16 | 179 ns | 280 ns | 260 ns | 1.2 μs | 540 ns | 210 ns | 480 ns | Linear (179 ns) | 1.17x | -| log | sorted_dense_burst | 4096 | 64 | 560 ns | 940 ns | 760 ns | 4.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | -| log | sorted_dense_burst | 4096 | 256 | 2.1 μs | 3.5 μs | 3.6 μs | 19.2 μs | 8.0 μs | 2.9 μs | 7.2 μs | Linear (2.1 μs) | 1.35x | -| log | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 75.3 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.7 μs) | 1.01x | -| log | sorted_dense_burst | 4096 | 4096 | 32.9 μs | 55.1 μs | 42.0 μs | 300.1 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (32.9 μs) | 0.94x | -| log | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| log | sorted_dense_burst | 16384 | 4 | 90 ns | 110 ns | 110 ns | 390 ns | 180 ns | 130 ns | 170 ns | Linear (90 ns) | 1.44x | -| log | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 1.4 μs | 620 ns | 220 ns | 559 ns | Linear (190 ns) | 1.16x | -| log | sorted_dense_burst | 16384 | 64 | 560 ns | 940 ns | 750 ns | 5.4 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | -| log | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 21.4 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | -| log | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 85.8 μs | 36.0 μs | 8.3 μs | 33.5 μs | Linear (7.8 μs) | 1.07x | -| log | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 54.8 μs | 42.0 μs | 342.9 μs | 144.1 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 100 ns | 100 ns | 70 ns | ExpFromLeft (80 ns) | 1.25x | -| log | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 450 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| log | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 250 ns | 1.6 μs | 690 ns | 210 ns | 630 ns | Linear (190 ns) | 1.11x | -| log | sorted_dense_burst | 65536 | 64 | 560 ns | 940 ns | 740 ns | 6.1 μs | 2.6 μs | 620 ns | 2.4 μs | Linear (560 ns) | 1.11x | -| log | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.1 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | -| log | sorted_dense_burst | 65536 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 97.0 μs | 40.8 μs | 8.3 μs | 38.1 μs | Linear (7.7 μs) | 1.07x | -| log | sorted_dense_burst | 65536 | 4096 | 32.9 μs | 55.0 μs | 42.0 μs | 385.8 μs | 163.1 μs | 30.8 μs | 152.6 μs | Linear (32.9 μs) | 0.94x | -| log | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| log | sorted_near_start | 16 | 4 | 100 ns | 120 ns | 100 ns | 150 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | -| log | sorted_near_start | 16 | 16 | 210 ns | 290 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (210 ns) | 0.95x | -| log | sorted_near_start | 16 | 64 | 570 ns | 960 ns | 760 ns | 1.7 μs | 810 ns | 600 ns | 680 ns | Linear (570 ns) | 1.05x | -| log | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.8 μs | 6.7 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | -| log | sorted_near_start | 16 | 1024 | 7.9 μs | 13.9 μs | 10.6 μs | 27.0 μs | 12.1 μs | 7.9 μs | 10.3 μs | Linear (7.9 μs) | 1.00x | -| log | sorted_near_start | 16 | 4096 | 30.9 μs | 54.9 μs | 42.1 μs | 106.6 μs | 48.1 μs | 31.0 μs | 40.7 μs | Linear (30.9 μs) | 1.00x | -| log | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| log | sorted_near_start | 64 | 4 | 150 ns | 120 ns | 120 ns | 160 ns | 110 ns | 120 ns | 90 ns | Binary (110 ns) | 1.09x | -| log | sorted_near_start | 64 | 16 | 250 ns | 280 ns | 230 ns | 530 ns | 320 ns | 270 ns | 280 ns | ExpFromLeft (230 ns) | 1.17x | -| log | sorted_near_start | 64 | 64 | 680 ns | 1.0 μs | 820 ns | 1.9 μs | 1.1 μs | 700 ns | 1.0 μs | Linear (680 ns) | 1.03x | -| log | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.3 μs | 4.2 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | -| log | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 29.2 μs | 16.9 μs | 8.0 μs | 15.2 μs | Linear (7.9 μs) | 1.00x | -| log | sorted_near_start | 64 | 4096 | 31.2 μs | 55.3 μs | 42.4 μs | 116.6 μs | 66.7 μs | 31.2 μs | 60.0 μs | Linear (31.2 μs) | 1.00x | -| log | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_near_start | 256 | 4 | 430 ns | 140 ns | 120 ns | 200 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | -| log | sorted_near_start | 256 | 16 | 540 ns | 340 ns | 260 ns | 640 ns | 450 ns | 290 ns | 390 ns | ExpFromLeft (260 ns) | 1.12x | -| log | sorted_near_start | 256 | 64 | 930 ns | 1.1 μs | 810 ns | 2.4 μs | 1.6 μs | 960 ns | 1.8 μs | ExpFromLeft (810 ns) | 1.19x | -| log | sorted_near_start | 256 | 256 | 2.6 μs | 3.9 μs | 3.0 μs | 9.6 μs | 5.8 μs | 2.6 μs | 5.3 μs | Linear (2.6 μs) | 1.01x | -| log | sorted_near_start | 256 | 1024 | 8.4 μs | 14.3 μs | 10.9 μs | 37.3 μs | 22.3 μs | 8.4 μs | 20.4 μs | Linear (8.4 μs) | 1.00x | -| log | sorted_near_start | 256 | 4096 | 31.7 μs | 56.4 μs | 43.0 μs | 149.9 μs | 87.7 μs | 31.7 μs | 80.4 μs | Linear (31.7 μs) | 1.00x | -| log | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| log | sorted_near_start | 1024 | 4 | 1.4 μs | 170 ns | 150 ns | 220 ns | 150 ns | 190 ns | 130 ns | ExpFromLeft (150 ns) | 1.27x | -| log | sorted_near_start | 1024 | 16 | 1.5 μs | 409 ns | 320 ns | 750 ns | 490 ns | 350 ns | 410 ns | ExpFromLeft (320 ns) | 1.09x | -| log | sorted_near_start | 1024 | 64 | 1.9 μs | 1.2 μs | 900 ns | 3.1 μs | 2.1 μs | 930 ns | 1.9 μs | ExpFromLeft (900 ns) | 1.03x | -| log | sorted_near_start | 1024 | 256 | 3.8 μs | 4.5 μs | 3.4 μs | 12.5 μs | 7.7 μs | 3.8 μs | 7.1 μs | ExpFromLeft (3.4 μs) | 1.11x | -| log | sorted_near_start | 1024 | 1024 | 10.5 μs | 15.4 μs | 12.0 μs | 48.7 μs | 27.6 μs | 10.4 μs | 25.9 μs | Linear (10.5 μs) | 1.00x | -| log | sorted_near_start | 1024 | 4096 | 33.8 μs | 57.5 μs | 43.7 μs | 191.3 μs | 108.8 μs | 33.8 μs | 102.9 μs | Linear (33.8 μs) | 1.00x | -| log | sorted_near_start | 4096 | 1 | 70 ns | 90 ns | 90 ns | 90 ns | 70 ns | 70 ns | 60 ns | Binary (70 ns) | 1.00x | -| log | sorted_near_start | 4096 | 4 | 6.1 μs | 200 ns | 180 ns | 260 ns | 170 ns | 210 ns | 150 ns | Binary (170 ns) | 1.24x | -| log | sorted_near_start | 4096 | 16 | 5.4 μs | 549 ns | 510 ns | 980 ns | 540 ns | 520 ns | 489 ns | ExpFromLeft (510 ns) | 1.02x | -| log | sorted_near_start | 4096 | 64 | 6.5 μs | 1.5 μs | 1.1 μs | 3.5 μs | 2.4 μs | 1.4 μs | 2.2 μs | ExpFromLeft (1.1 μs) | 1.27x | -| log | sorted_near_start | 4096 | 256 | 7.8 μs | 4.5 μs | 3.2 μs | 15.0 μs | 11.0 μs | 3.4 μs | 10.5 μs | ExpFromLeft (3.2 μs) | 1.07x | -| log | sorted_near_start | 4096 | 1024 | 16.2 μs | 18.4 μs | 14.1 μs | 64.2 μs | 43.9 μs | 16.1 μs | 38.4 μs | ExpFromLeft (14.1 μs) | 1.14x | -| log | sorted_near_start | 4096 | 4096 | 41.8 μs | 61.7 μs | 47.8 μs | 246.2 μs | 155.3 μs | 42.0 μs | 140.3 μs | Linear (41.8 μs) | 1.01x | -| log | sorted_near_start | 16384 | 1 | 70 ns | 70 ns | 80 ns | 100 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | -| log | sorted_near_start | 16384 | 4 | 21.2 μs | 240 ns | 200 ns | 310 ns | 180 ns | 230 ns | 160 ns | Binary (180 ns) | 1.28x | -| log | sorted_near_start | 16384 | 16 | 23.9 μs | 630 ns | 510 ns | 1.1 μs | 670 ns | 530 ns | 590 ns | ExpFromLeft (510 ns) | 1.04x | -| log | sorted_near_start | 16384 | 64 | 23.3 μs | 1.9 μs | 1.5 μs | 4.3 μs | 3.1 μs | 1.5 μs | 2.8 μs | ExpFromLeft (1.5 μs) | 1.01x | -| log | sorted_near_start | 16384 | 256 | 24.9 μs | 5.9 μs | 4.2 μs | 17.5 μs | 17.9 μs | 4.3 μs | 16.7 μs | ExpFromLeft (4.2 μs) | 1.04x | -| log | sorted_near_start | 16384 | 1024 | 34.2 μs | 20.4 μs | 13.9 μs | 84.9 μs | 77.0 μs | 14.2 μs | 70.8 μs | ExpFromLeft (13.9 μs) | 1.03x | -| log | sorted_near_start | 16384 | 4096 | 71.9 μs | 75.9 μs | 60.1 μs | 358.5 μs | 254.2 μs | 71.2 μs | 232.0 μs | ExpFromLeft (60.1 μs) | 1.18x | -| log | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 90 ns | 70 ns | ExpFromLeft (80 ns) | 1.12x | -| log | sorted_near_start | 65536 | 4 | 60.6 μs | 250 ns | 200 ns | 360 ns | 200 ns | 240 ns | 190 ns | ExpFromLeft (200 ns) | 1.20x | -| log | sorted_near_start | 65536 | 16 | 78.5 μs | 800 ns | 600 ns | 1.3 μs | 670 ns | 620 ns | 630 ns | ExpFromLeft (600 ns) | 1.03x | -| log | sorted_near_start | 65536 | 64 | 93.9 μs | 2.5 μs | 1.9 μs | 4.9 μs | 3.3 μs | 2.0 μs | 3.1 μs | ExpFromLeft (1.9 μs) | 1.02x | -| log | sorted_near_start | 65536 | 256 | 96.7 μs | 7.9 μs | 5.7 μs | 20.7 μs | 20.4 μs | 5.8 μs | 19.8 μs | ExpFromLeft (5.7 μs) | 1.01x | -| log | sorted_near_start | 65536 | 1024 | 103.1 μs | 26.5 μs | 19.6 μs | 117.7 μs | 95.2 μs | 18.8 μs | 89.8 μs | ExpFromLeft (19.6 μs) | 0.96x | -| log | sorted_near_start | 65536 | 4096 | 157.5 μs | 111.3 μs | 89.1 μs | 499.1 μs | 303.0 μs | 85.9 μs | 291.2 μs | ExpFromLeft (89.1 μs) | 0.96x | -| log | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| log | sorted_arithmetic | 16 | 4 | 100 ns | 100 ns | 100 ns | 160 ns | 100 ns | 110 ns | 80 ns | ExpFromLeft (100 ns) | 1.10x | -| log | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 220 ns | 550 ns | 240 ns | 210 ns | 210 ns | Linear (190 ns) | 1.11x | -| log | sorted_arithmetic | 16 | 64 | 590 ns | 970 ns | 770 ns | 2.2 μs | 910 ns | 620 ns | 800 ns | Linear (590 ns) | 1.05x | -| log | sorted_arithmetic | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 8.7 μs | 3.3 μs | 2.1 μs | 2.8 μs | Linear (2.1 μs) | 1.00x | -| log | sorted_arithmetic | 16 | 1024 | 7.9 μs | 13.5 μs | 10.7 μs | 33.7 μs | 12.6 μs | 8.0 μs | 11.2 μs | Linear (7.9 μs) | 1.01x | -| log | sorted_arithmetic | 16 | 4096 | 31.0 μs | 53.2 μs | 42.2 μs | 132.9 μs | 51.1 μs | 31.0 μs | 44.0 μs | Linear (31.0 μs) | 1.00x | -| log | sorted_arithmetic | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| log | sorted_arithmetic | 64 | 4 | 170 ns | 130 ns | 120 ns | 180 ns | 100 ns | 150 ns | 90 ns | Binary (100 ns) | 1.50x | -| log | sorted_arithmetic | 64 | 16 | 260 ns | 330 ns | 260 ns | 680 ns | 340 ns | 280 ns | 310 ns | ExpFromLeft (260 ns) | 1.08x | -| log | sorted_arithmetic | 64 | 64 | 660 ns | 1.1 μs | 779 ns | 2.7 μs | 1.4 μs | 660 ns | 1.3 μs | Linear (660 ns) | 1.00x | -| log | sorted_arithmetic | 64 | 256 | 2.3 μs | 3.9 μs | 3.0 μs | 11.2 μs | 4.8 μs | 2.3 μs | 4.4 μs | Linear (2.3 μs) | 1.01x | -| log | sorted_arithmetic | 64 | 1024 | 8.3 μs | 14.3 μs | 11.1 μs | 43.9 μs | 17.6 μs | 8.4 μs | 15.8 μs | Linear (8.3 μs) | 1.01x | -| log | sorted_arithmetic | 64 | 4096 | 31.6 μs | 55.6 μs | 42.8 μs | 170.5 μs | 68.2 μs | 31.7 μs | 60.7 μs | Linear (31.6 μs) | 1.00x | -| log | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_arithmetic | 256 | 4 | 480 ns | 170 ns | 150 ns | 200 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | -| log | sorted_arithmetic | 256 | 16 | 580 ns | 430 ns | 340 ns | 820 ns | 370 ns | 360 ns | 340 ns | ExpFromLeft (340 ns) | 1.06x | -| log | sorted_arithmetic | 256 | 64 | 960 ns | 1.2 μs | 850 ns | 3.3 μs | 1.6 μs | 960 ns | 1.4 μs | ExpFromLeft (850 ns) | 1.13x | -| log | sorted_arithmetic | 256 | 256 | 2.6 μs | 4.2 μs | 3.1 μs | 13.8 μs | 6.9 μs | 2.6 μs | 6.2 μs | Linear (2.6 μs) | 1.01x | -| log | sorted_arithmetic | 256 | 1024 | 9.3 μs | 15.7 μs | 12.0 μs | 57.6 μs | 24.0 μs | 9.3 μs | 21.7 μs | Linear (9.3 μs) | 0.99x | -| log | sorted_arithmetic | 256 | 4096 | 33.4 μs | 58.0 μs | 44.4 μs | 217.5 μs | 90.1 μs | 33.4 μs | 80.9 μs | Linear (33.4 μs) | 1.00x | -| log | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| log | sorted_arithmetic | 1024 | 4 | 1.6 μs | 190 ns | 160 ns | 210 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | -| log | sorted_arithmetic | 1024 | 16 | 1.8 μs | 550 ns | 450 ns | 950 ns | 450 ns | 470 ns | 420 ns | ExpFromLeft (450 ns) | 1.04x | -| log | sorted_arithmetic | 1024 | 64 | 2.2 μs | 1.6 μs | 1.2 μs | 3.9 μs | 1.7 μs | 1.2 μs | 1.6 μs | ExpFromLeft (1.2 μs) | 1.03x | -| log | sorted_arithmetic | 1024 | 256 | 3.8 μs | 5.0 μs | 3.5 μs | 16.2 μs | 8.3 μs | 3.8 μs | 7.7 μs | ExpFromLeft (3.5 μs) | 1.10x | -| log | sorted_arithmetic | 1024 | 1024 | 10.8 μs | 17.2 μs | 12.6 μs | 72.1 μs | 36.1 μs | 10.7 μs | 36.4 μs | Linear (10.8 μs) | 0.99x | -| log | sorted_arithmetic | 1024 | 4096 | 37.4 μs | 62.0 μs | 47.1 μs | 292.4 μs | 136.3 μs | 37.4 μs | 134.3 μs | Linear (37.4 μs) | 1.00x | -| log | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| log | sorted_arithmetic | 4096 | 4 | 6.0 μs | 230 ns | 200 ns | 240 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | -| log | sorted_arithmetic | 4096 | 16 | 6.3 μs | 700 ns | 550 ns | 1.1 μs | 530 ns | 560 ns | 480 ns | Binary (530 ns) | 1.06x | -| log | sorted_arithmetic | 4096 | 64 | 7.1 μs | 2.1 μs | 1.6 μs | 4.5 μs | 2.1 μs | 1.7 μs | 1.9 μs | ExpFromLeft (1.6 μs) | 1.03x | -| log | sorted_arithmetic | 4096 | 256 | 8.6 μs | 6.7 μs | 4.8 μs | 18.9 μs | 11.6 μs | 4.9 μs | 9.7 μs | ExpFromLeft (4.8 μs) | 1.01x | -| log | sorted_arithmetic | 4096 | 1024 | 15.8 μs | 20.4 μs | 14.1 μs | 97.5 μs | 76.0 μs | 15.8 μs | 72.2 μs | ExpFromLeft (14.1 μs) | 1.11x | -| log | sorted_arithmetic | 4096 | 4096 | 43.7 μs | 67.8 μs | 49.4 μs | 416.2 μs | 241.0 μs | 43.6 μs | 224.3 μs | Linear (43.7 μs) | 1.00x | -| log | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 80 ns | 130 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | -| log | sorted_arithmetic | 16384 | 4 | 23.4 μs | 260 ns | 230 ns | 260 ns | 180 ns | 240 ns | 160 ns | Binary (180 ns) | 1.33x | -| log | sorted_arithmetic | 16384 | 16 | 23.8 μs | 840 ns | 650 ns | 1.3 μs | 610 ns | 660 ns | 560 ns | Binary (610 ns) | 1.08x | -| log | sorted_arithmetic | 16384 | 64 | 25.2 μs | 2.9 μs | 2.1 μs | 5.2 μs | 2.6 μs | 2.1 μs | 2.4 μs | ExpFromLeft (2.1 μs) | 1.02x | -| log | sorted_arithmetic | 16384 | 256 | 28.8 μs | 9.1 μs | 8.3 μs | 22.6 μs | 16.0 μs | 8.4 μs | 13.7 μs | ExpFromLeft (8.3 μs) | 1.01x | -| log | sorted_arithmetic | 16384 | 1024 | 36.3 μs | 27.9 μs | 20.1 μs | 129.7 μs | 106.8 μs | 20.5 μs | 104.1 μs | ExpFromLeft (20.1 μs) | 1.02x | -| log | sorted_arithmetic | 16384 | 4096 | 65.8 μs | 82.7 μs | 58.2 μs | 536.3 μs | 341.4 μs | 65.8 μs | 341.5 μs | ExpFromLeft (58.2 μs) | 1.13x | -| log | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_arithmetic | 65536 | 4 | 93.0 μs | 290 ns | 230 ns | 270 ns | 200 ns | 260 ns | 190 ns | Binary (200 ns) | 1.30x | -| log | sorted_arithmetic | 65536 | 16 | 93.5 μs | 1.0 μs | 750 ns | 1.4 μs | 690 ns | 770 ns | 660 ns | Binary (690 ns) | 1.12x | -| log | sorted_arithmetic | 65536 | 64 | 95.2 μs | 3.4 μs | 2.5 μs | 6.0 μs | 2.9 μs | 2.6 μs | 2.7 μs | ExpFromLeft (2.5 μs) | 1.02x | -| log | sorted_arithmetic | 65536 | 256 | 100.1 μs | 11.4 μs | 8.7 μs | 27.1 μs | 18.2 μs | 8.8 μs | 18.7 μs | ExpFromLeft (8.7 μs) | 1.01x | -| log | sorted_arithmetic | 65536 | 1024 | 112.6 μs | 38.3 μs | 28.9 μs | 170.9 μs | 129.6 μs | 28.7 μs | 134.1 μs | ExpFromLeft (28.9 μs) | 1.00x | -| log | sorted_arithmetic | 65536 | 4096 | 144.1 μs | 116.8 μs | 84.8 μs | 672.5 μs | 447.5 μs | 85.4 μs | 448.4 μs | ExpFromLeft (84.8 μs) | 1.01x | -| log | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| log | sorted_geometric | 16 | 4 | 110 ns | 120 ns | 120 ns | 170 ns | 100 ns | 120 ns | 80 ns | Binary (100 ns) | 1.20x | -| log | sorted_geometric | 16 | 16 | 190 ns | 300 ns | 220 ns | 590 ns | 240 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| log | sorted_geometric | 16 | 64 | 580 ns | 970 ns | 760 ns | 2.4 μs | 930 ns | 629 ns | 800 ns | Linear (580 ns) | 1.08x | -| log | sorted_geometric | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 9.3 μs | 3.3 μs | 2.2 μs | 3.2 μs | Linear (2.2 μs) | 1.00x | -| log | sorted_geometric | 16 | 1024 | 8.0 μs | 14.1 μs | 10.8 μs | 36.0 μs | 12.4 μs | 8.1 μs | 10.5 μs | Linear (8.0 μs) | 1.00x | -| log | sorted_geometric | 16 | 4096 | 31.1 μs | 55.1 μs | 42.3 μs | 141.2 μs | 48.5 μs | 31.1 μs | 41.0 μs | Linear (31.1 μs) | 1.00x | -| log | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| log | sorted_geometric | 64 | 4 | 170 ns | 150 ns | 130 ns | 190 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | -| log | sorted_geometric | 64 | 16 | 260 ns | 360 ns | 270 ns | 720 ns | 300 ns | 280 ns | 270 ns | Linear (260 ns) | 1.08x | -| log | sorted_geometric | 64 | 64 | 670 ns | 1.2 μs | 780 ns | 2.9 μs | 1.3 μs | 690 ns | 1.3 μs | Linear (670 ns) | 1.03x | -| log | sorted_geometric | 64 | 256 | 2.3 μs | 4.0 μs | 3.0 μs | 12.1 μs | 5.2 μs | 2.3 μs | 4.7 μs | Linear (2.3 μs) | 1.01x | -| log | sorted_geometric | 64 | 1024 | 8.9 μs | 14.7 μs | 11.6 μs | 47.2 μs | 17.8 μs | 8.9 μs | 15.8 μs | Linear (8.9 μs) | 1.00x | -| log | sorted_geometric | 64 | 4096 | 32.2 μs | 56.5 μs | 43.2 μs | 182.3 μs | 67.6 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | -| log | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_geometric | 256 | 4 | 520 ns | 170 ns | 160 ns | 210 ns | 119 ns | 180 ns | 110 ns | Binary (119 ns) | 1.51x | -| log | sorted_geometric | 256 | 16 | 530 ns | 470 ns | 400 ns | 870 ns | 370 ns | 430 ns | 340 ns | Binary (370 ns) | 1.16x | -| log | sorted_geometric | 256 | 64 | 960 ns | 1.5 μs | 990 ns | 3.5 μs | 1.4 μs | 970 ns | 1.2 μs | Linear (960 ns) | 1.01x | -| log | sorted_geometric | 256 | 256 | 3.4 μs | 5.4 μs | 3.1 μs | 14.8 μs | 7.1 μs | 2.7 μs | 6.6 μs | ExpFromLeft (3.1 μs) | 0.86x | -| log | sorted_geometric | 256 | 1024 | 9.3 μs | 15.7 μs | 11.7 μs | 61.3 μs | 26.8 μs | 9.4 μs | 23.9 μs | Linear (9.3 μs) | 1.01x | -| log | sorted_geometric | 256 | 4096 | 35.7 μs | 59.5 μs | 46.2 μs | 233.8 μs | 91.7 μs | 35.8 μs | 83.8 μs | Linear (35.7 μs) | 1.00x | -| log | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| log | sorted_geometric | 1024 | 4 | 1.6 μs | 210 ns | 180 ns | 230 ns | 150 ns | 200 ns | 130 ns | Binary (150 ns) | 1.33x | -| log | sorted_geometric | 1024 | 16 | 2.0 μs | 650 ns | 500 ns | 999 ns | 450 ns | 510 ns | 410 ns | Binary (450 ns) | 1.13x | -| log | sorted_geometric | 1024 | 64 | 2.2 μs | 1.9 μs | 1.5 μs | 4.1 μs | 1.7 μs | 1.6 μs | 1.6 μs | ExpFromLeft (1.5 μs) | 1.03x | -| log | sorted_geometric | 1024 | 256 | 3.8 μs | 5.9 μs | 3.9 μs | 16.9 μs | 7.9 μs | 3.8 μs | 8.0 μs | Linear (3.8 μs) | 1.01x | -| log | sorted_geometric | 1024 | 1024 | 10.9 μs | 18.0 μs | 12.5 μs | 77.1 μs | 77.0 μs | 10.9 μs | 74.3 μs | Linear (10.9 μs) | 1.00x | -| log | sorted_geometric | 1024 | 4096 | 36.6 μs | 61.5 μs | 46.0 μs | 326.5 μs | 190.6 μs | 36.7 μs | 188.4 μs | Linear (36.6 μs) | 1.00x | -| log | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| log | sorted_geometric | 4096 | 4 | 6.0 μs | 240 ns | 210 ns | 250 ns | 170 ns | 240 ns | 150 ns | Binary (170 ns) | 1.41x | -| log | sorted_geometric | 4096 | 16 | 6.4 μs | 770 ns | 620 ns | 1.1 μs | 540 ns | 660 ns | 480 ns | Binary (540 ns) | 1.22x | -| log | sorted_geometric | 4096 | 64 | 7.7 μs | 2.5 μs | 1.9 μs | 4.7 μs | 2.0 μs | 2.0 μs | 1.9 μs | ExpFromLeft (1.9 μs) | 1.02x | -| log | sorted_geometric | 4096 | 256 | 9.6 μs | 7.9 μs | 5.9 μs | 19.5 μs | 10.7 μs | 6.0 μs | 10.0 μs | ExpFromLeft (5.9 μs) | 1.02x | -| log | sorted_geometric | 4096 | 1024 | 16.0 μs | 24.0 μs | 15.9 μs | 107.4 μs | 100.2 μs | 15.9 μs | 92.3 μs | ExpFromLeft (15.9 μs) | 1.00x | -| log | sorted_geometric | 4096 | 4096 | 43.1 μs | 70.6 μs | 48.8 μs | 453.2 μs | 321.8 μs | 43.0 μs | 312.1 μs | Linear (43.1 μs) | 1.00x | -| log | sorted_geometric | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| log | sorted_geometric | 16384 | 4 | 22.7 μs | 270 ns | 230 ns | 260 ns | 190 ns | 240 ns | 170 ns | Binary (190 ns) | 1.26x | -| log | sorted_geometric | 16384 | 16 | 24.3 μs | 929 ns | 690 ns | 1.3 μs | 610 ns | 710 ns | 570 ns | Binary (610 ns) | 1.16x | -| log | sorted_geometric | 16384 | 64 | 25.8 μs | 3.1 μs | 2.4 μs | 5.4 μs | 2.4 μs | 2.4 μs | 2.2 μs | ExpFromLeft (2.4 μs) | 1.01x | -| log | sorted_geometric | 16384 | 256 | 30.9 μs | 10.4 μs | 7.8 μs | 22.9 μs | 14.4 μs | 7.9 μs | 14.2 μs | ExpFromLeft (7.8 μs) | 1.01x | -| log | sorted_geometric | 16384 | 1024 | 38.2 μs | 32.8 μs | 24.6 μs | 135.8 μs | 127.6 μs | 24.9 μs | 127.5 μs | ExpFromLeft (24.6 μs) | 1.01x | -| log | sorted_geometric | 16384 | 4096 | 63.3 μs | 94.5 μs | 64.4 μs | 563.6 μs | 425.4 μs | 63.0 μs | 420.4 μs | Linear (63.3 μs) | 1.00x | -| log | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| log | sorted_geometric | 65536 | 4 | 93.7 μs | 310 ns | 250 ns | 290 ns | 200 ns | 280 ns | 180 ns | Binary (200 ns) | 1.40x | -| log | sorted_geometric | 65536 | 16 | 95.7 μs | 1.1 μs | 809 ns | 1.4 μs | 690 ns | 830 ns | 660 ns | Binary (690 ns) | 1.20x | -| log | sorted_geometric | 65536 | 64 | 97.6 μs | 3.8 μs | 2.7 μs | 6.1 μs | 2.9 μs | 2.8 μs | 2.9 μs | ExpFromLeft (2.7 μs) | 1.03x | -| log | sorted_geometric | 65536 | 256 | 102.9 μs | 13.4 μs | 10.3 μs | 27.6 μs | 17.8 μs | 10.6 μs | 15.8 μs | ExpFromLeft (10.3 μs) | 1.03x | -| log | sorted_geometric | 65536 | 1024 | 113.9 μs | 44.3 μs | 33.8 μs | 185.2 μs | 158.6 μs | 33.6 μs | 164.0 μs | ExpFromLeft (33.8 μs) | 1.00x | -| log | sorted_geometric | 65536 | 4096 | 148.2 μs | 132.0 μs | 100.5 μs | 718.7 μs | 515.2 μs | 101.1 μs | 519.4 μs | ExpFromLeft (100.5 μs) | 1.01x | -| log | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 50 ns | 60 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| log | sorted_bimodal | 16 | 4 | 90 ns | 120 ns | 100 ns | 170 ns | 99 ns | 110 ns | 80 ns | Linear (90 ns) | 1.22x | -| log | sorted_bimodal | 16 | 16 | 190 ns | 280 ns | 220 ns | 540 ns | 250 ns | 210 ns | 210 ns | Linear (190 ns) | 1.11x | -| log | sorted_bimodal | 16 | 64 | 570 ns | 930 ns | 770 ns | 2.1 μs | 899 ns | 600 ns | 800 ns | Linear (570 ns) | 1.05x | -| log | sorted_bimodal | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 8.1 μs | 3.4 μs | 2.1 μs | 2.9 μs | Linear (2.1 μs) | 1.00x | -| log | sorted_bimodal | 16 | 1024 | 8.0 μs | 13.3 μs | 10.7 μs | 31.7 μs | 13.3 μs | 7.9 μs | 11.5 μs | Linear (8.0 μs) | 0.99x | -| log | sorted_bimodal | 16 | 4096 | 31.0 μs | 52.0 μs | 42.3 μs | 125.5 μs | 52.0 μs | 31.0 μs | 45.8 μs | Linear (31.0 μs) | 1.00x | -| log | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_bimodal | 64 | 4 | 120 ns | 130 ns | 110 ns | 190 ns | 110 ns | 130 ns | 90 ns | ExpFromLeft (110 ns) | 1.18x | -| log | sorted_bimodal | 64 | 16 | 240 ns | 320 ns | 250 ns | 650 ns | 320 ns | 259 ns | 280 ns | Linear (240 ns) | 1.08x | -| log | sorted_bimodal | 64 | 64 | 640 ns | 980 ns | 760 ns | 2.5 μs | 1.3 μs | 660 ns | 1.2 μs | Linear (640 ns) | 1.03x | -| log | sorted_bimodal | 64 | 256 | 2.1 μs | 3.6 μs | 2.9 μs | 9.9 μs | 4.8 μs | 2.2 μs | 4.3 μs | Linear (2.1 μs) | 1.02x | -| log | sorted_bimodal | 64 | 1024 | 8.2 μs | 13.6 μs | 11.0 μs | 39.2 μs | 18.4 μs | 8.2 μs | 16.2 μs | Linear (8.2 μs) | 1.00x | -| log | sorted_bimodal | 64 | 4096 | 31.6 μs | 52.5 μs | 42.7 μs | 154.0 μs | 71.5 μs | 31.6 μs | 63.2 μs | Linear (31.6 μs) | 1.00x | -| log | sorted_bimodal | 256 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_bimodal | 256 | 4 | 260 ns | 150 ns | 140 ns | 230 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | -| log | sorted_bimodal | 256 | 16 | 430 ns | 370 ns | 310 ns | 760 ns | 390 ns | 330 ns | 360 ns | ExpFromLeft (310 ns) | 1.06x | -| log | sorted_bimodal | 256 | 64 | 900 ns | 1.2 μs | 910 ns | 3.0 μs | 1.6 μs | 930 ns | 1.5 μs | Linear (900 ns) | 1.03x | -| log | sorted_bimodal | 256 | 256 | 2.4 μs | 3.9 μs | 2.9 μs | 12.3 μs | 6.2 μs | 2.4 μs | 5.8 μs | Linear (2.4 μs) | 1.00x | -| log | sorted_bimodal | 256 | 1024 | 8.8 μs | 15.1 μs | 11.5 μs | 50.8 μs | 23.5 μs | 8.8 μs | 21.8 μs | Linear (8.8 μs) | 1.00x | -| log | sorted_bimodal | 256 | 4096 | 33.1 μs | 56.5 μs | 43.9 μs | 192.1 μs | 90.0 μs | 33.0 μs | 81.2 μs | Linear (33.1 μs) | 1.00x | -| log | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_bimodal | 1024 | 4 | 660 ns | 170 ns | 159 ns | 260 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | -| log | sorted_bimodal | 1024 | 16 | 1.1 μs | 460 ns | 360 ns | 920 ns | 560 ns | 400 ns | 540 ns | ExpFromLeft (360 ns) | 1.11x | -| log | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.4 μs | 1.0 μs | 3.6 μs | 2.1 μs | 1.1 μs | 1.9 μs | ExpFromLeft (1.0 μs) | 1.05x | -| log | sorted_bimodal | 1024 | 256 | 3.7 μs | 4.5 μs | 3.3 μs | 14.7 μs | 7.7 μs | 3.5 μs | 7.0 μs | ExpFromLeft (3.3 μs) | 1.08x | -| log | sorted_bimodal | 1024 | 1024 | 9.8 μs | 15.8 μs | 11.6 μs | 61.0 μs | 30.9 μs | 10.0 μs | 28.7 μs | Linear (9.8 μs) | 1.01x | -| log | sorted_bimodal | 1024 | 4096 | 36.9 μs | 60.7 μs | 46.7 μs | 241.7 μs | 119.7 μs | 36.3 μs | 112.5 μs | Linear (36.9 μs) | 0.98x | -| log | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| log | sorted_bimodal | 4096 | 4 | 5.7 μs | 210 ns | 180 ns | 290 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | -| log | sorted_bimodal | 4096 | 16 | 3.2 μs | 550 ns | 430 ns | 1.1 μs | 580 ns | 450 ns | 560 ns | ExpFromLeft (430 ns) | 1.05x | -| log | sorted_bimodal | 4096 | 64 | 5.6 μs | 1.7 μs | 1.2 μs | 4.3 μs | 2.5 μs | 1.3 μs | 2.4 μs | ExpFromLeft (1.2 μs) | 1.04x | -| log | sorted_bimodal | 4096 | 256 | 7.8 μs | 5.3 μs | 3.9 μs | 17.7 μs | 10.3 μs | 3.9 μs | 9.8 μs | ExpFromLeft (3.9 μs) | 1.00x | -| log | sorted_bimodal | 4096 | 1024 | 15.6 μs | 18.6 μs | 13.8 μs | 78.8 μs | 50.3 μs | 15.8 μs | 46.1 μs | ExpFromLeft (13.8 μs) | 1.15x | -| log | sorted_bimodal | 4096 | 4096 | 44.8 μs | 69.0 μs | 51.3 μs | 337.5 μs | 197.4 μs | 43.8 μs | 194.3 μs | Linear (44.8 μs) | 0.98x | -| log | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 80 ns | 100 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | -| log | sorted_bimodal | 16384 | 4 | 10.1 μs | 230 ns | 190 ns | 340 ns | 170 ns | 230 ns | 170 ns | Binary (170 ns) | 1.35x | -| log | sorted_bimodal | 16384 | 16 | 17.8 μs | 739 ns | 560 ns | 1.3 μs | 660 ns | 580 ns | 630 ns | ExpFromLeft (560 ns) | 1.04x | -| log | sorted_bimodal | 16384 | 64 | 20.4 μs | 2.2 μs | 1.6 μs | 4.9 μs | 2.9 μs | 1.7 μs | 2.8 μs | ExpFromLeft (1.6 μs) | 1.03x | -| log | sorted_bimodal | 16384 | 256 | 25.2 μs | 6.8 μs | 5.0 μs | 20.1 μs | 16.0 μs | 5.1 μs | 15.3 μs | ExpFromLeft (5.0 μs) | 1.03x | -| log | sorted_bimodal | 16384 | 1024 | 34.0 μs | 23.5 μs | 17.1 μs | 103.6 μs | 82.6 μs | 21.8 μs | 80.9 μs | ExpFromLeft (17.1 μs) | 1.28x | -| log | sorted_bimodal | 16384 | 4096 | 74.2 μs | 89.9 μs | 65.4 μs | 455.0 μs | 280.3 μs | 71.9 μs | 273.6 μs | ExpFromLeft (65.4 μs) | 1.10x | -| log | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_bimodal | 65536 | 4 | 50.3 μs | 260 ns | 220 ns | 360 ns | 190 ns | 240 ns | 190 ns | Binary (190 ns) | 1.26x | -| log | sorted_bimodal | 65536 | 16 | 69.2 μs | 860 ns | 640 ns | 1.4 μs | 750 ns | 660 ns | 710 ns | ExpFromLeft (640 ns) | 1.03x | -| log | sorted_bimodal | 65536 | 64 | 89.6 μs | 2.8 μs | 2.2 μs | 5.7 μs | 3.4 μs | 2.2 μs | 3.2 μs | ExpFromLeft (2.2 μs) | 0.99x | -| log | sorted_bimodal | 65536 | 256 | 94.4 μs | 9.1 μs | 6.7 μs | 23.4 μs | 18.5 μs | 6.7 μs | 17.6 μs | ExpFromLeft (6.7 μs) | 1.01x | -| log | sorted_bimodal | 65536 | 1024 | 110.1 μs | 32.2 μs | 24.0 μs | 151.1 μs | 107.9 μs | 24.1 μs | 109.0 μs | ExpFromLeft (24.0 μs) | 1.00x | -| log | sorted_bimodal | 65536 | 4096 | 167.5 μs | 149.9 μs | 116.5 μs | 598.4 μs | 356.9 μs | 115.1 μs | 358.7 μs | ExpFromLeft (116.5 μs) | 0.99x | -| log | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| log | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| log | sorted_repeated | 16 | 16 | 170 ns | 260 ns | 210 ns | 630 ns | 230 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | -| log | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 680 ns | 2.4 μs | 790 ns | 580 ns | 640 ns | Linear (550 ns) | 1.05x | -| log | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 9.3 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.02x | -| log | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 37.1 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.00x | -| log | sorted_repeated | 16 | 4096 | 30.8 μs | 55.0 μs | 39.0 μs | 147.5 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 90 ns | 60 ns | 70 ns | 50 ns | ExpFromLeft (50 ns) | 1.40x | -| log | sorted_repeated | 64 | 4 | 80 ns | 90 ns | 90 ns | 210 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| log | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 200 ns | 750 ns | 320 ns | 190 ns | 260 ns | Linear (170 ns) | 1.12x | -| log | sorted_repeated | 64 | 64 | 550 ns | 919 ns | 690 ns | 2.9 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | -| log | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 11.2 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | -| log | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 44.5 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | -| log | sorted_repeated | 64 | 4096 | 30.8 μs | 55.1 μs | 39.0 μs | 178.0 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 110 ns | 270 ns | 130 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| log | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 970 ns | 380 ns | 200 ns | 350 ns | Linear (170 ns) | 1.18x | -| log | sorted_repeated | 256 | 64 | 550 ns | 930 ns | 690 ns | 3.7 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | -| log | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 3.2 μs | 14.6 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| log | sorted_repeated | 256 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 58.4 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.7 μs) | 1.00x | -| log | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 233.0 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 290 ns | 140 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | -| log | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 220 ns | 1.1 μs | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | -| log | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 4.1 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| log | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 16.3 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| log | sorted_repeated | 1024 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 64.7 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.7 μs) | 1.00x | -| log | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.0 μs | 39.3 μs | 258.6 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| log | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 340 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | -| log | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 1.2 μs | 530 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | -| log | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 710 ns | 4.7 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | -| log | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 18.8 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| log | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 75.0 μs | 31.1 μs | 7.8 μs | 28.5 μs | Linear (7.8 μs) | 1.00x | -| log | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.0 μs | 299.9 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_repeated | 16384 | 1 | 90 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| log | sorted_repeated | 16384 | 4 | 90 ns | 110 ns | 110 ns | 390 ns | 190 ns | 120 ns | 170 ns | Linear (90 ns) | 1.33x | -| log | sorted_repeated | 16384 | 16 | 180 ns | 290 ns | 240 ns | 1.4 μs | 600 ns | 210 ns | 560 ns | Linear (180 ns) | 1.17x | -| log | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 720 ns | 5.4 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | -| log | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 21.5 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | -| log | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 86.0 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | -| log | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.1 μs | 39.3 μs | 342.9 μs | 144.0 μs | 30.8 μs | 133.5 μs | Linear (30.8 μs) | 1.00x | -| log | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| log | sorted_repeated | 65536 | 4 | 100 ns | 110 ns | 110 ns | 430 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| log | sorted_repeated | 65536 | 16 | 190 ns | 300 ns | 230 ns | 1.5 μs | 690 ns | 210 ns | 640 ns | Linear (190 ns) | 1.11x | -| log | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 710 ns | 6.1 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| log | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 23.8 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.02x | -| log | sorted_repeated | 65536 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 95.4 μs | 40.8 μs | 7.8 μs | 38.2 μs | Linear (7.7 μs) | 1.01x | -| log | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 380.7 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| log | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| log | unsorted | 16 | 4 | 100 ns | 90 ns | 100 ns | 100 ns | 100 ns | 110 ns | 70 ns | Gallop (90 ns) | 1.22x | -| log | unsorted | 16 | 16 | 230 ns | 230 ns | 220 ns | 230 ns | 220 ns | 230 ns | 210 ns | ExpFromLeft (220 ns) | 1.05x | -| log | unsorted | 16 | 64 | 730 ns | 730 ns | 740 ns | 720 ns | 720 ns | 740 ns | 720 ns | InterpSearch (720 ns) | 1.03x | -| log | unsorted | 16 | 256 | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.8 μs | 3.3 μs | 3.3 μs | Binary (2.8 μs) | 1.17x | -| log | unsorted | 16 | 1024 | 14.3 μs | 13.7 μs | 13.7 μs | 13.5 μs | 13.6 μs | 13.5 μs | 13.7 μs | InterpSearch (13.5 μs) | 1.00x | -| log | unsorted | 16 | 4096 | 92.7 μs | 88.1 μs | 88.6 μs | 88.9 μs | 88.3 μs | 88.2 μs | 92.6 μs | Gallop (88.1 μs) | 1.00x | -| log | unsorted | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| log | unsorted | 64 | 4 | 110 ns | 100 ns | 110 ns | 110 ns | 120 ns | 130 ns | 90 ns | Gallop (100 ns) | 1.30x | -| log | unsorted | 64 | 16 | 280 ns | 280 ns | 270 ns | 279 ns | 280 ns | 290 ns | 270 ns | ExpFromLeft (270 ns) | 1.07x | -| log | unsorted | 64 | 64 | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | InterpSearch (1.0 μs) | 1.00x | -| log | unsorted | 64 | 256 | 5.6 μs | 5.6 μs | 5.5 μs | 5.5 μs | 5.5 μs | 5.5 μs | 5.8 μs | Binary (5.5 μs) | 1.00x | -| log | unsorted | 64 | 1024 | 29.8 μs | 29.5 μs | 29.6 μs | 29.4 μs | 29.4 μs | 29.3 μs | 31.4 μs | InterpSearch (29.4 μs) | 1.00x | -| log | unsorted | 64 | 4096 | 172.7 μs | 166.7 μs | 166.4 μs | 165.5 μs | 167.9 μs | 167.0 μs | 173.3 μs | InterpSearch (165.5 μs) | 1.01x | -| log | unsorted | 256 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| log | unsorted | 256 | 4 | 130 ns | 130 ns | 120 ns | 120 ns | 120 ns | 130 ns | 110 ns | InterpSearch (120 ns) | 1.08x | -| log | unsorted | 256 | 16 | 340 ns | 350 ns | 360 ns | 350 ns | 340 ns | 360 ns | 340 ns | Binary (340 ns) | 1.06x | -| log | unsorted | 256 | 64 | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | Binary (1.5 μs) | 1.01x | -| log | unsorted | 256 | 256 | 8.4 μs | 8.1 μs | 8.0 μs | 8.1 μs | 8.0 μs | 7.7 μs | 8.0 μs | ExpFromLeft (8.0 μs) | 0.96x | -| log | unsorted | 256 | 1024 | 47.7 μs | 47.3 μs | 45.2 μs | 46.6 μs | 45.4 μs | 45.9 μs | 46.0 μs | ExpFromLeft (45.2 μs) | 1.01x | -| log | unsorted | 256 | 4096 | 254.6 μs | 258.8 μs | 252.9 μs | 250.5 μs | 250.1 μs | 252.7 μs | 258.4 μs | Binary (250.1 μs) | 1.01x | -| log | unsorted | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| log | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 129 ns | InterpSearch (140 ns) | 1.07x | -| log | unsorted | 1024 | 16 | 420 ns | 420 ns | 420 ns | 410 ns | 420 ns | 430 ns | 420 ns | InterpSearch (410 ns) | 1.05x | -| log | unsorted | 1024 | 64 | 1.9 μs | 1.9 μs | 1.9 μs | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | Binary (1.8 μs) | 0.99x | -| log | unsorted | 1024 | 256 | 10.0 μs | 9.9 μs | 9.5 μs | 9.8 μs | 9.8 μs | 9.8 μs | 10.0 μs | ExpFromLeft (9.5 μs) | 1.03x | -| log | unsorted | 1024 | 1024 | 69.6 μs | 68.8 μs | 68.3 μs | 67.9 μs | 67.7 μs | 67.1 μs | 70.7 μs | Binary (67.7 μs) | 0.99x | -| log | unsorted | 1024 | 4096 | 346.5 μs | 348.4 μs | 347.6 μs | 341.8 μs | 340.3 μs | 343.2 μs | 346.4 μs | Binary (340.3 μs) | 1.01x | -| log | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| log | unsorted | 4096 | 4 | 160 ns | 150 ns | 160 ns | 160 ns | 160 ns | 170 ns | 150 ns | Gallop (150 ns) | 1.13x | -| log | unsorted | 4096 | 16 | 490 ns | 500 ns | 490 ns | 500 ns | 500 ns | 500 ns | 480 ns | ExpFromLeft (490 ns) | 1.02x | -| log | unsorted | 4096 | 64 | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | InterpSearch (2.1 μs) | 1.00x | -| log | unsorted | 4096 | 256 | 11.8 μs | 11.5 μs | 11.4 μs | 11.4 μs | 11.4 μs | 11.1 μs | 11.9 μs | Binary (11.4 μs) | 0.97x | -| log | unsorted | 4096 | 1024 | 89.7 μs | 88.0 μs | 87.5 μs | 86.4 μs | 85.7 μs | 87.0 μs | 89.5 μs | Binary (85.7 μs) | 1.02x | -| log | unsorted | 4096 | 4096 | 428.6 μs | 431.1 μs | 423.5 μs | 430.9 μs | 423.9 μs | 422.9 μs | 430.9 μs | ExpFromLeft (423.5 μs) | 1.00x | -| log | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 120 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | -| log | unsorted | 16384 | 4 | 170 ns | 180 ns | 170 ns | 180 ns | 170 ns | 180 ns | 160 ns | ExpFromLeft (170 ns) | 1.06x | -| log | unsorted | 16384 | 16 | 570 ns | 580 ns | 570 ns | 570 ns | 570 ns | 580 ns | 560 ns | InterpSearch (570 ns) | 1.02x | -| log | unsorted | 16384 | 64 | 2.5 μs | 2.5 μs | 2.5 μs | 2.5 μs | 2.5 μs | 2.5 μs | 2.5 μs | InterpSearch (2.5 μs) | 1.01x | -| log | unsorted | 16384 | 256 | 13.2 μs | 12.8 μs | 12.9 μs | 12.8 μs | 12.7 μs | 12.7 μs | 15.5 μs | Binary (12.7 μs) | 1.00x | -| log | unsorted | 16384 | 1024 | 116.9 μs | 114.2 μs | 113.5 μs | 112.5 μs | 112.5 μs | 112.1 μs | 112.7 μs | InterpSearch (112.5 μs) | 1.00x | -| log | unsorted | 16384 | 4096 | 552.6 μs | 550.7 μs | 551.9 μs | 549.2 μs | 552.4 μs | 552.0 μs | 547.4 μs | InterpSearch (549.2 μs) | 1.00x | -| log | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | -| log | unsorted | 65536 | 4 | 200 ns | 200 ns | 200 ns | 210 ns | 200 ns | 210 ns | 190 ns | ExpFromLeft (200 ns) | 1.05x | -| log | unsorted | 65536 | 16 | 660 ns | 660 ns | 660 ns | 660 ns | 660 ns | 670 ns | 640 ns | InterpSearch (660 ns) | 1.02x | -| log | unsorted | 65536 | 64 | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.9 μs | InterpSearch (2.8 μs) | 1.00x | -| log | unsorted | 65536 | 256 | 15.8 μs | 15.6 μs | 15.5 μs | 15.4 μs | 15.4 μs | 15.4 μs | 18.2 μs | Binary (15.4 μs) | 1.00x | -| log | unsorted | 65536 | 1024 | 158.2 μs | 154.8 μs | 152.1 μs | 151.9 μs | 151.7 μs | 151.9 μs | 154.8 μs | Binary (151.7 μs) | 1.00x | -| log | unsorted | 65536 | 4096 | 709.2 μs | 708.3 μs | 705.0 μs | 706.6 μs | 707.8 μs | 709.2 μs | 706.6 μs | ExpFromLeft (705.0 μs) | 1.01x | -| jittered | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | sorted_uniform | 16 | 4 | 90 ns | 110 ns | 100 ns | 160 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| jittered | sorted_uniform | 16 | 16 | 180 ns | 280 ns | 210 ns | 520 ns | 220 ns | 210 ns | 190 ns | Linear (180 ns) | 1.17x | -| jittered | sorted_uniform | 16 | 64 | 560 ns | 1.0 μs | 730 ns | 1.9 μs | 1.0 μs | 590 ns | 880 ns | Linear (560 ns) | 1.05x | -| jittered | sorted_uniform | 16 | 256 | 2.3 μs | 3.7 μs | 2.9 μs | 7.7 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.03x | -| jittered | sorted_uniform | 16 | 1024 | 8.1 μs | 14.0 μs | 10.8 μs | 28.2 μs | 12.2 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | -| jittered | sorted_uniform | 16 | 4096 | 31.0 μs | 54.8 μs | 42.4 μs | 109.5 μs | 48.2 μs | 31.1 μs | 40.7 μs | Linear (31.0 μs) | 1.00x | -| jittered | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| jittered | sorted_uniform | 64 | 4 | 130 ns | 130 ns | 120 ns | 150 ns | 100 ns | 140 ns | 90 ns | Binary (100 ns) | 1.40x | -| jittered | sorted_uniform | 64 | 16 | 250 ns | 350 ns | 280 ns | 470 ns | 310 ns | 270 ns | 290 ns | Linear (250 ns) | 1.08x | -| jittered | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 770 ns | 2.0 μs | 1.4 μs | 650 ns | 1.4 μs | Linear (630 ns) | 1.03x | -| jittered | sorted_uniform | 64 | 256 | 2.1 μs | 4.2 μs | 3.1 μs | 9.3 μs | 5.1 μs | 2.2 μs | 4.7 μs | Linear (2.1 μs) | 1.02x | -| jittered | sorted_uniform | 64 | 1024 | 9.2 μs | 14.8 μs | 11.7 μs | 31.4 μs | 17.8 μs | 9.1 μs | 16.0 μs | Linear (9.2 μs) | 0.99x | -| jittered | sorted_uniform | 64 | 4096 | 32.1 μs | 56.0 μs | 43.2 μs | 113.6 μs | 67.2 μs | 32.2 μs | 60.2 μs | Linear (32.1 μs) | 1.00x | -| jittered | sorted_uniform | 256 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_uniform | 256 | 4 | 430 ns | 170 ns | 140 ns | 140 ns | 130 ns | 160 ns | 110 ns | Binary (130 ns) | 1.23x | -| jittered | sorted_uniform | 256 | 16 | 480 ns | 450 ns | 370 ns | 470 ns | 410 ns | 380 ns | 380 ns | ExpFromLeft (370 ns) | 1.03x | -| jittered | sorted_uniform | 256 | 64 | 910 ns | 1.3 μs | 960 ns | 1.9 μs | 1.7 μs | 930 ns | 1.5 μs | Linear (910 ns) | 1.02x | -| jittered | sorted_uniform | 256 | 256 | 2.4 μs | 4.2 μs | 2.9 μs | 9.1 μs | 7.5 μs | 2.4 μs | 7.1 μs | Linear (2.4 μs) | 1.01x | -| jittered | sorted_uniform | 256 | 1024 | 10.2 μs | 17.8 μs | 13.6 μs | 37.1 μs | 27.1 μs | 10.3 μs | 25.5 μs | Linear (10.2 μs) | 1.01x | -| jittered | sorted_uniform | 256 | 4096 | 36.6 μs | 59.4 μs | 46.7 μs | 126.0 μs | 91.7 μs | 48.0 μs | 87.4 μs | Linear (36.6 μs) | 1.31x | -| jittered | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | -| jittered | sorted_uniform | 1024 | 4 | 1.5 μs | 190 ns | 160 ns | 150 ns | 150 ns | 200 ns | 120 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_uniform | 1024 | 16 | 1.7 μs | 580 ns | 470 ns | 490 ns | 450 ns | 490 ns | 410 ns | Binary (450 ns) | 1.09x | -| jittered | sorted_uniform | 1024 | 64 | 2.1 μs | 1.7 μs | 1.4 μs | 2.0 μs | 1.9 μs | 2.1 μs | 1.8 μs | ExpFromLeft (1.4 μs) | 1.57x | -| jittered | sorted_uniform | 1024 | 256 | 3.6 μs | 5.2 μs | 3.9 μs | 8.9 μs | 7.7 μs | 3.8 μs | 7.6 μs | Linear (3.6 μs) | 1.06x | -| jittered | sorted_uniform | 1024 | 1024 | 10.8 μs | 17.7 μs | 12.5 μs | 38.9 μs | 56.6 μs | 10.7 μs | 54.0 μs | Linear (10.8 μs) | 0.99x | -| jittered | sorted_uniform | 1024 | 4096 | 48.4 μs | 72.4 μs | 58.0 μs | 148.8 μs | 193.7 μs | 48.6 μs | 186.8 μs | Linear (48.4 μs) | 1.01x | -| jittered | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_uniform | 4096 | 4 | 5.6 μs | 240 ns | 200 ns | 150 ns | 160 ns | 200 ns | 150 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_uniform | 4096 | 16 | 5.8 μs | 720 ns | 550 ns | 470 ns | 540 ns | 530 ns | 490 ns | InterpSearch (470 ns) | 1.13x | -| jittered | sorted_uniform | 4096 | 64 | 7.0 μs | 2.2 μs | 1.7 μs | 2.0 μs | 2.2 μs | 2.2 μs | 1.9 μs | ExpFromLeft (1.7 μs) | 1.31x | -| jittered | sorted_uniform | 4096 | 256 | 8.9 μs | 7.2 μs | 5.3 μs | 9.3 μs | 10.5 μs | 9.8 μs | 10.6 μs | ExpFromLeft (5.3 μs) | 1.84x | -| jittered | sorted_uniform | 4096 | 1024 | 16.5 μs | 24.0 μs | 17.3 μs | 37.6 μs | 95.3 μs | 15.0 μs | 91.3 μs | Linear (16.5 μs) | 0.91x | -| jittered | sorted_uniform | 4096 | 4096 | 68.5 μs | 93.8 μs | 72.7 μs | 155.5 μs | 305.7 μs | 65.1 μs | 297.2 μs | Linear (68.5 μs) | 0.95x | -| jittered | sorted_uniform | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_uniform | 16384 | 4 | 20.7 μs | 260 ns | 220 ns | 150 ns | 180 ns | 200 ns | 160 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_uniform | 16384 | 16 | 21.9 μs | 890 ns | 660 ns | 500 ns | 590 ns | 560 ns | 560 ns | InterpSearch (500 ns) | 1.12x | -| jittered | sorted_uniform | 16384 | 64 | 24.8 μs | 3.7 μs | 2.2 μs | 2.2 μs | 2.4 μs | 2.3 μs | 2.2 μs | InterpSearch (2.2 μs) | 1.06x | -| jittered | sorted_uniform | 16384 | 256 | 30.5 μs | 9.8 μs | 7.0 μs | 9.2 μs | 13.2 μs | 9.7 μs | 13.3 μs | ExpFromLeft (7.0 μs) | 1.39x | -| jittered | sorted_uniform | 16384 | 1024 | 40.1 μs | 35.0 μs | 25.9 μs | 38.6 μs | 126.5 μs | 40.5 μs | 125.4 μs | ExpFromLeft (25.9 μs) | 1.56x | -| jittered | sorted_uniform | 16384 | 4096 | 115.9 μs | 160.8 μs | 121.1 μs | 153.8 μs | 404.3 μs | 112.0 μs | 397.3 μs | Linear (115.9 μs) | 0.97x | -| jittered | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_uniform | 65536 | 4 | 87.4 μs | 300 ns | 240 ns | 150 ns | 210 ns | 200 ns | 180 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_uniform | 65536 | 16 | 79.4 μs | 1.1 μs | 760 ns | 500 ns | 690 ns | 570 ns | 630 ns | InterpSearch (500 ns) | 1.14x | -| jittered | sorted_uniform | 65536 | 64 | 93.0 μs | 3.6 μs | 2.7 μs | 2.0 μs | 2.8 μs | 2.1 μs | 2.6 μs | InterpSearch (2.0 μs) | 1.09x | -| jittered | sorted_uniform | 65536 | 256 | 102.7 μs | 12.2 μs | 9.7 μs | 9.3 μs | 16.1 μs | 10.0 μs | 17.0 μs | InterpSearch (9.3 μs) | 1.07x | -| jittered | sorted_uniform | 65536 | 1024 | 119.3 μs | 60.6 μs | 44.0 μs | 39.3 μs | 156.2 μs | 41.6 μs | 159.3 μs | InterpSearch (39.3 μs) | 1.06x | -| jittered | sorted_uniform | 65536 | 4096 | 196.4 μs | 252.4 μs | 200.9 μs | 153.0 μs | 493.3 μs | 160.9 μs | 494.8 μs | InterpSearch (153.0 μs) | 1.05x | -| jittered | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| jittered | sorted_dense_burst | 16 | 16 | 170 ns | 270 ns | 220 ns | 500 ns | 230 ns | 200 ns | 190 ns | Linear (170 ns) | 1.18x | -| jittered | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 730 ns | 1.8 μs | 790 ns | 580 ns | 660 ns | Linear (550 ns) | 1.05x | -| jittered | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.01x | -| jittered | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 27.4 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.00x | -| jittered | sorted_dense_burst | 16 | 4096 | 30.8 μs | 55.0 μs | 41.8 μs | 108.9 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 100 ns | 140 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| jittered | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 230 ns | 490 ns | 300 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | -| jittered | sorted_dense_burst | 64 | 64 | 560 ns | 920 ns | 730 ns | 1.8 μs | 1.1 μs | 580 ns | 930 ns | Linear (560 ns) | 1.04x | -| jittered | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | -| jittered | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.7 μs | 10.5 μs | 26.9 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | -| jittered | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.9 μs | 42.0 μs | 107.4 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_dense_burst | 256 | 4 | 80 ns | 100 ns | 100 ns | 150 ns | 120 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | -| jittered | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 500 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| jittered | sorted_dense_burst | 256 | 64 | 550 ns | 940 ns | 740 ns | 1.8 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | -| jittered | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| jittered | sorted_dense_burst | 256 | 1024 | 7.7 μs | 14.0 μs | 10.4 μs | 27.3 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.7 μs) | 1.00x | -| jittered | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.7 μs | 41.6 μs | 108.4 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_dense_burst | 1024 | 4 | 100 ns | 120 ns | 110 ns | 160 ns | 140 ns | 110 ns | 130 ns | Linear (100 ns) | 1.10x | -| jittered | sorted_dense_burst | 1024 | 16 | 180 ns | 290 ns | 250 ns | 490 ns | 460 ns | 210 ns | 400 ns | Linear (180 ns) | 1.17x | -| jittered | sorted_dense_burst | 1024 | 64 | 559 ns | 930 ns | 740 ns | 1.8 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (559 ns) | 1.06x | -| jittered | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| jittered | sorted_dense_burst | 1024 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 27.8 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.01x | -| jittered | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 54.8 μs | 42.0 μs | 110.5 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_dense_burst | 4096 | 4 | 89 ns | 110 ns | 110 ns | 150 ns | 160 ns | 120 ns | 150 ns | Linear (89 ns) | 1.35x | -| jittered | sorted_dense_burst | 4096 | 16 | 180 ns | 290 ns | 250 ns | 490 ns | 540 ns | 260 ns | 490 ns | Linear (180 ns) | 1.44x | -| jittered | sorted_dense_burst | 4096 | 64 | 570 ns | 930 ns | 750 ns | 1.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (570 ns) | 1.04x | -| jittered | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| jittered | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 27.1 μs | 31.1 μs | 7.8 μs | 28.5 μs | Linear (7.7 μs) | 1.01x | -| jittered | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 54.9 μs | 42.0 μs | 107.7 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_dense_burst | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 180 ns | 120 ns | 170 ns | Linear (100 ns) | 1.20x | -| jittered | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 490 ns | 610 ns | 220 ns | 570 ns | Linear (190 ns) | 1.16x | -| jittered | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 749 ns | 1.8 μs | 2.3 μs | 610 ns | 2.1 μs | Linear (570 ns) | 1.07x | -| jittered | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | -| jittered | sorted_dense_burst | 16384 | 1024 | 8.3 μs | 13.7 μs | 10.6 μs | 27.2 μs | 36.1 μs | 7.8 μs | 33.5 μs | Linear (8.3 μs) | 0.94x | -| jittered | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 107.7 μs | 144.1 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 150 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| jittered | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 250 ns | 510 ns | 680 ns | 260 ns | 640 ns | Linear (190 ns) | 1.37x | -| jittered | sorted_dense_burst | 65536 | 64 | 570 ns | 950 ns | 750 ns | 1.8 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| jittered | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | -| jittered | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 27.0 μs | 40.8 μs | 7.8 μs | 38.2 μs | Linear (7.8 μs) | 1.00x | -| jittered | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 107.4 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | sorted_near_start | 16 | 4 | 80 ns | 100 ns | 100 ns | 150 ns | 90 ns | 110 ns | 70 ns | Linear (80 ns) | 1.38x | -| jittered | sorted_near_start | 16 | 16 | 180 ns | 290 ns | 220 ns | 490 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | -| jittered | sorted_near_start | 16 | 64 | 570 ns | 959 ns | 740 ns | 1.8 μs | 810 ns | 610 ns | 679 ns | Linear (570 ns) | 1.07x | -| jittered | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | -| jittered | sorted_near_start | 16 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 27.5 μs | 12.2 μs | 7.9 μs | 10.3 μs | Linear (7.9 μs) | 1.00x | -| jittered | sorted_near_start | 16 | 4096 | 31.1 μs | 55.2 μs | 42.2 μs | 107.0 μs | 47.8 μs | 31.1 μs | 40.3 μs | Linear (31.1 μs) | 1.00x | -| jittered | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| jittered | sorted_near_start | 64 | 4 | 140 ns | 130 ns | 110 ns | 150 ns | 110 ns | 120 ns | 90 ns | ExpFromLeft (110 ns) | 1.09x | -| jittered | sorted_near_start | 64 | 16 | 260 ns | 300 ns | 250 ns | 480 ns | 320 ns | 270 ns | 280 ns | ExpFromLeft (250 ns) | 1.08x | -| jittered | sorted_near_start | 64 | 64 | 680 ns | 1.0 μs | 820 ns | 1.9 μs | 1.1 μs | 700 ns | 1.0 μs | Linear (680 ns) | 1.03x | -| jittered | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.2 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.02x | -| jittered | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 28.0 μs | 17.2 μs | 7.9 μs | 15.6 μs | Linear (7.9 μs) | 1.00x | -| jittered | sorted_near_start | 64 | 4096 | 31.8 μs | 56.1 μs | 43.1 μs | 111.0 μs | 67.1 μs | 31.8 μs | 59.9 μs | Linear (31.8 μs) | 1.00x | -| jittered | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_near_start | 256 | 4 | 250 ns | 130 ns | 120 ns | 150 ns | 120 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | -| jittered | sorted_near_start | 256 | 16 | 440 ns | 340 ns | 260 ns | 490 ns | 390 ns | 280 ns | 370 ns | ExpFromLeft (260 ns) | 1.08x | -| jittered | sorted_near_start | 256 | 64 | 890 ns | 1.1 μs | 850 ns | 1.9 μs | 1.6 μs | 920 ns | 1.5 μs | ExpFromLeft (850 ns) | 1.08x | -| jittered | sorted_near_start | 256 | 256 | 2.6 μs | 3.9 μs | 3.1 μs | 7.6 μs | 5.7 μs | 2.6 μs | 5.2 μs | Linear (2.6 μs) | 1.00x | -| jittered | sorted_near_start | 256 | 1024 | 8.5 μs | 14.5 μs | 11.0 μs | 28.8 μs | 22.2 μs | 8.5 μs | 20.3 μs | Linear (8.5 μs) | 1.00x | -| jittered | sorted_near_start | 256 | 4096 | 31.7 μs | 56.3 μs | 42.5 μs | 114.1 μs | 89.7 μs | 31.5 μs | 81.8 μs | Linear (31.7 μs) | 0.99x | -| jittered | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_near_start | 1024 | 4 | 550 ns | 180 ns | 160 ns | 150 ns | 130 ns | 200 ns | 120 ns | Binary (130 ns) | 1.54x | -| jittered | sorted_near_start | 1024 | 16 | 1.3 μs | 400 ns | 330 ns | 470 ns | 500 ns | 350 ns | 450 ns | ExpFromLeft (330 ns) | 1.06x | -| jittered | sorted_near_start | 1024 | 64 | 1.9 μs | 1.2 μs | 880 ns | 2.0 μs | 2.1 μs | 920 ns | 1.9 μs | ExpFromLeft (880 ns) | 1.05x | -| jittered | sorted_near_start | 1024 | 256 | 3.7 μs | 4.5 μs | 3.5 μs | 8.6 μs | 7.7 μs | 3.7 μs | 7.1 μs | ExpFromLeft (3.5 μs) | 1.05x | -| jittered | sorted_near_start | 1024 | 1024 | 10.7 μs | 15.7 μs | 12.3 μs | 31.0 μs | 27.3 μs | 10.6 μs | 25.7 μs | Linear (10.7 μs) | 0.99x | -| jittered | sorted_near_start | 1024 | 4096 | 33.8 μs | 58.1 μs | 44.1 μs | 116.9 μs | 110.4 μs | 33.9 μs | 104.5 μs | Linear (33.8 μs) | 1.00x | -| jittered | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_near_start | 4096 | 4 | 3.6 μs | 220 ns | 180 ns | 150 ns | 160 ns | 200 ns | 150 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_near_start | 4096 | 16 | 3.2 μs | 500 ns | 420 ns | 470 ns | 540 ns | 430 ns | 500 ns | ExpFromLeft (420 ns) | 1.02x | -| jittered | sorted_near_start | 4096 | 64 | 5.3 μs | 1.5 μs | 1.1 μs | 2.0 μs | 2.3 μs | 1.2 μs | 2.2 μs | ExpFromLeft (1.1 μs) | 1.05x | -| jittered | sorted_near_start | 4096 | 256 | 8.2 μs | 4.8 μs | 3.4 μs | 9.0 μs | 11.0 μs | 3.5 μs | 10.5 μs | ExpFromLeft (3.4 μs) | 1.03x | -| jittered | sorted_near_start | 4096 | 1024 | 16.4 μs | 19.1 μs | 14.9 μs | 36.2 μs | 43.0 μs | 16.5 μs | 38.4 μs | ExpFromLeft (14.9 μs) | 1.11x | -| jittered | sorted_near_start | 4096 | 4096 | 42.3 μs | 63.1 μs | 49.7 μs | 123.3 μs | 155.7 μs | 42.1 μs | 140.7 μs | Linear (42.3 μs) | 1.00x | -| jittered | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_near_start | 16384 | 4 | 12.9 μs | 230 ns | 200 ns | 150 ns | 180 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_near_start | 16384 | 16 | 14.5 μs | 660 ns | 510 ns | 460 ns | 600 ns | 530 ns | 560 ns | InterpSearch (460 ns) | 1.15x | -| jittered | sorted_near_start | 16384 | 64 | 24.5 μs | 2.0 μs | 1.4 μs | 2.0 μs | 3.2 μs | 1.5 μs | 2.9 μs | ExpFromLeft (1.4 μs) | 1.03x | -| jittered | sorted_near_start | 16384 | 256 | 23.2 μs | 6.0 μs | 4.5 μs | 9.2 μs | 17.7 μs | 4.4 μs | 16.4 μs | ExpFromLeft (4.5 μs) | 1.00x | -| jittered | sorted_near_start | 16384 | 1024 | 32.8 μs | 21.0 μs | 14.8 μs | 38.4 μs | 74.8 μs | 14.8 μs | 67.5 μs | ExpFromLeft (14.8 μs) | 1.00x | -| jittered | sorted_near_start | 16384 | 4096 | 73.9 μs | 78.7 μs | 62.5 μs | 148.2 μs | 256.1 μs | 73.9 μs | 239.6 μs | ExpFromLeft (62.5 μs) | 1.18x | -| jittered | sorted_near_start | 65536 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_near_start | 65536 | 4 | 49.0 μs | 250 ns | 210 ns | 150 ns | 200 ns | 200 ns | 190 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_near_start | 65536 | 16 | 24.1 μs | 750 ns | 580 ns | 470 ns | 700 ns | 600 ns | 670 ns | InterpSearch (470 ns) | 1.28x | -| jittered | sorted_near_start | 65536 | 64 | 92.7 μs | 2.5 μs | 1.9 μs | 2.0 μs | 3.3 μs | 2.0 μs | 3.2 μs | ExpFromLeft (1.9 μs) | 1.01x | -| jittered | sorted_near_start | 65536 | 256 | 97.9 μs | 8.1 μs | 5.9 μs | 9.0 μs | 20.7 μs | 5.9 μs | 19.5 μs | ExpFromLeft (5.9 μs) | 1.00x | -| jittered | sorted_near_start | 65536 | 1024 | 106.4 μs | 27.3 μs | 19.7 μs | 38.4 μs | 96.6 μs | 18.0 μs | 87.9 μs | ExpFromLeft (19.7 μs) | 0.91x | -| jittered | sorted_near_start | 65536 | 4096 | 157.3 μs | 121.6 μs | 95.3 μs | 154.7 μs | 322.8 μs | 92.5 μs | 296.2 μs | ExpFromLeft (95.3 μs) | 0.97x | -| jittered | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | sorted_arithmetic | 16 | 4 | 100 ns | 120 ns | 120 ns | 150 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | -| jittered | sorted_arithmetic | 16 | 16 | 190 ns | 300 ns | 210 ns | 500 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| jittered | sorted_arithmetic | 16 | 64 | 590 ns | 1.1 μs | 760 ns | 2.0 μs | 1.0 μs | 620 ns | 890 ns | Linear (590 ns) | 1.05x | -| jittered | sorted_arithmetic | 16 | 256 | 2.3 μs | 3.7 μs | 3.0 μs | 7.8 μs | 3.3 μs | 2.4 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | -| jittered | sorted_arithmetic | 16 | 1024 | 11.3 μs | 18.7 μs | 14.2 μs | 28.2 μs | 12.1 μs | 8.1 μs | 10.5 μs | Linear (11.3 μs) | 0.71x | -| jittered | sorted_arithmetic | 16 | 4096 | 31.1 μs | 54.9 μs | 42.3 μs | 109.7 μs | 47.9 μs | 31.1 μs | 40.7 μs | Linear (31.1 μs) | 1.00x | -| jittered | sorted_arithmetic | 64 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 50 ns | 50 ns | Binary (60 ns) | 0.83x | -| jittered | sorted_arithmetic | 64 | 4 | 170 ns | 140 ns | 140 ns | 150 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | -| jittered | sorted_arithmetic | 64 | 16 | 260 ns | 410 ns | 320 ns | 490 ns | 300 ns | 290 ns | 260 ns | Linear (260 ns) | 1.12x | -| jittered | sorted_arithmetic | 64 | 64 | 640 ns | 1.2 μs | 789 ns | 2.1 μs | 1.3 μs | 670 ns | 1.1 μs | Linear (640 ns) | 1.05x | -| jittered | sorted_arithmetic | 64 | 256 | 2.5 μs | 4.1 μs | 3.1 μs | 7.8 μs | 5.4 μs | 2.6 μs | 4.7 μs | Linear (2.5 μs) | 1.02x | -| jittered | sorted_arithmetic | 64 | 1024 | 9.0 μs | 14.8 μs | 11.7 μs | 31.7 μs | 17.8 μs | 9.0 μs | 15.9 μs | Linear (9.0 μs) | 1.01x | -| jittered | sorted_arithmetic | 64 | 4096 | 32.2 μs | 56.1 μs | 43.2 μs | 113.1 μs | 67.3 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | -| jittered | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_arithmetic | 256 | 4 | 470 ns | 180 ns | 160 ns | 140 ns | 130 ns | 180 ns | 110 ns | Binary (130 ns) | 1.38x | -| jittered | sorted_arithmetic | 256 | 16 | 650 ns | 530 ns | 400 ns | 460 ns | 390 ns | 430 ns | 340 ns | Binary (390 ns) | 1.10x | -| jittered | sorted_arithmetic | 256 | 64 | 1.0 μs | 1.7 μs | 1.3 μs | 2.0 μs | 1.4 μs | 1.1 μs | 1.3 μs | Linear (1.0 μs) | 1.02x | -| jittered | sorted_arithmetic | 256 | 256 | 2.5 μs | 4.4 μs | 2.9 μs | 8.4 μs | 7.1 μs | 2.5 μs | 6.8 μs | Linear (2.5 μs) | 1.01x | -| jittered | sorted_arithmetic | 256 | 1024 | 10.1 μs | 16.1 μs | 12.2 μs | 30.0 μs | 27.1 μs | 10.1 μs | 25.0 μs | Linear (10.1 μs) | 1.00x | -| jittered | sorted_arithmetic | 256 | 4096 | 36.0 μs | 59.6 μs | 46.6 μs | 124.5 μs | 91.4 μs | 35.8 μs | 83.3 μs | Linear (36.0 μs) | 1.00x | -| jittered | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| jittered | sorted_arithmetic | 1024 | 4 | 1.6 μs | 210 ns | 170 ns | 150 ns | 150 ns | 190 ns | 130 ns | InterpSearch (150 ns) | 1.27x | -| jittered | sorted_arithmetic | 1024 | 16 | 1.7 μs | 700 ns | 520 ns | 470 ns | 450 ns | 540 ns | 410 ns | Binary (450 ns) | 1.20x | -| jittered | sorted_arithmetic | 1024 | 64 | 2.2 μs | 2.2 μs | 1.6 μs | 1.9 μs | 1.7 μs | 2.1 μs | 1.6 μs | ExpFromLeft (1.6 μs) | 1.25x | -| jittered | sorted_arithmetic | 1024 | 256 | 4.5 μs | 6.2 μs | 4.7 μs | 7.2 μs | 8.3 μs | 3.6 μs | 8.0 μs | Linear (4.5 μs) | 0.80x | -| jittered | sorted_arithmetic | 1024 | 1024 | 10.6 μs | 19.0 μs | 12.4 μs | 36.6 μs | 75.8 μs | 10.4 μs | 77.0 μs | Linear (10.6 μs) | 0.98x | -| jittered | sorted_arithmetic | 1024 | 4096 | 41.5 μs | 64.6 μs | 49.7 μs | 119.0 μs | 197.0 μs | 41.5 μs | 192.3 μs | Linear (41.5 μs) | 1.00x | -| jittered | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| jittered | sorted_arithmetic | 4096 | 4 | 6.0 μs | 240 ns | 200 ns | 150 ns | 160 ns | 190 ns | 150 ns | InterpSearch (150 ns) | 1.27x | -| jittered | sorted_arithmetic | 4096 | 16 | 6.4 μs | 820 ns | 610 ns | 520 ns | 540 ns | 580 ns | 490 ns | InterpSearch (520 ns) | 1.12x | -| jittered | sorted_arithmetic | 4096 | 64 | 6.4 μs | 2.7 μs | 1.9 μs | 1.9 μs | 2.0 μs | 2.0 μs | 1.9 μs | InterpSearch (1.9 μs) | 1.08x | -| jittered | sorted_arithmetic | 4096 | 256 | 8.7 μs | 8.7 μs | 6.6 μs | 8.0 μs | 8.2 μs | 8.6 μs | 8.1 μs | ExpFromLeft (6.6 μs) | 1.30x | -| jittered | sorted_arithmetic | 4096 | 1024 | 14.5 μs | 25.0 μs | 18.8 μs | 29.9 μs | 86.1 μs | 14.5 μs | 75.9 μs | Linear (14.5 μs) | 1.00x | -| jittered | sorted_arithmetic | 4096 | 4096 | 39.0 μs | 66.3 μs | 44.2 μs | 116.3 μs | 314.0 μs | 39.0 μs | 310.8 μs | Linear (39.0 μs) | 1.00x | -| jittered | sorted_arithmetic | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 90 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_arithmetic | 16384 | 4 | 23.4 μs | 270 ns | 230 ns | 150 ns | 180 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_arithmetic | 16384 | 16 | 23.8 μs | 1.0 μs | 720 ns | 500 ns | 620 ns | 560 ns | 570 ns | InterpSearch (500 ns) | 1.12x | -| jittered | sorted_arithmetic | 16384 | 64 | 25.3 μs | 3.4 μs | 2.2 μs | 2.0 μs | 2.3 μs | 2.1 μs | 2.2 μs | InterpSearch (2.0 μs) | 1.05x | -| jittered | sorted_arithmetic | 16384 | 256 | 26.2 μs | 10.8 μs | 8.0 μs | 7.7 μs | 13.6 μs | 8.0 μs | 13.3 μs | InterpSearch (7.7 μs) | 1.04x | -| jittered | sorted_arithmetic | 16384 | 1024 | 33.1 μs | 33.5 μs | 25.3 μs | 31.7 μs | 107.3 μs | 32.2 μs | 106.4 μs | ExpFromLeft (25.3 μs) | 1.28x | -| jittered | sorted_arithmetic | 16384 | 4096 | 59.0 μs | 101.9 μs | 78.0 μs | 123.0 μs | 405.6 μs | 59.0 μs | 397.3 μs | Linear (59.0 μs) | 1.00x | -| jittered | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_arithmetic | 65536 | 4 | 93.0 μs | 320 ns | 250 ns | 150 ns | 210 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | -| jittered | sorted_arithmetic | 65536 | 16 | 93.6 μs | 1.2 μs | 1.1 μs | 470 ns | 730 ns | 530 ns | 660 ns | InterpSearch (470 ns) | 1.13x | -| jittered | sorted_arithmetic | 65536 | 64 | 95.8 μs | 4.0 μs | 2.8 μs | 1.9 μs | 2.9 μs | 2.1 μs | 2.7 μs | InterpSearch (1.9 μs) | 1.09x | -| jittered | sorted_arithmetic | 65536 | 256 | 101.7 μs | 14.9 μs | 10.5 μs | 9.2 μs | 13.2 μs | 9.7 μs | 13.0 μs | InterpSearch (9.2 μs) | 1.06x | -| jittered | sorted_arithmetic | 65536 | 1024 | 105.3 μs | 44.0 μs | 33.1 μs | 32.0 μs | 115.6 μs | 33.8 μs | 116.8 μs | InterpSearch (32.0 μs) | 1.06x | -| jittered | sorted_arithmetic | 65536 | 4096 | 131.6 μs | 134.6 μs | 102.1 μs | 118.8 μs | 419.4 μs | 126.4 μs | 410.8 μs | ExpFromLeft (102.1 μs) | 1.24x | -| jittered | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 50 ns | 50 ns | 40 ns | Binary (50 ns) | 1.00x | -| jittered | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| jittered | sorted_geometric | 16 | 16 | 190 ns | 310 ns | 220 ns | 490 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| jittered | sorted_geometric | 16 | 64 | 560 ns | 1.0 μs | 730 ns | 2.0 μs | 990 ns | 590 ns | 820 ns | Linear (560 ns) | 1.05x | -| jittered | sorted_geometric | 16 | 256 | 2.3 μs | 3.8 μs | 2.9 μs | 7.9 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | -| jittered | sorted_geometric | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 28.7 μs | 12.1 μs | 8.1 μs | 10.3 μs | Linear (8.1 μs) | 1.00x | -| jittered | sorted_geometric | 16 | 4096 | 31.1 μs | 55.6 μs | 42.3 μs | 111.4 μs | 47.6 μs | 31.1 μs | 40.1 μs | Linear (31.1 μs) | 1.00x | -| jittered | sorted_geometric | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| jittered | sorted_geometric | 64 | 4 | 170 ns | 140 ns | 120 ns | 150 ns | 110 ns | 140 ns | 100 ns | Binary (110 ns) | 1.27x | -| jittered | sorted_geometric | 64 | 16 | 270 ns | 370 ns | 300 ns | 460 ns | 300 ns | 290 ns | 270 ns | Linear (270 ns) | 1.07x | -| jittered | sorted_geometric | 64 | 64 | 640 ns | 1.1 μs | 740 ns | 1.9 μs | 1.2 μs | 660 ns | 1.1 μs | Linear (640 ns) | 1.03x | -| jittered | sorted_geometric | 64 | 256 | 2.3 μs | 4.2 μs | 3.1 μs | 8.6 μs | 5.3 μs | 2.3 μs | 5.0 μs | Linear (2.3 μs) | 1.00x | -| jittered | sorted_geometric | 64 | 1024 | 9.1 μs | 14.9 μs | 11.7 μs | 30.9 μs | 17.7 μs | 9.1 μs | 15.9 μs | Linear (9.1 μs) | 1.00x | -| jittered | sorted_geometric | 64 | 4096 | 32.1 μs | 56.6 μs | 43.2 μs | 112.0 μs | 67.1 μs | 32.2 μs | 60.3 μs | Linear (32.1 μs) | 1.00x | -| jittered | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_geometric | 256 | 4 | 490 ns | 180 ns | 150 ns | 150 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | -| jittered | sorted_geometric | 256 | 16 | 530 ns | 490 ns | 380 ns | 470 ns | 370 ns | 410 ns | 350 ns | Binary (370 ns) | 1.11x | -| jittered | sorted_geometric | 256 | 64 | 920 ns | 1.4 μs | 1.0 μs | 2.0 μs | 1.4 μs | 940 ns | 1.2 μs | Linear (920 ns) | 1.02x | -| jittered | sorted_geometric | 256 | 256 | 2.4 μs | 4.5 μs | 2.9 μs | 8.5 μs | 6.6 μs | 2.5 μs | 6.1 μs | Linear (2.4 μs) | 1.01x | -| jittered | sorted_geometric | 256 | 1024 | 10.1 μs | 16.5 μs | 12.7 μs | 34.9 μs | 27.6 μs | 10.1 μs | 25.9 μs | Linear (10.1 μs) | 1.00x | -| jittered | sorted_geometric | 256 | 4096 | 36.4 μs | 59.6 μs | 46.4 μs | 123.7 μs | 91.2 μs | 36.5 μs | 83.2 μs | Linear (36.4 μs) | 1.00x | -| jittered | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| jittered | sorted_geometric | 1024 | 4 | 1.6 μs | 200 ns | 180 ns | 150 ns | 150 ns | 200 ns | 130 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_geometric | 1024 | 16 | 1.9 μs | 630 ns | 490 ns | 470 ns | 450 ns | 500 ns | 410 ns | Binary (450 ns) | 1.11x | -| jittered | sorted_geometric | 1024 | 64 | 2.1 μs | 1.9 μs | 1.4 μs | 2.0 μs | 1.7 μs | 1.5 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.01x | -| jittered | sorted_geometric | 1024 | 256 | 3.6 μs | 5.5 μs | 3.8 μs | 8.6 μs | 7.9 μs | 3.6 μs | 7.2 μs | Linear (3.6 μs) | 0.99x | -| jittered | sorted_geometric | 1024 | 1024 | 11.2 μs | 18.8 μs | 12.6 μs | 34.3 μs | 66.0 μs | 11.3 μs | 65.0 μs | Linear (11.2 μs) | 1.00x | -| jittered | sorted_geometric | 1024 | 4096 | 42.5 μs | 66.0 μs | 51.0 μs | 130.6 μs | 192.8 μs | 42.7 μs | 191.9 μs | Linear (42.5 μs) | 1.00x | -| jittered | sorted_geometric | 4096 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | -| jittered | sorted_geometric | 4096 | 4 | 6.0 μs | 230 ns | 180 ns | 150 ns | 160 ns | 180 ns | 150 ns | InterpSearch (150 ns) | 1.20x | -| jittered | sorted_geometric | 4096 | 16 | 6.3 μs | 760 ns | 590 ns | 460 ns | 540 ns | 620 ns | 490 ns | InterpSearch (460 ns) | 1.35x | -| jittered | sorted_geometric | 4096 | 64 | 7.3 μs | 2.4 μs | 1.8 μs | 2.0 μs | 2.0 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.8 μs) | 1.02x | -| jittered | sorted_geometric | 4096 | 256 | 8.7 μs | 7.5 μs | 5.7 μs | 8.9 μs | 10.3 μs | 5.8 μs | 9.7 μs | ExpFromLeft (5.7 μs) | 1.01x | -| jittered | sorted_geometric | 4096 | 1024 | 15.8 μs | 24.2 μs | 16.8 μs | 36.0 μs | 95.1 μs | 15.8 μs | 88.1 μs | Linear (15.8 μs) | 1.00x | -| jittered | sorted_geometric | 4096 | 4096 | 48.4 μs | 76.7 μs | 53.0 μs | 137.8 μs | 309.0 μs | 48.0 μs | 300.4 μs | Linear (48.4 μs) | 0.99x | -| jittered | sorted_geometric | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_geometric | 16384 | 4 | 23.4 μs | 270 ns | 230 ns | 140 ns | 180 ns | 190 ns | 170 ns | InterpSearch (140 ns) | 1.36x | -| jittered | sorted_geometric | 16384 | 16 | 23.9 μs | 920 ns | 690 ns | 470 ns | 600 ns | 700 ns | 570 ns | InterpSearch (470 ns) | 1.49x | -| jittered | sorted_geometric | 16384 | 64 | 25.5 μs | 3.1 μs | 2.4 μs | 2.1 μs | 2.3 μs | 2.4 μs | 2.2 μs | InterpSearch (2.1 μs) | 1.13x | -| jittered | sorted_geometric | 16384 | 256 | 29.8 μs | 10.2 μs | 7.6 μs | 9.1 μs | 13.4 μs | 7.6 μs | 13.2 μs | ExpFromLeft (7.6 μs) | 1.00x | -| jittered | sorted_geometric | 16384 | 1024 | 36.3 μs | 31.7 μs | 24.5 μs | 36.6 μs | 124.1 μs | 24.8 μs | 122.2 μs | ExpFromLeft (24.5 μs) | 1.01x | -| jittered | sorted_geometric | 16384 | 4096 | 69.3 μs | 101.1 μs | 72.6 μs | 139.4 μs | 416.3 μs | 69.3 μs | 409.8 μs | Linear (69.3 μs) | 1.00x | -| jittered | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_geometric | 65536 | 4 | 90.2 μs | 310 ns | 260 ns | 150 ns | 200 ns | 200 ns | 190 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_geometric | 65536 | 16 | 92.2 μs | 1.1 μs | 820 ns | 470 ns | 710 ns | 810 ns | 690 ns | InterpSearch (470 ns) | 1.72x | -| jittered | sorted_geometric | 65536 | 64 | 93.3 μs | 3.8 μs | 2.8 μs | 2.3 μs | 2.9 μs | 2.9 μs | 2.7 μs | InterpSearch (2.3 μs) | 1.26x | -| jittered | sorted_geometric | 65536 | 256 | 101.3 μs | 13.7 μs | 10.4 μs | 9.6 μs | 16.9 μs | 10.2 μs | 17.9 μs | InterpSearch (9.6 μs) | 1.07x | -| jittered | sorted_geometric | 65536 | 1024 | 119.2 μs | 47.0 μs | 37.2 μs | 40.0 μs | 153.8 μs | 35.1 μs | 157.1 μs | ExpFromLeft (37.2 μs) | 0.95x | -| jittered | sorted_geometric | 65536 | 4096 | 151.7 μs | 137.0 μs | 108.0 μs | 142.7 μs | 502.4 μs | 109.3 μs | 504.0 μs | ExpFromLeft (108.0 μs) | 1.01x | -| jittered | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| jittered | sorted_bimodal | 16 | 4 | 90 ns | 120 ns | 110 ns | 150 ns | 100 ns | 110 ns | 80 ns | Linear (90 ns) | 1.22x | -| jittered | sorted_bimodal | 16 | 16 | 180 ns | 290 ns | 220 ns | 480 ns | 240 ns | 220 ns | 209 ns | Linear (180 ns) | 1.22x | -| jittered | sorted_bimodal | 16 | 64 | 610 ns | 960 ns | 780 ns | 1.9 μs | 900 ns | 630 ns | 790 ns | Linear (610 ns) | 1.03x | -| jittered | sorted_bimodal | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.0 μs | 3.3 μs | 2.1 μs | 2.9 μs | Linear (2.1 μs) | 1.01x | -| jittered | sorted_bimodal | 16 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 27.5 μs | 12.8 μs | 7.8 μs | 11.1 μs | Linear (7.9 μs) | 0.99x | -| jittered | sorted_bimodal | 16 | 4096 | 30.8 μs | 52.9 μs | 42.1 μs | 105.8 μs | 50.8 μs | 30.9 μs | 44.3 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 150 ns | 150 ns | 100 ns | 150 ns | 90 ns | Binary (100 ns) | 1.50x | -| jittered | sorted_bimodal | 64 | 16 | 260 ns | 320 ns | 230 ns | 470 ns | 340 ns | 290 ns | 300 ns | ExpFromLeft (230 ns) | 1.26x | -| jittered | sorted_bimodal | 64 | 64 | 620 ns | 980 ns | 730 ns | 2.0 μs | 1.3 μs | 660 ns | 1.2 μs | Linear (620 ns) | 1.06x | -| jittered | sorted_bimodal | 64 | 256 | 2.3 μs | 3.7 μs | 2.9 μs | 7.6 μs | 4.4 μs | 2.3 μs | 4.0 μs | Linear (2.3 μs) | 1.01x | -| jittered | sorted_bimodal | 64 | 1024 | 8.1 μs | 13.9 μs | 10.8 μs | 28.0 μs | 16.9 μs | 8.1 μs | 15.3 μs | Linear (8.1 μs) | 1.00x | -| jittered | sorted_bimodal | 64 | 4096 | 31.1 μs | 54.7 μs | 42.3 μs | 108.6 μs | 67.0 μs | 31.1 μs | 60.3 μs | Linear (31.1 μs) | 1.00x | -| jittered | sorted_bimodal | 256 | 1 | 80 ns | 70 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_bimodal | 256 | 4 | 450 ns | 150 ns | 140 ns | 150 ns | 130 ns | 160 ns | 110 ns | Binary (130 ns) | 1.23x | -| jittered | sorted_bimodal | 256 | 16 | 550 ns | 370 ns | 300 ns | 480 ns | 380 ns | 300 ns | 380 ns | ExpFromLeft (300 ns) | 1.00x | -| jittered | sorted_bimodal | 256 | 64 | 930 ns | 1.1 μs | 750 ns | 2.1 μs | 1.8 μs | 950 ns | 1.7 μs | ExpFromLeft (750 ns) | 1.27x | -| jittered | sorted_bimodal | 256 | 256 | 2.6 μs | 4.2 μs | 3.2 μs | 9.0 μs | 6.4 μs | 2.6 μs | 5.9 μs | Linear (2.6 μs) | 1.01x | -| jittered | sorted_bimodal | 256 | 1024 | 9.2 μs | 14.7 μs | 11.6 μs | 31.0 μs | 22.4 μs | 9.2 μs | 20.6 μs | Linear (9.2 μs) | 1.00x | -| jittered | sorted_bimodal | 256 | 4096 | 32.3 μs | 55.8 μs | 43.0 μs | 115.3 μs | 86.5 μs | 32.2 μs | 79.5 μs | Linear (32.3 μs) | 1.00x | -| jittered | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_bimodal | 1024 | 4 | 1.4 μs | 180 ns | 140 ns | 150 ns | 140 ns | 190 ns | 130 ns | ExpFromLeft (140 ns) | 1.36x | -| jittered | sorted_bimodal | 1024 | 16 | 1.6 μs | 480 ns | 389 ns | 470 ns | 450 ns | 400 ns | 410 ns | ExpFromLeft (389 ns) | 1.03x | -| jittered | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 950 ns | 2.0 μs | 1.9 μs | 980 ns | 1.8 μs | ExpFromLeft (950 ns) | 1.03x | -| jittered | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.1 μs | 2.8 μs | 8.8 μs | 8.5 μs | 3.5 μs | 8.0 μs | ExpFromLeft (2.8 μs) | 1.25x | -| jittered | sorted_bimodal | 1024 | 1024 | 11.7 μs | 17.2 μs | 13.6 μs | 36.9 μs | 30.5 μs | 11.8 μs | 28.4 μs | Linear (11.7 μs) | 1.01x | -| jittered | sorted_bimodal | 1024 | 4096 | 36.8 μs | 58.8 μs | 46.5 μs | 124.0 μs | 108.6 μs | 36.7 μs | 102.0 μs | Linear (36.8 μs) | 1.00x | -| jittered | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_bimodal | 4096 | 4 | 5.2 μs | 200 ns | 190 ns | 150 ns | 160 ns | 200 ns | 140 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_bimodal | 4096 | 16 | 6.1 μs | 630 ns | 510 ns | 470 ns | 550 ns | 530 ns | 500 ns | InterpSearch (470 ns) | 1.13x | -| jittered | sorted_bimodal | 4096 | 64 | 6.5 μs | 1.7 μs | 1.3 μs | 2.1 μs | 2.2 μs | 1.3 μs | 2.2 μs | ExpFromLeft (1.3 μs) | 1.02x | -| jittered | sorted_bimodal | 4096 | 256 | 9.6 μs | 5.9 μs | 5.0 μs | 9.5 μs | 11.5 μs | 5.0 μs | 10.7 μs | ExpFromLeft (5.0 μs) | 1.00x | -| jittered | sorted_bimodal | 4096 | 1024 | 14.4 μs | 17.6 μs | 12.2 μs | 37.9 μs | 59.5 μs | 14.7 μs | 55.2 μs | ExpFromLeft (12.2 μs) | 1.21x | -| jittered | sorted_bimodal | 4096 | 4096 | 51.1 μs | 69.4 μs | 56.0 μs | 145.2 μs | 180.4 μs | 51.3 μs | 168.0 μs | Linear (51.1 μs) | 1.00x | -| jittered | sorted_bimodal | 16384 | 1 | 90 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_bimodal | 16384 | 4 | 22.5 μs | 250 ns | 200 ns | 150 ns | 190 ns | 200 ns | 160 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_bimodal | 16384 | 16 | 22.1 μs | 720 ns | 550 ns | 470 ns | 600 ns | 560 ns | 570 ns | InterpSearch (470 ns) | 1.19x | -| jittered | sorted_bimodal | 16384 | 64 | 25.1 μs | 2.3 μs | 1.7 μs | 2.0 μs | 2.7 μs | 1.8 μs | 2.5 μs | ExpFromLeft (1.7 μs) | 1.02x | -| jittered | sorted_bimodal | 16384 | 256 | 26.2 μs | 6.7 μs | 5.2 μs | 9.1 μs | 15.1 μs | 5.2 μs | 14.4 μs | ExpFromLeft (5.2 μs) | 1.00x | -| jittered | sorted_bimodal | 16384 | 1024 | 33.1 μs | 22.9 μs | 16.6 μs | 38.5 μs | 87.9 μs | 15.9 μs | 87.4 μs | ExpFromLeft (16.6 μs) | 0.96x | -| jittered | sorted_bimodal | 16384 | 4096 | 79.5 μs | 89.8 μs | 67.1 μs | 157.9 μs | 270.5 μs | 79.2 μs | 263.6 μs | ExpFromLeft (67.1 μs) | 1.18x | -| jittered | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_bimodal | 65536 | 4 | 82.9 μs | 260 ns | 210 ns | 150 ns | 180 ns | 200 ns | 190 ns | InterpSearch (150 ns) | 1.33x | -| jittered | sorted_bimodal | 65536 | 16 | 92.4 μs | 860 ns | 640 ns | 490 ns | 750 ns | 660 ns | 690 ns | InterpSearch (490 ns) | 1.35x | -| jittered | sorted_bimodal | 65536 | 64 | 94.9 μs | 2.9 μs | 2.2 μs | 2.0 μs | 3.1 μs | 2.2 μs | 2.8 μs | InterpSearch (2.0 μs) | 1.11x | -| jittered | sorted_bimodal | 65536 | 256 | 97.7 μs | 9.0 μs | 6.9 μs | 9.2 μs | 18.1 μs | 6.9 μs | 18.7 μs | ExpFromLeft (6.9 μs) | 1.00x | -| jittered | sorted_bimodal | 65536 | 1024 | 107.6 μs | 31.5 μs | 25.2 μs | 38.6 μs | 114.2 μs | 23.2 μs | 112.4 μs | ExpFromLeft (25.2 μs) | 0.92x | -| jittered | sorted_bimodal | 65536 | 4096 | 182.8 μs | 149.4 μs | 109.6 μs | 160.6 μs | 349.7 μs | 107.8 μs | 345.6 μs | ExpFromLeft (109.6 μs) | 0.98x | -| jittered | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | sorted_repeated | 16 | 4 | 80 ns | 100 ns | 80 ns | 150 ns | 90 ns | 100 ns | 80 ns | ExpFromLeft (80 ns) | 1.25x | -| jittered | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 200 ns | 460 ns | 230 ns | 200 ns | 200 ns | Linear (170 ns) | 1.18x | -| jittered | sorted_repeated | 16 | 64 | 550 ns | 910 ns | 690 ns | 1.7 μs | 789 ns | 570 ns | 700 ns | Linear (550 ns) | 1.04x | -| jittered | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.02x | -| jittered | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 25.8 μs | 11.8 μs | 7.8 μs | 10.3 μs | Linear (7.7 μs) | 1.00x | -| jittered | sorted_repeated | 16 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 103.3 μs | 47.2 μs | 30.8 μs | 41.0 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| jittered | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 100 ns | 140 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| jittered | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 200 ns | 460 ns | 310 ns | 200 ns | 270 ns | Linear (170 ns) | 1.18x | -| jittered | sorted_repeated | 64 | 64 | 560 ns | 920 ns | 690 ns | 1.7 μs | 1.1 μs | 580 ns | 920 ns | Linear (560 ns) | 1.04x | -| jittered | sorted_repeated | 64 | 256 | 2.8 μs | 4.7 μs | 3.2 μs | 6.5 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.8 μs) | 0.71x | -| jittered | sorted_repeated | 64 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 25.8 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.8 μs) | 1.00x | -| jittered | sorted_repeated | 64 | 4096 | 30.8 μs | 54.8 μs | 39.4 μs | 103.3 μs | 66.6 μs | 32.9 μs | 56.7 μs | Linear (30.8 μs) | 1.07x | -| jittered | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 100 ns | 140 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| jittered | sorted_repeated | 256 | 16 | 220 ns | 350 ns | 250 ns | 500 ns | 399 ns | 240 ns | 340 ns | Linear (220 ns) | 1.09x | -| jittered | sorted_repeated | 256 | 64 | 550 ns | 930 ns | 710 ns | 1.7 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | -| jittered | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| jittered | sorted_repeated | 256 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 26.0 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | -| jittered | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 103.3 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| jittered | sorted_repeated | 1024 | 4 | 90 ns | 110 ns | 100 ns | 150 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | -| jittered | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 210 ns | 490 ns | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | -| jittered | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 1.8 μs | 1.7 μs | 580 ns | 1.5 μs | Linear (560 ns) | 1.04x | -| jittered | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 7.0 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| jittered | sorted_repeated | 1024 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 27.7 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.8 μs) | 1.00x | -| jittered | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.0 μs | 39.2 μs | 110.5 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| jittered | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 110 ns | 140 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | -| jittered | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 230 ns | 450 ns | 530 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | -| jittered | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 700 ns | 1.7 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | -| jittered | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| jittered | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 25.8 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | -| jittered | sorted_repeated | 4096 | 4096 | 30.8 μs | 54.9 μs | 39.5 μs | 103.2 μs | 124.6 μs | 30.8 μs | 114.1 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_repeated | 16384 | 4 | 90 ns | 120 ns | 110 ns | 140 ns | 180 ns | 130 ns | 170 ns | Linear (90 ns) | 1.44x | -| jittered | sorted_repeated | 16384 | 16 | 190 ns | 300 ns | 220 ns | 450 ns | 610 ns | 220 ns | 560 ns | Linear (190 ns) | 1.16x | -| jittered | sorted_repeated | 16384 | 64 | 570 ns | 940 ns | 710 ns | 1.7 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | -| jittered | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 9.0 μs | 2.0 μs | 8.3 μs | Linear (2.0 μs) | 1.02x | -| jittered | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 25.9 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.00x | -| jittered | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 103.3 μs | 144.1 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | -| jittered | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | sorted_repeated | 65536 | 4 | 100 ns | 110 ns | 110 ns | 140 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| jittered | sorted_repeated | 65536 | 16 | 190 ns | 370 ns | 290 ns | 460 ns | 690 ns | 220 ns | 630 ns | Linear (190 ns) | 1.16x | -| jittered | sorted_repeated | 65536 | 64 | 580 ns | 950 ns | 720 ns | 1.7 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (580 ns) | 1.03x | -| jittered | sorted_repeated | 65536 | 256 | 2.1 μs | 3.5 μs | 2.5 μs | 6.5 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.1 μs) | 0.96x | -| jittered | sorted_repeated | 65536 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 25.9 μs | 40.8 μs | 8.3 μs | 38.1 μs | Linear (7.7 μs) | 1.07x | -| jittered | sorted_repeated | 65536 | 4096 | 32.9 μs | 55.0 μs | 39.5 μs | 103.3 μs | 163.2 μs | 30.8 μs | 152.3 μs | Linear (32.9 μs) | 0.94x | -| jittered | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| jittered | unsorted | 16 | 4 | 100 ns | 90 ns | 90 ns | 100 ns | 90 ns | 110 ns | 70 ns | ExpFromLeft (90 ns) | 1.22x | -| jittered | unsorted | 16 | 16 | 210 ns | 210 ns | 200 ns | 200 ns | 210 ns | 220 ns | 200 ns | InterpSearch (200 ns) | 1.10x | -| jittered | unsorted | 16 | 64 | 700 ns | 700 ns | 680 ns | 700 ns | 690 ns | 700 ns | 680 ns | ExpFromLeft (680 ns) | 1.03x | -| jittered | unsorted | 16 | 256 | 3.2 μs | 3.2 μs | 3.2 μs | 3.2 μs | 3.1 μs | 3.2 μs | 3.0 μs | Binary (3.1 μs) | 1.01x | -| jittered | unsorted | 16 | 1024 | 20.5 μs | 20.5 μs | 19.9 μs | 19.9 μs | 19.8 μs | 20.0 μs | 22.0 μs | Binary (19.8 μs) | 1.01x | -| jittered | unsorted | 16 | 4096 | 143.7 μs | 139.7 μs | 141.1 μs | 138.7 μs | 138.9 μs | 139.9 μs | 143.7 μs | InterpSearch (138.7 μs) | 1.01x | -| jittered | unsorted | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| jittered | unsorted | 64 | 4 | 100 ns | 100 ns | 100 ns | 100 ns | 100 ns | 120 ns | 90 ns | InterpSearch (100 ns) | 1.20x | -| jittered | unsorted | 64 | 16 | 290 ns | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 270 ns | InterpSearch (280 ns) | 1.04x | -| jittered | unsorted | 64 | 64 | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | InterpSearch (1.1 μs) | 1.02x | -| jittered | unsorted | 64 | 256 | 5.9 μs | 5.9 μs | 5.9 μs | 6.0 μs | 5.9 μs | 6.1 μs | 5.8 μs | Linear (5.9 μs) | 1.03x | -| jittered | unsorted | 64 | 1024 | 40.1 μs | 39.8 μs | 39.7 μs | 39.8 μs | 39.3 μs | 39.5 μs | 40.3 μs | Binary (39.3 μs) | 1.00x | -| jittered | unsorted | 64 | 4096 | 222.6 μs | 222.0 μs | 221.7 μs | 220.6 μs | 222.3 μs | 224.2 μs | 225.7 μs | InterpSearch (220.6 μs) | 1.02x | -| jittered | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | unsorted | 256 | 4 | 130 ns | 130 ns | 130 ns | 120 ns | 120 ns | 130 ns | 110 ns | InterpSearch (120 ns) | 1.08x | -| jittered | unsorted | 256 | 16 | 370 ns | 370 ns | 370 ns | 360 ns | 370 ns | 370 ns | 360 ns | InterpSearch (360 ns) | 1.03x | -| jittered | unsorted | 256 | 64 | 1.3 μs | 1.3 μs | 1.4 μs | 1.3 μs | 1.4 μs | 1.4 μs | 1.3 μs | InterpSearch (1.3 μs) | 1.02x | -| jittered | unsorted | 256 | 256 | 6.5 μs | 6.5 μs | 6.4 μs | 6.5 μs | 6.5 μs | 6.5 μs | 6.6 μs | ExpFromLeft (6.4 μs) | 1.01x | -| jittered | unsorted | 256 | 1024 | 55.0 μs | 54.8 μs | 54.0 μs | 54.3 μs | 54.2 μs | 53.4 μs | 53.1 μs | ExpFromLeft (54.0 μs) | 0.99x | -| jittered | unsorted | 256 | 4096 | 309.1 μs | 307.9 μs | 305.5 μs | 303.5 μs | 303.4 μs | 305.2 μs | 306.5 μs | Binary (303.4 μs) | 1.01x | -| jittered | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| jittered | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| jittered | unsorted | 1024 | 16 | 420 ns | 419 ns | 420 ns | 420 ns | 430 ns | 430 ns | 410 ns | Gallop (419 ns) | 1.03x | -| jittered | unsorted | 1024 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | ExpFromLeft (1.6 μs) | 1.00x | -| jittered | unsorted | 1024 | 256 | 7.9 μs | 7.9 μs | 7.8 μs | 7.8 μs | 7.8 μs | 7.9 μs | 8.3 μs | InterpSearch (7.8 μs) | 1.00x | -| jittered | unsorted | 1024 | 1024 | 80.4 μs | 78.2 μs | 77.5 μs | 76.0 μs | 76.1 μs | 76.1 μs | 78.0 μs | InterpSearch (76.0 μs) | 1.00x | -| jittered | unsorted | 1024 | 4096 | 412.6 μs | 410.4 μs | 410.2 μs | 411.7 μs | 409.3 μs | 410.2 μs | 407.2 μs | Binary (409.3 μs) | 1.00x | -| jittered | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| jittered | unsorted | 4096 | 4 | 150 ns | 150 ns | 150 ns | 160 ns | 150 ns | 170 ns | 140 ns | ExpFromLeft (150 ns) | 1.13x | -| jittered | unsorted | 4096 | 16 | 490 ns | 500 ns | 490 ns | 490 ns | 500 ns | 500 ns | 490 ns | InterpSearch (490 ns) | 1.02x | -| jittered | unsorted | 4096 | 64 | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | ExpFromLeft (1.9 μs) | 1.02x | -| jittered | unsorted | 4096 | 256 | 8.9 μs | 8.7 μs | 8.5 μs | 8.6 μs | 8.5 μs | 8.6 μs | 11.2 μs | ExpFromLeft (8.5 μs) | 1.01x | -| jittered | unsorted | 4096 | 1024 | 98.2 μs | 96.1 μs | 94.8 μs | 94.4 μs | 94.0 μs | 93.3 μs | 98.4 μs | Binary (94.0 μs) | 0.99x | -| jittered | unsorted | 4096 | 4096 | 492.8 μs | 494.1 μs | 489.8 μs | 490.6 μs | 490.2 μs | 491.3 μs | 493.6 μs | ExpFromLeft (489.8 μs) | 1.00x | -| jittered | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| jittered | unsorted | 16384 | 4 | 170 ns | 180 ns | 180 ns | 180 ns | 180 ns | 190 ns | 170 ns | Linear (170 ns) | 1.12x | -| jittered | unsorted | 16384 | 16 | 580 ns | 580 ns | 590 ns | 580 ns | 580 ns | 590 ns | 570 ns | InterpSearch (580 ns) | 1.02x | -| jittered | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | InterpSearch (2.3 μs) | 1.01x | -| jittered | unsorted | 16384 | 256 | 11.1 μs | 10.9 μs | 10.6 μs | 10.7 μs | 10.7 μs | 10.7 μs | 12.8 μs | ExpFromLeft (10.6 μs) | 1.01x | -| jittered | unsorted | 16384 | 1024 | 142.1 μs | 138.8 μs | 135.7 μs | 136.1 μs | 135.4 μs | 135.4 μs | 141.1 μs | Binary (135.4 μs) | 1.00x | -| jittered | unsorted | 16384 | 4096 | 665.1 μs | 665.0 μs | 665.5 μs | 670.2 μs | 669.7 μs | 670.3 μs | 670.2 μs | Gallop (665.0 μs) | 1.01x | -| jittered | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| jittered | unsorted | 65536 | 4 | 200 ns | 200 ns | 190 ns | 200 ns | 200 ns | 200 ns | 190 ns | ExpFromLeft (190 ns) | 1.05x | -| jittered | unsorted | 65536 | 16 | 680 ns | 680 ns | 670 ns | 660 ns | 660 ns | 680 ns | 650 ns | InterpSearch (660 ns) | 1.03x | -| jittered | unsorted | 65536 | 64 | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | Linear (2.8 μs) | 1.01x | -| jittered | unsorted | 65536 | 256 | 14.5 μs | 14.0 μs | 13.9 μs | 13.9 μs | 13.9 μs | 13.8 μs | 16.9 μs | ExpFromLeft (13.9 μs) | 0.99x | -| jittered | unsorted | 65536 | 1024 | 190.5 μs | 186.6 μs | 186.0 μs | 183.7 μs | 184.0 μs | 184.6 μs | 190.6 μs | InterpSearch (183.7 μs) | 1.00x | -| jittered | unsorted | 65536 | 4096 | 867.2 μs | 867.6 μs | 867.5 μs | 867.1 μs | 868.1 μs | 867.2 μs | 866.4 μs | InterpSearch (867.1 μs) | 1.00x | -| random | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| random | sorted_uniform | 16 | 4 | 90 ns | 110 ns | 110 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| random | sorted_uniform | 16 | 16 | 190 ns | 280 ns | 220 ns | 509 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| random | sorted_uniform | 16 | 64 | 560 ns | 979 ns | 740 ns | 1.9 μs | 900 ns | 590 ns | 780 ns | Linear (560 ns) | 1.05x | -| random | sorted_uniform | 16 | 256 | 2.2 μs | 3.7 μs | 2.8 μs | 7.8 μs | 3.2 μs | 2.2 μs | 2.7 μs | Linear (2.2 μs) | 1.01x | -| random | sorted_uniform | 16 | 1024 | 8.0 μs | 14.1 μs | 10.8 μs | 29.3 μs | 12.2 μs | 8.0 μs | 10.5 μs | Linear (8.0 μs) | 1.00x | -| random | sorted_uniform | 16 | 4096 | 31.4 μs | 58.1 μs | 42.2 μs | 117.2 μs | 47.9 μs | 31.0 μs | 40.6 μs | Linear (31.4 μs) | 0.99x | -| random | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| random | sorted_uniform | 64 | 4 | 110 ns | 120 ns | 110 ns | 160 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | -| random | sorted_uniform | 64 | 16 | 240 ns | 330 ns | 270 ns | 500 ns | 310 ns | 260 ns | 270 ns | Linear (240 ns) | 1.08x | -| random | sorted_uniform | 64 | 64 | 670 ns | 1.1 μs | 760 ns | 1.9 μs | 1.4 μs | 710 ns | 1.3 μs | Linear (670 ns) | 1.06x | -| random | sorted_uniform | 64 | 256 | 2.3 μs | 4.0 μs | 3.1 μs | 8.3 μs | 5.0 μs | 2.3 μs | 4.5 μs | Linear (2.3 μs) | 0.99x | -| random | sorted_uniform | 64 | 1024 | 9.0 μs | 14.8 μs | 11.6 μs | 32.5 μs | 17.7 μs | 9.0 μs | 15.9 μs | Linear (9.0 μs) | 1.00x | -| random | sorted_uniform | 64 | 4096 | 32.1 μs | 55.9 μs | 43.2 μs | 121.1 μs | 67.3 μs | 32.1 μs | 60.0 μs | Linear (32.1 μs) | 1.00x | -| random | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_uniform | 256 | 4 | 440 ns | 160 ns | 150 ns | 180 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | -| random | sorted_uniform | 256 | 16 | 510 ns | 440 ns | 380 ns | 580 ns | 380 ns | 390 ns | 370 ns | ExpFromLeft (380 ns) | 1.03x | -| random | sorted_uniform | 256 | 64 | 920 ns | 1.3 μs | 1.0 μs | 2.7 μs | 1.7 μs | 920 ns | 1.6 μs | Linear (920 ns) | 1.00x | -| random | sorted_uniform | 256 | 256 | 2.4 μs | 4.2 μs | 2.9 μs | 9.6 μs | 6.8 μs | 2.4 μs | 6.6 μs | Linear (2.4 μs) | 1.00x | -| random | sorted_uniform | 256 | 1024 | 9.6 μs | 16.6 μs | 13.0 μs | 42.5 μs | 25.6 μs | 9.7 μs | 23.7 μs | Linear (9.6 μs) | 1.01x | -| random | sorted_uniform | 256 | 4096 | 36.2 μs | 59.3 μs | 46.6 μs | 158.7 μs | 91.0 μs | 36.1 μs | 83.7 μs | Linear (36.2 μs) | 1.00x | -| random | sorted_uniform | 1024 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (70 ns) | 0.86x | -| random | sorted_uniform | 1024 | 4 | 1.4 μs | 180 ns | 150 ns | 180 ns | 139 ns | 180 ns | 130 ns | Binary (139 ns) | 1.29x | -| random | sorted_uniform | 1024 | 16 | 1.6 μs | 600 ns | 480 ns | 640 ns | 450 ns | 500 ns | 410 ns | Binary (450 ns) | 1.11x | -| random | sorted_uniform | 1024 | 64 | 2.0 μs | 1.8 μs | 1.3 μs | 2.6 μs | 1.8 μs | 1.4 μs | 1.8 μs | ExpFromLeft (1.3 μs) | 1.04x | -| random | sorted_uniform | 1024 | 256 | 3.6 μs | 5.2 μs | 3.9 μs | 10.2 μs | 8.2 μs | 3.5 μs | 7.8 μs | Linear (3.6 μs) | 0.98x | -| random | sorted_uniform | 1024 | 1024 | 10.5 μs | 17.8 μs | 12.5 μs | 48.0 μs | 45.4 μs | 13.7 μs | 42.5 μs | Linear (10.5 μs) | 1.31x | -| random | sorted_uniform | 1024 | 4096 | 44.1 μs | 69.5 μs | 55.1 μs | 187.7 μs | 169.8 μs | 44.0 μs | 166.1 μs | Linear (44.1 μs) | 1.00x | -| random | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| random | sorted_uniform | 4096 | 4 | 4.4 μs | 240 ns | 190 ns | 190 ns | 160 ns | 220 ns | 150 ns | Binary (160 ns) | 1.38x | -| random | sorted_uniform | 4096 | 16 | 6.7 μs | 790 ns | 690 ns | 680 ns | 550 ns | 720 ns | 499 ns | Binary (550 ns) | 1.31x | -| random | sorted_uniform | 4096 | 64 | 7.4 μs | 2.3 μs | 1.8 μs | 2.6 μs | 2.1 μs | 1.8 μs | 2.0 μs | ExpFromLeft (1.8 μs) | 1.03x | -| random | sorted_uniform | 4096 | 256 | 8.5 μs | 7.0 μs | 5.1 μs | 10.5 μs | 10.9 μs | 5.2 μs | 10.4 μs | ExpFromLeft (5.1 μs) | 1.01x | -| random | sorted_uniform | 4096 | 1024 | 15.6 μs | 23.4 μs | 17.4 μs | 50.3 μs | 90.4 μs | 16.0 μs | 84.7 μs | Linear (15.6 μs) | 1.03x | -| random | sorted_uniform | 4096 | 4096 | 77.5 μs | 100.8 μs | 81.0 μs | 220.8 μs | 280.7 μs | 74.3 μs | 272.1 μs | Linear (77.5 μs) | 0.96x | -| random | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_uniform | 16384 | 4 | 17.9 μs | 270 ns | 220 ns | 210 ns | 180 ns | 250 ns | 170 ns | Binary (180 ns) | 1.39x | -| random | sorted_uniform | 16384 | 16 | 23.0 μs | 870 ns | 650 ns | 740 ns | 600 ns | 690 ns | 560 ns | Binary (600 ns) | 1.15x | -| random | sorted_uniform | 16384 | 64 | 25.2 μs | 3.0 μs | 2.3 μs | 3.0 μs | 2.5 μs | 2.3 μs | 2.3 μs | ExpFromLeft (2.3 μs) | 1.02x | -| random | sorted_uniform | 16384 | 256 | 30.4 μs | 9.6 μs | 7.4 μs | 11.9 μs | 12.7 μs | 7.4 μs | 13.0 μs | ExpFromLeft (7.4 μs) | 0.99x | -| random | sorted_uniform | 16384 | 1024 | 37.9 μs | 33.5 μs | 25.6 μs | 61.1 μs | 124.6 μs | 23.8 μs | 124.5 μs | ExpFromLeft (25.6 μs) | 0.93x | -| random | sorted_uniform | 16384 | 4096 | 115.0 μs | 161.1 μs | 121.5 μs | 283.2 μs | 384.5 μs | 114.2 μs | 388.6 μs | Linear (115.0 μs) | 0.99x | -| random | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | InterpSearch (80 ns) | 1.00x | -| random | sorted_uniform | 65536 | 4 | 16.9 μs | 270 ns | 220 ns | 220 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | -| random | sorted_uniform | 65536 | 16 | 80.0 μs | 1.1 μs | 750 ns | 780 ns | 690 ns | 790 ns | 650 ns | Binary (690 ns) | 1.14x | -| random | sorted_uniform | 65536 | 64 | 91.7 μs | 3.6 μs | 2.6 μs | 3.3 μs | 2.9 μs | 2.6 μs | 2.7 μs | ExpFromLeft (2.6 μs) | 1.01x | -| random | sorted_uniform | 65536 | 256 | 102.6 μs | 12.9 μs | 9.5 μs | 13.5 μs | 15.9 μs | 9.6 μs | 17.1 μs | ExpFromLeft (9.5 μs) | 1.01x | -| random | sorted_uniform | 65536 | 1024 | 122.0 μs | 60.7 μs | 44.2 μs | 75.2 μs | 154.8 μs | 40.2 μs | 161.6 μs | ExpFromLeft (44.2 μs) | 0.91x | -| random | sorted_uniform | 65536 | 4096 | 199.0 μs | 246.4 μs | 200.4 μs | 351.2 μs | 484.6 μs | 200.5 μs | 487.9 μs | Linear (199.0 μs) | 1.01x | -| random | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| random | sorted_dense_burst | 16 | 4 | 80 ns | 90 ns | 90 ns | 150 ns | 80 ns | 100 ns | 70 ns | Binary (80 ns) | 1.25x | -| random | sorted_dense_burst | 16 | 16 | 180 ns | 280 ns | 230 ns | 510 ns | 230 ns | 190 ns | 190 ns | Linear (180 ns) | 1.06x | -| random | sorted_dense_burst | 16 | 64 | 550 ns | 960 ns | 730 ns | 1.9 μs | 810 ns | 580 ns | 660 ns | Linear (550 ns) | 1.05x | -| random | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 7.3 μs | 3.0 μs | 2.0 μs | 2.7 μs | Linear (2.0 μs) | 1.01x | -| random | sorted_dense_burst | 16 | 1024 | 7.8 μs | 14.5 μs | 10.6 μs | 29.3 μs | 12.0 μs | 7.9 μs | 9.6 μs | Linear (7.8 μs) | 1.00x | -| random | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.9 μs | 42.1 μs | 113.3 μs | 47.2 μs | 32.9 μs | 38.4 μs | Linear (30.8 μs) | 1.07x | -| random | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| random | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 90 ns | 209 ns | 130 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| random | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 220 ns | 540 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | -| random | sorted_dense_burst | 64 | 64 | 550 ns | 930 ns | 730 ns | 2.0 μs | 1.1 μs | 580 ns | 920 ns | Linear (550 ns) | 1.05x | -| random | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 3.4 μs | 7.9 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | -| random | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 31.4 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | -| random | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.9 μs | 42.0 μs | 125.2 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 220 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| random | sorted_dense_burst | 256 | 16 | 170 ns | 279 ns | 230 ns | 790 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| random | sorted_dense_burst | 256 | 64 | 550 ns | 930 ns | 740 ns | 3.0 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | -| random | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.7 μs | 5.6 μs | 2.9 μs | 4.9 μs | Linear (2.0 μs) | 1.43x | -| random | sorted_dense_burst | 256 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 46.4 μs | 21.4 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | -| random | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.0 μs | 42.1 μs | 184.9 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_dense_burst | 1024 | 4 | 110 ns | 130 ns | 110 ns | 200 ns | 140 ns | 120 ns | 130 ns | ExpFromLeft (110 ns) | 1.09x | -| random | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 250 ns | 700 ns | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | -| random | sorted_dense_burst | 1024 | 64 | 770 ns | 1.2 μs | 950 ns | 2.8 μs | 1.8 μs | 590 ns | 1.5 μs | Linear (770 ns) | 0.77x | -| random | sorted_dense_burst | 1024 | 256 | 2.5 μs | 3.5 μs | 2.7 μs | 10.5 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.5 μs) | 0.82x | -| random | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 41.6 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | -| random | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.1 μs | 41.9 μs | 166.1 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 130 ns | 230 ns | 170 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | -| random | sorted_dense_burst | 4096 | 16 | 180 ns | 280 ns | 240 ns | 860 ns | 540 ns | 250 ns | 490 ns | Linear (180 ns) | 1.39x | -| random | sorted_dense_burst | 4096 | 64 | 560 ns | 930 ns | 740 ns | 3.2 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | -| random | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 12.6 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | -| random | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 50.2 μs | 31.2 μs | 7.8 μs | 28.5 μs | Linear (7.8 μs) | 1.00x | -| random | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 201.0 μs | 124.7 μs | 30.9 μs | 114.1 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 210 ns | 180 ns | 120 ns | 160 ns | Linear (100 ns) | 1.20x | -| random | sorted_dense_burst | 16384 | 16 | 180 ns | 289 ns | 240 ns | 750 ns | 610 ns | 210 ns | 560 ns | Linear (180 ns) | 1.17x | -| random | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 760 ns | 2.9 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | -| random | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.3 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | -| random | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 45.1 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.00x | -| random | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.0 μs | 42.1 μs | 179.9 μs | 143.9 μs | 30.9 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| random | sorted_dense_burst | 65536 | 4 | 100 ns | 130 ns | 110 ns | 250 ns | 200 ns | 120 ns | 180 ns | Linear (100 ns) | 1.20x | -| random | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 250 ns | 950 ns | 680 ns | 210 ns | 640 ns | Linear (190 ns) | 1.11x | -| random | sorted_dense_burst | 65536 | 64 | 570 ns | 940 ns | 750 ns | 3.6 μs | 2.6 μs | 610 ns | 2.4 μs | Linear (570 ns) | 1.07x | -| random | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 14.1 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | -| random | sorted_dense_burst | 65536 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 56.1 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.7 μs) | 1.01x | -| random | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 222.6 μs | 163.1 μs | 30.8 μs | 152.4 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| random | sorted_near_start | 16 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 80 ns | 110 ns | 70 ns | Binary (80 ns) | 1.38x | -| random | sorted_near_start | 16 | 16 | 180 ns | 290 ns | 210 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | -| random | sorted_near_start | 16 | 64 | 570 ns | 950 ns | 760 ns | 1.8 μs | 790 ns | 610 ns | 680 ns | Linear (570 ns) | 1.07x | -| random | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | -| random | sorted_near_start | 16 | 1024 | 7.9 μs | 13.9 μs | 14.1 μs | 26.9 μs | 12.1 μs | 7.9 μs | 10.2 μs | Linear (7.9 μs) | 1.00x | -| random | sorted_near_start | 16 | 4096 | 31.1 μs | 55.3 μs | 42.3 μs | 107.1 μs | 47.7 μs | 31.1 μs | 40.3 μs | Linear (31.1 μs) | 1.00x | -| random | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| random | sorted_near_start | 64 | 4 | 160 ns | 120 ns | 110 ns | 150 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | -| random | sorted_near_start | 64 | 16 | 220 ns | 300 ns | 240 ns | 470 ns | 310 ns | 250 ns | 280 ns | Linear (220 ns) | 1.14x | -| random | sorted_near_start | 64 | 64 | 690 ns | 1.0 μs | 840 ns | 1.9 μs | 1.1 μs | 700 ns | 1.0 μs | Linear (690 ns) | 1.01x | -| random | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | -| random | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 27.5 μs | 17.1 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.00x | -| random | sorted_near_start | 64 | 4096 | 31.4 μs | 74.5 μs | 56.4 μs | 110.4 μs | 66.8 μs | 31.4 μs | 60.0 μs | Linear (31.4 μs) | 1.00x | -| random | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_near_start | 256 | 4 | 110 ns | 120 ns | 120 ns | 160 ns | 130 ns | 130 ns | 110 ns | Linear (110 ns) | 1.18x | -| random | sorted_near_start | 256 | 16 | 390 ns | 330 ns | 260 ns | 500 ns | 440 ns | 270 ns | 450 ns | ExpFromLeft (260 ns) | 1.04x | -| random | sorted_near_start | 256 | 64 | 890 ns | 1.1 μs | 840 ns | 2.0 μs | 1.5 μs | 900 ns | 1.4 μs | ExpFromLeft (840 ns) | 1.07x | -| random | sorted_near_start | 256 | 256 | 2.5 μs | 3.9 μs | 3.1 μs | 7.8 μs | 5.7 μs | 2.5 μs | 5.2 μs | Linear (2.5 μs) | 1.01x | -| random | sorted_near_start | 256 | 1024 | 8.5 μs | 14.5 μs | 11.0 μs | 29.6 μs | 22.1 μs | 8.4 μs | 20.3 μs | Linear (8.5 μs) | 0.99x | -| random | sorted_near_start | 256 | 4096 | 31.5 μs | 56.1 μs | 42.7 μs | 117.4 μs | 88.6 μs | 31.4 μs | 80.7 μs | Linear (31.5 μs) | 1.00x | -| random | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 50 ns | Gallop (60 ns) | 1.00x | -| random | sorted_near_start | 1024 | 4 | 860 ns | 160 ns | 180 ns | 180 ns | 140 ns | 170 ns | 130 ns | Binary (140 ns) | 1.21x | -| random | sorted_near_start | 1024 | 16 | 1.1 μs | 379 ns | 290 ns | 590 ns | 460 ns | 330 ns | 430 ns | ExpFromLeft (290 ns) | 1.14x | -| random | sorted_near_start | 1024 | 64 | 2.0 μs | 1.2 μs | 880 ns | 2.1 μs | 1.9 μs | 930 ns | 1.8 μs | ExpFromLeft (880 ns) | 1.06x | -| random | sorted_near_start | 1024 | 256 | 3.9 μs | 4.4 μs | 3.4 μs | 9.1 μs | 7.2 μs | 3.9 μs | 6.7 μs | ExpFromLeft (3.4 μs) | 1.15x | -| random | sorted_near_start | 1024 | 1024 | 10.1 μs | 15.6 μs | 12.1 μs | 35.2 μs | 27.2 μs | 10.1 μs | 25.6 μs | Linear (10.1 μs) | 1.00x | -| random | sorted_near_start | 1024 | 4096 | 34.0 μs | 58.2 μs | 44.5 μs | 136.0 μs | 110.1 μs | 33.6 μs | 103.7 μs | Linear (34.0 μs) | 0.99x | -| random | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| random | sorted_near_start | 4096 | 4 | 2.1 μs | 210 ns | 180 ns | 190 ns | 160 ns | 200 ns | 140 ns | Binary (160 ns) | 1.25x | -| random | sorted_near_start | 4096 | 16 | 3.7 μs | 530 ns | 430 ns | 650 ns | 550 ns | 440 ns | 490 ns | ExpFromLeft (430 ns) | 1.02x | -| random | sorted_near_start | 4096 | 64 | 6.0 μs | 1.5 μs | 1.1 μs | 2.5 μs | 2.2 μs | 1.2 μs | 2.1 μs | ExpFromLeft (1.1 μs) | 1.02x | -| random | sorted_near_start | 4096 | 256 | 7.7 μs | 4.7 μs | 3.3 μs | 10.2 μs | 10.6 μs | 3.5 μs | 9.6 μs | ExpFromLeft (3.3 μs) | 1.04x | -| random | sorted_near_start | 4096 | 1024 | 16.2 μs | 18.4 μs | 14.3 μs | 44.1 μs | 40.1 μs | 16.2 μs | 36.1 μs | ExpFromLeft (14.3 μs) | 1.14x | -| random | sorted_near_start | 4096 | 4096 | 41.3 μs | 63.2 μs | 48.9 μs | 166.9 μs | 151.3 μs | 41.7 μs | 137.9 μs | Linear (41.3 μs) | 1.01x | -| random | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_near_start | 16384 | 4 | 19.0 μs | 239 ns | 200 ns | 220 ns | 180 ns | 230 ns | 160 ns | Binary (180 ns) | 1.28x | -| random | sorted_near_start | 16384 | 16 | 21.0 μs | 630 ns | 500 ns | 710 ns | 680 ns | 520 ns | 660 ns | ExpFromLeft (500 ns) | 1.04x | -| random | sorted_near_start | 16384 | 64 | 22.7 μs | 2.0 μs | 1.5 μs | 2.8 μs | 3.0 μs | 1.5 μs | 2.7 μs | ExpFromLeft (1.5 μs) | 1.02x | -| random | sorted_near_start | 16384 | 256 | 23.6 μs | 6.1 μs | 4.3 μs | 11.7 μs | 16.9 μs | 4.4 μs | 16.5 μs | ExpFromLeft (4.3 μs) | 1.03x | -| random | sorted_near_start | 16384 | 1024 | 33.2 μs | 20.7 μs | 15.0 μs | 53.4 μs | 71.8 μs | 15.2 μs | 65.4 μs | ExpFromLeft (15.0 μs) | 1.01x | -| random | sorted_near_start | 16384 | 4096 | 70.4 μs | 77.8 μs | 61.7 μs | 213.8 μs | 235.8 μs | 70.6 μs | 228.5 μs | ExpFromLeft (61.7 μs) | 1.14x | -| random | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | InterpSearch (80 ns) | 1.00x | -| random | sorted_near_start | 65536 | 4 | 34.1 μs | 250 ns | 210 ns | 240 ns | 200 ns | 240 ns | 180 ns | Binary (200 ns) | 1.20x | -| random | sorted_near_start | 65536 | 16 | 80.7 μs | 820 ns | 620 ns | 710 ns | 680 ns | 650 ns | 630 ns | ExpFromLeft (620 ns) | 1.05x | -| random | sorted_near_start | 65536 | 64 | 78.7 μs | 2.6 μs | 2.0 μs | 2.8 μs | 3.4 μs | 2.0 μs | 3.3 μs | ExpFromLeft (2.0 μs) | 1.02x | -| random | sorted_near_start | 65536 | 256 | 86.7 μs | 7.8 μs | 5.8 μs | 11.6 μs | 20.9 μs | 6.0 μs | 20.0 μs | ExpFromLeft (5.8 μs) | 1.03x | -| random | sorted_near_start | 65536 | 1024 | 99.7 μs | 26.5 μs | 19.3 μs | 53.4 μs | 92.0 μs | 19.6 μs | 85.1 μs | ExpFromLeft (19.3 μs) | 1.02x | -| random | sorted_near_start | 65536 | 4096 | 158.9 μs | 127.0 μs | 102.7 μs | 247.3 μs | 307.4 μs | 100.6 μs | 289.2 μs | ExpFromLeft (102.7 μs) | 0.98x | -| random | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 60 ns | ExpFromLeft (50 ns) | 1.00x | -| random | sorted_arithmetic | 16 | 4 | 100 ns | 110 ns | 120 ns | 160 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | -| random | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 220 ns | 500 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| random | sorted_arithmetic | 16 | 64 | 560 ns | 1.0 μs | 780 ns | 2.0 μs | 930 ns | 590 ns | 770 ns | Linear (560 ns) | 1.05x | -| random | sorted_arithmetic | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 8.2 μs | 3.2 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.01x | -| random | sorted_arithmetic | 16 | 1024 | 8.0 μs | 14.0 μs | 10.8 μs | 31.0 μs | 12.1 μs | 8.1 μs | 10.2 μs | Linear (8.0 μs) | 1.00x | -| random | sorted_arithmetic | 16 | 4096 | 31.1 μs | 55.1 μs | 42.3 μs | 120.7 μs | 46.8 μs | 31.1 μs | 40.0 μs | Linear (31.1 μs) | 1.00x | -| random | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| random | sorted_arithmetic | 64 | 4 | 170 ns | 150 ns | 130 ns | 150 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | -| random | sorted_arithmetic | 64 | 16 | 260 ns | 370 ns | 280 ns | 510 ns | 300 ns | 280 ns | 270 ns | Linear (260 ns) | 1.08x | -| random | sorted_arithmetic | 64 | 64 | 640 ns | 1.1 μs | 760 ns | 2.0 μs | 1.4 μs | 670 ns | 1.3 μs | Linear (640 ns) | 1.05x | -| random | sorted_arithmetic | 64 | 256 | 2.2 μs | 4.0 μs | 3.0 μs | 8.1 μs | 5.1 μs | 2.3 μs | 4.5 μs | Linear (2.2 μs) | 1.01x | -| random | sorted_arithmetic | 64 | 1024 | 8.8 μs | 14.7 μs | 11.5 μs | 33.6 μs | 17.7 μs | 8.9 μs | 15.9 μs | Linear (8.8 μs) | 1.00x | -| random | sorted_arithmetic | 64 | 4096 | 32.2 μs | 55.8 μs | 43.2 μs | 126.4 μs | 67.6 μs | 32.2 μs | 60.4 μs | Linear (32.2 μs) | 1.00x | -| random | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_arithmetic | 256 | 4 | 500 ns | 180 ns | 150 ns | 160 ns | 160 ns | 170 ns | 110 ns | ExpFromLeft (150 ns) | 1.13x | -| random | sorted_arithmetic | 256 | 16 | 540 ns | 510 ns | 410 ns | 600 ns | 370 ns | 440 ns | 340 ns | Binary (370 ns) | 1.19x | -| random | sorted_arithmetic | 256 | 64 | 910 ns | 1.4 μs | 1.1 μs | 2.3 μs | 1.4 μs | 950 ns | 1.3 μs | Linear (910 ns) | 1.04x | -| random | sorted_arithmetic | 256 | 256 | 2.4 μs | 4.2 μs | 2.8 μs | 9.5 μs | 6.9 μs | 2.4 μs | 6.4 μs | Linear (2.4 μs) | 1.01x | -| random | sorted_arithmetic | 256 | 1024 | 9.8 μs | 17.0 μs | 12.9 μs | 41.7 μs | 25.1 μs | 9.7 μs | 23.3 μs | Linear (9.8 μs) | 1.00x | -| random | sorted_arithmetic | 256 | 4096 | 36.1 μs | 59.3 μs | 46.4 μs | 155.2 μs | 90.1 μs | 36.0 μs | 83.3 μs | Linear (36.1 μs) | 1.00x | -| random | sorted_arithmetic | 1024 | 1 | 60 ns | 60 ns | 70 ns | 80 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| random | sorted_arithmetic | 1024 | 4 | 1.6 μs | 210 ns | 170 ns | 180 ns | 140 ns | 210 ns | 130 ns | Binary (140 ns) | 1.50x | -| random | sorted_arithmetic | 1024 | 16 | 1.9 μs | 660 ns | 500 ns | 660 ns | 440 ns | 540 ns | 420 ns | Binary (440 ns) | 1.23x | -| random | sorted_arithmetic | 1024 | 64 | 2.1 μs | 1.9 μs | 1.5 μs | 2.5 μs | 1.7 μs | 1.5 μs | 1.6 μs | ExpFromLeft (1.5 μs) | 1.04x | -| random | sorted_arithmetic | 1024 | 256 | 3.6 μs | 5.7 μs | 4.0 μs | 10.4 μs | 7.8 μs | 3.5 μs | 8.0 μs | Linear (3.6 μs) | 0.98x | -| random | sorted_arithmetic | 1024 | 1024 | 10.2 μs | 17.5 μs | 12.1 μs | 46.6 μs | 55.8 μs | 10.4 μs | 52.9 μs | Linear (10.2 μs) | 1.02x | -| random | sorted_arithmetic | 1024 | 4096 | 45.2 μs | 70.3 μs | 55.3 μs | 191.7 μs | 181.6 μs | 45.2 μs | 174.4 μs | Linear (45.2 μs) | 1.00x | -| random | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| random | sorted_arithmetic | 4096 | 4 | 5.9 μs | 240 ns | 200 ns | 180 ns | 170 ns | 230 ns | 140 ns | Binary (170 ns) | 1.35x | -| random | sorted_arithmetic | 4096 | 16 | 6.5 μs | 810 ns | 580 ns | 600 ns | 520 ns | 620 ns | 470 ns | Binary (520 ns) | 1.19x | -| random | sorted_arithmetic | 4096 | 64 | 7.8 μs | 2.5 μs | 1.9 μs | 2.5 μs | 2.1 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.9 μs) | 1.04x | -| random | sorted_arithmetic | 4096 | 256 | 9.2 μs | 7.8 μs | 5.8 μs | 9.9 μs | 10.1 μs | 5.9 μs | 11.3 μs | ExpFromLeft (5.8 μs) | 1.01x | -| random | sorted_arithmetic | 4096 | 1024 | 15.0 μs | 24.2 μs | 17.8 μs | 45.2 μs | 106.5 μs | 15.0 μs | 101.5 μs | Linear (15.0 μs) | 1.00x | -| random | sorted_arithmetic | 4096 | 4096 | 66.1 μs | 96.8 μs | 71.8 μs | 211.4 μs | 295.7 μs | 64.6 μs | 294.5 μs | Linear (66.1 μs) | 0.98x | -| random | sorted_arithmetic | 16384 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_arithmetic | 16384 | 4 | 22.6 μs | 280 ns | 220 ns | 160 ns | 190 ns | 250 ns | 160 ns | InterpSearch (160 ns) | 1.56x | -| random | sorted_arithmetic | 16384 | 16 | 24.5 μs | 950 ns | 710 ns | 730 ns | 600 ns | 730 ns | 560 ns | Binary (600 ns) | 1.22x | -| random | sorted_arithmetic | 16384 | 64 | 25.9 μs | 3.2 μs | 2.3 μs | 2.8 μs | 2.6 μs | 2.4 μs | 2.4 μs | ExpFromLeft (2.3 μs) | 1.02x | -| random | sorted_arithmetic | 16384 | 256 | 31.3 μs | 10.4 μs | 7.8 μs | 11.6 μs | 13.4 μs | 7.9 μs | 13.1 μs | ExpFromLeft (7.8 μs) | 1.01x | -| random | sorted_arithmetic | 16384 | 1024 | 44.1 μs | 35.1 μs | 27.7 μs | 60.3 μs | 133.6 μs | 26.6 μs | 136.6 μs | ExpFromLeft (27.7 μs) | 0.96x | -| random | sorted_arithmetic | 16384 | 4096 | 113.5 μs | 150.1 μs | 104.3 μs | 295.6 μs | 426.9 μs | 113.9 μs | 420.5 μs | ExpFromLeft (104.3 μs) | 1.09x | -| random | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | InterpSearch (80 ns) | 1.00x | -| random | sorted_arithmetic | 65536 | 4 | 92.9 μs | 310 ns | 250 ns | 200 ns | 200 ns | 280 ns | 190 ns | InterpSearch (200 ns) | 1.40x | -| random | sorted_arithmetic | 65536 | 16 | 95.6 μs | 1.1 μs | 820 ns | 800 ns | 709 ns | 860 ns | 660 ns | Binary (709 ns) | 1.21x | -| random | sorted_arithmetic | 65536 | 64 | 98.1 μs | 3.9 μs | 2.9 μs | 3.4 μs | 2.8 μs | 2.9 μs | 2.7 μs | Binary (2.8 μs) | 1.04x | -| random | sorted_arithmetic | 65536 | 256 | 103.7 μs | 13.6 μs | 10.3 μs | 13.7 μs | 15.8 μs | 10.1 μs | 16.4 μs | ExpFromLeft (10.3 μs) | 0.98x | -| random | sorted_arithmetic | 65536 | 1024 | 121.9 μs | 50.5 μs | 39.5 μs | 75.1 μs | 164.7 μs | 35.7 μs | 169.8 μs | ExpFromLeft (39.5 μs) | 0.90x | -| random | sorted_arithmetic | 65536 | 4096 | 197.6 μs | 231.8 μs | 192.0 μs | 358.6 μs | 517.4 μs | 193.3 μs | 520.6 μs | ExpFromLeft (192.0 μs) | 1.01x | -| random | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| random | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 110 ns | 160 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | -| random | sorted_geometric | 16 | 16 | 199 ns | 290 ns | 210 ns | 480 ns | 230 ns | 210 ns | 190 ns | Linear (199 ns) | 1.06x | -| random | sorted_geometric | 16 | 64 | 580 ns | 1.0 μs | 750 ns | 1.9 μs | 1.0 μs | 590 ns | 850 ns | Linear (580 ns) | 1.02x | -| random | sorted_geometric | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 7.6 μs | 3.2 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.01x | -| random | sorted_geometric | 16 | 1024 | 8.1 μs | 14.0 μs | 10.8 μs | 28.5 μs | 12.2 μs | 8.1 μs | 10.3 μs | Linear (8.1 μs) | 1.00x | -| random | sorted_geometric | 16 | 4096 | 31.1 μs | 54.9 μs | 42.3 μs | 111.7 μs | 47.9 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | -| random | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| random | sorted_geometric | 64 | 4 | 170 ns | 140 ns | 130 ns | 150 ns | 100 ns | 150 ns | 90 ns | Binary (100 ns) | 1.50x | -| random | sorted_geometric | 64 | 16 | 270 ns | 360 ns | 290 ns | 510 ns | 300 ns | 290 ns | 270 ns | Linear (270 ns) | 1.07x | -| random | sorted_geometric | 64 | 64 | 790 ns | 1.1 μs | 740 ns | 1.9 μs | 1.2 μs | 659 ns | 1.1 μs | ExpFromLeft (740 ns) | 0.89x | -| random | sorted_geometric | 64 | 256 | 2.2 μs | 4.0 μs | 2.9 μs | 8.4 μs | 5.0 μs | 2.2 μs | 4.6 μs | Linear (2.2 μs) | 1.03x | -| random | sorted_geometric | 64 | 1024 | 8.9 μs | 14.8 μs | 11.6 μs | 33.4 μs | 17.6 μs | 8.9 μs | 16.0 μs | Linear (8.9 μs) | 1.00x | -| random | sorted_geometric | 64 | 4096 | 45.2 μs | 74.7 μs | 56.6 μs | 133.2 μs | 66.9 μs | 32.2 μs | 60.5 μs | Linear (45.2 μs) | 0.71x | -| random | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_geometric | 256 | 4 | 490 ns | 180 ns | 150 ns | 150 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | -| random | sorted_geometric | 256 | 16 | 530 ns | 490 ns | 400 ns | 540 ns | 370 ns | 410 ns | 340 ns | Binary (370 ns) | 1.11x | -| random | sorted_geometric | 256 | 64 | 920 ns | 1.4 μs | 1.0 μs | 2.1 μs | 1.5 μs | 940 ns | 1.4 μs | Linear (920 ns) | 1.02x | -| random | sorted_geometric | 256 | 256 | 2.4 μs | 4.2 μs | 2.8 μs | 8.4 μs | 6.9 μs | 2.5 μs | 6.4 μs | Linear (2.4 μs) | 1.01x | -| random | sorted_geometric | 256 | 1024 | 9.4 μs | 16.1 μs | 12.4 μs | 37.1 μs | 25.6 μs | 9.4 μs | 23.6 μs | Linear (9.4 μs) | 1.00x | -| random | sorted_geometric | 256 | 4096 | 35.8 μs | 59.1 μs | 46.1 μs | 139.7 μs | 90.6 μs | 35.6 μs | 82.3 μs | Linear (35.8 μs) | 1.00x | -| random | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_geometric | 1024 | 4 | 1.6 μs | 200 ns | 170 ns | 160 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| random | sorted_geometric | 1024 | 16 | 1.8 μs | 630 ns | 500 ns | 560 ns | 440 ns | 499 ns | 420 ns | Binary (440 ns) | 1.13x | -| random | sorted_geometric | 1024 | 64 | 2.0 μs | 1.9 μs | 1.8 μs | 2.2 μs | 1.7 μs | 1.4 μs | 1.6 μs | Binary (1.7 μs) | 0.86x | -| random | sorted_geometric | 1024 | 256 | 3.6 μs | 5.4 μs | 3.9 μs | 9.1 μs | 7.6 μs | 3.5 μs | 7.2 μs | Linear (3.6 μs) | 0.97x | -| random | sorted_geometric | 1024 | 1024 | 9.7 μs | 18.2 μs | 12.2 μs | 41.9 μs | 48.3 μs | 10.2 μs | 45.8 μs | Linear (9.7 μs) | 1.05x | -| random | sorted_geometric | 1024 | 4096 | 42.5 μs | 67.8 μs | 52.5 μs | 170.6 μs | 172.7 μs | 42.3 μs | 169.8 μs | Linear (42.5 μs) | 0.99x | -| random | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| random | sorted_geometric | 4096 | 4 | 6.2 μs | 230 ns | 190 ns | 170 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | -| random | sorted_geometric | 4096 | 16 | 6.5 μs | 770 ns | 590 ns | 680 ns | 520 ns | 610 ns | 490 ns | Binary (520 ns) | 1.17x | -| random | sorted_geometric | 4096 | 64 | 7.4 μs | 2.5 μs | 1.8 μs | 2.8 μs | 2.0 μs | 1.9 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.02x | -| random | sorted_geometric | 4096 | 256 | 8.9 μs | 7.4 μs | 5.6 μs | 11.3 μs | 10.7 μs | 5.7 μs | 11.8 μs | ExpFromLeft (5.6 μs) | 1.02x | -| random | sorted_geometric | 4096 | 1024 | 15.7 μs | 23.1 μs | 16.9 μs | 54.1 μs | 89.6 μs | 18.5 μs | 83.0 μs | Linear (15.7 μs) | 1.18x | -| random | sorted_geometric | 4096 | 4096 | 62.8 μs | 91.3 μs | 69.9 μs | 235.5 μs | 280.0 μs | 59.2 μs | 275.5 μs | Linear (62.8 μs) | 0.94x | -| random | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| random | sorted_geometric | 16384 | 4 | 23.4 μs | 270 ns | 220 ns | 180 ns | 180 ns | 260 ns | 170 ns | InterpSearch (180 ns) | 1.44x | -| random | sorted_geometric | 16384 | 16 | 23.8 μs | 910 ns | 680 ns | 730 ns | 610 ns | 710 ns | 560 ns | Binary (610 ns) | 1.16x | -| random | sorted_geometric | 16384 | 64 | 25.4 μs | 3.1 μs | 2.3 μs | 3.0 μs | 2.4 μs | 2.4 μs | 2.2 μs | ExpFromLeft (2.3 μs) | 1.01x | -| random | sorted_geometric | 16384 | 256 | 30.0 μs | 10.0 μs | 7.7 μs | 12.7 μs | 12.8 μs | 7.7 μs | 13.9 μs | ExpFromLeft (7.7 μs) | 0.99x | -| random | sorted_geometric | 16384 | 1024 | 38.1 μs | 33.6 μs | 26.5 μs | 59.9 μs | 122.3 μs | 24.8 μs | 123.7 μs | ExpFromLeft (26.5 μs) | 0.94x | -| random | sorted_geometric | 16384 | 4096 | 108.8 μs | 145.6 μs | 110.8 μs | 289.0 μs | 403.0 μs | 113.6 μs | 393.4 μs | Linear (108.8 μs) | 1.04x | -| random | sorted_geometric | 65536 | 1 | 80 ns | 70 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| random | sorted_geometric | 65536 | 4 | 93.0 μs | 300 ns | 250 ns | 210 ns | 210 ns | 290 ns | 190 ns | InterpSearch (210 ns) | 1.38x | -| random | sorted_geometric | 65536 | 16 | 93.5 μs | 1.1 μs | 789 ns | 860 ns | 700 ns | 800 ns | 670 ns | Binary (700 ns) | 1.14x | -| random | sorted_geometric | 65536 | 64 | 95.3 μs | 3.7 μs | 2.7 μs | 3.6 μs | 3.0 μs | 2.7 μs | 2.8 μs | ExpFromLeft (2.7 μs) | 1.01x | -| random | sorted_geometric | 65536 | 256 | 101.9 μs | 13.6 μs | 10.3 μs | 15.0 μs | 16.9 μs | 10.3 μs | 16.7 μs | ExpFromLeft (10.3 μs) | 1.00x | -| random | sorted_geometric | 65536 | 1024 | 122.5 μs | 57.3 μs | 43.9 μs | 81.4 μs | 156.0 μs | 39.9 μs | 158.9 μs | ExpFromLeft (43.9 μs) | 0.91x | -| random | sorted_geometric | 65536 | 4096 | 180.9 μs | 225.0 μs | 184.6 μs | 367.5 μs | 502.9 μs | 182.9 μs | 502.1 μs | Linear (180.9 μs) | 1.01x | -| random | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 50 ns | 70 ns | 50 ns | Binary (50 ns) | 1.40x | -| random | sorted_bimodal | 16 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | -| random | sorted_bimodal | 16 | 16 | 190 ns | 290 ns | 220 ns | 480 ns | 240 ns | 210 ns | 200 ns | Linear (190 ns) | 1.11x | -| random | sorted_bimodal | 16 | 64 | 620 ns | 1.0 μs | 770 ns | 1.9 μs | 840 ns | 640 ns | 730 ns | Linear (620 ns) | 1.03x | -| random | sorted_bimodal | 16 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.3 μs | 3.1 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.01x | -| random | sorted_bimodal | 16 | 1024 | 7.9 μs | 14.5 μs | 10.6 μs | 28.8 μs | 12.1 μs | 8.0 μs | 10.5 μs | Linear (7.9 μs) | 1.00x | -| random | sorted_bimodal | 16 | 4096 | 31.3 μs | 57.9 μs | 42.1 μs | 114.3 μs | 47.9 μs | 30.9 μs | 40.8 μs | Linear (31.3 μs) | 0.99x | -| random | sorted_bimodal | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| random | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 120 ns | 160 ns | 110 ns | 130 ns | 90 ns | Binary (110 ns) | 1.18x | -| random | sorted_bimodal | 64 | 16 | 269 ns | 320 ns | 230 ns | 490 ns | 350 ns | 280 ns | 310 ns | ExpFromLeft (230 ns) | 1.22x | -| random | sorted_bimodal | 64 | 64 | 850 ns | 1.3 μs | 990 ns | 2.1 μs | 1.3 μs | 870 ns | 1.1 μs | Linear (850 ns) | 1.02x | -| random | sorted_bimodal | 64 | 256 | 2.2 μs | 3.6 μs | 2.9 μs | 7.6 μs | 4.3 μs | 2.2 μs | 3.9 μs | Linear (2.2 μs) | 1.00x | -| random | sorted_bimodal | 64 | 1024 | 8.0 μs | 13.9 μs | 10.8 μs | 28.5 μs | 16.9 μs | 8.0 μs | 15.2 μs | Linear (8.0 μs) | 1.00x | -| random | sorted_bimodal | 64 | 4096 | 31.0 μs | 54.8 μs | 42.2 μs | 112.5 μs | 66.7 μs | 31.1 μs | 59.8 μs | Linear (31.0 μs) | 1.00x | -| random | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_bimodal | 256 | 4 | 420 ns | 150 ns | 140 ns | 170 ns | 130 ns | 150 ns | 110 ns | Binary (130 ns) | 1.15x | -| random | sorted_bimodal | 256 | 16 | 560 ns | 370 ns | 310 ns | 530 ns | 410 ns | 320 ns | 380 ns | ExpFromLeft (310 ns) | 1.03x | -| random | sorted_bimodal | 256 | 64 | 930 ns | 1.1 μs | 760 ns | 2.0 μs | 1.7 μs | 950 ns | 1.6 μs | ExpFromLeft (760 ns) | 1.25x | -| random | sorted_bimodal | 256 | 256 | 2.6 μs | 4.0 μs | 3.1 μs | 8.8 μs | 6.1 μs | 2.6 μs | 5.7 μs | Linear (2.6 μs) | 1.01x | -| random | sorted_bimodal | 256 | 1024 | 9.0 μs | 14.7 μs | 11.5 μs | 33.0 μs | 22.5 μs | 9.1 μs | 20.6 μs | Linear (9.0 μs) | 1.00x | -| random | sorted_bimodal | 256 | 4096 | 32.3 μs | 56.0 μs | 43.1 μs | 125.8 μs | 86.3 μs | 32.3 μs | 79.4 μs | Linear (32.3 μs) | 1.00x | -| random | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 80 ns | 80 ns | 60 ns | ExpFromLeft (60 ns) | 1.33x | -| random | sorted_bimodal | 1024 | 4 | 1.5 μs | 190 ns | 180 ns | 200 ns | 140 ns | 190 ns | 120 ns | Binary (140 ns) | 1.36x | -| random | sorted_bimodal | 1024 | 16 | 1.7 μs | 480 ns | 400 ns | 680 ns | 450 ns | 390 ns | 400 ns | ExpFromLeft (400 ns) | 0.97x | -| random | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 930 ns | 2.6 μs | 2.0 μs | 970 ns | 2.2 μs | ExpFromLeft (930 ns) | 1.04x | -| random | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.1 μs | 2.9 μs | 11.3 μs | 8.2 μs | 3.5 μs | 7.5 μs | ExpFromLeft (2.9 μs) | 1.22x | -| random | sorted_bimodal | 1024 | 1024 | 10.7 μs | 16.2 μs | 12.5 μs | 45.8 μs | 29.6 μs | 10.7 μs | 27.2 μs | Linear (10.7 μs) | 1.00x | -| random | sorted_bimodal | 1024 | 4096 | 36.3 μs | 58.6 μs | 45.8 μs | 169.4 μs | 108.5 μs | 36.2 μs | 102.1 μs | Linear (36.3 μs) | 1.00x | -| random | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_bimodal | 4096 | 4 | 5.8 μs | 240 ns | 190 ns | 190 ns | 160 ns | 220 ns | 150 ns | Binary (160 ns) | 1.38x | -| random | sorted_bimodal | 4096 | 16 | 6.2 μs | 590 ns | 469 ns | 650 ns | 590 ns | 490 ns | 540 ns | ExpFromLeft (469 ns) | 1.04x | -| random | sorted_bimodal | 4096 | 64 | 6.6 μs | 1.7 μs | 1.3 μs | 2.6 μs | 2.2 μs | 1.4 μs | 1.9 μs | ExpFromLeft (1.3 μs) | 1.03x | -| random | sorted_bimodal | 4096 | 256 | 7.9 μs | 5.1 μs | 3.6 μs | 10.3 μs | 10.4 μs | 3.7 μs | 10.2 μs | ExpFromLeft (3.6 μs) | 1.02x | -| random | sorted_bimodal | 4096 | 1024 | 15.0 μs | 17.6 μs | 12.8 μs | 45.3 μs | 51.4 μs | 14.7 μs | 47.7 μs | ExpFromLeft (12.8 μs) | 1.15x | -| random | sorted_bimodal | 4096 | 4096 | 46.0 μs | 67.6 μs | 53.4 μs | 180.3 μs | 167.9 μs | 46.5 μs | 151.3 μs | Linear (46.0 μs) | 1.01x | -| random | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_bimodal | 16384 | 4 | 21.7 μs | 250 ns | 210 ns | 210 ns | 180 ns | 219 ns | 170 ns | Binary (180 ns) | 1.22x | -| random | sorted_bimodal | 16384 | 16 | 22.4 μs | 740 ns | 570 ns | 670 ns | 600 ns | 600 ns | 560 ns | ExpFromLeft (570 ns) | 1.05x | -| random | sorted_bimodal | 16384 | 64 | 24.6 μs | 2.2 μs | 2.1 μs | 2.6 μs | 2.7 μs | 1.7 μs | 2.5 μs | ExpFromLeft (2.1 μs) | 0.82x | -| random | sorted_bimodal | 16384 | 256 | 25.9 μs | 6.6 μs | 5.0 μs | 10.3 μs | 15.2 μs | 5.1 μs | 14.9 μs | ExpFromLeft (5.0 μs) | 1.00x | -| random | sorted_bimodal | 16384 | 1024 | 33.4 μs | 22.8 μs | 16.3 μs | 48.6 μs | 84.9 μs | 15.9 μs | 82.0 μs | ExpFromLeft (16.3 μs) | 0.98x | -| random | sorted_bimodal | 16384 | 4096 | 85.6 μs | 94.0 μs | 74.0 μs | 215.3 μs | 259.6 μs | 84.5 μs | 241.2 μs | ExpFromLeft (74.0 μs) | 1.14x | -| random | sorted_bimodal | 65536 | 1 | 80 ns | 70 ns | 80 ns | 80 ns | 80 ns | 80 ns | 70 ns | Gallop (70 ns) | 1.14x | -| random | sorted_bimodal | 65536 | 4 | 89.2 μs | 270 ns | 230 ns | 230 ns | 200 ns | 260 ns | 180 ns | Binary (200 ns) | 1.30x | -| random | sorted_bimodal | 65536 | 16 | 93.6 μs | 830 ns | 620 ns | 730 ns | 680 ns | 640 ns | 630 ns | ExpFromLeft (620 ns) | 1.03x | -| random | sorted_bimodal | 65536 | 64 | 91.2 μs | 2.9 μs | 2.2 μs | 2.7 μs | 2.8 μs | 2.2 μs | 2.7 μs | ExpFromLeft (2.2 μs) | 0.99x | -| random | sorted_bimodal | 65536 | 256 | 97.4 μs | 9.1 μs | 6.8 μs | 11.0 μs | 18.5 μs | 7.1 μs | 18.2 μs | ExpFromLeft (6.8 μs) | 1.03x | -| random | sorted_bimodal | 65536 | 1024 | 108.8 μs | 32.0 μs | 24.3 μs | 53.9 μs | 109.5 μs | 23.1 μs | 110.8 μs | ExpFromLeft (24.3 μs) | 0.95x | -| random | sorted_bimodal | 65536 | 4096 | 184.5 μs | 148.3 μs | 112.5 μs | 266.4 μs | 347.3 μs | 111.1 μs | 339.4 μs | ExpFromLeft (112.5 μs) | 0.99x | -| random | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 40 ns | ExpFromLeft (50 ns) | 1.20x | -| random | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 170 ns | 90 ns | 100 ns | 80 ns | Linear (80 ns) | 1.25x | -| random | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 210 ns | 550 ns | 220 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | -| random | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 690 ns | 2.0 μs | 790 ns | 580 ns | 640 ns | Linear (550 ns) | 1.05x | -| random | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 7.9 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.01x | -| random | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 31.7 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.00x | -| random | sorted_repeated | 16 | 4096 | 30.8 μs | 54.9 μs | 39.0 μs | 125.3 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 70 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| random | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 80 ns | 190 ns | 100 ns | 110 ns | 90 ns | ExpFromLeft (80 ns) | 1.38x | -| random | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 220 ns | 650 ns | 310 ns | 199 ns | 270 ns | Linear (170 ns) | 1.17x | -| random | sorted_repeated | 64 | 64 | 550 ns | 920 ns | 700 ns | 2.5 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | -| random | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 9.7 μs | 4.2 μs | 2.1 μs | 3.6 μs | Linear (2.0 μs) | 1.08x | -| random | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 38.6 μs | 16.7 μs | 8.3 μs | 14.2 μs | Linear (7.7 μs) | 1.07x | -| random | sorted_repeated | 64 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 154.4 μs | 70.5 μs | 44.3 μs | 60.7 μs | Linear (30.8 μs) | 1.44x | -| random | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 90 ns | 190 ns | 120 ns | 110 ns | 110 ns | ExpFromLeft (90 ns) | 1.22x | -| random | sorted_repeated | 256 | 16 | 220 ns | 350 ns | 250 ns | 700 ns | 400 ns | 240 ns | 340 ns | Linear (220 ns) | 1.09x | -| random | sorted_repeated | 256 | 64 | 560 ns | 929 ns | 700 ns | 2.5 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (560 ns) | 1.04x | -| random | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 10.0 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| random | sorted_repeated | 256 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 39.9 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.01x | -| random | sorted_repeated | 256 | 4096 | 30.8 μs | 54.9 μs | 39.5 μs | 159.4 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 70 ns | 80 ns | 60 ns | 70 ns | 60 ns | Binary (60 ns) | 1.17x | -| random | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 110 ns | 210 ns | 140 ns | 110 ns | 130 ns | Linear (90 ns) | 1.22x | -| random | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 210 ns | 750 ns | 460 ns | 200 ns | 420 ns | Linear (180 ns) | 1.11x | -| random | sorted_repeated | 1024 | 64 | 560 ns | 940 ns | 700 ns | 2.9 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| random | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 11.2 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | -| random | sorted_repeated | 1024 | 1024 | 7.8 μs | 13.9 μs | 10.0 μs | 44.8 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | -| random | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.7 μs | 39.8 μs | 178.8 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_repeated | 4096 | 4 | 90 ns | 120 ns | 100 ns | 220 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | -| random | sorted_repeated | 4096 | 16 | 180 ns | 280 ns | 220 ns | 770 ns | 540 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | -| random | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 700 ns | 2.9 μs | 2.0 μs | 600 ns | 1.8 μs | Linear (560 ns) | 1.07x | -| random | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 11.4 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | -| random | sorted_repeated | 4096 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 45.5 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.7 μs) | 1.01x | -| random | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.1 μs | 182.2 μs | 124.7 μs | 30.8 μs | 114.3 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| random | sorted_repeated | 16384 | 4 | 90 ns | 110 ns | 110 ns | 190 ns | 180 ns | 120 ns | 170 ns | Linear (90 ns) | 1.33x | -| random | sorted_repeated | 16384 | 16 | 180 ns | 290 ns | 230 ns | 680 ns | 610 ns | 210 ns | 560 ns | Linear (180 ns) | 1.17x | -| random | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 700 ns | 2.6 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | -| random | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 10.1 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | -| random | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 40.1 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | -| random | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.0 μs | 39.2 μs | 160.0 μs | 144.1 μs | 30.8 μs | 133.7 μs | Linear (30.8 μs) | 1.00x | -| random | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 70 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| random | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 240 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| random | sorted_repeated | 65536 | 16 | 190 ns | 300 ns | 230 ns | 850 ns | 690 ns | 220 ns | 640 ns | Linear (190 ns) | 1.16x | -| random | sorted_repeated | 65536 | 64 | 570 ns | 949 ns | 710 ns | 3.2 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| random | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 12.9 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.00x | -| random | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 51.1 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 0.99x | -| random | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.0 μs | 39.2 μs | 204.0 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| random | unsorted | 16 | 1 | 60 ns | 50 ns | 50 ns | 60 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| random | unsorted | 16 | 4 | 90 ns | 100 ns | 90 ns | 100 ns | 100 ns | 100 ns | 70 ns | ExpFromLeft (90 ns) | 1.11x | -| random | unsorted | 16 | 16 | 210 ns | 210 ns | 219 ns | 210 ns | 210 ns | 220 ns | 200 ns | InterpSearch (210 ns) | 1.05x | -| random | unsorted | 16 | 64 | 710 ns | 700 ns | 880 ns | 710 ns | 690 ns | 720 ns | 680 ns | Binary (690 ns) | 1.04x | -| random | unsorted | 16 | 256 | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | InterpSearch (2.7 μs) | 1.00x | -| random | unsorted | 16 | 1024 | 15.2 μs | 15.2 μs | 15.2 μs | 15.0 μs | 14.9 μs | 14.8 μs | 15.6 μs | Binary (14.9 μs) | 0.99x | -| random | unsorted | 16 | 4096 | 115.4 μs | 115.3 μs | 113.3 μs | 113.0 μs | 112.7 μs | 112.9 μs | 116.5 μs | Binary (112.7 μs) | 1.00x | -| random | unsorted | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| random | unsorted | 64 | 4 | 110 ns | 100 ns | 100 ns | 100 ns | 110 ns | 110 ns | 90 ns | InterpSearch (100 ns) | 1.10x | -| random | unsorted | 64 | 16 | 280 ns | 280 ns | 280 ns | 280 ns | 280 ns | 290 ns | 260 ns | InterpSearch (280 ns) | 1.04x | -| random | unsorted | 64 | 64 | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.1 μs | Binary (1.1 μs) | 0.99x | -| random | unsorted | 64 | 256 | 6.4 μs | 6.3 μs | 6.3 μs | 6.2 μs | 6.2 μs | 6.2 μs | 6.4 μs | Binary (6.2 μs) | 1.00x | -| random | unsorted | 64 | 1024 | 37.7 μs | 37.4 μs | 36.9 μs | 37.5 μs | 36.8 μs | 36.7 μs | 39.1 μs | Binary (36.8 μs) | 1.00x | -| random | unsorted | 64 | 4096 | 206.5 μs | 204.7 μs | 202.8 μs | 202.5 μs | 201.9 μs | 203.8 μs | 200.7 μs | Binary (201.9 μs) | 1.01x | -| random | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| random | unsorted | 256 | 4 | 120 ns | 120 ns | 120 ns | 120 ns | 130 ns | 130 ns | 110 ns | InterpSearch (120 ns) | 1.08x | -| random | unsorted | 256 | 16 | 350 ns | 350 ns | 340 ns | 350 ns | 340 ns | 360 ns | 340 ns | ExpFromLeft (340 ns) | 1.06x | -| random | unsorted | 256 | 64 | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.5 μs | InterpSearch (1.4 μs) | 1.01x | -| random | unsorted | 256 | 256 | 7.3 μs | 7.2 μs | 7.2 μs | 7.1 μs | 7.1 μs | 7.1 μs | 7.3 μs | Binary (7.1 μs) | 1.00x | -| random | unsorted | 256 | 1024 | 51.5 μs | 51.3 μs | 50.9 μs | 50.6 μs | 49.6 μs | 50.2 μs | 51.2 μs | Binary (49.6 μs) | 1.01x | -| random | unsorted | 256 | 4096 | 280.9 μs | 278.4 μs | 273.9 μs | 272.8 μs | 274.6 μs | 275.9 μs | 278.2 μs | InterpSearch (272.8 μs) | 1.01x | -| random | unsorted | 1024 | 1 | 70 ns | 60 ns | 70 ns | 80 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| random | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 150 ns | 140 ns | 150 ns | 130 ns | ExpFromLeft (140 ns) | 1.07x | -| random | unsorted | 1024 | 16 | 410 ns | 420 ns | 420 ns | 430 ns | 420 ns | 430 ns | 410 ns | Linear (410 ns) | 1.05x | -| random | unsorted | 1024 | 64 | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.8 μs | 1.7 μs | Linear (1.7 μs) | 1.02x | -| random | unsorted | 1024 | 256 | 8.3 μs | 8.0 μs | 8.0 μs | 8.0 μs | 8.0 μs | 8.0 μs | 8.3 μs | Binary (8.0 μs) | 1.00x | -| random | unsorted | 1024 | 1024 | 77.0 μs | 76.3 μs | 75.1 μs | 74.4 μs | 74.1 μs | 73.7 μs | 75.9 μs | Binary (74.1 μs) | 0.99x | -| random | unsorted | 1024 | 4096 | 379.5 μs | 380.8 μs | 380.3 μs | 377.5 μs | 381.1 μs | 380.0 μs | 378.8 μs | InterpSearch (377.5 μs) | 1.01x | -| random | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| random | unsorted | 4096 | 4 | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 170 ns | 140 ns | InterpSearch (160 ns) | 1.06x | -| random | unsorted | 4096 | 16 | 490 ns | 500 ns | 480 ns | 490 ns | 510 ns | 500 ns | 480 ns | ExpFromLeft (480 ns) | 1.04x | -| random | unsorted | 4096 | 64 | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | Gallop (1.9 μs) | 1.01x | -| random | unsorted | 4096 | 256 | 9.8 μs | 9.8 μs | 9.4 μs | 9.5 μs | 9.4 μs | 9.5 μs | 11.0 μs | ExpFromLeft (9.4 μs) | 1.01x | -| random | unsorted | 4096 | 1024 | 96.3 μs | 94.0 μs | 93.0 μs | 92.1 μs | 91.6 μs | 91.5 μs | 95.5 μs | Binary (91.6 μs) | 1.00x | -| random | unsorted | 4096 | 4096 | 483.4 μs | 479.6 μs | 478.6 μs | 481.5 μs | 480.6 μs | 481.0 μs | 485.3 μs | ExpFromLeft (478.6 μs) | 1.01x | -| random | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| random | unsorted | 16384 | 4 | 180 ns | 180 ns | 180 ns | 180 ns | 180 ns | 180 ns | 170 ns | InterpSearch (180 ns) | 1.00x | -| random | unsorted | 16384 | 16 | 570 ns | 580 ns | 580 ns | 580 ns | 570 ns | 580 ns | 560 ns | Binary (570 ns) | 1.02x | -| random | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.2 μs | 2.3 μs | 2.2 μs | Binary (2.2 μs) | 1.02x | -| random | unsorted | 16384 | 256 | 11.2 μs | 11.1 μs | 11.1 μs | 11.1 μs | 11.1 μs | 11.1 μs | 14.1 μs | ExpFromLeft (11.1 μs) | 1.00x | -| random | unsorted | 16384 | 1024 | 139.6 μs | 135.6 μs | 134.0 μs | 134.5 μs | 132.2 μs | 131.6 μs | 138.4 μs | Binary (132.2 μs) | 1.00x | -| random | unsorted | 16384 | 4096 | 660.5 μs | 661.2 μs | 660.3 μs | 666.5 μs | 658.7 μs | 660.7 μs | 660.5 μs | Binary (658.7 μs) | 1.00x | -| random | unsorted | 65536 | 1 | 80 ns | 80 ns | 70 ns | 90 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| random | unsorted | 65536 | 4 | 200 ns | 190 ns | 200 ns | 190 ns | 200 ns | 210 ns | 190 ns | InterpSearch (190 ns) | 1.11x | -| random | unsorted | 65536 | 16 | 710 ns | 710 ns | 710 ns | 700 ns | 720 ns | 720 ns | 690 ns | InterpSearch (700 ns) | 1.03x | -| random | unsorted | 65536 | 64 | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | 2.8 μs | Gallop (2.8 μs) | 1.01x | -| random | unsorted | 65536 | 256 | 13.9 μs | 13.7 μs | 13.7 μs | 13.6 μs | 13.6 μs | 13.3 μs | 18.5 μs | Binary (13.6 μs) | 0.98x | -| random | unsorted | 65536 | 1024 | 187.8 μs | 183.9 μs | 183.2 μs | 182.0 μs | 181.6 μs | 181.4 μs | 185.2 μs | Binary (181.6 μs) | 1.00x | -| random | unsorted | 65536 | 4096 | 845.5 μs | 843.9 μs | 846.9 μs | 846.7 μs | 846.0 μs | 845.3 μs | 844.8 μs | Gallop (843.9 μs) | 1.00x | -| two_scale | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 40 ns | ExpFromLeft (50 ns) | 1.20x | -| two_scale | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 100 ns | 160 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| two_scale | sorted_uniform | 16 | 16 | 170 ns | 260 ns | 210 ns | 540 ns | 230 ns | 200 ns | 190 ns | Linear (170 ns) | 1.18x | -| two_scale | sorted_uniform | 16 | 64 | 560 ns | 970 ns | 740 ns | 2.2 μs | 910 ns | 600 ns | 750 ns | Linear (560 ns) | 1.07x | -| two_scale | sorted_uniform | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 8.8 μs | 3.1 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.01x | -| two_scale | sorted_uniform | 16 | 1024 | 7.9 μs | 13.9 μs | 10.7 μs | 33.4 μs | 12.2 μs | 7.9 μs | 10.1 μs | Linear (7.9 μs) | 1.00x | -| two_scale | sorted_uniform | 16 | 4096 | 30.9 μs | 55.5 μs | 42.1 μs | 131.4 μs | 48.8 μs | 31.4 μs | 40.8 μs | Linear (30.9 μs) | 1.02x | -| two_scale | sorted_uniform | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_uniform | 64 | 4 | 120 ns | 130 ns | 130 ns | 200 ns | 110 ns | 140 ns | 90 ns | Binary (110 ns) | 1.27x | -| two_scale | sorted_uniform | 64 | 16 | 210 ns | 320 ns | 240 ns | 710 ns | 350 ns | 240 ns | 310 ns | Linear (210 ns) | 1.14x | -| two_scale | sorted_uniform | 64 | 64 | 590 ns | 1.0 μs | 730 ns | 2.6 μs | 1.3 μs | 630 ns | 1.2 μs | Linear (590 ns) | 1.07x | -| two_scale | sorted_uniform | 64 | 256 | 2.4 μs | 4.1 μs | 3.1 μs | 11.2 μs | 4.8 μs | 2.4 μs | 4.3 μs | Linear (2.4 μs) | 1.01x | -| two_scale | sorted_uniform | 64 | 1024 | 8.5 μs | 15.0 μs | 11.1 μs | 43.7 μs | 17.4 μs | 8.5 μs | 15.5 μs | Linear (8.5 μs) | 1.00x | -| two_scale | sorted_uniform | 64 | 4096 | 31.9 μs | 58.4 μs | 42.7 μs | 167.6 μs | 68.4 μs | 32.0 μs | 59.6 μs | Linear (31.9 μs) | 1.00x | -| two_scale | sorted_uniform | 256 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_uniform | 256 | 4 | 150 ns | 150 ns | 140 ns | 250 ns | 120 ns | 150 ns | 110 ns | Binary (120 ns) | 1.25x | -| two_scale | sorted_uniform | 256 | 16 | 340 ns | 410 ns | 350 ns | 870 ns | 370 ns | 340 ns | 339 ns | Linear (340 ns) | 1.00x | -| two_scale | sorted_uniform | 256 | 64 | 720 ns | 1.2 μs | 830 ns | 3.2 μs | 1.6 μs | 760 ns | 1.6 μs | Linear (720 ns) | 1.06x | -| two_scale | sorted_uniform | 256 | 256 | 2.2 μs | 4.0 μs | 2.8 μs | 13.4 μs | 6.6 μs | 2.2 μs | 6.0 μs | Linear (2.2 μs) | 1.01x | -| two_scale | sorted_uniform | 256 | 1024 | 9.9 μs | 16.0 μs | 12.7 μs | 56.7 μs | 23.7 μs | 9.9 μs | 21.6 μs | Linear (9.9 μs) | 1.00x | -| two_scale | sorted_uniform | 256 | 4096 | 33.8 μs | 58.0 μs | 44.6 μs | 214.4 μs | 88.3 μs | 33.7 μs | 80.6 μs | Linear (33.8 μs) | 1.00x | -| two_scale | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 80 ns | 130 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| two_scale | sorted_uniform | 1024 | 4 | 740 ns | 180 ns | 160 ns | 270 ns | 150 ns | 190 ns | 130 ns | Binary (150 ns) | 1.27x | -| two_scale | sorted_uniform | 1024 | 16 | 1.1 μs | 520 ns | 400 ns | 980 ns | 480 ns | 440 ns | 440 ns | ExpFromLeft (400 ns) | 1.10x | -| two_scale | sorted_uniform | 1024 | 64 | 1.3 μs | 1.5 μs | 1.2 μs | 4.0 μs | 1.8 μs | 1.2 μs | 1.8 μs | ExpFromLeft (1.2 μs) | 1.03x | -| two_scale | sorted_uniform | 1024 | 256 | 2.7 μs | 4.7 μs | 3.2 μs | 16.1 μs | 8.2 μs | 2.8 μs | 7.9 μs | Linear (2.7 μs) | 1.03x | -| two_scale | sorted_uniform | 1024 | 1024 | 10.3 μs | 17.4 μs | 12.4 μs | 71.7 μs | 34.6 μs | 10.3 μs | 33.0 μs | Linear (10.3 μs) | 1.00x | -| two_scale | sorted_uniform | 1024 | 4096 | 40.0 μs | 63.5 μs | 50.2 μs | 291.1 μs | 120.0 μs | 40.0 μs | 114.1 μs | Linear (40.0 μs) | 1.00x | -| two_scale | sorted_uniform | 4096 | 1 | 70 ns | 80 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | sorted_uniform | 4096 | 4 | 1.0 μs | 210 ns | 190 ns | 340 ns | 170 ns | 220 ns | 140 ns | Binary (170 ns) | 1.29x | -| two_scale | sorted_uniform | 4096 | 16 | 3.1 μs | 730 ns | 540 ns | 1.1 μs | 550 ns | 560 ns | 520 ns | ExpFromLeft (540 ns) | 1.04x | -| two_scale | sorted_uniform | 4096 | 64 | 4.2 μs | 2.0 μs | 1.6 μs | 4.6 μs | 2.2 μs | 1.6 μs | 2.5 μs | ExpFromLeft (1.6 μs) | 1.05x | -| two_scale | sorted_uniform | 4096 | 256 | 5.2 μs | 6.2 μs | 4.5 μs | 18.8 μs | 11.0 μs | 4.5 μs | 10.2 μs | ExpFromLeft (4.5 μs) | 1.00x | -| two_scale | sorted_uniform | 4096 | 1024 | 15.5 μs | 23.4 μs | 15.0 μs | 95.4 μs | 74.0 μs | 15.5 μs | 66.5 μs | ExpFromLeft (15.0 μs) | 1.03x | -| two_scale | sorted_uniform | 4096 | 4096 | 54.7 μs | 79.6 μs | 62.5 μs | 414.4 μs | 216.7 μs | 53.6 μs | 209.5 μs | Linear (54.7 μs) | 0.98x | -| two_scale | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| two_scale | sorted_uniform | 16384 | 4 | 7.4 μs | 240 ns | 200 ns | 360 ns | 180 ns | 230 ns | 160 ns | Binary (180 ns) | 1.28x | -| two_scale | sorted_uniform | 16384 | 16 | 11.8 μs | 810 ns | 610 ns | 1.3 μs | 600 ns | 640 ns | 570 ns | Binary (600 ns) | 1.07x | -| two_scale | sorted_uniform | 16384 | 64 | 13.3 μs | 2.7 μs | 2.0 μs | 5.3 μs | 2.6 μs | 2.1 μs | 2.4 μs | ExpFromLeft (2.0 μs) | 1.04x | -| two_scale | sorted_uniform | 16384 | 256 | 16.6 μs | 8.3 μs | 6.4 μs | 22.7 μs | 14.7 μs | 6.5 μs | 14.4 μs | ExpFromLeft (6.4 μs) | 1.02x | -| two_scale | sorted_uniform | 16384 | 1024 | 23.5 μs | 29.1 μs | 20.1 μs | 127.8 μs | 106.0 μs | 20.4 μs | 104.5 μs | ExpFromLeft (20.1 μs) | 1.02x | -| two_scale | sorted_uniform | 16384 | 4096 | 102.7 μs | 127.3 μs | 97.3 μs | 529.1 μs | 327.1 μs | 98.7 μs | 319.7 μs | ExpFromLeft (97.3 μs) | 1.01x | -| two_scale | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_uniform | 65536 | 4 | 39.5 μs | 280 ns | 220 ns | 390 ns | 200 ns | 250 ns | 190 ns | Binary (200 ns) | 1.25x | -| two_scale | sorted_uniform | 65536 | 16 | 42.4 μs | 940 ns | 690 ns | 1.5 μs | 720 ns | 729 ns | 680 ns | ExpFromLeft (690 ns) | 1.06x | -| two_scale | sorted_uniform | 65536 | 64 | 47.2 μs | 3.2 μs | 2.4 μs | 5.9 μs | 2.9 μs | 2.5 μs | 2.8 μs | ExpFromLeft (2.4 μs) | 1.04x | -| two_scale | sorted_uniform | 65536 | 256 | 54.5 μs | 11.0 μs | 8.4 μs | 26.6 μs | 19.2 μs | 8.5 μs | 16.8 μs | ExpFromLeft (8.4 μs) | 1.01x | -| two_scale | sorted_uniform | 65536 | 1024 | 73.1 μs | 44.4 μs | 33.7 μs | 173.1 μs | 131.8 μs | 31.0 μs | 135.6 μs | ExpFromLeft (33.7 μs) | 0.92x | -| two_scale | sorted_uniform | 65536 | 4096 | 188.7 μs | 202.3 μs | 159.1 μs | 681.2 μs | 414.0 μs | 158.0 μs | 413.9 μs | ExpFromLeft (159.1 μs) | 0.99x | -| two_scale | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| two_scale | sorted_dense_burst | 16 | 4 | 80 ns | 90 ns | 90 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| two_scale | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 220 ns | 630 ns | 230 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | -| two_scale | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 720 ns | 2.3 μs | 780 ns | 580 ns | 640 ns | Linear (550 ns) | 1.05x | -| two_scale | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.9 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.01x | -| two_scale | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 35.4 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.01x | -| two_scale | sorted_dense_burst | 16 | 4096 | 30.8 μs | 55.1 μs | 41.9 μs | 141.0 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| two_scale | sorted_dense_burst | 64 | 4 | 80 ns | 90 ns | 90 ns | 210 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| two_scale | sorted_dense_burst | 64 | 16 | 180 ns | 270 ns | 220 ns | 790 ns | 310 ns | 190 ns | 260 ns | Linear (180 ns) | 1.06x | -| two_scale | sorted_dense_burst | 64 | 64 | 549 ns | 930 ns | 729 ns | 3.0 μs | 1.4 μs | 580 ns | 920 ns | Linear (549 ns) | 1.06x | -| two_scale | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.4 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | -| two_scale | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.7 μs | 10.6 μs | 45.2 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.01x | -| two_scale | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 180.3 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 250 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| two_scale | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 950 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| two_scale | sorted_dense_burst | 256 | 64 | 550 ns | 920 ns | 740 ns | 3.6 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | -| two_scale | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 14.0 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| two_scale | sorted_dense_burst | 256 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 55.9 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.7 μs) | 1.01x | -| two_scale | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 222.8 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 100 ns | 290 ns | 140 ns | 110 ns | 130 ns | Linear (90 ns) | 1.22x | -| two_scale | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 240 ns | 1.1 μs | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | -| two_scale | sorted_dense_burst | 1024 | 64 | 560 ns | 939 ns | 740 ns | 4.2 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| two_scale | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.4 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| two_scale | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.9 μs | 10.6 μs | 65.4 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.1 μs | 42.1 μs | 260.7 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 130 ns | 350 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | -| two_scale | sorted_dense_burst | 4096 | 16 | 190 ns | 290 ns | 240 ns | 1.2 μs | 530 ns | 210 ns | 490 ns | Linear (190 ns) | 1.11x | -| two_scale | sorted_dense_burst | 4096 | 64 | 560 ns | 930 ns | 740 ns | 4.8 μs | 2.0 μs | 600 ns | 1.8 μs | Linear (560 ns) | 1.07x | -| two_scale | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 18.8 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| two_scale | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 74.7 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 54.9 μs | 42.1 μs | 299.4 μs | 124.7 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| two_scale | sorted_dense_burst | 16384 | 4 | 90 ns | 110 ns | 100 ns | 380 ns | 180 ns | 120 ns | 170 ns | Linear (90 ns) | 1.33x | -| two_scale | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 1.4 μs | 600 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | -| two_scale | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 740 ns | 5.5 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | -| two_scale | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 21.6 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | -| two_scale | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 85.9 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 343.8 μs | 144.1 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_dense_burst | 65536 | 4 | 100 ns | 110 ns | 110 ns | 520 ns | 250 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| two_scale | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 260 ns | 1.6 μs | 690 ns | 210 ns | 640 ns | Linear (190 ns) | 1.11x | -| two_scale | sorted_dense_burst | 65536 | 64 | 570 ns | 940 ns | 750 ns | 6.2 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| two_scale | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.6 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | -| two_scale | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 97.3 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.01x | -| two_scale | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 42.1 μs | 386.4 μs | 163.2 μs | 30.9 μs | 152.6 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| two_scale | sorted_near_start | 16 | 4 | 90 ns | 110 ns | 100 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| two_scale | sorted_near_start | 16 | 16 | 190 ns | 280 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | -| two_scale | sorted_near_start | 16 | 64 | 570 ns | 950 ns | 760 ns | 1.7 μs | 810 ns | 590 ns | 690 ns | Linear (570 ns) | 1.04x | -| two_scale | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.7 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.02x | -| two_scale | sorted_near_start | 16 | 1024 | 11.2 μs | 14.0 μs | 10.8 μs | 26.7 μs | 12.0 μs | 7.9 μs | 10.2 μs | ExpFromLeft (10.8 μs) | 0.74x | -| two_scale | sorted_near_start | 16 | 4096 | 31.0 μs | 55.2 μs | 42.2 μs | 105.9 μs | 47.5 μs | 31.0 μs | 40.1 μs | Linear (31.0 μs) | 1.00x | -| two_scale | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 70 ns | 70 ns | 50 ns | Gallop (50 ns) | 1.40x | -| two_scale | sorted_near_start | 64 | 4 | 150 ns | 120 ns | 120 ns | 150 ns | 110 ns | 120 ns | 90 ns | Binary (110 ns) | 1.09x | -| two_scale | sorted_near_start | 64 | 16 | 220 ns | 310 ns | 230 ns | 520 ns | 320 ns | 240 ns | 289 ns | Linear (220 ns) | 1.09x | -| two_scale | sorted_near_start | 64 | 64 | 630 ns | 980 ns | 780 ns | 1.8 μs | 1.1 μs | 650 ns | 990 ns | Linear (630 ns) | 1.03x | -| two_scale | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.0 μs | 4.4 μs | 2.1 μs | 4.0 μs | Linear (2.1 μs) | 1.01x | -| two_scale | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.8 μs | 27.7 μs | 16.9 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.01x | -| two_scale | sorted_near_start | 64 | 4096 | 31.4 μs | 55.6 μs | 42.6 μs | 111.3 μs | 66.2 μs | 31.4 μs | 60.3 μs | Linear (31.4 μs) | 1.00x | -| two_scale | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_near_start | 256 | 4 | 270 ns | 130 ns | 110 ns | 220 ns | 129 ns | 290 ns | 100 ns | ExpFromLeft (110 ns) | 2.64x | -| two_scale | sorted_near_start | 256 | 16 | 540 ns | 390 ns | 320 ns | 670 ns | 380 ns | 290 ns | 359 ns | ExpFromLeft (320 ns) | 0.91x | -| two_scale | sorted_near_start | 256 | 64 | 920 ns | 1.1 μs | 810 ns | 2.6 μs | 1.5 μs | 940 ns | 1.3 μs | ExpFromLeft (810 ns) | 1.16x | -| two_scale | sorted_near_start | 256 | 256 | 2.5 μs | 3.9 μs | 3.0 μs | 10.3 μs | 5.7 μs | 2.5 μs | 5.2 μs | Linear (2.5 μs) | 1.01x | -| two_scale | sorted_near_start | 256 | 1024 | 8.3 μs | 14.3 μs | 10.9 μs | 40.0 μs | 22.3 μs | 8.4 μs | 20.4 μs | Linear (8.3 μs) | 1.01x | -| two_scale | sorted_near_start | 256 | 4096 | 31.6 μs | 56.3 μs | 42.8 μs | 161.3 μs | 87.8 μs | 31.6 μs | 80.2 μs | Linear (31.6 μs) | 1.00x | -| two_scale | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| two_scale | sorted_near_start | 1024 | 4 | 1.4 μs | 170 ns | 150 ns | 230 ns | 140 ns | 180 ns | 130 ns | Binary (140 ns) | 1.29x | -| two_scale | sorted_near_start | 1024 | 16 | 1.7 μs | 420 ns | 330 ns | 740 ns | 470 ns | 340 ns | 440 ns | ExpFromLeft (330 ns) | 1.03x | -| two_scale | sorted_near_start | 1024 | 64 | 2.0 μs | 1.2 μs | 870 ns | 2.9 μs | 2.1 μs | 920 ns | 2.0 μs | ExpFromLeft (870 ns) | 1.06x | -| two_scale | sorted_near_start | 1024 | 256 | 3.8 μs | 4.3 μs | 3.3 μs | 11.8 μs | 7.3 μs | 3.8 μs | 6.7 μs | ExpFromLeft (3.3 μs) | 1.13x | -| two_scale | sorted_near_start | 1024 | 1024 | 10.4 μs | 15.5 μs | 12.0 μs | 47.0 μs | 27.5 μs | 10.4 μs | 26.0 μs | Linear (10.4 μs) | 1.00x | -| two_scale | sorted_near_start | 1024 | 4096 | 33.5 μs | 57.2 μs | 43.5 μs | 188.2 μs | 108.7 μs | 35.2 μs | 102.0 μs | Linear (33.5 μs) | 1.05x | -| two_scale | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | sorted_near_start | 4096 | 4 | 3.7 μs | 210 ns | 170 ns | 270 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | -| two_scale | sorted_near_start | 4096 | 16 | 3.9 μs | 500 ns | 390 ns | 940 ns | 550 ns | 420 ns | 530 ns | ExpFromLeft (390 ns) | 1.08x | -| two_scale | sorted_near_start | 4096 | 64 | 6.5 μs | 1.4 μs | 1.1 μs | 3.7 μs | 2.4 μs | 1.1 μs | 2.3 μs | ExpFromLeft (1.1 μs) | 1.04x | -| two_scale | sorted_near_start | 4096 | 256 | 8.1 μs | 4.6 μs | 3.4 μs | 14.6 μs | 10.1 μs | 3.5 μs | 9.2 μs | ExpFromLeft (3.4 μs) | 1.03x | -| two_scale | sorted_near_start | 4096 | 1024 | 15.9 μs | 17.7 μs | 13.6 μs | 62.2 μs | 40.3 μs | 15.8 μs | 36.3 μs | ExpFromLeft (13.6 μs) | 1.16x | -| two_scale | sorted_near_start | 4096 | 4096 | 41.8 μs | 61.9 μs | 48.2 μs | 241.8 μs | 152.5 μs | 41.7 μs | 138.1 μs | Linear (41.8 μs) | 1.00x | -| two_scale | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | sorted_near_start | 16384 | 4 | 20.5 μs | 220 ns | 190 ns | 310 ns | 170 ns | 230 ns | 170 ns | Binary (170 ns) | 1.35x | -| two_scale | sorted_near_start | 16384 | 16 | 22.6 μs | 630 ns | 510 ns | 1.1 μs | 640 ns | 510 ns | 560 ns | ExpFromLeft (510 ns) | 1.00x | -| two_scale | sorted_near_start | 16384 | 64 | 23.8 μs | 1.8 μs | 1.4 μs | 4.3 μs | 3.0 μs | 1.4 μs | 2.7 μs | ExpFromLeft (1.4 μs) | 1.02x | -| two_scale | sorted_near_start | 16384 | 256 | 25.0 μs | 5.8 μs | 4.2 μs | 17.8 μs | 16.9 μs | 4.4 μs | 16.4 μs | ExpFromLeft (4.2 μs) | 1.05x | -| two_scale | sorted_near_start | 16384 | 1024 | 33.2 μs | 20.2 μs | 14.7 μs | 82.1 μs | 70.6 μs | 15.2 μs | 64.7 μs | ExpFromLeft (14.7 μs) | 1.03x | -| two_scale | sorted_near_start | 16384 | 4096 | 68.7 μs | 75.0 μs | 71.2 μs | 348.7 μs | 237.3 μs | 69.0 μs | 227.1 μs | Linear (68.7 μs) | 1.00x | -| two_scale | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_near_start | 65536 | 4 | 53.1 μs | 250 ns | 230 ns | 350 ns | 200 ns | 240 ns | 180 ns | Binary (200 ns) | 1.20x | -| two_scale | sorted_near_start | 65536 | 16 | 86.2 μs | 820 ns | 620 ns | 1.2 μs | 670 ns | 630 ns | 620 ns | ExpFromLeft (620 ns) | 1.02x | -| two_scale | sorted_near_start | 65536 | 64 | 85.2 μs | 2.6 μs | 1.9 μs | 4.9 μs | 3.3 μs | 1.9 μs | 3.2 μs | ExpFromLeft (1.9 μs) | 1.01x | -| two_scale | sorted_near_start | 65536 | 256 | 94.1 μs | 7.6 μs | 5.8 μs | 20.8 μs | 20.6 μs | 5.8 μs | 19.1 μs | ExpFromLeft (5.8 μs) | 0.99x | -| two_scale | sorted_near_start | 65536 | 1024 | 103.4 μs | 27.1 μs | 19.4 μs | 113.9 μs | 90.7 μs | 19.7 μs | 84.3 μs | ExpFromLeft (19.4 μs) | 1.02x | -| two_scale | sorted_near_start | 65536 | 4096 | 160.5 μs | 121.3 μs | 97.6 μs | 475.2 μs | 305.4 μs | 96.3 μs | 289.0 μs | ExpFromLeft (97.6 μs) | 0.99x | -| two_scale | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| two_scale | sorted_arithmetic | 16 | 4 | 100 ns | 110 ns | 100 ns | 159 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| two_scale | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 220 ns | 530 ns | 240 ns | 200 ns | 200 ns | Linear (190 ns) | 1.05x | -| two_scale | sorted_arithmetic | 16 | 64 | 570 ns | 1.0 μs | 770 ns | 2.1 μs | 910 ns | 600 ns | 800 ns | Linear (570 ns) | 1.05x | -| two_scale | sorted_arithmetic | 16 | 256 | 2.2 μs | 3.6 μs | 2.8 μs | 8.6 μs | 3.2 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.01x | -| two_scale | sorted_arithmetic | 16 | 1024 | 7.9 μs | 13.7 μs | 10.7 μs | 32.7 μs | 12.5 μs | 7.9 μs | 10.5 μs | Linear (7.9 μs) | 1.00x | -| two_scale | sorted_arithmetic | 16 | 4096 | 30.9 μs | 54.2 μs | 42.2 μs | 128.6 μs | 49.2 μs | 31.0 μs | 42.3 μs | Linear (30.9 μs) | 1.00x | -| two_scale | sorted_arithmetic | 64 | 1 | 60 ns | 60 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| two_scale | sorted_arithmetic | 64 | 4 | 170 ns | 140 ns | 130 ns | 180 ns | 110 ns | 170 ns | 100 ns | Binary (110 ns) | 1.55x | -| two_scale | sorted_arithmetic | 64 | 16 | 260 ns | 360 ns | 250 ns | 680 ns | 300 ns | 280 ns | 270 ns | ExpFromLeft (250 ns) | 1.12x | -| two_scale | sorted_arithmetic | 64 | 64 | 630 ns | 1.0 μs | 740 ns | 2.6 μs | 1.4 μs | 660 ns | 1.3 μs | Linear (630 ns) | 1.05x | -| two_scale | sorted_arithmetic | 64 | 256 | 2.4 μs | 4.0 μs | 3.1 μs | 11.0 μs | 4.8 μs | 2.5 μs | 4.3 μs | Linear (2.4 μs) | 1.00x | -| two_scale | sorted_arithmetic | 64 | 1024 | 8.5 μs | 14.3 μs | 11.1 μs | 42.9 μs | 17.4 μs | 8.5 μs | 15.2 μs | Linear (8.5 μs) | 1.00x | -| two_scale | sorted_arithmetic | 64 | 4096 | 31.5 μs | 55.3 μs | 42.7 μs | 165.7 μs | 67.6 μs | 31.5 μs | 59.7 μs | Linear (31.5 μs) | 1.00x | -| two_scale | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_arithmetic | 256 | 4 | 510 ns | 180 ns | 150 ns | 190 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | -| two_scale | sorted_arithmetic | 256 | 16 | 570 ns | 460 ns | 380 ns | 800 ns | 370 ns | 399 ns | 340 ns | Binary (370 ns) | 1.08x | -| two_scale | sorted_arithmetic | 256 | 64 | 920 ns | 1.2 μs | 860 ns | 3.2 μs | 1.8 μs | 959 ns | 1.5 μs | ExpFromLeft (860 ns) | 1.12x | -| two_scale | sorted_arithmetic | 256 | 256 | 2.5 μs | 4.0 μs | 2.8 μs | 13.6 μs | 6.5 μs | 2.5 μs | 6.0 μs | Linear (2.5 μs) | 0.99x | -| two_scale | sorted_arithmetic | 256 | 1024 | 9.7 μs | 15.7 μs | 12.3 μs | 58.1 μs | 23.9 μs | 9.7 μs | 21.9 μs | Linear (9.7 μs) | 1.00x | -| two_scale | sorted_arithmetic | 256 | 4096 | 33.7 μs | 57.4 μs | 44.3 μs | 212.8 μs | 88.4 μs | 33.7 μs | 80.3 μs | Linear (33.7 μs) | 1.00x | -| two_scale | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| two_scale | sorted_arithmetic | 1024 | 4 | 1.6 μs | 200 ns | 180 ns | 210 ns | 150 ns | 190 ns | 130 ns | Binary (150 ns) | 1.27x | -| two_scale | sorted_arithmetic | 1024 | 16 | 1.9 μs | 610 ns | 480 ns | 930 ns | 450 ns | 500 ns | 420 ns | Binary (450 ns) | 1.11x | -| two_scale | sorted_arithmetic | 1024 | 64 | 2.1 μs | 1.7 μs | 1.3 μs | 3.8 μs | 1.8 μs | 1.3 μs | 1.6 μs | ExpFromLeft (1.3 μs) | 1.03x | -| two_scale | sorted_arithmetic | 1024 | 256 | 3.5 μs | 4.9 μs | 3.3 μs | 16.2 μs | 8.2 μs | 3.5 μs | 8.0 μs | ExpFromLeft (3.3 μs) | 1.07x | -| two_scale | sorted_arithmetic | 1024 | 1024 | 10.4 μs | 17.1 μs | 12.1 μs | 74.2 μs | 36.3 μs | 10.6 μs | 34.4 μs | Linear (10.4 μs) | 1.03x | -| two_scale | sorted_arithmetic | 1024 | 4096 | 41.3 μs | 63.9 μs | 50.2 μs | 301.8 μs | 121.7 μs | 41.2 μs | 116.4 μs | Linear (41.3 μs) | 1.00x | -| two_scale | sorted_arithmetic | 4096 | 1 | 70 ns | 90 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | sorted_arithmetic | 4096 | 4 | 6.0 μs | 240 ns | 200 ns | 230 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | -| two_scale | sorted_arithmetic | 4096 | 16 | 6.4 μs | 740 ns | 590 ns | 1.1 μs | 520 ns | 600 ns | 490 ns | Binary (520 ns) | 1.15x | -| two_scale | sorted_arithmetic | 4096 | 64 | 7.8 μs | 2.2 μs | 1.7 μs | 4.5 μs | 2.0 μs | 1.8 μs | 1.9 μs | ExpFromLeft (1.7 μs) | 1.02x | -| two_scale | sorted_arithmetic | 4096 | 256 | 8.3 μs | 6.6 μs | 5.2 μs | 18.9 μs | 11.4 μs | 5.3 μs | 11.0 μs | ExpFromLeft (5.2 μs) | 1.03x | -| two_scale | sorted_arithmetic | 4096 | 1024 | 14.8 μs | 20.6 μs | 13.6 μs | 100.8 μs | 84.5 μs | 14.8 μs | 76.9 μs | ExpFromLeft (13.6 μs) | 1.09x | -| two_scale | sorted_arithmetic | 4096 | 4096 | 57.3 μs | 81.3 μs | 63.1 μs | 424.2 μs | 227.0 μs | 57.2 μs | 225.1 μs | Linear (57.3 μs) | 1.00x | -| two_scale | sorted_arithmetic | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | sorted_arithmetic | 16384 | 4 | 23.6 μs | 270 ns | 220 ns | 260 ns | 180 ns | 240 ns | 170 ns | Binary (180 ns) | 1.33x | -| two_scale | sorted_arithmetic | 16384 | 16 | 24.2 μs | 900 ns | 679 ns | 1.2 μs | 610 ns | 690 ns | 570 ns | Binary (610 ns) | 1.13x | -| two_scale | sorted_arithmetic | 16384 | 64 | 25.7 μs | 2.9 μs | 2.2 μs | 5.1 μs | 2.5 μs | 2.2 μs | 2.3 μs | ExpFromLeft (2.2 μs) | 1.01x | -| two_scale | sorted_arithmetic | 16384 | 256 | 30.6 μs | 9.0 μs | 6.8 μs | 22.5 μs | 15.6 μs | 6.7 μs | 14.5 μs | ExpFromLeft (6.8 μs) | 1.00x | -| two_scale | sorted_arithmetic | 16384 | 1024 | 37.0 μs | 29.2 μs | 23.4 μs | 134.1 μs | 114.7 μs | 23.2 μs | 112.8 μs | ExpFromLeft (23.4 μs) | 0.99x | -| two_scale | sorted_arithmetic | 16384 | 4096 | 99.8 μs | 117.3 μs | 87.3 μs | 547.2 μs | 354.3 μs | 93.9 μs | 341.4 μs | ExpFromLeft (87.3 μs) | 1.08x | -| two_scale | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_arithmetic | 65536 | 4 | 93.1 μs | 310 ns | 240 ns | 270 ns | 200 ns | 270 ns | 190 ns | Binary (200 ns) | 1.35x | -| two_scale | sorted_arithmetic | 65536 | 16 | 93.6 μs | 1.1 μs | 760 ns | 1.4 μs | 710 ns | 790 ns | 660 ns | Binary (710 ns) | 1.11x | -| two_scale | sorted_arithmetic | 65536 | 64 | 95.4 μs | 3.6 μs | 2.7 μs | 5.9 μs | 3.0 μs | 2.7 μs | 2.8 μs | ExpFromLeft (2.7 μs) | 1.01x | -| two_scale | sorted_arithmetic | 65536 | 256 | 100.3 μs | 11.7 μs | 8.9 μs | 27.7 μs | 18.4 μs | 9.2 μs | 12.9 μs | ExpFromLeft (8.9 μs) | 1.04x | -| two_scale | sorted_arithmetic | 65536 | 1024 | 118.7 μs | 42.9 μs | 32.1 μs | 183.2 μs | 141.0 μs | 30.3 μs | 143.4 μs | ExpFromLeft (32.1 μs) | 0.94x | -| two_scale | sorted_arithmetic | 65536 | 4096 | 195.6 μs | 190.8 μs | 153.7 μs | 699.3 μs | 455.7 μs | 152.3 μs | 453.8 μs | ExpFromLeft (153.7 μs) | 0.99x | -| two_scale | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| two_scale | sorted_geometric | 16 | 4 | 90 ns | 110 ns | 110 ns | 170 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | -| two_scale | sorted_geometric | 16 | 16 | 190 ns | 290 ns | 220 ns | 610 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | -| two_scale | sorted_geometric | 16 | 64 | 580 ns | 1.0 μs | 770 ns | 2.3 μs | 860 ns | 610 ns | 700 ns | Linear (580 ns) | 1.05x | -| two_scale | sorted_geometric | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 9.1 μs | 3.1 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.02x | -| two_scale | sorted_geometric | 16 | 1024 | 8.0 μs | 14.1 μs | 10.7 μs | 35.9 μs | 12.2 μs | 8.0 μs | 10.3 μs | Linear (8.0 μs) | 1.00x | -| two_scale | sorted_geometric | 16 | 4096 | 31.1 μs | 55.4 μs | 42.3 μs | 140.4 μs | 48.0 μs | 31.1 μs | 39.9 μs | Linear (31.1 μs) | 1.00x | -| two_scale | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| two_scale | sorted_geometric | 64 | 4 | 170 ns | 140 ns | 130 ns | 180 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | -| two_scale | sorted_geometric | 64 | 16 | 260 ns | 340 ns | 270 ns | 720 ns | 310 ns | 280 ns | 260 ns | Linear (260 ns) | 1.08x | -| two_scale | sorted_geometric | 64 | 64 | 660 ns | 1.0 μs | 800 ns | 3.0 μs | 1.2 μs | 670 ns | 1.1 μs | Linear (660 ns) | 1.02x | -| two_scale | sorted_geometric | 64 | 256 | 2.3 μs | 3.8 μs | 2.9 μs | 11.7 μs | 4.8 μs | 2.3 μs | 4.2 μs | Linear (2.3 μs) | 1.02x | -| two_scale | sorted_geometric | 64 | 1024 | 8.2 μs | 14.6 μs | 11.1 μs | 46.8 μs | 17.6 μs | 8.2 μs | 15.3 μs | Linear (8.2 μs) | 1.00x | -| two_scale | sorted_geometric | 64 | 4096 | 32.1 μs | 56.5 μs | 43.1 μs | 183.2 μs | 73.8 μs | 45.2 μs | 63.8 μs | Linear (32.1 μs) | 1.41x | -| two_scale | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 70 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_geometric | 256 | 4 | 530 ns | 170 ns | 160 ns | 210 ns | 130 ns | 180 ns | 110 ns | Binary (130 ns) | 1.38x | -| two_scale | sorted_geometric | 256 | 16 | 540 ns | 420 ns | 350 ns | 860 ns | 380 ns | 360 ns | 340 ns | ExpFromLeft (350 ns) | 1.03x | -| two_scale | sorted_geometric | 256 | 64 | 920 ns | 1.2 μs | 920 ns | 3.6 μs | 1.5 μs | 930 ns | 1.3 μs | ExpFromLeft (920 ns) | 1.01x | -| two_scale | sorted_geometric | 256 | 256 | 2.5 μs | 4.1 μs | 3.1 μs | 14.4 μs | 6.1 μs | 3.4 μs | 5.7 μs | Linear (2.5 μs) | 1.32x | -| two_scale | sorted_geometric | 256 | 1024 | 8.8 μs | 15.3 μs | 11.4 μs | 58.9 μs | 23.8 μs | 8.8 μs | 21.6 μs | Linear (8.8 μs) | 1.00x | -| two_scale | sorted_geometric | 256 | 4096 | 33.8 μs | 58.7 μs | 44.9 μs | 229.9 μs | 90.3 μs | 33.7 μs | 82.3 μs | Linear (33.8 μs) | 1.00x | -| two_scale | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_geometric | 1024 | 4 | 1.6 μs | 210 ns | 170 ns | 230 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| two_scale | sorted_geometric | 1024 | 16 | 1.8 μs | 520 ns | 400 ns | 990 ns | 460 ns | 440 ns | 390 ns | ExpFromLeft (400 ns) | 1.10x | -| two_scale | sorted_geometric | 1024 | 64 | 2.3 μs | 1.5 μs | 1.1 μs | 4.0 μs | 1.8 μs | 1.2 μs | 1.6 μs | ExpFromLeft (1.1 μs) | 1.05x | -| two_scale | sorted_geometric | 1024 | 256 | 3.6 μs | 4.9 μs | 3.6 μs | 16.6 μs | 7.5 μs | 3.7 μs | 6.9 μs | Linear (3.6 μs) | 1.01x | -| two_scale | sorted_geometric | 1024 | 1024 | 10.0 μs | 16.6 μs | 12.3 μs | 71.4 μs | 32.7 μs | 10.3 μs | 30.1 μs | Linear (10.0 μs) | 1.03x | -| two_scale | sorted_geometric | 1024 | 4096 | 48.3 μs | 62.4 μs | 46.4 μs | 292.4 μs | 144.9 μs | 36.3 μs | 140.7 μs | ExpFromLeft (46.4 μs) | 0.78x | -| two_scale | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| two_scale | sorted_geometric | 4096 | 4 | 6.0 μs | 230 ns | 190 ns | 240 ns | 160 ns | 240 ns | 150 ns | Binary (160 ns) | 1.50x | -| two_scale | sorted_geometric | 4096 | 16 | 6.3 μs | 660 ns | 490 ns | 1.1 μs | 520 ns | 520 ns | 490 ns | ExpFromLeft (490 ns) | 1.06x | -| two_scale | sorted_geometric | 4096 | 64 | 7.1 μs | 2.0 μs | 1.5 μs | 4.7 μs | 2.1 μs | 1.5 μs | 2.1 μs | ExpFromLeft (1.5 μs) | 1.04x | -| two_scale | sorted_geometric | 4096 | 256 | 9.3 μs | 6.2 μs | 4.5 μs | 19.3 μs | 9.7 μs | 4.7 μs | 9.3 μs | ExpFromLeft (4.5 μs) | 1.02x | -| two_scale | sorted_geometric | 4096 | 1024 | 16.1 μs | 20.6 μs | 15.6 μs | 92.4 μs | 54.0 μs | 15.7 μs | 46.7 μs | ExpFromLeft (15.6 μs) | 1.00x | -| two_scale | sorted_geometric | 4096 | 4096 | 47.1 μs | 74.6 μs | 55.4 μs | 395.4 μs | 228.1 μs | 46.0 μs | 219.4 μs | Linear (47.1 μs) | 0.98x | -| two_scale | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| two_scale | sorted_geometric | 16384 | 4 | 23.4 μs | 260 ns | 230 ns | 270 ns | 180 ns | 260 ns | 170 ns | Binary (180 ns) | 1.44x | -| two_scale | sorted_geometric | 16384 | 16 | 23.8 μs | 790 ns | 620 ns | 1.3 μs | 600 ns | 640 ns | 560 ns | Binary (600 ns) | 1.07x | -| two_scale | sorted_geometric | 16384 | 64 | 24.9 μs | 2.6 μs | 1.9 μs | 5.3 μs | 2.8 μs | 2.0 μs | 2.6 μs | ExpFromLeft (1.9 μs) | 1.03x | -| two_scale | sorted_geometric | 16384 | 256 | 28.1 μs | 7.9 μs | 5.8 μs | 22.7 μs | 15.6 μs | 5.9 μs | 14.9 μs | ExpFromLeft (5.8 μs) | 1.01x | -| two_scale | sorted_geometric | 16384 | 1024 | 38.3 μs | 27.4 μs | 20.3 μs | 118.9 μs | 86.0 μs | 21.1 μs | 81.6 μs | ExpFromLeft (20.3 μs) | 1.04x | -| two_scale | sorted_geometric | 16384 | 4096 | 80.6 μs | 107.1 μs | 81.4 μs | 503.8 μs | 309.8 μs | 78.9 μs | 309.0 μs | Linear (80.6 μs) | 0.98x | -| two_scale | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 69 ns | 80 ns | 80 ns | 70 ns | InterpSearch (69 ns) | 1.16x | -| two_scale | sorted_geometric | 65536 | 4 | 94.2 μs | 300 ns | 240 ns | 280 ns | 200 ns | 270 ns | 180 ns | Binary (200 ns) | 1.35x | -| two_scale | sorted_geometric | 65536 | 16 | 95.0 μs | 950 ns | 750 ns | 1.4 μs | 690 ns | 770 ns | 630 ns | Binary (690 ns) | 1.12x | -| two_scale | sorted_geometric | 65536 | 64 | 106.4 μs | 3.2 μs | 2.8 μs | 6.1 μs | 3.4 μs | 2.4 μs | 3.0 μs | ExpFromLeft (2.8 μs) | 0.87x | -| two_scale | sorted_geometric | 65536 | 256 | 96.9 μs | 10.1 μs | 7.8 μs | 27.9 μs | 19.4 μs | 7.7 μs | 17.9 μs | ExpFromLeft (7.8 μs) | 0.98x | -| two_scale | sorted_geometric | 65536 | 1024 | 110.7 μs | 41.0 μs | 30.6 μs | 178.1 μs | 114.7 μs | 30.3 μs | 113.1 μs | ExpFromLeft (30.6 μs) | 0.99x | -| two_scale | sorted_geometric | 65536 | 4096 | 160.6 μs | 170.4 μs | 138.1 μs | 668.6 μs | 401.4 μs | 138.0 μs | 397.9 μs | ExpFromLeft (138.1 μs) | 1.00x | -| two_scale | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| two_scale | sorted_bimodal | 16 | 4 | 90 ns | 110 ns | 100 ns | 170 ns | 90 ns | 100 ns | 80 ns | Binary (90 ns) | 1.11x | -| two_scale | sorted_bimodal | 16 | 16 | 190 ns | 290 ns | 240 ns | 570 ns | 250 ns | 200 ns | 200 ns | Linear (190 ns) | 1.05x | -| two_scale | sorted_bimodal | 16 | 64 | 570 ns | 970 ns | 770 ns | 2.2 μs | 880 ns | 600 ns | 780 ns | Linear (570 ns) | 1.05x | -| two_scale | sorted_bimodal | 16 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 8.2 μs | 3.3 μs | 2.1 μs | 2.8 μs | Linear (2.1 μs) | 1.01x | -| two_scale | sorted_bimodal | 16 | 1024 | 8.0 μs | 14.2 μs | 10.6 μs | 32.2 μs | 12.8 μs | 8.0 μs | 10.9 μs | Linear (8.0 μs) | 1.00x | -| two_scale | sorted_bimodal | 16 | 4096 | 31.3 μs | 56.5 μs | 42.1 μs | 126.5 μs | 49.9 μs | 30.9 μs | 42.5 μs | Linear (31.3 μs) | 0.99x | -| two_scale | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_bimodal | 64 | 4 | 120 ns | 120 ns | 110 ns | 190 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | -| two_scale | sorted_bimodal | 64 | 16 | 220 ns | 300 ns | 230 ns | 649 ns | 310 ns | 240 ns | 280 ns | Linear (220 ns) | 1.09x | -| two_scale | sorted_bimodal | 64 | 64 | 610 ns | 970 ns | 770 ns | 2.6 μs | 1.3 μs | 640 ns | 1.1 μs | Linear (610 ns) | 1.05x | -| two_scale | sorted_bimodal | 64 | 256 | 2.2 μs | 3.5 μs | 2.9 μs | 10.0 μs | 4.6 μs | 2.2 μs | 4.0 μs | Linear (2.2 μs) | 1.01x | -| two_scale | sorted_bimodal | 64 | 1024 | 8.0 μs | 13.5 μs | 10.7 μs | 38.9 μs | 17.6 μs | 8.0 μs | 15.6 μs | Linear (8.0 μs) | 1.00x | -| two_scale | sorted_bimodal | 64 | 4096 | 31.0 μs | 53.3 μs | 42.3 μs | 154.1 μs | 70.1 μs | 31.1 μs | 61.3 μs | Linear (31.0 μs) | 1.00x | -| two_scale | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_bimodal | 256 | 4 | 270 ns | 140 ns | 140 ns | 210 ns | 120 ns | 160 ns | 110 ns | Binary (120 ns) | 1.33x | -| two_scale | sorted_bimodal | 256 | 16 | 370 ns | 350 ns | 270 ns | 720 ns | 450 ns | 280 ns | 420 ns | ExpFromLeft (270 ns) | 1.04x | -| two_scale | sorted_bimodal | 256 | 64 | 870 ns | 1.0 μs | 770 ns | 2.8 μs | 1.7 μs | 870 ns | 1.5 μs | ExpFromLeft (770 ns) | 1.13x | -| two_scale | sorted_bimodal | 256 | 256 | 2.6 μs | 4.0 μs | 3.2 μs | 11.8 μs | 5.9 μs | 2.6 μs | 5.5 μs | Linear (2.6 μs) | 1.00x | -| two_scale | sorted_bimodal | 256 | 1024 | 8.7 μs | 14.3 μs | 11.2 μs | 44.9 μs | 22.3 μs | 8.7 μs | 20.3 μs | Linear (8.7 μs) | 1.00x | -| two_scale | sorted_bimodal | 256 | 4096 | 31.8 μs | 55.4 μs | 42.8 μs | 174.2 μs | 87.0 μs | 31.8 μs | 79.0 μs | Linear (31.8 μs) | 1.00x | -| two_scale | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_bimodal | 1024 | 4 | 850 ns | 190 ns | 160 ns | 240 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | -| two_scale | sorted_bimodal | 1024 | 16 | 870 ns | 420 ns | 350 ns | 900 ns | 490 ns | 360 ns | 450 ns | ExpFromLeft (350 ns) | 1.03x | -| two_scale | sorted_bimodal | 1024 | 64 | 1.6 μs | 1.2 μs | 900 ns | 3.5 μs | 2.0 μs | 940 ns | 1.9 μs | ExpFromLeft (900 ns) | 1.04x | -| two_scale | sorted_bimodal | 1024 | 256 | 2.9 μs | 4.0 μs | 2.9 μs | 14.6 μs | 7.9 μs | 2.9 μs | 7.5 μs | Linear (2.9 μs) | 1.01x | -| two_scale | sorted_bimodal | 1024 | 1024 | 10.6 μs | 15.7 μs | 12.3 μs | 60.1 μs | 28.4 μs | 10.6 μs | 26.3 μs | Linear (10.6 μs) | 1.00x | -| two_scale | sorted_bimodal | 1024 | 4096 | 34.8 μs | 57.6 μs | 44.6 μs | 228.2 μs | 108.0 μs | 34.7 μs | 99.7 μs | Linear (34.8 μs) | 1.00x | -| two_scale | sorted_bimodal | 4096 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 69 ns | 70 ns | 60 ns | Binary (69 ns) | 1.01x | -| two_scale | sorted_bimodal | 4096 | 4 | 3.0 μs | 200 ns | 170 ns | 290 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | -| two_scale | sorted_bimodal | 4096 | 16 | 3.2 μs | 500 ns | 410 ns | 1.1 μs | 580 ns | 430 ns | 550 ns | ExpFromLeft (410 ns) | 1.05x | -| two_scale | sorted_bimodal | 4096 | 64 | 3.9 μs | 1.5 μs | 1.1 μs | 4.2 μs | 2.4 μs | 1.2 μs | 2.4 μs | ExpFromLeft (1.1 μs) | 1.03x | -| two_scale | sorted_bimodal | 4096 | 256 | 7.0 μs | 4.5 μs | 3.1 μs | 17.2 μs | 11.4 μs | 3.3 μs | 10.5 μs | ExpFromLeft (3.1 μs) | 1.04x | -| two_scale | sorted_bimodal | 4096 | 1024 | 13.3 μs | 17.0 μs | 12.7 μs | 74.5 μs | 42.8 μs | 13.2 μs | 37.7 μs | ExpFromLeft (12.7 μs) | 1.04x | -| two_scale | sorted_bimodal | 4096 | 4096 | 43.4 μs | 61.9 μs | 48.6 μs | 298.1 μs | 146.5 μs | 43.2 μs | 130.7 μs | Linear (43.4 μs) | 1.00x | -| two_scale | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 90 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| two_scale | sorted_bimodal | 16384 | 4 | 9.9 μs | 230 ns | 200 ns | 320 ns | 180 ns | 220 ns | 160 ns | Binary (180 ns) | 1.22x | -| two_scale | sorted_bimodal | 16384 | 16 | 11.4 μs | 660 ns | 520 ns | 1.2 μs | 620 ns | 530 ns | 570 ns | ExpFromLeft (520 ns) | 1.02x | -| two_scale | sorted_bimodal | 16384 | 64 | 12.7 μs | 2.0 μs | 1.5 μs | 4.9 μs | 2.9 μs | 1.6 μs | 2.7 μs | ExpFromLeft (1.5 μs) | 1.02x | -| two_scale | sorted_bimodal | 16384 | 256 | 18.3 μs | 5.8 μs | 4.4 μs | 19.8 μs | 15.8 μs | 4.4 μs | 14.7 μs | ExpFromLeft (4.4 μs) | 1.01x | -| two_scale | sorted_bimodal | 16384 | 1024 | 30.6 μs | 19.9 μs | 14.5 μs | 98.0 μs | 74.5 μs | 14.2 μs | 72.8 μs | ExpFromLeft (14.5 μs) | 0.98x | -| two_scale | sorted_bimodal | 16384 | 4096 | 69.1 μs | 75.7 μs | 58.9 μs | 414.5 μs | 227.7 μs | 80.5 μs | 222.6 μs | ExpFromLeft (58.9 μs) | 1.37x | -| two_scale | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_bimodal | 65536 | 4 | 84.0 μs | 300 ns | 230 ns | 350 ns | 200 ns | 260 ns | 180 ns | Binary (200 ns) | 1.30x | -| two_scale | sorted_bimodal | 65536 | 16 | 92.4 μs | 890 ns | 650 ns | 1.4 μs | 760 ns | 680 ns | 710 ns | ExpFromLeft (650 ns) | 1.05x | -| two_scale | sorted_bimodal | 65536 | 64 | 48.3 μs | 2.6 μs | 2.0 μs | 5.5 μs | 2.9 μs | 2.0 μs | 2.8 μs | ExpFromLeft (2.0 μs) | 1.01x | -| two_scale | sorted_bimodal | 65536 | 256 | 92.5 μs | 7.9 μs | 6.1 μs | 24.2 μs | 20.3 μs | 6.1 μs | 19.1 μs | ExpFromLeft (6.1 μs) | 1.00x | -| two_scale | sorted_bimodal | 65536 | 1024 | 101.2 μs | 26.4 μs | 19.9 μs | 140.7 μs | 95.5 μs | 19.5 μs | 95.3 μs | ExpFromLeft (19.9 μs) | 0.98x | -| two_scale | sorted_bimodal | 65536 | 4096 | 172.4 μs | 118.0 μs | 93.2 μs | 559.9 μs | 286.0 μs | 91.9 μs | 285.8 μs | ExpFromLeft (93.2 μs) | 0.99x | -| two_scale | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| two_scale | sorted_repeated | 16 | 4 | 79 ns | 90 ns | 100 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (79 ns) | 1.27x | -| two_scale | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 220 ns | 620 ns | 220 ns | 200 ns | 180 ns | Linear (170 ns) | 1.18x | -| two_scale | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 680 ns | 2.4 μs | 790 ns | 570 ns | 630 ns | Linear (550 ns) | 1.04x | -| two_scale | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 9.3 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.02x | -| two_scale | sorted_repeated | 16 | 1024 | 7.7 μs | 13.7 μs | 10.0 μs | 36.9 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.00x | -| two_scale | sorted_repeated | 16 | 4096 | 30.8 μs | 54.9 μs | 39.3 μs | 147.5 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_repeated | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 90 ns | 230 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| two_scale | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 220 ns | 810 ns | 310 ns | 200 ns | 270 ns | Linear (170 ns) | 1.18x | -| two_scale | sorted_repeated | 64 | 64 | 559 ns | 920 ns | 709 ns | 3.1 μs | 1.1 μs | 580 ns | 920 ns | Linear (559 ns) | 1.04x | -| two_scale | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 12.1 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | -| two_scale | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 48.0 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | -| two_scale | sorted_repeated | 64 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 191.8 μs | 66.5 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 59 ns | 60 ns | 50 ns | Binary (59 ns) | 1.02x | -| two_scale | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 100 ns | 260 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| two_scale | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 950 ns | 390 ns | 190 ns | 340 ns | Linear (170 ns) | 1.12x | -| two_scale | sorted_repeated | 256 | 64 | 550 ns | 920 ns | 700 ns | 3.7 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | -| two_scale | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 14.4 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| two_scale | sorted_repeated | 256 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 57.9 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | -| two_scale | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 231.4 μs | 86.1 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 290 ns | 150 ns | 110 ns | 120 ns | Linear (90 ns) | 1.22x | -| two_scale | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 220 ns | 1.1 μs | 450 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | -| two_scale | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 4.1 μs | 1.7 μs | 580 ns | 1.5 μs | Linear (560 ns) | 1.04x | -| two_scale | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 16.3 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| two_scale | sorted_repeated | 1024 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 64.8 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | -| two_scale | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.1 μs | 39.3 μs | 259.6 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 360 ns | 170 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | -| two_scale | sorted_repeated | 4096 | 16 | 180 ns | 300 ns | 220 ns | 1.3 μs | 530 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | -| two_scale | sorted_repeated | 4096 | 64 | 710 ns | 1.1 μs | 690 ns | 5.0 μs | 2.0 μs | 600 ns | 1.8 μs | ExpFromLeft (690 ns) | 0.87x | -| two_scale | sorted_repeated | 4096 | 256 | 2.0 μs | 3.7 μs | 2.5 μs | 19.7 μs | 7.8 μs | 2.1 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| two_scale | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 77.9 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | -| two_scale | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.1 μs | 311.8 μs | 124.4 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | sorted_repeated | 16384 | 4 | 90 ns | 120 ns | 110 ns | 390 ns | 180 ns | 120 ns | 160 ns | Linear (90 ns) | 1.33x | -| two_scale | sorted_repeated | 16384 | 16 | 190 ns | 290 ns | 230 ns | 1.4 μs | 610 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | -| two_scale | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 710 ns | 5.4 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | -| two_scale | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 21.6 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | -| two_scale | sorted_repeated | 16384 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 86.1 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.7 μs) | 1.01x | -| two_scale | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.1 μs | 39.6 μs | 344.5 μs | 144.0 μs | 30.8 μs | 133.7 μs | Linear (30.8 μs) | 1.00x | -| two_scale | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 430 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| two_scale | sorted_repeated | 65536 | 16 | 190 ns | 300 ns | 230 ns | 1.6 μs | 690 ns | 210 ns | 630 ns | Linear (190 ns) | 1.11x | -| two_scale | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 710 ns | 6.1 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| two_scale | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 24.2 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.02x | -| two_scale | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 96.8 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.01x | -| two_scale | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 384.6 μs | 163.2 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| two_scale | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| two_scale | unsorted | 16 | 4 | 100 ns | 100 ns | 100 ns | 100 ns | 90 ns | 100 ns | 80 ns | Binary (90 ns) | 1.11x | -| two_scale | unsorted | 16 | 16 | 210 ns | 200 ns | 210 ns | 210 ns | 210 ns | 220 ns | 190 ns | Gallop (200 ns) | 1.10x | -| two_scale | unsorted | 16 | 64 | 710 ns | 720 ns | 700 ns | 700 ns | 710 ns | 710 ns | 750 ns | InterpSearch (700 ns) | 1.01x | -| two_scale | unsorted | 16 | 256 | 3.5 μs | 3.5 μs | 3.5 μs | 3.4 μs | 3.3 μs | 3.4 μs | 3.4 μs | Binary (3.3 μs) | 1.02x | -| two_scale | unsorted | 16 | 1024 | 18.4 μs | 18.1 μs | 18.2 μs | 18.2 μs | 18.1 μs | 18.1 μs | 18.4 μs | Binary (18.1 μs) | 1.00x | -| two_scale | unsorted | 16 | 4096 | 98.5 μs | 97.8 μs | 102.3 μs | 99.2 μs | 97.9 μs | 98.4 μs | 98.7 μs | Gallop (97.8 μs) | 1.01x | -| two_scale | unsorted | 64 | 1 | 60 ns | 50 ns | 50 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| two_scale | unsorted | 64 | 4 | 100 ns | 110 ns | 100 ns | 110 ns | 100 ns | 110 ns | 90 ns | ExpFromLeft (100 ns) | 1.10x | -| two_scale | unsorted | 64 | 16 | 280 ns | 280 ns | 280 ns | 280 ns | 270 ns | 280 ns | 260 ns | Binary (270 ns) | 1.04x | -| two_scale | unsorted | 64 | 64 | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | ExpFromLeft (1.2 μs) | 1.02x | -| two_scale | unsorted | 64 | 256 | 6.7 μs | 6.6 μs | 6.7 μs | 6.6 μs | 6.6 μs | 6.7 μs | 6.7 μs | InterpSearch (6.6 μs) | 1.01x | -| two_scale | unsorted | 64 | 1024 | 36.1 μs | 36.1 μs | 35.4 μs | 35.4 μs | 35.4 μs | 36.0 μs | 35.0 μs | Binary (35.4 μs) | 1.02x | -| two_scale | unsorted | 64 | 4096 | 166.2 μs | 165.8 μs | 165.0 μs | 165.2 μs | 164.9 μs | 165.2 μs | 169.8 μs | Binary (164.9 μs) | 1.00x | -| two_scale | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | unsorted | 256 | 4 | 130 ns | 130 ns | 130 ns | 130 ns | 120 ns | 130 ns | 110 ns | Binary (120 ns) | 1.08x | -| two_scale | unsorted | 256 | 16 | 350 ns | 350 ns | 350 ns | 350 ns | 360 ns | 350 ns | 340 ns | InterpSearch (350 ns) | 1.00x | -| two_scale | unsorted | 256 | 64 | 1.7 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | InterpSearch (1.6 μs) | 1.00x | -| two_scale | unsorted | 256 | 256 | 8.9 μs | 9.0 μs | 9.1 μs | 9.1 μs | 8.8 μs | 9.0 μs | 8.9 μs | Binary (8.8 μs) | 1.01x | -| two_scale | unsorted | 256 | 1024 | 51.8 μs | 50.6 μs | 49.8 μs | 50.7 μs | 49.6 μs | 50.1 μs | 52.3 μs | Binary (49.6 μs) | 1.01x | -| two_scale | unsorted | 256 | 4096 | 253.1 μs | 257.7 μs | 251.8 μs | 251.4 μs | 251.2 μs | 252.2 μs | 258.8 μs | Binary (251.2 μs) | 1.00x | -| two_scale | unsorted | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| two_scale | unsorted | 1024 | 4 | 140 ns | 140 ns | 150 ns | 140 ns | 140 ns | 140 ns | 129 ns | InterpSearch (140 ns) | 1.00x | -| two_scale | unsorted | 1024 | 16 | 420 ns | 420 ns | 420 ns | 430 ns | 430 ns | 430 ns | 410 ns | ExpFromLeft (420 ns) | 1.02x | -| two_scale | unsorted | 1024 | 64 | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.8 μs | Binary (1.7 μs) | 1.02x | -| two_scale | unsorted | 1024 | 256 | 9.2 μs | 9.0 μs | 8.9 μs | 8.9 μs | 8.9 μs | 8.7 μs | 9.7 μs | ExpFromLeft (8.9 μs) | 0.98x | -| two_scale | unsorted | 1024 | 1024 | 69.2 μs | 67.5 μs | 67.2 μs | 66.8 μs | 67.1 μs | 67.1 μs | 69.0 μs | InterpSearch (66.8 μs) | 1.00x | -| two_scale | unsorted | 1024 | 4096 | 339.7 μs | 340.6 μs | 337.1 μs | 334.7 μs | 334.2 μs | 334.3 μs | 340.2 μs | Binary (334.2 μs) | 1.00x | -| two_scale | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | unsorted | 4096 | 4 | 150 ns | 150 ns | 150 ns | 150 ns | 160 ns | 170 ns | 140 ns | InterpSearch (150 ns) | 1.13x | -| two_scale | unsorted | 4096 | 16 | 490 ns | 490 ns | 490 ns | 490 ns | 490 ns | 500 ns | 480 ns | InterpSearch (490 ns) | 1.02x | -| two_scale | unsorted | 4096 | 64 | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | InterpSearch (2.0 μs) | 1.02x | -| two_scale | unsorted | 4096 | 256 | 10.5 μs | 10.2 μs | 10.3 μs | 10.1 μs | 10.0 μs | 10.0 μs | 10.6 μs | Binary (10.0 μs) | 1.00x | -| two_scale | unsorted | 4096 | 1024 | 90.7 μs | 89.3 μs | 88.8 μs | 88.7 μs | 86.7 μs | 87.8 μs | 91.5 μs | Binary (86.7 μs) | 1.01x | -| two_scale | unsorted | 4096 | 4096 | 439.6 μs | 440.4 μs | 435.2 μs | 440.3 μs | 434.5 μs | 434.6 μs | 434.1 μs | Binary (434.5 μs) | 1.00x | -| two_scale | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| two_scale | unsorted | 16384 | 4 | 180 ns | 170 ns | 180 ns | 180 ns | 180 ns | 180 ns | 160 ns | Gallop (170 ns) | 1.06x | -| two_scale | unsorted | 16384 | 16 | 630 ns | 640 ns | 640 ns | 640 ns | 620 ns | 620 ns | 630 ns | Binary (620 ns) | 1.00x | -| two_scale | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | ExpFromLeft (2.3 μs) | 1.01x | -| two_scale | unsorted | 16384 | 256 | 12.8 μs | 12.7 μs | 12.5 μs | 12.5 μs | 12.3 μs | 12.3 μs | 15.4 μs | Binary (12.3 μs) | 1.00x | -| two_scale | unsorted | 16384 | 1024 | 130.2 μs | 126.6 μs | 124.5 μs | 123.5 μs | 120.2 μs | 119.7 μs | 126.9 μs | Binary (120.2 μs) | 1.00x | -| two_scale | unsorted | 16384 | 4096 | 600.4 μs | 601.6 μs | 601.6 μs | 601.8 μs | 601.7 μs | 600.6 μs | 601.6 μs | Linear (600.4 μs) | 1.00x | -| two_scale | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| two_scale | unsorted | 65536 | 4 | 190 ns | 200 ns | 190 ns | 190 ns | 200 ns | 200 ns | 190 ns | InterpSearch (190 ns) | 1.05x | -| two_scale | unsorted | 65536 | 16 | 650 ns | 640 ns | 650 ns | 660 ns | 649 ns | 670 ns | 650 ns | Gallop (640 ns) | 1.05x | -| two_scale | unsorted | 65536 | 64 | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | ExpFromLeft (2.7 μs) | 1.01x | -| two_scale | unsorted | 65536 | 256 | 14.8 μs | 14.7 μs | 14.7 μs | 14.6 μs | 14.3 μs | 14.3 μs | 17.7 μs | Binary (14.3 μs) | 1.00x | -| two_scale | unsorted | 65536 | 1024 | 170.1 μs | 166.2 μs | 163.4 μs | 165.5 μs | 164.8 μs | 163.4 μs | 168.5 μs | ExpFromLeft (163.4 μs) | 1.00x | -| two_scale | unsorted | 65536 | 4096 | 753.3 μs | 752.6 μs | 755.3 μs | 755.4 μs | 754.4 μs | 753.0 μs | 751.9 μs | Gallop (752.6 μs) | 1.00x | -| power2 | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| power2 | sorted_uniform | 16 | 4 | 90 ns | 100 ns | 100 ns | 170 ns | 90 ns | 100 ns | 70 ns | Binary (90 ns) | 1.11x | -| power2 | sorted_uniform | 16 | 16 | 190 ns | 290 ns | 210 ns | 520 ns | 240 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| power2 | sorted_uniform | 16 | 64 | 590 ns | 1.0 μs | 750 ns | 2.1 μs | 960 ns | 620 ns | 810 ns | Linear (590 ns) | 1.05x | -| power2 | sorted_uniform | 16 | 256 | 2.2 μs | 3.8 μs | 2.9 μs | 8.4 μs | 3.3 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.00x | -| power2 | sorted_uniform | 16 | 1024 | 8.1 μs | 14.7 μs | 10.8 μs | 31.7 μs | 12.6 μs | 8.0 μs | 10.5 μs | Linear (8.1 μs) | 0.99x | -| power2 | sorted_uniform | 16 | 4096 | 31.0 μs | 54.5 μs | 42.3 μs | 121.9 μs | 48.7 μs | 31.1 μs | 41.2 μs | Linear (31.0 μs) | 1.00x | -| power2 | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 60 ns | 90 ns | 70 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| power2 | sorted_uniform | 64 | 4 | 140 ns | 140 ns | 140 ns | 190 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | -| power2 | sorted_uniform | 64 | 16 | 250 ns | 340 ns | 270 ns | 640 ns | 340 ns | 280 ns | 310 ns | Linear (250 ns) | 1.12x | -| power2 | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 750 ns | 2.5 μs | 1.5 μs | 670 ns | 1.4 μs | Linear (630 ns) | 1.06x | -| power2 | sorted_uniform | 64 | 256 | 2.3 μs | 4.1 μs | 3.1 μs | 10.6 μs | 5.2 μs | 2.3 μs | 4.5 μs | Linear (2.3 μs) | 1.02x | -| power2 | sorted_uniform | 64 | 1024 | 8.9 μs | 14.8 μs | 11.6 μs | 41.4 μs | 17.7 μs | 8.9 μs | 15.9 μs | Linear (8.9 μs) | 1.00x | -| power2 | sorted_uniform | 64 | 4096 | 32.1 μs | 55.6 μs | 43.1 μs | 158.4 μs | 67.6 μs | 32.1 μs | 60.2 μs | Linear (32.1 μs) | 1.00x | -| power2 | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_uniform | 256 | 4 | 330 ns | 150 ns | 140 ns | 220 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | -| power2 | sorted_uniform | 256 | 16 | 440 ns | 430 ns | 360 ns | 830 ns | 420 ns | 389 ns | 370 ns | ExpFromLeft (360 ns) | 1.08x | -| power2 | sorted_uniform | 256 | 64 | 880 ns | 1.3 μs | 930 ns | 3.1 μs | 1.6 μs | 910 ns | 1.4 μs | Linear (880 ns) | 1.03x | -| power2 | sorted_uniform | 256 | 256 | 2.4 μs | 4.1 μs | 2.8 μs | 13.4 μs | 7.6 μs | 3.2 μs | 6.8 μs | Linear (2.4 μs) | 1.35x | -| power2 | sorted_uniform | 256 | 1024 | 9.9 μs | 16.9 μs | 13.2 μs | 53.8 μs | 25.8 μs | 9.9 μs | 23.7 μs | Linear (9.9 μs) | 1.01x | -| power2 | sorted_uniform | 256 | 4096 | 35.5 μs | 59.0 μs | 46.1 μs | 203.2 μs | 90.3 μs | 35.4 μs | 83.7 μs | Linear (35.5 μs) | 1.00x | -| power2 | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| power2 | sorted_uniform | 1024 | 4 | 740 ns | 190 ns | 160 ns | 280 ns | 140 ns | 190 ns | 120 ns | Binary (140 ns) | 1.36x | -| power2 | sorted_uniform | 1024 | 16 | 1.6 μs | 590 ns | 470 ns | 960 ns | 450 ns | 490 ns | 410 ns | Binary (450 ns) | 1.09x | -| power2 | sorted_uniform | 1024 | 64 | 1.8 μs | 1.6 μs | 1.3 μs | 3.7 μs | 1.8 μs | 1.3 μs | 1.6 μs | ExpFromLeft (1.3 μs) | 1.03x | -| power2 | sorted_uniform | 1024 | 256 | 3.5 μs | 5.1 μs | 3.7 μs | 15.5 μs | 8.3 μs | 3.5 μs | 8.1 μs | Linear (3.5 μs) | 1.01x | -| power2 | sorted_uniform | 1024 | 1024 | 13.7 μs | 21.8 μs | 15.9 μs | 69.4 μs | 49.9 μs | 13.7 μs | 48.7 μs | Linear (13.7 μs) | 1.00x | -| power2 | sorted_uniform | 1024 | 4096 | 45.4 μs | 69.1 μs | 54.3 μs | 271.3 μs | 181.6 μs | 45.2 μs | 175.7 μs | Linear (45.4 μs) | 1.00x | -| power2 | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_uniform | 4096 | 4 | 3.0 μs | 220 ns | 180 ns | 310 ns | 160 ns | 210 ns | 150 ns | Binary (160 ns) | 1.31x | -| power2 | sorted_uniform | 4096 | 16 | 5.7 μs | 700 ns | 550 ns | 1.1 μs | 560 ns | 570 ns | 520 ns | ExpFromLeft (550 ns) | 1.04x | -| power2 | sorted_uniform | 4096 | 64 | 6.6 μs | 2.1 μs | 1.6 μs | 4.3 μs | 2.1 μs | 1.7 μs | 1.9 μs | ExpFromLeft (1.6 μs) | 1.04x | -| power2 | sorted_uniform | 4096 | 256 | 9.1 μs | 6.7 μs | 5.0 μs | 17.7 μs | 11.1 μs | 5.1 μs | 10.9 μs | ExpFromLeft (5.0 μs) | 1.02x | -| power2 | sorted_uniform | 4096 | 1024 | 16.9 μs | 22.9 μs | 17.0 μs | 85.0 μs | 88.9 μs | 15.7 μs | 83.4 μs | Linear (16.9 μs) | 0.93x | -| power2 | sorted_uniform | 4096 | 4096 | 64.1 μs | 90.8 μs | 67.7 μs | 371.6 μs | 286.4 μs | 62.8 μs | 281.8 μs | Linear (64.1 μs) | 0.98x | -| power2 | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_uniform | 16384 | 4 | 5.2 μs | 240 ns | 200 ns | 350 ns | 180 ns | 220 ns | 170 ns | Binary (180 ns) | 1.22x | -| power2 | sorted_uniform | 16384 | 16 | 17.5 μs | 840 ns | 660 ns | 1.3 μs | 590 ns | 670 ns | 560 ns | Binary (590 ns) | 1.14x | -| power2 | sorted_uniform | 16384 | 64 | 23.6 μs | 2.9 μs | 2.1 μs | 5.0 μs | 2.5 μs | 2.2 μs | 2.3 μs | ExpFromLeft (2.1 μs) | 1.03x | -| power2 | sorted_uniform | 16384 | 256 | 28.6 μs | 9.3 μs | 7.0 μs | 21.3 μs | 14.0 μs | 7.1 μs | 13.6 μs | ExpFromLeft (7.0 μs) | 1.01x | -| power2 | sorted_uniform | 16384 | 1024 | 38.9 μs | 33.4 μs | 25.2 μs | 114.6 μs | 118.7 μs | 24.2 μs | 117.4 μs | ExpFromLeft (25.2 μs) | 0.96x | -| power2 | sorted_uniform | 16384 | 4096 | 112.7 μs | 155.6 μs | 117.1 μs | 487.5 μs | 386.5 μs | 111.9 μs | 380.3 μs | Linear (112.7 μs) | 0.99x | -| power2 | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| power2 | sorted_uniform | 65536 | 4 | 20.3 μs | 280 ns | 220 ns | 390 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | -| power2 | sorted_uniform | 65536 | 16 | 72.2 μs | 1.0 μs | 749 ns | 1.4 μs | 690 ns | 770 ns | 650 ns | Binary (690 ns) | 1.12x | -| power2 | sorted_uniform | 65536 | 64 | 89.0 μs | 3.6 μs | 2.5 μs | 5.9 μs | 2.8 μs | 2.6 μs | 2.7 μs | ExpFromLeft (2.5 μs) | 1.02x | -| power2 | sorted_uniform | 65536 | 256 | 93.4 μs | 12.2 μs | 8.9 μs | 26.0 μs | 17.3 μs | 9.2 μs | 15.6 μs | ExpFromLeft (8.9 μs) | 1.03x | -| power2 | sorted_uniform | 65536 | 1024 | 113.6 μs | 56.3 μs | 40.1 μs | 147.9 μs | 148.4 μs | 36.5 μs | 154.4 μs | ExpFromLeft (40.1 μs) | 0.91x | -| power2 | sorted_uniform | 65536 | 4096 | 196.7 μs | 242.6 μs | 190.2 μs | 597.2 μs | 473.5 μs | 189.8 μs | 478.7 μs | ExpFromLeft (190.2 μs) | 1.00x | -| power2 | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| power2 | sorted_dense_burst | 16 | 4 | 80 ns | 110 ns | 90 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| power2 | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 220 ns | 560 ns | 230 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | -| power2 | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 730 ns | 2.1 μs | 790 ns | 580 ns | 650 ns | Linear (550 ns) | 1.05x | -| power2 | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.2 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.02x | -| power2 | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 32.5 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.01x | -| power2 | sorted_dense_burst | 16 | 4096 | 30.8 μs | 55.0 μs | 41.9 μs | 129.9 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| power2 | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 90 ns | 200 ns | 110 ns | 100 ns | 90 ns | Linear (80 ns) | 1.25x | -| power2 | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 230 ns | 720 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | -| power2 | sorted_dense_burst | 64 | 64 | 550 ns | 920 ns | 740 ns | 2.8 μs | 1.1 μs | 610 ns | 940 ns | Linear (550 ns) | 1.11x | -| power2 | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 10.9 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | -| power2 | sorted_dense_burst | 64 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 43.5 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.8 μs) | 1.00x | -| power2 | sorted_dense_burst | 64 | 4096 | 30.8 μs | 54.7 μs | 42.0 μs | 173.4 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 100 ns | 260 ns | 130 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| power2 | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 910 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| power2 | sorted_dense_burst | 256 | 64 | 560 ns | 940 ns | 730 ns | 3.5 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (560 ns) | 1.04x | -| power2 | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 13.7 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| power2 | sorted_dense_burst | 256 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 54.6 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.00x | -| power2 | sorted_dense_burst | 256 | 4096 | 30.8 μs | 54.8 μs | 42.1 μs | 217.8 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_dense_burst | 1024 | 4 | 90 ns | 110 ns | 100 ns | 280 ns | 139 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | -| power2 | sorted_dense_burst | 1024 | 16 | 190 ns | 280 ns | 240 ns | 1.0 μs | 460 ns | 210 ns | 419 ns | Linear (190 ns) | 1.11x | -| power2 | sorted_dense_burst | 1024 | 64 | 560 ns | 930 ns | 730 ns | 4.0 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| power2 | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 15.9 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| power2 | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 63.6 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.01x | -| power2 | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 253.8 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (70 ns) | 0.86x | -| power2 | sorted_dense_burst | 4096 | 4 | 100 ns | 110 ns | 100 ns | 320 ns | 160 ns | 120 ns | 150 ns | ExpFromLeft (100 ns) | 1.20x | -| power2 | sorted_dense_burst | 4096 | 16 | 180 ns | 290 ns | 250 ns | 1.2 μs | 540 ns | 210 ns | 480 ns | Linear (180 ns) | 1.17x | -| power2 | sorted_dense_burst | 4096 | 64 | 560 ns | 939 ns | 750 ns | 4.7 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | -| power2 | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 18.4 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | -| power2 | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 73.3 μs | 31.1 μs | 7.8 μs | 28.5 μs | Linear (7.7 μs) | 1.01x | -| power2 | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 292.8 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_dense_burst | 16384 | 4 | 90 ns | 110 ns | 110 ns | 370 ns | 179 ns | 130 ns | 160 ns | Linear (90 ns) | 1.44x | -| power2 | sorted_dense_burst | 16384 | 16 | 180 ns | 290 ns | 240 ns | 1.4 μs | 600 ns | 210 ns | 560 ns | Linear (180 ns) | 1.17x | -| power2 | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 740 ns | 5.3 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | -| power2 | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 21.2 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | -| power2 | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 14.1 μs | 10.6 μs | 84.0 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.01x | -| power2 | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.0 μs | 42.1 μs | 335.7 μs | 144.1 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| power2 | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 440 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| power2 | sorted_dense_burst | 65536 | 16 | 190 ns | 290 ns | 250 ns | 1.6 μs | 680 ns | 220 ns | 630 ns | Linear (190 ns) | 1.16x | -| power2 | sorted_dense_burst | 65536 | 64 | 570 ns | 950 ns | 750 ns | 6.2 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| power2 | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 24.9 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | -| power2 | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 99.3 μs | 40.8 μs | 7.8 μs | 38.2 μs | Linear (7.8 μs) | 1.00x | -| power2 | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 397.0 μs | 163.0 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| power2 | sorted_near_start | 16 | 4 | 90 ns | 120 ns | 100 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| power2 | sorted_near_start | 16 | 16 | 190 ns | 300 ns | 220 ns | 470 ns | 230 ns | 200 ns | 200 ns | Linear (190 ns) | 1.05x | -| power2 | sorted_near_start | 16 | 64 | 780 ns | 1.2 μs | 740 ns | 1.7 μs | 790 ns | 600 ns | 680 ns | ExpFromLeft (740 ns) | 0.81x | -| power2 | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 3.0 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | -| power2 | sorted_near_start | 16 | 1024 | 7.9 μs | 13.9 μs | 10.7 μs | 26.6 μs | 12.1 μs | 7.9 μs | 10.3 μs | Linear (7.9 μs) | 1.00x | -| power2 | sorted_near_start | 16 | 4096 | 31.0 μs | 55.1 μs | 42.0 μs | 105.7 μs | 47.8 μs | 31.1 μs | 40.4 μs | Linear (31.0 μs) | 1.00x | -| power2 | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| power2 | sorted_near_start | 64 | 4 | 170 ns | 130 ns | 110 ns | 160 ns | 110 ns | 130 ns | 100 ns | ExpFromLeft (110 ns) | 1.18x | -| power2 | sorted_near_start | 64 | 16 | 240 ns | 300 ns | 250 ns | 520 ns | 320 ns | 260 ns | 290 ns | Linear (240 ns) | 1.08x | -| power2 | sorted_near_start | 64 | 64 | 880 ns | 1.3 μs | 1.0 μs | 2.0 μs | 1.1 μs | 730 ns | 990 ns | Linear (880 ns) | 0.83x | -| power2 | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.4 μs | 4.3 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | -| power2 | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 29.3 μs | 17.2 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.00x | -| power2 | sorted_near_start | 64 | 4096 | 31.6 μs | 55.7 μs | 42.7 μs | 118.2 μs | 66.8 μs | 31.7 μs | 59.7 μs | Linear (31.6 μs) | 1.00x | -| power2 | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_near_start | 256 | 4 | 320 ns | 140 ns | 120 ns | 200 ns | 120 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | -| power2 | sorted_near_start | 256 | 16 | 530 ns | 340 ns | 250 ns | 650 ns | 400 ns | 280 ns | 350 ns | ExpFromLeft (250 ns) | 1.12x | -| power2 | sorted_near_start | 256 | 64 | 870 ns | 1.1 μs | 870 ns | 2.6 μs | 1.5 μs | 900 ns | 1.4 μs | ExpFromLeft (870 ns) | 1.03x | -| power2 | sorted_near_start | 256 | 256 | 2.5 μs | 4.0 μs | 3.0 μs | 9.9 μs | 5.6 μs | 2.6 μs | 5.2 μs | Linear (2.5 μs) | 1.01x | -| power2 | sorted_near_start | 256 | 1024 | 8.3 μs | 14.5 μs | 11.1 μs | 39.6 μs | 22.2 μs | 8.4 μs | 20.3 μs | Linear (8.3 μs) | 1.00x | -| power2 | sorted_near_start | 256 | 4096 | 31.7 μs | 56.3 μs | 42.5 μs | 156.5 μs | 88.8 μs | 31.6 μs | 81.1 μs | Linear (31.7 μs) | 1.00x | -| power2 | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| power2 | sorted_near_start | 1024 | 4 | 1.1 μs | 170 ns | 160 ns | 250 ns | 140 ns | 180 ns | 130 ns | Binary (140 ns) | 1.29x | -| power2 | sorted_near_start | 1024 | 16 | 1.3 μs | 410 ns | 320 ns | 800 ns | 490 ns | 340 ns | 460 ns | ExpFromLeft (320 ns) | 1.06x | -| power2 | sorted_near_start | 1024 | 64 | 1.9 μs | 1.2 μs | 870 ns | 3.1 μs | 2.0 μs | 930 ns | 1.8 μs | ExpFromLeft (870 ns) | 1.07x | -| power2 | sorted_near_start | 1024 | 256 | 3.8 μs | 4.4 μs | 3.5 μs | 13.0 μs | 7.2 μs | 3.8 μs | 6.8 μs | ExpFromLeft (3.5 μs) | 1.11x | -| power2 | sorted_near_start | 1024 | 1024 | 10.1 μs | 15.6 μs | 12.1 μs | 50.2 μs | 27.3 μs | 10.1 μs | 25.7 μs | Linear (10.1 μs) | 1.00x | -| power2 | sorted_near_start | 1024 | 4096 | 34.0 μs | 58.0 μs | 44.2 μs | 200.7 μs | 109.7 μs | 34.1 μs | 103.9 μs | Linear (34.0 μs) | 1.00x | -| power2 | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 90 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_near_start | 4096 | 4 | 5.3 μs | 200 ns | 180 ns | 260 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | -| power2 | sorted_near_start | 4096 | 16 | 5.2 μs | 470 ns | 380 ns | 980 ns | 520 ns | 400 ns | 490 ns | ExpFromLeft (380 ns) | 1.05x | -| power2 | sorted_near_start | 4096 | 64 | 5.9 μs | 1.5 μs | 1.1 μs | 3.8 μs | 2.4 μs | 1.1 μs | 2.3 μs | ExpFromLeft (1.1 μs) | 1.05x | -| power2 | sorted_near_start | 4096 | 256 | 7.6 μs | 4.8 μs | 3.3 μs | 16.0 μs | 11.3 μs | 3.4 μs | 10.3 μs | ExpFromLeft (3.3 μs) | 1.02x | -| power2 | sorted_near_start | 4096 | 1024 | 19.3 μs | 22.3 μs | 17.2 μs | 66.3 μs | 40.0 μs | 16.0 μs | 36.6 μs | ExpFromLeft (17.2 μs) | 0.93x | -| power2 | sorted_near_start | 4096 | 4096 | 41.1 μs | 63.0 μs | 48.5 μs | 254.2 μs | 155.9 μs | 41.1 μs | 141.4 μs | Linear (41.1 μs) | 1.00x | -| power2 | sorted_near_start | 16384 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (80 ns) | 0.88x | -| power2 | sorted_near_start | 16384 | 4 | 9.2 μs | 230 ns | 180 ns | 320 ns | 180 ns | 210 ns | 170 ns | ExpFromLeft (180 ns) | 1.17x | -| power2 | sorted_near_start | 16384 | 16 | 20.1 μs | 650 ns | 490 ns | 1.1 μs | 610 ns | 520 ns | 560 ns | ExpFromLeft (490 ns) | 1.06x | -| power2 | sorted_near_start | 16384 | 64 | 23.0 μs | 1.9 μs | 1.4 μs | 4.4 μs | 3.0 μs | 1.4 μs | 2.8 μs | ExpFromLeft (1.4 μs) | 1.04x | -| power2 | sorted_near_start | 16384 | 256 | 24.2 μs | 5.9 μs | 4.3 μs | 18.2 μs | 18.4 μs | 4.2 μs | 17.7 μs | ExpFromLeft (4.3 μs) | 0.99x | -| power2 | sorted_near_start | 16384 | 1024 | 33.4 μs | 20.5 μs | 14.3 μs | 84.8 μs | 75.6 μs | 14.7 μs | 69.9 μs | ExpFromLeft (14.3 μs) | 1.03x | -| power2 | sorted_near_start | 16384 | 4096 | 69.7 μs | 75.5 μs | 59.6 μs | 351.9 μs | 246.6 μs | 69.3 μs | 231.4 μs | ExpFromLeft (59.6 μs) | 1.16x | -| power2 | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| power2 | sorted_near_start | 65536 | 4 | 73.4 μs | 270 ns | 210 ns | 360 ns | 200 ns | 240 ns | 239 ns | Binary (200 ns) | 1.20x | -| power2 | sorted_near_start | 65536 | 16 | 80.8 μs | 760 ns | 730 ns | 1.6 μs | 730 ns | 610 ns | 690 ns | ExpFromLeft (730 ns) | 0.84x | -| power2 | sorted_near_start | 65536 | 64 | 96.5 μs | 2.6 μs | 2.3 μs | 5.1 μs | 3.5 μs | 1.9 μs | 3.2 μs | ExpFromLeft (2.3 μs) | 0.84x | -| power2 | sorted_near_start | 65536 | 256 | 84.4 μs | 7.7 μs | 5.8 μs | 21.1 μs | 20.7 μs | 5.8 μs | 19.6 μs | ExpFromLeft (5.8 μs) | 1.01x | -| power2 | sorted_near_start | 65536 | 1024 | 101.6 μs | 26.2 μs | 18.8 μs | 115.8 μs | 92.2 μs | 18.6 μs | 85.6 μs | ExpFromLeft (18.8 μs) | 0.99x | -| power2 | sorted_near_start | 65536 | 4096 | 151.2 μs | 113.9 μs | 90.0 μs | 486.9 μs | 305.3 μs | 87.7 μs | 292.2 μs | ExpFromLeft (90.0 μs) | 0.97x | -| power2 | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| power2 | sorted_arithmetic | 16 | 4 | 100 ns | 120 ns | 110 ns | 160 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | -| power2 | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 210 ns | 510 ns | 240 ns | 210 ns | 200 ns | Linear (190 ns) | 1.11x | -| power2 | sorted_arithmetic | 16 | 64 | 580 ns | 990 ns | 750 ns | 2.0 μs | 950 ns | 610 ns | 790 ns | Linear (580 ns) | 1.05x | -| power2 | sorted_arithmetic | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 8.2 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.2 μs) | 1.01x | -| power2 | sorted_arithmetic | 16 | 1024 | 8.0 μs | 13.9 μs | 10.8 μs | 31.0 μs | 12.4 μs | 8.1 μs | 10.6 μs | Linear (8.0 μs) | 1.01x | -| power2 | sorted_arithmetic | 16 | 4096 | 31.1 μs | 54.5 μs | 42.3 μs | 121.6 μs | 48.0 μs | 31.1 μs | 41.2 μs | Linear (31.1 μs) | 1.00x | -| power2 | sorted_arithmetic | 64 | 1 | 60 ns | 60 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| power2 | sorted_arithmetic | 64 | 4 | 170 ns | 140 ns | 130 ns | 170 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | -| power2 | sorted_arithmetic | 64 | 16 | 290 ns | 390 ns | 300 ns | 620 ns | 310 ns | 280 ns | 270 ns | Linear (290 ns) | 0.97x | -| power2 | sorted_arithmetic | 64 | 64 | 660 ns | 1.1 μs | 760 ns | 2.5 μs | 1.3 μs | 680 ns | 1.2 μs | Linear (660 ns) | 1.03x | -| power2 | sorted_arithmetic | 64 | 256 | 2.4 μs | 4.0 μs | 3.0 μs | 10.6 μs | 5.2 μs | 2.4 μs | 4.6 μs | Linear (2.4 μs) | 1.00x | -| power2 | sorted_arithmetic | 64 | 1024 | 8.9 μs | 14.7 μs | 11.5 μs | 41.6 μs | 17.8 μs | 8.9 μs | 15.7 μs | Linear (8.9 μs) | 1.00x | -| power2 | sorted_arithmetic | 64 | 4096 | 32.1 μs | 55.9 μs | 43.1 μs | 158.7 μs | 67.6 μs | 32.1 μs | 60.0 μs | Linear (32.1 μs) | 1.00x | -| power2 | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_arithmetic | 256 | 4 | 470 ns | 180 ns | 150 ns | 190 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | -| power2 | sorted_arithmetic | 256 | 16 | 550 ns | 500 ns | 400 ns | 750 ns | 380 ns | 410 ns | 330 ns | Binary (380 ns) | 1.08x | -| power2 | sorted_arithmetic | 256 | 64 | 920 ns | 1.4 μs | 960 ns | 3.0 μs | 1.4 μs | 950 ns | 1.3 μs | Linear (920 ns) | 1.03x | -| power2 | sorted_arithmetic | 256 | 256 | 2.6 μs | 4.4 μs | 3.0 μs | 12.8 μs | 7.3 μs | 2.6 μs | 6.7 μs | Linear (2.6 μs) | 1.01x | -| power2 | sorted_arithmetic | 256 | 1024 | 9.8 μs | 16.0 μs | 12.2 μs | 55.8 μs | 25.8 μs | 9.9 μs | 24.9 μs | Linear (9.8 μs) | 1.01x | -| power2 | sorted_arithmetic | 256 | 4096 | 35.7 μs | 59.2 μs | 45.9 μs | 204.5 μs | 91.4 μs | 35.7 μs | 83.7 μs | Linear (35.7 μs) | 1.00x | -| power2 | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_arithmetic | 1024 | 4 | 1.5 μs | 210 ns | 180 ns | 210 ns | 150 ns | 200 ns | 130 ns | Binary (150 ns) | 1.33x | -| power2 | sorted_arithmetic | 1024 | 16 | 1.7 μs | 620 ns | 490 ns | 890 ns | 450 ns | 520 ns | 420 ns | Binary (450 ns) | 1.16x | -| power2 | sorted_arithmetic | 1024 | 64 | 2.1 μs | 1.9 μs | 1.4 μs | 3.7 μs | 1.8 μs | 1.5 μs | 1.5 μs | ExpFromLeft (1.4 μs) | 1.03x | -| power2 | sorted_arithmetic | 1024 | 256 | 3.8 μs | 5.8 μs | 3.9 μs | 15.2 μs | 8.1 μs | 3.9 μs | 7.5 μs | Linear (3.8 μs) | 1.01x | -| power2 | sorted_arithmetic | 1024 | 1024 | 13.6 μs | 21.8 μs | 16.2 μs | 69.2 μs | 72.1 μs | 10.7 μs | 71.6 μs | Linear (13.6 μs) | 0.79x | -| power2 | sorted_arithmetic | 1024 | 4096 | 37.5 μs | 62.0 μs | 46.6 μs | 279.9 μs | 188.4 μs | 37.6 μs | 180.8 μs | Linear (37.5 μs) | 1.00x | -| power2 | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_arithmetic | 4096 | 4 | 5.7 μs | 240 ns | 200 ns | 230 ns | 160 ns | 220 ns | 150 ns | Binary (160 ns) | 1.38x | -| power2 | sorted_arithmetic | 4096 | 16 | 6.0 μs | 750 ns | 589 ns | 1.0 μs | 530 ns | 620 ns | 490 ns | Binary (530 ns) | 1.17x | -| power2 | sorted_arithmetic | 4096 | 64 | 7.2 μs | 2.5 μs | 1.9 μs | 4.2 μs | 2.0 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.9 μs) | 0.99x | -| power2 | sorted_arithmetic | 4096 | 256 | 8.8 μs | 7.8 μs | 5.9 μs | 18.2 μs | 11.4 μs | 6.0 μs | 11.2 μs | ExpFromLeft (5.9 μs) | 1.02x | -| power2 | sorted_arithmetic | 4096 | 1024 | 16.0 μs | 24.1 μs | 15.8 μs | 89.7 μs | 99.1 μs | 16.0 μs | 90.6 μs | ExpFromLeft (15.8 μs) | 1.01x | -| power2 | sorted_arithmetic | 4096 | 4096 | 43.3 μs | 70.6 μs | 49.0 μs | 374.9 μs | 312.2 μs | 43.3 μs | 307.4 μs | Linear (43.3 μs) | 1.00x | -| power2 | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_arithmetic | 16384 | 4 | 22.6 μs | 270 ns | 230 ns | 250 ns | 190 ns | 240 ns | 170 ns | Binary (190 ns) | 1.26x | -| power2 | sorted_arithmetic | 16384 | 16 | 23.5 μs | 920 ns | 680 ns | 1.2 μs | 600 ns | 710 ns | 570 ns | Binary (600 ns) | 1.18x | -| power2 | sorted_arithmetic | 16384 | 64 | 24.4 μs | 3.2 μs | 2.4 μs | 5.0 μs | 2.4 μs | 2.4 μs | 2.3 μs | ExpFromLeft (2.4 μs) | 1.02x | -| power2 | sorted_arithmetic | 16384 | 256 | 28.2 μs | 10.1 μs | 7.5 μs | 21.0 μs | 14.0 μs | 7.5 μs | 13.8 μs | ExpFromLeft (7.5 μs) | 1.00x | -| power2 | sorted_arithmetic | 16384 | 1024 | 36.2 μs | 32.6 μs | 24.4 μs | 122.2 μs | 125.8 μs | 24.9 μs | 124.0 μs | ExpFromLeft (24.4 μs) | 1.02x | -| power2 | sorted_arithmetic | 16384 | 4096 | 65.3 μs | 98.0 μs | 65.4 μs | 506.3 μs | 425.1 μs | 65.2 μs | 411.6 μs | Linear (65.3 μs) | 1.00x | -| power2 | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| power2 | sorted_arithmetic | 65536 | 4 | 87.8 μs | 300 ns | 240 ns | 270 ns | 200 ns | 270 ns | 190 ns | Binary (200 ns) | 1.35x | -| power2 | sorted_arithmetic | 65536 | 16 | 88.5 μs | 1.1 μs | 790 ns | 1.4 μs | 700 ns | 820 ns | 650 ns | Binary (700 ns) | 1.17x | -| power2 | sorted_arithmetic | 65536 | 64 | 92.4 μs | 3.7 μs | 2.7 μs | 5.7 μs | 2.8 μs | 2.8 μs | 2.6 μs | ExpFromLeft (2.7 μs) | 1.03x | -| power2 | sorted_arithmetic | 65536 | 256 | 97.6 μs | 13.2 μs | 9.9 μs | 25.3 μs | 18.3 μs | 9.9 μs | 16.4 μs | ExpFromLeft (9.9 μs) | 1.00x | -| power2 | sorted_arithmetic | 65536 | 1024 | 109.9 μs | 45.5 μs | 34.2 μs | 152.8 μs | 153.6 μs | 33.9 μs | 158.1 μs | ExpFromLeft (34.2 μs) | 0.99x | -| power2 | sorted_arithmetic | 65536 | 4096 | 142.2 μs | 134.6 μs | 100.7 μs | 613.7 μs | 501.1 μs | 101.9 μs | 509.1 μs | ExpFromLeft (100.7 μs) | 1.01x | -| power2 | sorted_geometric | 16 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| power2 | sorted_geometric | 16 | 4 | 100 ns | 120 ns | 120 ns | 150 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | -| power2 | sorted_geometric | 16 | 16 | 190 ns | 280 ns | 219 ns | 510 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | -| power2 | sorted_geometric | 16 | 64 | 630 ns | 1.0 μs | 780 ns | 2.1 μs | 1.0 μs | 660 ns | 880 ns | Linear (630 ns) | 1.05x | -| power2 | sorted_geometric | 16 | 256 | 2.3 μs | 3.7 μs | 3.0 μs | 8.4 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | -| power2 | sorted_geometric | 16 | 1024 | 8.1 μs | 14.1 μs | 10.8 μs | 31.5 μs | 12.2 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | -| power2 | sorted_geometric | 16 | 4096 | 31.1 μs | 55.4 μs | 42.3 μs | 123.8 μs | 47.1 μs | 31.1 μs | 39.9 μs | Linear (31.1 μs) | 1.00x | -| power2 | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| power2 | sorted_geometric | 64 | 4 | 170 ns | 150 ns | 140 ns | 170 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | -| power2 | sorted_geometric | 64 | 16 | 270 ns | 390 ns | 290 ns | 660 ns | 300 ns | 280 ns | 270 ns | Linear (270 ns) | 1.04x | -| power2 | sorted_geometric | 64 | 64 | 660 ns | 1.1 μs | 780 ns | 2.6 μs | 1.2 μs | 690 ns | 1.1 μs | Linear (660 ns) | 1.05x | -| power2 | sorted_geometric | 64 | 256 | 2.4 μs | 4.0 μs | 3.1 μs | 11.0 μs | 5.2 μs | 2.4 μs | 4.8 μs | Linear (2.4 μs) | 1.00x | -| power2 | sorted_geometric | 64 | 1024 | 9.2 μs | 14.9 μs | 11.7 μs | 42.8 μs | 17.6 μs | 9.2 μs | 15.8 μs | Linear (9.2 μs) | 1.00x | -| power2 | sorted_geometric | 64 | 4096 | 32.2 μs | 56.4 μs | 43.2 μs | 162.9 μs | 67.1 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | -| power2 | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_geometric | 256 | 4 | 490 ns | 180 ns | 160 ns | 190 ns | 130 ns | 180 ns | 110 ns | Binary (130 ns) | 1.38x | -| power2 | sorted_geometric | 256 | 16 | 630 ns | 520 ns | 510 ns | 800 ns | 370 ns | 430 ns | 340 ns | Binary (370 ns) | 1.16x | -| power2 | sorted_geometric | 256 | 64 | 970 ns | 1.5 μs | 1.1 μs | 3.2 μs | 1.4 μs | 980 ns | 1.2 μs | Linear (970 ns) | 1.01x | -| power2 | sorted_geometric | 256 | 256 | 2.8 μs | 4.6 μs | 3.2 μs | 13.0 μs | 6.7 μs | 2.9 μs | 6.3 μs | Linear (2.8 μs) | 1.03x | -| power2 | sorted_geometric | 256 | 1024 | 9.5 μs | 15.6 μs | 11.8 μs | 56.3 μs | 27.0 μs | 9.5 μs | 25.0 μs | Linear (9.5 μs) | 1.00x | -| power2 | sorted_geometric | 256 | 4096 | 34.9 μs | 59.5 μs | 46.1 μs | 208.6 μs | 90.7 μs | 35.0 μs | 83.5 μs | Linear (34.9 μs) | 1.00x | -| power2 | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | 60 ns | InterpSearch (60 ns) | 1.00x | -| power2 | sorted_geometric | 1024 | 4 | 1.5 μs | 210 ns | 170 ns | 220 ns | 150 ns | 200 ns | 130 ns | Binary (150 ns) | 1.33x | -| power2 | sorted_geometric | 1024 | 16 | 1.8 μs | 630 ns | 500 ns | 920 ns | 450 ns | 520 ns | 400 ns | Binary (450 ns) | 1.16x | -| power2 | sorted_geometric | 1024 | 64 | 2.1 μs | 1.9 μs | 1.5 μs | 3.7 μs | 1.7 μs | 1.5 μs | 1.5 μs | ExpFromLeft (1.5 μs) | 1.03x | -| power2 | sorted_geometric | 1024 | 256 | 3.9 μs | 6.3 μs | 5.8 μs | 16.2 μs | 8.0 μs | 4.8 μs | 7.3 μs | Linear (3.9 μs) | 1.22x | -| power2 | sorted_geometric | 1024 | 1024 | 11.2 μs | 18.1 μs | 12.4 μs | 70.3 μs | 85.2 μs | 11.2 μs | 84.6 μs | Linear (11.2 μs) | 1.00x | -| power2 | sorted_geometric | 1024 | 4096 | 37.1 μs | 61.2 μs | 45.8 μs | 281.8 μs | 195.9 μs | 37.2 μs | 192.4 μs | Linear (37.1 μs) | 1.00x | -| power2 | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| power2 | sorted_geometric | 4096 | 4 | 5.9 μs | 240 ns | 190 ns | 230 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | -| power2 | sorted_geometric | 4096 | 16 | 6.2 μs | 780 ns | 570 ns | 1.1 μs | 530 ns | 630 ns | 490 ns | Binary (530 ns) | 1.19x | -| power2 | sorted_geometric | 4096 | 64 | 7.3 μs | 2.5 μs | 1.9 μs | 4.3 μs | 2.0 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.9 μs) | 1.01x | -| power2 | sorted_geometric | 4096 | 256 | 8.9 μs | 7.9 μs | 6.2 μs | 17.8 μs | 10.7 μs | 6.3 μs | 10.9 μs | ExpFromLeft (6.2 μs) | 1.01x | -| power2 | sorted_geometric | 4096 | 1024 | 16.2 μs | 25.2 μs | 18.0 μs | 86.7 μs | 101.6 μs | 16.2 μs | 97.9 μs | Linear (16.2 μs) | 1.00x | -| power2 | sorted_geometric | 4096 | 4096 | 43.3 μs | 70.2 μs | 48.2 μs | 377.6 μs | 316.8 μs | 43.4 μs | 310.2 μs | Linear (43.3 μs) | 1.00x | -| power2 | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| power2 | sorted_geometric | 16384 | 4 | 22.6 μs | 280 ns | 240 ns | 250 ns | 180 ns | 270 ns | 170 ns | Binary (180 ns) | 1.50x | -| power2 | sorted_geometric | 16384 | 16 | 23.2 μs | 940 ns | 690 ns | 1.2 μs | 610 ns | 720 ns | 560 ns | Binary (610 ns) | 1.18x | -| power2 | sorted_geometric | 16384 | 64 | 24.6 μs | 3.2 μs | 2.4 μs | 5.0 μs | 2.4 μs | 2.4 μs | 2.2 μs | Binary (2.4 μs) | 1.03x | -| power2 | sorted_geometric | 16384 | 256 | 28.7 μs | 10.2 μs | 7.8 μs | 21.2 μs | 14.6 μs | 7.8 μs | 13.7 μs | ExpFromLeft (7.8 μs) | 1.01x | -| power2 | sorted_geometric | 16384 | 1024 | 36.1 μs | 33.0 μs | 26.0 μs | 118.3 μs | 131.2 μs | 26.3 μs | 132.5 μs | ExpFromLeft (26.0 μs) | 1.01x | -| power2 | sorted_geometric | 16384 | 4096 | 64.6 μs | 99.5 μs | 71.9 μs | 500.6 μs | 422.6 μs | 64.5 μs | 425.5 μs | Linear (64.6 μs) | 1.00x | -| power2 | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| power2 | sorted_geometric | 65536 | 4 | 94.0 μs | 310 ns | 260 ns | 280 ns | 210 ns | 300 ns | 190 ns | Binary (210 ns) | 1.43x | -| power2 | sorted_geometric | 65536 | 16 | 94.0 μs | 1.1 μs | 820 ns | 1.4 μs | 720 ns | 840 ns | 680 ns | Binary (720 ns) | 1.17x | -| power2 | sorted_geometric | 65536 | 64 | 95.1 μs | 3.8 μs | 2.8 μs | 5.9 μs | 2.9 μs | 2.8 μs | 2.9 μs | ExpFromLeft (2.8 μs) | 1.01x | -| power2 | sorted_geometric | 65536 | 256 | 100.2 μs | 13.7 μs | 10.6 μs | 27.5 μs | 18.2 μs | 10.7 μs | 16.9 μs | ExpFromLeft (10.6 μs) | 1.01x | -| power2 | sorted_geometric | 65536 | 1024 | 111.7 μs | 44.7 μs | 34.5 μs | 153.2 μs | 161.7 μs | 33.8 μs | 167.2 μs | ExpFromLeft (34.5 μs) | 0.98x | -| power2 | sorted_geometric | 65536 | 4096 | 140.2 μs | 131.9 μs | 106.4 μs | 615.3 μs | 512.3 μs | 108.5 μs | 519.0 μs | ExpFromLeft (106.4 μs) | 1.02x | -| power2 | sorted_bimodal | 16 | 1 | 60 ns | 60 ns | 50 ns | 90 ns | 70 ns | 70 ns | 50 ns | ExpFromLeft (50 ns) | 1.40x | -| power2 | sorted_bimodal | 16 | 4 | 100 ns | 120 ns | 110 ns | 160 ns | 100 ns | 110 ns | 80 ns | Binary (100 ns) | 1.10x | -| power2 | sorted_bimodal | 16 | 16 | 190 ns | 320 ns | 240 ns | 490 ns | 250 ns | 220 ns | 200 ns | Linear (190 ns) | 1.16x | -| power2 | sorted_bimodal | 16 | 64 | 570 ns | 970 ns | 770 ns | 1.9 μs | 910 ns | 590 ns | 790 ns | Linear (570 ns) | 1.04x | -| power2 | sorted_bimodal | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 7.4 μs | 3.4 μs | 2.1 μs | 3.0 μs | Linear (2.1 μs) | 1.00x | -| power2 | sorted_bimodal | 16 | 1024 | 8.0 μs | 13.9 μs | 10.7 μs | 29.1 μs | 13.1 μs | 8.0 μs | 11.6 μs | Linear (8.0 μs) | 1.00x | -| power2 | sorted_bimodal | 16 | 4096 | 31.3 μs | 55.0 μs | 42.1 μs | 113.0 μs | 51.6 μs | 30.9 μs | 45.5 μs | Linear (31.3 μs) | 0.99x | -| power2 | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 50 ns | InterpSearch (60 ns) | 1.00x | -| power2 | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 110 ns | 180 ns | 110 ns | 140 ns | 90 ns | ExpFromLeft (110 ns) | 1.27x | -| power2 | sorted_bimodal | 64 | 16 | 250 ns | 320 ns | 250 ns | 570 ns | 320 ns | 280 ns | 270 ns | ExpFromLeft (250 ns) | 1.12x | -| power2 | sorted_bimodal | 64 | 64 | 620 ns | 1.0 μs | 760 ns | 2.3 μs | 1.2 μs | 660 ns | 1.1 μs | Linear (620 ns) | 1.06x | -| power2 | sorted_bimodal | 64 | 256 | 2.2 μs | 3.8 μs | 2.9 μs | 9.4 μs | 4.6 μs | 2.3 μs | 4.1 μs | Linear (2.2 μs) | 1.01x | -| power2 | sorted_bimodal | 64 | 1024 | 8.3 μs | 14.0 μs | 11.0 μs | 35.7 μs | 17.2 μs | 8.3 μs | 15.5 μs | Linear (8.3 μs) | 1.00x | -| power2 | sorted_bimodal | 64 | 4096 | 31.3 μs | 54.6 μs | 42.5 μs | 140.2 μs | 67.3 μs | 31.3 μs | 60.7 μs | Linear (31.3 μs) | 1.00x | -| power2 | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_bimodal | 256 | 4 | 380 ns | 140 ns | 130 ns | 210 ns | 120 ns | 150 ns | 110 ns | Binary (120 ns) | 1.25x | -| power2 | sorted_bimodal | 256 | 16 | 540 ns | 380 ns | 300 ns | 720 ns | 400 ns | 330 ns | 380 ns | ExpFromLeft (300 ns) | 1.10x | -| power2 | sorted_bimodal | 256 | 64 | 950 ns | 1.1 μs | 800 ns | 2.9 μs | 1.6 μs | 980 ns | 1.5 μs | ExpFromLeft (800 ns) | 1.23x | -| power2 | sorted_bimodal | 256 | 256 | 2.6 μs | 4.0 μs | 3.0 μs | 11.3 μs | 6.6 μs | 2.6 μs | 6.0 μs | Linear (2.6 μs) | 0.99x | -| power2 | sorted_bimodal | 256 | 1024 | 9.3 μs | 14.9 μs | 11.8 μs | 45.3 μs | 23.2 μs | 9.2 μs | 21.1 μs | Linear (9.3 μs) | 1.00x | -| power2 | sorted_bimodal | 256 | 4096 | 32.9 μs | 56.3 μs | 43.7 μs | 173.4 μs | 87.9 μs | 32.8 μs | 80.3 μs | Linear (32.9 μs) | 1.00x | -| power2 | sorted_bimodal | 1024 | 1 | 70 ns | 70 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_bimodal | 1024 | 4 | 1.3 μs | 180 ns | 160 ns | 240 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | -| power2 | sorted_bimodal | 1024 | 16 | 1.7 μs | 500 ns | 390 ns | 880 ns | 440 ns | 410 ns | 410 ns | ExpFromLeft (390 ns) | 1.05x | -| power2 | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.4 μs | 1.0 μs | 3.4 μs | 1.8 μs | 1.1 μs | 1.7 μs | ExpFromLeft (1.0 μs) | 1.05x | -| power2 | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.3 μs | 3.0 μs | 13.8 μs | 8.1 μs | 3.5 μs | 7.5 μs | ExpFromLeft (3.0 μs) | 1.17x | -| power2 | sorted_bimodal | 1024 | 1024 | 10.7 μs | 16.2 μs | 12.1 μs | 58.4 μs | 31.3 μs | 10.7 μs | 29.7 μs | Linear (10.7 μs) | 1.00x | -| power2 | sorted_bimodal | 1024 | 4096 | 37.7 μs | 60.3 μs | 47.2 μs | 223.8 μs | 114.1 μs | 37.7 μs | 106.1 μs | Linear (37.7 μs) | 1.00x | -| power2 | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_bimodal | 4096 | 4 | 5.7 μs | 220 ns | 190 ns | 270 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | -| power2 | sorted_bimodal | 4096 | 16 | 5.6 μs | 600 ns | 460 ns | 960 ns | 530 ns | 490 ns | 510 ns | ExpFromLeft (460 ns) | 1.07x | -| power2 | sorted_bimodal | 4096 | 64 | 6.7 μs | 1.8 μs | 1.3 μs | 3.9 μs | 2.3 μs | 1.4 μs | 2.0 μs | ExpFromLeft (1.3 μs) | 1.04x | -| power2 | sorted_bimodal | 4096 | 256 | 8.1 μs | 5.5 μs | 3.9 μs | 16.2 μs | 10.7 μs | 4.0 μs | 10.7 μs | ExpFromLeft (3.9 μs) | 1.02x | -| power2 | sorted_bimodal | 4096 | 1024 | 15.4 μs | 18.5 μs | 12.7 μs | 76.9 μs | 61.1 μs | 15.2 μs | 55.0 μs | ExpFromLeft (12.7 μs) | 1.19x | -| power2 | sorted_bimodal | 4096 | 4096 | 48.1 μs | 69.2 μs | 52.0 μs | 309.9 μs | 201.8 μs | 47.0 μs | 188.9 μs | Linear (48.1 μs) | 0.98x | -| power2 | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 70 ns | 80 ns | 70 ns | ExpFromLeft (70 ns) | 1.14x | -| power2 | sorted_bimodal | 16384 | 4 | 17.0 μs | 240 ns | 200 ns | 310 ns | 180 ns | 230 ns | 170 ns | Binary (180 ns) | 1.28x | -| power2 | sorted_bimodal | 16384 | 16 | 22.1 μs | 720 ns | 550 ns | 1.2 μs | 630 ns | 590 ns | 610 ns | ExpFromLeft (550 ns) | 1.07x | -| power2 | sorted_bimodal | 16384 | 64 | 22.5 μs | 2.3 μs | 1.7 μs | 4.6 μs | 2.8 μs | 1.8 μs | 2.7 μs | ExpFromLeft (1.7 μs) | 1.03x | -| power2 | sorted_bimodal | 16384 | 256 | 26.1 μs | 6.9 μs | 5.3 μs | 19.3 μs | 15.8 μs | 5.3 μs | 14.5 μs | ExpFromLeft (5.3 μs) | 1.00x | -| power2 | sorted_bimodal | 16384 | 1024 | 34.5 μs | 23.8 μs | 17.2 μs | 101.0 μs | 92.8 μs | 17.0 μs | 93.9 μs | ExpFromLeft (17.2 μs) | 0.99x | -| power2 | sorted_bimodal | 16384 | 4096 | 83.8 μs | 94.9 μs | 73.2 μs | 430.5 μs | 297.7 μs | 81.4 μs | 286.1 μs | ExpFromLeft (73.2 μs) | 1.11x | -| power2 | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| power2 | sorted_bimodal | 65536 | 4 | 79.1 μs | 290 ns | 240 ns | 370 ns | 200 ns | 270 ns | 180 ns | Binary (200 ns) | 1.35x | -| power2 | sorted_bimodal | 65536 | 16 | 80.3 μs | 920 ns | 650 ns | 1.4 μs | 670 ns | 690 ns | 630 ns | ExpFromLeft (650 ns) | 1.06x | -| power2 | sorted_bimodal | 65536 | 64 | 92.4 μs | 3.0 μs | 2.3 μs | 5.4 μs | 3.2 μs | 2.3 μs | 3.1 μs | ExpFromLeft (2.3 μs) | 1.00x | -| power2 | sorted_bimodal | 65536 | 256 | 95.6 μs | 9.4 μs | 7.2 μs | 22.3 μs | 19.5 μs | 7.3 μs | 17.4 μs | ExpFromLeft (7.2 μs) | 1.00x | -| power2 | sorted_bimodal | 65536 | 1024 | 106.6 μs | 35.4 μs | 26.7 μs | 132.7 μs | 118.9 μs | 25.5 μs | 120.5 μs | ExpFromLeft (26.7 μs) | 0.96x | -| power2 | sorted_bimodal | 65536 | 4096 | 180.3 μs | 160.4 μs | 125.7 μs | 547.8 μs | 378.9 μs | 126.3 μs | 370.2 μs | ExpFromLeft (125.7 μs) | 1.00x | -| power2 | sorted_repeated | 16 | 1 | 70 ns | 60 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| power2 | sorted_repeated | 16 | 4 | 80 ns | 100 ns | 100 ns | 180 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| power2 | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 220 ns | 620 ns | 230 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | -| power2 | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 690 ns | 2.3 μs | 790 ns | 580 ns | 720 ns | Linear (550 ns) | 1.05x | -| power2 | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 9.2 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.02x | -| power2 | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 36.6 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.01x | -| power2 | sorted_repeated | 16 | 4096 | 30.8 μs | 54.9 μs | 39.6 μs | 146.2 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 90 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| power2 | sorted_repeated | 64 | 4 | 100 ns | 90 ns | 90 ns | 220 ns | 110 ns | 110 ns | 90 ns | ExpFromLeft (90 ns) | 1.22x | -| power2 | sorted_repeated | 64 | 16 | 180 ns | 270 ns | 200 ns | 780 ns | 300 ns | 190 ns | 270 ns | Linear (180 ns) | 1.06x | -| power2 | sorted_repeated | 64 | 64 | 560 ns | 920 ns | 700 ns | 3.0 μs | 1.1 μs | 580 ns | 920 ns | Linear (560 ns) | 1.04x | -| power2 | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 11.7 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | -| power2 | sorted_repeated | 64 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 47.0 μs | 16.6 μs | 7.8 μs | 14.2 μs | Linear (7.8 μs) | 1.00x | -| power2 | sorted_repeated | 64 | 4096 | 30.8 μs | 55.1 μs | 39.4 μs | 186.4 μs | 66.5 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_repeated | 256 | 4 | 90 ns | 120 ns | 100 ns | 270 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| power2 | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 920 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| power2 | sorted_repeated | 256 | 64 | 550 ns | 940 ns | 700 ns | 3.5 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | -| power2 | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 13.9 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| power2 | sorted_repeated | 256 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 55.7 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.8 μs) | 1.00x | -| power2 | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 222.3 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 300 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | -| power2 | sorted_repeated | 1024 | 16 | 180 ns | 290 ns | 220 ns | 1.1 μs | 460 ns | 210 ns | 410 ns | Linear (180 ns) | 1.17x | -| power2 | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 4.1 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| power2 | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 16.4 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | -| power2 | sorted_repeated | 1024 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 65.0 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.00x | -| power2 | sorted_repeated | 1024 | 4096 | 30.8 μs | 56.1 μs | 39.2 μs | 260.0 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 350 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | -| power2 | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 1.2 μs | 520 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | -| power2 | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 710 ns | 4.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | -| power2 | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 18.9 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| power2 | sorted_repeated | 4096 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 75.9 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.7 μs) | 1.01x | -| power2 | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 302.3 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_repeated | 16384 | 1 | 80 ns | 90 ns | 70 ns | 130 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | sorted_repeated | 16384 | 4 | 100 ns | 110 ns | 110 ns | 400 ns | 180 ns | 120 ns | 160 ns | Linear (100 ns) | 1.20x | -| power2 | sorted_repeated | 16384 | 16 | 190 ns | 290 ns | 220 ns | 1.4 μs | 600 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | -| power2 | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 710 ns | 5.5 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | -| power2 | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 22.1 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | -| power2 | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 88.4 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.00x | -| power2 | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.1 μs | 39.2 μs | 353.1 μs | 144.2 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | -| power2 | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| power2 | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 430 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| power2 | sorted_repeated | 65536 | 16 | 190 ns | 290 ns | 220 ns | 1.6 μs | 680 ns | 220 ns | 640 ns | Linear (190 ns) | 1.16x | -| power2 | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 709 ns | 6.2 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| power2 | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 24.8 μs | 10.2 μs | 2.1 μs | 9.6 μs | Linear (2.0 μs) | 1.03x | -| power2 | sorted_repeated | 65536 | 1024 | 7.8 μs | 14.0 μs | 9.9 μs | 99.1 μs | 40.7 μs | 7.8 μs | 38.2 μs | Linear (7.8 μs) | 1.00x | -| power2 | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.1 μs | 39.4 μs | 396.4 μs | 163.2 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| power2 | unsorted | 16 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 70 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| power2 | unsorted | 16 | 4 | 90 ns | 90 ns | 100 ns | 90 ns | 100 ns | 100 ns | 70 ns | InterpSearch (90 ns) | 1.11x | -| power2 | unsorted | 16 | 16 | 220 ns | 210 ns | 210 ns | 200 ns | 210 ns | 210 ns | 180 ns | InterpSearch (200 ns) | 1.05x | -| power2 | unsorted | 16 | 64 | 690 ns | 680 ns | 700 ns | 680 ns | 700 ns | 710 ns | 680 ns | InterpSearch (680 ns) | 1.04x | -| power2 | unsorted | 16 | 256 | 2.9 μs | 3.0 μs | 2.9 μs | 3.0 μs | 3.0 μs | 3.0 μs | 2.9 μs | ExpFromLeft (2.9 μs) | 1.00x | -| power2 | unsorted | 16 | 1024 | 16.9 μs | 16.7 μs | 16.5 μs | 16.6 μs | 16.5 μs | 16.7 μs | 18.6 μs | Binary (16.5 μs) | 1.01x | -| power2 | unsorted | 16 | 4096 | 130.4 μs | 127.2 μs | 126.8 μs | 126.8 μs | 126.3 μs | 126.1 μs | 128.0 μs | Binary (126.3 μs) | 1.00x | -| power2 | unsorted | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | unsorted | 64 | 4 | 110 ns | 110 ns | 100 ns | 110 ns | 110 ns | 110 ns | 90 ns | ExpFromLeft (100 ns) | 1.10x | -| power2 | unsorted | 64 | 16 | 280 ns | 270 ns | 280 ns | 280 ns | 280 ns | 290 ns | 270 ns | Gallop (270 ns) | 1.07x | -| power2 | unsorted | 64 | 64 | 1.1 μs | 1.1 μs | 1.0 μs | 1.1 μs | 1.1 μs | 1.1 μs | 1.0 μs | ExpFromLeft (1.0 μs) | 1.03x | -| power2 | unsorted | 64 | 256 | 5.0 μs | 5.0 μs | 5.0 μs | 5.0 μs | 5.0 μs | 5.0 μs | 5.1 μs | InterpSearch (5.0 μs) | 1.00x | -| power2 | unsorted | 64 | 1024 | 38.2 μs | 37.9 μs | 38.3 μs | 38.0 μs | 38.7 μs | 38.0 μs | 40.2 μs | Gallop (37.9 μs) | 1.00x | -| power2 | unsorted | 64 | 4096 | 207.9 μs | 205.7 μs | 206.0 μs | 206.0 μs | 206.5 μs | 204.9 μs | 208.3 μs | Gallop (205.7 μs) | 1.00x | -| power2 | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | unsorted | 256 | 4 | 119 ns | 120 ns | 120 ns | 120 ns | 130 ns | 130 ns | 110 ns | Linear (119 ns) | 1.09x | -| power2 | unsorted | 256 | 16 | 340 ns | 350 ns | 350 ns | 349 ns | 350 ns | 350 ns | 330 ns | Linear (340 ns) | 1.03x | -| power2 | unsorted | 256 | 64 | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | ExpFromLeft (1.4 μs) | 1.01x | -| power2 | unsorted | 256 | 256 | 7.2 μs | 7.1 μs | 7.1 μs | 7.0 μs | 6.9 μs | 7.0 μs | 7.2 μs | Binary (6.9 μs) | 1.02x | -| power2 | unsorted | 256 | 1024 | 52.5 μs | 52.0 μs | 51.7 μs | 51.3 μs | 51.2 μs | 51.1 μs | 52.0 μs | Binary (51.2 μs) | 1.00x | -| power2 | unsorted | 256 | 4096 | 298.3 μs | 293.5 μs | 290.7 μs | 290.9 μs | 290.3 μs | 291.4 μs | 294.6 μs | Binary (290.3 μs) | 1.00x | -| power2 | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 69 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| power2 | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 149 ns | 130 ns | InterpSearch (140 ns) | 1.06x | -| power2 | unsorted | 1024 | 16 | 430 ns | 410 ns | 410 ns | 420 ns | 430 ns | 440 ns | 410 ns | ExpFromLeft (410 ns) | 1.07x | -| power2 | unsorted | 1024 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | InterpSearch (1.6 μs) | 1.01x | -| power2 | unsorted | 1024 | 256 | 8.0 μs | 7.9 μs | 7.9 μs | 7.8 μs | 7.9 μs | 7.9 μs | 8.8 μs | InterpSearch (7.8 μs) | 1.02x | -| power2 | unsorted | 1024 | 1024 | 77.3 μs | 76.5 μs | 75.5 μs | 74.8 μs | 73.8 μs | 73.7 μs | 77.8 μs | Binary (73.8 μs) | 1.00x | -| power2 | unsorted | 1024 | 4096 | 388.3 μs | 385.9 μs | 385.2 μs | 390.4 μs | 389.1 μs | 386.6 μs | 387.2 μs | ExpFromLeft (385.2 μs) | 1.00x | -| power2 | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| power2 | unsorted | 4096 | 4 | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 140 ns | InterpSearch (160 ns) | 1.00x | -| power2 | unsorted | 4096 | 16 | 500 ns | 500 ns | 490 ns | 490 ns | 490 ns | 510 ns | 480 ns | InterpSearch (490 ns) | 1.04x | -| power2 | unsorted | 4096 | 64 | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | Gallop (2.0 μs) | 1.00x | -| power2 | unsorted | 4096 | 256 | 10.0 μs | 9.9 μs | 9.9 μs | 9.9 μs | 9.8 μs | 9.6 μs | 10.9 μs | Binary (9.8 μs) | 0.98x | -| power2 | unsorted | 4096 | 1024 | 96.9 μs | 94.9 μs | 93.8 μs | 90.6 μs | 91.8 μs | 91.6 μs | 94.7 μs | InterpSearch (90.6 μs) | 1.01x | -| power2 | unsorted | 4096 | 4096 | 474.6 μs | 470.7 μs | 471.6 μs | 469.4 μs | 468.6 μs | 474.7 μs | 472.6 μs | Binary (468.6 μs) | 1.01x | -| power2 | unsorted | 16384 | 1 | 80 ns | 70 ns | 80 ns | 120 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | -| power2 | unsorted | 16384 | 4 | 170 ns | 170 ns | 180 ns | 180 ns | 180 ns | 190 ns | 160 ns | Gallop (170 ns) | 1.12x | -| power2 | unsorted | 16384 | 16 | 570 ns | 570 ns | 560 ns | 570 ns | 580 ns | 580 ns | 560 ns | ExpFromLeft (560 ns) | 1.04x | -| power2 | unsorted | 16384 | 64 | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.2 μs | InterpSearch (2.3 μs) | 1.00x | -| power2 | unsorted | 16384 | 256 | 12.0 μs | 11.6 μs | 11.4 μs | 11.4 μs | 11.4 μs | 11.4 μs | 14.8 μs | ExpFromLeft (11.4 μs) | 1.01x | -| power2 | unsorted | 16384 | 1024 | 134.5 μs | 131.3 μs | 129.4 μs | 128.1 μs | 127.6 μs | 127.3 μs | 134.1 μs | Binary (127.6 μs) | 1.00x | -| power2 | unsorted | 16384 | 4096 | 629.9 μs | 632.0 μs | 629.5 μs | 631.2 μs | 630.9 μs | 629.7 μs | 630.1 μs | ExpFromLeft (629.5 μs) | 1.00x | -| power2 | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| power2 | unsorted | 65536 | 4 | 190 ns | 200 ns | 190 ns | 200 ns | 190 ns | 200 ns | 180 ns | ExpFromLeft (190 ns) | 1.05x | -| power2 | unsorted | 65536 | 16 | 700 ns | 710 ns | 700 ns | 700 ns | 710 ns | 710 ns | 690 ns | InterpSearch (700 ns) | 1.01x | -| power2 | unsorted | 65536 | 64 | 2.7 μs | 2.7 μs | 2.6 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | ExpFromLeft (2.6 μs) | 1.01x | -| power2 | unsorted | 65536 | 256 | 14.3 μs | 14.0 μs | 13.6 μs | 13.5 μs | 13.6 μs | 13.4 μs | 18.0 μs | InterpSearch (13.5 μs) | 0.99x | -| power2 | unsorted | 65536 | 1024 | 179.4 μs | 176.4 μs | 176.4 μs | 175.0 μs | 174.0 μs | 173.1 μs | 178.5 μs | Binary (174.0 μs) | 0.99x | -| power2 | unsorted | 65536 | 4096 | 798.1 μs | 797.6 μs | 797.0 μs | 796.8 μs | 795.3 μs | 796.4 μs | 794.1 μs | Binary (795.3 μs) | 1.00x | -| sqrt | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| sqrt | sorted_uniform | 16 | 4 | 90 ns | 100 ns | 90 ns | 160 ns | 90 ns | 110 ns | 70 ns | ExpFromLeft (90 ns) | 1.22x | -| sqrt | sorted_uniform | 16 | 16 | 190 ns | 310 ns | 220 ns | 530 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| sqrt | sorted_uniform | 16 | 64 | 560 ns | 1.0 μs | 750 ns | 2.2 μs | 980 ns | 600 ns | 860 ns | Linear (560 ns) | 1.07x | -| sqrt | sorted_uniform | 16 | 256 | 2.3 μs | 3.8 μs | 3.0 μs | 8.4 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | -| sqrt | sorted_uniform | 16 | 1024 | 8.1 μs | 14.0 μs | 10.8 μs | 32.8 μs | 12.2 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | -| sqrt | sorted_uniform | 16 | 4096 | 31.1 μs | 55.0 μs | 42.3 μs | 128.7 μs | 47.7 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | -| sqrt | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| sqrt | sorted_uniform | 64 | 4 | 90 ns | 110 ns | 100 ns | 180 ns | 110 ns | 120 ns | 90 ns | Linear (90 ns) | 1.33x | -| sqrt | sorted_uniform | 64 | 16 | 310 ns | 410 ns | 340 ns | 670 ns | 320 ns | 320 ns | 260 ns | Linear (310 ns) | 1.03x | -| sqrt | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 790 ns | 2.4 μs | 1.3 μs | 670 ns | 1.1 μs | Linear (630 ns) | 1.06x | -| sqrt | sorted_uniform | 64 | 256 | 2.3 μs | 4.0 μs | 3.0 μs | 10.5 μs | 5.3 μs | 2.3 μs | 4.7 μs | Linear (2.3 μs) | 1.02x | -| sqrt | sorted_uniform | 64 | 1024 | 9.1 μs | 14.9 μs | 11.7 μs | 41.1 μs | 17.7 μs | 9.1 μs | 16.0 μs | Linear (9.1 μs) | 1.00x | -| sqrt | sorted_uniform | 64 | 4096 | 32.2 μs | 56.1 μs | 43.2 μs | 158.3 μs | 67.0 μs | 32.2 μs | 60.4 μs | Linear (32.2 μs) | 1.00x | -| sqrt | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_uniform | 256 | 4 | 180 ns | 140 ns | 120 ns | 240 ns | 130 ns | 150 ns | 110 ns | ExpFromLeft (120 ns) | 1.25x | -| sqrt | sorted_uniform | 256 | 16 | 480 ns | 440 ns | 350 ns | 800 ns | 370 ns | 370 ns | 340 ns | ExpFromLeft (350 ns) | 1.06x | -| sqrt | sorted_uniform | 256 | 64 | 910 ns | 1.3 μs | 970 ns | 3.1 μs | 1.5 μs | 940 ns | 1.4 μs | Linear (910 ns) | 1.03x | -| sqrt | sorted_uniform | 256 | 256 | 2.4 μs | 4.2 μs | 2.9 μs | 13.0 μs | 7.2 μs | 2.4 μs | 6.8 μs | Linear (2.4 μs) | 1.00x | -| sqrt | sorted_uniform | 256 | 1024 | 9.6 μs | 16.4 μs | 12.4 μs | 52.4 μs | 26.7 μs | 9.6 μs | 24.7 μs | Linear (9.6 μs) | 1.00x | -| sqrt | sorted_uniform | 256 | 4096 | 36.6 μs | 59.3 μs | 46.6 μs | 199.8 μs | 91.6 μs | 36.5 μs | 83.8 μs | Linear (36.6 μs) | 1.00x | -| sqrt | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_uniform | 1024 | 4 | 940 ns | 200 ns | 170 ns | 270 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| sqrt | sorted_uniform | 1024 | 16 | 1.8 μs | 630 ns | 480 ns | 930 ns | 450 ns | 490 ns | 420 ns | Binary (450 ns) | 1.09x | -| sqrt | sorted_uniform | 1024 | 64 | 1.9 μs | 1.7 μs | 1.3 μs | 3.8 μs | 1.9 μs | 1.3 μs | 1.7 μs | ExpFromLeft (1.3 μs) | 1.02x | -| sqrt | sorted_uniform | 1024 | 256 | 3.6 μs | 5.0 μs | 3.7 μs | 14.8 μs | 8.1 μs | 3.7 μs | 7.3 μs | Linear (3.6 μs) | 1.03x | -| sqrt | sorted_uniform | 1024 | 1024 | 10.0 μs | 17.9 μs | 12.6 μs | 65.4 μs | 48.9 μs | 10.2 μs | 44.0 μs | Linear (10.0 μs) | 1.02x | -| sqrt | sorted_uniform | 1024 | 4096 | 45.3 μs | 69.9 μs | 54.0 μs | 262.1 μs | 183.8 μs | 45.0 μs | 182.8 μs | Linear (45.3 μs) | 0.99x | -| sqrt | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_uniform | 4096 | 4 | 2.6 μs | 220 ns | 190 ns | 290 ns | 160 ns | 209 ns | 150 ns | Binary (160 ns) | 1.31x | -| sqrt | sorted_uniform | 4096 | 16 | 5.9 μs | 690 ns | 520 ns | 1.1 μs | 520 ns | 550 ns | 480 ns | ExpFromLeft (520 ns) | 1.06x | -| sqrt | sorted_uniform | 4096 | 64 | 6.8 μs | 2.2 μs | 1.7 μs | 4.3 μs | 2.1 μs | 1.7 μs | 2.0 μs | ExpFromLeft (1.7 μs) | 1.02x | -| sqrt | sorted_uniform | 4096 | 256 | 8.5 μs | 7.2 μs | 5.0 μs | 17.8 μs | 11.3 μs | 5.2 μs | 10.6 μs | ExpFromLeft (5.0 μs) | 1.03x | -| sqrt | sorted_uniform | 4096 | 1024 | 15.8 μs | 22.6 μs | 15.9 μs | 82.6 μs | 83.3 μs | 15.8 μs | 79.0 μs | Linear (15.8 μs) | 1.00x | -| sqrt | sorted_uniform | 4096 | 4096 | 63.1 μs | 90.4 μs | 68.0 μs | 350.5 μs | 286.2 μs | 58.5 μs | 278.1 μs | Linear (63.1 μs) | 0.93x | -| sqrt | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_uniform | 16384 | 4 | 8.1 μs | 240 ns | 200 ns | 350 ns | 170 ns | 230 ns | 160 ns | Binary (170 ns) | 1.35x | -| sqrt | sorted_uniform | 16384 | 16 | 24.2 μs | 870 ns | 650 ns | 1.2 μs | 630 ns | 680 ns | 560 ns | Binary (630 ns) | 1.08x | -| sqrt | sorted_uniform | 16384 | 64 | 22.8 μs | 2.9 μs | 2.2 μs | 5.0 μs | 2.4 μs | 2.2 μs | 2.2 μs | ExpFromLeft (2.2 μs) | 1.03x | -| sqrt | sorted_uniform | 16384 | 256 | 27.4 μs | 8.9 μs | 6.7 μs | 19.9 μs | 13.7 μs | 6.7 μs | 13.0 μs | ExpFromLeft (6.7 μs) | 1.01x | -| sqrt | sorted_uniform | 16384 | 1024 | 38.6 μs | 32.8 μs | 24.5 μs | 108.5 μs | 114.8 μs | 23.8 μs | 113.4 μs | ExpFromLeft (24.5 μs) | 0.97x | -| sqrt | sorted_uniform | 16384 | 4096 | 108.5 μs | 149.5 μs | 114.0 μs | 464.3 μs | 381.7 μs | 104.7 μs | 374.0 μs | Linear (108.5 μs) | 0.96x | -| sqrt | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 109 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | sorted_uniform | 65536 | 4 | 31.0 μs | 290 ns | 219 ns | 400 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | -| sqrt | sorted_uniform | 65536 | 16 | 82.0 μs | 1.0 μs | 750 ns | 1.5 μs | 690 ns | 760 ns | 650 ns | Binary (690 ns) | 1.10x | -| sqrt | sorted_uniform | 65536 | 64 | 92.8 μs | 3.6 μs | 2.6 μs | 5.8 μs | 2.9 μs | 2.7 μs | 2.8 μs | ExpFromLeft (2.6 μs) | 1.02x | -| sqrt | sorted_uniform | 65536 | 256 | 99.3 μs | 12.0 μs | 8.9 μs | 25.2 μs | 16.8 μs | 9.2 μs | 16.3 μs | ExpFromLeft (8.9 μs) | 1.03x | -| sqrt | sorted_uniform | 65536 | 1024 | 113.3 μs | 53.5 μs | 38.6 μs | 152.8 μs | 142.6 μs | 36.9 μs | 147.9 μs | ExpFromLeft (38.6 μs) | 0.96x | -| sqrt | sorted_uniform | 65536 | 4096 | 182.1 μs | 240.1 μs | 188.3 μs | 611.1 μs | 470.7 μs | 190.8 μs | 470.1 μs | Linear (182.1 μs) | 1.05x | -| sqrt | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| sqrt | sorted_dense_burst | 16 | 4 | 80 ns | 90 ns | 90 ns | 179 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| sqrt | sorted_dense_burst | 16 | 16 | 170 ns | 270 ns | 240 ns | 620 ns | 230 ns | 180 ns | 180 ns | Linear (170 ns) | 1.06x | -| sqrt | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 740 ns | 2.3 μs | 780 ns | 570 ns | 649 ns | Linear (550 ns) | 1.04x | -| sqrt | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.7 μs | 3.0 μs | 2.0 μs | 2.4 μs | Linear (2.0 μs) | 1.03x | -| sqrt | sorted_dense_burst | 16 | 1024 | 11.1 μs | 18.5 μs | 14.0 μs | 35.1 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (11.1 μs) | 0.70x | -| sqrt | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.9 μs | 41.9 μs | 139.9 μs | 47.2 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| sqrt | sorted_dense_burst | 64 | 4 | 90 ns | 110 ns | 100 ns | 200 ns | 110 ns | 100 ns | 90 ns | Linear (90 ns) | 1.11x | -| sqrt | sorted_dense_burst | 64 | 16 | 170 ns | 280 ns | 220 ns | 710 ns | 300 ns | 200 ns | 270 ns | Linear (170 ns) | 1.18x | -| sqrt | sorted_dense_burst | 64 | 64 | 550 ns | 939 ns | 730 ns | 2.6 μs | 1.1 μs | 580 ns | 940 ns | Linear (550 ns) | 1.05x | -| sqrt | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 10.2 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | -| sqrt | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.7 μs | 10.5 μs | 40.6 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | -| sqrt | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.0 μs | 42.0 μs | 161.9 μs | 66.5 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_dense_burst | 256 | 4 | 80 ns | 100 ns | 100 ns | 230 ns | 130 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | -| sqrt | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 240 ns | 850 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| sqrt | sorted_dense_burst | 256 | 64 | 760 ns | 1.2 μs | 940 ns | 3.3 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (760 ns) | 0.78x | -| sqrt | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 12.6 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.01x | -| sqrt | sorted_dense_burst | 256 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 50.4 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.8 μs) | 1.01x | -| sqrt | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.1 μs | 42.1 μs | 200.6 μs | 86.0 μs | 30.8 μs | 76.5 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 90 ns | 270 ns | 140 ns | 120 ns | 130 ns | ExpFromLeft (90 ns) | 1.33x | -| sqrt | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 240 ns | 1.0 μs | 450 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | -| sqrt | sorted_dense_burst | 1024 | 64 | 560 ns | 930 ns | 740 ns | 3.9 μs | 1.7 μs | 589 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| sqrt | sorted_dense_burst | 1024 | 256 | 2.8 μs | 4.7 μs | 3.6 μs | 15.5 μs | 6.8 μs | 2.9 μs | 5.9 μs | Linear (2.8 μs) | 1.01x | -| sqrt | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.5 μs | 60.5 μs | 26.4 μs | 7.8 μs | 23.9 μs | Linear (7.8 μs) | 1.00x | -| sqrt | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 42.1 μs | 241.7 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 110 ns | 310 ns | 160 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | -| sqrt | sorted_dense_burst | 4096 | 16 | 190 ns | 290 ns | 240 ns | 1.2 μs | 530 ns | 210 ns | 490 ns | Linear (190 ns) | 1.11x | -| sqrt | sorted_dense_burst | 4096 | 64 | 560 ns | 930 ns | 740 ns | 4.5 μs | 2.0 μs | 600 ns | 1.8 μs | Linear (560 ns) | 1.07x | -| sqrt | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 17.6 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| sqrt | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.6 μs | 70.4 μs | 31.1 μs | 7.8 μs | 28.5 μs | Linear (7.7 μs) | 1.01x | -| sqrt | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 281.6 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 350 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | -| sqrt | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 1.3 μs | 600 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | -| sqrt | sorted_dense_burst | 16384 | 64 | 570 ns | 940 ns | 750 ns | 5.1 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | -| sqrt | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 20.2 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.01x | -| sqrt | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 80.5 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | -| sqrt | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.1 μs | 42.1 μs | 321.9 μs | 144.1 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 390 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| sqrt | sorted_dense_burst | 65536 | 16 | 190 ns | 290 ns | 250 ns | 1.5 μs | 690 ns | 220 ns | 630 ns | Linear (190 ns) | 1.16x | -| sqrt | sorted_dense_burst | 65536 | 64 | 570 ns | 950 ns | 740 ns | 5.8 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| sqrt | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 23.3 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | -| sqrt | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 92.7 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.00x | -| sqrt | sorted_dense_burst | 65536 | 4096 | 44.3 μs | 73.8 μs | 55.8 μs | 371.4 μs | 163.2 μs | 30.8 μs | 152.5 μs | Linear (44.3 μs) | 0.70x | -| sqrt | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| sqrt | sorted_near_start | 16 | 4 | 80 ns | 100 ns | 100 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| sqrt | sorted_near_start | 16 | 16 | 180 ns | 280 ns | 240 ns | 510 ns | 220 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | -| sqrt | sorted_near_start | 16 | 64 | 570 ns | 940 ns | 749 ns | 2.0 μs | 800 ns | 600 ns | 670 ns | Linear (570 ns) | 1.05x | -| sqrt | sorted_near_start | 16 | 256 | 2.8 μs | 4.7 μs | 3.6 μs | 8.2 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.8 μs) | 0.72x | -| sqrt | sorted_near_start | 16 | 1024 | 7.8 μs | 14.0 μs | 10.7 μs | 30.1 μs | 12.2 μs | 7.9 μs | 10.3 μs | Linear (7.8 μs) | 1.00x | -| sqrt | sorted_near_start | 16 | 4096 | 31.1 μs | 55.2 μs | 42.2 μs | 119.1 μs | 47.7 μs | 31.1 μs | 40.3 μs | Linear (31.1 μs) | 1.00x | -| sqrt | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 70 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| sqrt | sorted_near_start | 64 | 4 | 100 ns | 110 ns | 100 ns | 180 ns | 100 ns | 120 ns | 90 ns | ExpFromLeft (100 ns) | 1.20x | -| sqrt | sorted_near_start | 64 | 16 | 210 ns | 290 ns | 230 ns | 560 ns | 360 ns | 230 ns | 310 ns | Linear (210 ns) | 1.10x | -| sqrt | sorted_near_start | 64 | 64 | 660 ns | 1.0 μs | 820 ns | 2.2 μs | 1.1 μs | 700 ns | 990 ns | Linear (660 ns) | 1.06x | -| sqrt | sorted_near_start | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 8.6 μs | 4.2 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | -| sqrt | sorted_near_start | 64 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 33.8 μs | 16.9 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.00x | -| sqrt | sorted_near_start | 64 | 4096 | 31.6 μs | 56.2 μs | 43.0 μs | 134.8 μs | 67.0 μs | 31.6 μs | 60.1 μs | Linear (31.6 μs) | 1.00x | -| sqrt | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 70 ns | 50 ns | ExpFromLeft (60 ns) | 1.17x | -| sqrt | sorted_near_start | 256 | 4 | 260 ns | 140 ns | 120 ns | 200 ns | 130 ns | 130 ns | 110 ns | ExpFromLeft (120 ns) | 1.08x | -| sqrt | sorted_near_start | 256 | 16 | 300 ns | 330 ns | 250 ns | 659 ns | 400 ns | 270 ns | 350 ns | ExpFromLeft (250 ns) | 1.08x | -| sqrt | sorted_near_start | 256 | 64 | 900 ns | 1.1 μs | 860 ns | 2.6 μs | 1.6 μs | 900 ns | 1.4 μs | ExpFromLeft (860 ns) | 1.05x | -| sqrt | sorted_near_start | 256 | 256 | 2.6 μs | 3.9 μs | 3.1 μs | 10.7 μs | 5.6 μs | 2.6 μs | 5.2 μs | Linear (2.6 μs) | 1.00x | -| sqrt | sorted_near_start | 256 | 1024 | 8.7 μs | 14.4 μs | 11.0 μs | 42.4 μs | 22.4 μs | 8.8 μs | 20.4 μs | Linear (8.7 μs) | 1.02x | -| sqrt | sorted_near_start | 256 | 4096 | 31.5 μs | 56.2 μs | 42.6 μs | 167.5 μs | 89.1 μs | 31.7 μs | 82.2 μs | Linear (31.5 μs) | 1.01x | -| sqrt | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| sqrt | sorted_near_start | 1024 | 4 | 1.0 μs | 180 ns | 160 ns | 250 ns | 140 ns | 180 ns | 130 ns | Binary (140 ns) | 1.29x | -| sqrt | sorted_near_start | 1024 | 16 | 1.3 μs | 410 ns | 320 ns | 840 ns | 450 ns | 350 ns | 450 ns | ExpFromLeft (320 ns) | 1.09x | -| sqrt | sorted_near_start | 1024 | 64 | 1.8 μs | 1.2 μs | 880 ns | 3.3 μs | 2.1 μs | 930 ns | 1.9 μs | ExpFromLeft (880 ns) | 1.06x | -| sqrt | sorted_near_start | 1024 | 256 | 3.6 μs | 4.5 μs | 3.3 μs | 13.5 μs | 7.6 μs | 3.6 μs | 7.0 μs | ExpFromLeft (3.3 μs) | 1.09x | -| sqrt | sorted_near_start | 1024 | 1024 | 10.4 μs | 15.8 μs | 12.2 μs | 53.4 μs | 27.4 μs | 10.5 μs | 25.5 μs | Linear (10.4 μs) | 1.01x | -| sqrt | sorted_near_start | 1024 | 4096 | 33.8 μs | 58.0 μs | 44.1 μs | 211.7 μs | 111.5 μs | 34.0 μs | 105.3 μs | Linear (33.8 μs) | 1.01x | -| sqrt | sorted_near_start | 4096 | 1 | 70 ns | 60 ns | 70 ns | 90 ns | 70 ns | 70 ns | 60 ns | Gallop (60 ns) | 1.17x | -| sqrt | sorted_near_start | 4096 | 4 | 900 ns | 170 ns | 160 ns | 280 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (160 ns) | 1.06x | -| sqrt | sorted_near_start | 4096 | 16 | 5.1 μs | 530 ns | 420 ns | 960 ns | 520 ns | 450 ns | 490 ns | ExpFromLeft (420 ns) | 1.07x | -| sqrt | sorted_near_start | 4096 | 64 | 4.3 μs | 1.5 μs | 1.1 μs | 3.9 μs | 2.5 μs | 1.1 μs | 2.3 μs | ExpFromLeft (1.1 μs) | 1.04x | -| sqrt | sorted_near_start | 4096 | 256 | 8.1 μs | 4.8 μs | 3.4 μs | 15.9 μs | 10.5 μs | 3.5 μs | 9.7 μs | ExpFromLeft (3.4 μs) | 1.02x | -| sqrt | sorted_near_start | 4096 | 1024 | 16.3 μs | 18.4 μs | 14.0 μs | 67.1 μs | 42.6 μs | 16.1 μs | 37.3 μs | ExpFromLeft (14.0 μs) | 1.15x | -| sqrt | sorted_near_start | 4096 | 4096 | 43.0 μs | 63.3 μs | 49.1 μs | 271.4 μs | 156.0 μs | 43.0 μs | 140.1 μs | Linear (43.0 μs) | 1.00x | -| sqrt | sorted_near_start | 16384 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_near_start | 16384 | 4 | 3.1 μs | 230 ns | 180 ns | 320 ns | 190 ns | 220 ns | 170 ns | ExpFromLeft (180 ns) | 1.22x | -| sqrt | sorted_near_start | 16384 | 16 | 17.3 μs | 630 ns | 500 ns | 1.2 μs | 600 ns | 500 ns | 550 ns | ExpFromLeft (500 ns) | 1.00x | -| sqrt | sorted_near_start | 16384 | 64 | 15.3 μs | 1.8 μs | 1.4 μs | 4.4 μs | 3.0 μs | 1.4 μs | 2.9 μs | ExpFromLeft (1.4 μs) | 1.02x | -| sqrt | sorted_near_start | 16384 | 256 | 24.6 μs | 5.9 μs | 4.2 μs | 18.8 μs | 17.9 μs | 4.3 μs | 16.5 μs | ExpFromLeft (4.2 μs) | 1.01x | -| sqrt | sorted_near_start | 16384 | 1024 | 33.4 μs | 21.2 μs | 14.8 μs | 83.0 μs | 73.8 μs | 15.3 μs | 69.0 μs | ExpFromLeft (14.8 μs) | 1.03x | -| sqrt | sorted_near_start | 16384 | 4096 | 70.4 μs | 77.6 μs | 60.7 μs | 364.8 μs | 246.2 μs | 70.3 μs | 231.9 μs | ExpFromLeft (60.7 μs) | 1.16x | -| sqrt | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | sorted_near_start | 65536 | 4 | 74.8 μs | 260 ns | 230 ns | 370 ns | 200 ns | 240 ns | 180 ns | Binary (200 ns) | 1.20x | -| sqrt | sorted_near_start | 65536 | 16 | 36.1 μs | 710 ns | 540 ns | 1.3 μs | 770 ns | 560 ns | 740 ns | ExpFromLeft (540 ns) | 1.04x | -| sqrt | sorted_near_start | 65536 | 64 | 82.6 μs | 2.4 μs | 1.8 μs | 5.1 μs | 3.7 μs | 1.8 μs | 3.6 μs | ExpFromLeft (1.8 μs) | 1.02x | -| sqrt | sorted_near_start | 65536 | 256 | 72.4 μs | 7.6 μs | 5.7 μs | 21.7 μs | 20.3 μs | 5.6 μs | 18.7 μs | ExpFromLeft (5.7 μs) | 0.99x | -| sqrt | sorted_near_start | 65536 | 1024 | 102.0 μs | 27.0 μs | 19.4 μs | 109.6 μs | 90.3 μs | 19.1 μs | 86.5 μs | ExpFromLeft (19.4 μs) | 0.98x | -| sqrt | sorted_near_start | 65536 | 4096 | 152.8 μs | 114.1 μs | 89.4 μs | 477.5 μs | 310.2 μs | 88.1 μs | 289.8 μs | ExpFromLeft (89.4 μs) | 0.99x | -| sqrt | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| sqrt | sorted_arithmetic | 16 | 4 | 100 ns | 120 ns | 110 ns | 160 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | -| sqrt | sorted_arithmetic | 16 | 16 | 190 ns | 290 ns | 220 ns | 540 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| sqrt | sorted_arithmetic | 16 | 64 | 559 ns | 1.1 μs | 750 ns | 2.1 μs | 1.1 μs | 590 ns | 890 ns | Linear (559 ns) | 1.06x | -| sqrt | sorted_arithmetic | 16 | 256 | 2.3 μs | 3.8 μs | 3.0 μs | 8.6 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (2.3 μs) | 1.01x | -| sqrt | sorted_arithmetic | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 32.8 μs | 12.0 μs | 8.1 μs | 10.4 μs | Linear (8.1 μs) | 1.00x | -| sqrt | sorted_arithmetic | 16 | 4096 | 31.1 μs | 55.8 μs | 42.4 μs | 129.1 μs | 47.2 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | -| sqrt | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 50 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| sqrt | sorted_arithmetic | 64 | 4 | 170 ns | 140 ns | 120 ns | 170 ns | 110 ns | 140 ns | 100 ns | Binary (110 ns) | 1.27x | -| sqrt | sorted_arithmetic | 64 | 16 | 270 ns | 370 ns | 290 ns | 660 ns | 300 ns | 300 ns | 270 ns | Linear (270 ns) | 1.11x | -| sqrt | sorted_arithmetic | 64 | 64 | 640 ns | 1.1 μs | 750 ns | 2.6 μs | 1.3 μs | 660 ns | 1.1 μs | Linear (640 ns) | 1.03x | -| sqrt | sorted_arithmetic | 64 | 256 | 2.4 μs | 4.1 μs | 3.1 μs | 10.8 μs | 5.4 μs | 2.5 μs | 5.0 μs | Linear (2.4 μs) | 1.02x | -| sqrt | sorted_arithmetic | 64 | 1024 | 9.1 μs | 14.9 μs | 11.7 μs | 43.2 μs | 17.7 μs | 9.1 μs | 16.0 μs | Linear (9.1 μs) | 1.00x | -| sqrt | sorted_arithmetic | 64 | 4096 | 45.2 μs | 74.8 μs | 56.6 μs | 164.8 μs | 67.0 μs | 32.2 μs | 60.2 μs | Linear (45.2 μs) | 0.71x | -| sqrt | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_arithmetic | 256 | 4 | 480 ns | 160 ns | 150 ns | 190 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | -| sqrt | sorted_arithmetic | 256 | 16 | 530 ns | 470 ns | 370 ns | 760 ns | 370 ns | 400 ns | 330 ns | ExpFromLeft (370 ns) | 1.08x | -| sqrt | sorted_arithmetic | 256 | 64 | 960 ns | 1.4 μs | 1.0 μs | 3.0 μs | 1.4 μs | 930 ns | 1.2 μs | Linear (960 ns) | 0.97x | -| sqrt | sorted_arithmetic | 256 | 256 | 2.5 μs | 4.5 μs | 3.0 μs | 12.4 μs | 6.4 μs | 2.6 μs | 6.0 μs | Linear (2.5 μs) | 1.01x | -| sqrt | sorted_arithmetic | 256 | 1024 | 9.7 μs | 16.2 μs | 12.3 μs | 53.6 μs | 28.0 μs | 9.7 μs | 25.9 μs | Linear (9.7 μs) | 1.00x | -| sqrt | sorted_arithmetic | 256 | 4096 | 47.0 μs | 58.7 μs | 45.2 μs | 200.5 μs | 90.7 μs | 34.9 μs | 83.8 μs | ExpFromLeft (45.2 μs) | 0.77x | -| sqrt | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| sqrt | sorted_arithmetic | 1024 | 4 | 1.6 μs | 200 ns | 180 ns | 210 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| sqrt | sorted_arithmetic | 1024 | 16 | 1.8 μs | 610 ns | 480 ns | 890 ns | 440 ns | 500 ns | 420 ns | Binary (440 ns) | 1.14x | -| sqrt | sorted_arithmetic | 1024 | 64 | 2.2 μs | 1.8 μs | 1.4 μs | 3.6 μs | 1.7 μs | 1.4 μs | 1.5 μs | ExpFromLeft (1.4 μs) | 1.04x | -| sqrt | sorted_arithmetic | 1024 | 256 | 3.7 μs | 5.7 μs | 4.3 μs | 15.2 μs | 7.3 μs | 3.7 μs | 7.8 μs | Linear (3.7 μs) | 1.00x | -| sqrt | sorted_arithmetic | 1024 | 1024 | 10.7 μs | 18.4 μs | 12.3 μs | 63.9 μs | 69.2 μs | 10.8 μs | 67.6 μs | Linear (10.7 μs) | 1.01x | -| sqrt | sorted_arithmetic | 1024 | 4096 | 38.9 μs | 62.4 μs | 47.7 μs | 270.5 μs | 200.8 μs | 49.7 μs | 196.3 μs | Linear (38.9 μs) | 1.28x | -| sqrt | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_arithmetic | 4096 | 4 | 6.0 μs | 230 ns | 190 ns | 230 ns | 160 ns | 230 ns | 150 ns | Binary (160 ns) | 1.44x | -| sqrt | sorted_arithmetic | 4096 | 16 | 6.2 μs | 760 ns | 570 ns | 1.0 μs | 530 ns | 600 ns | 480 ns | Binary (530 ns) | 1.13x | -| sqrt | sorted_arithmetic | 4096 | 64 | 7.0 μs | 2.4 μs | 1.8 μs | 4.2 μs | 2.0 μs | 1.9 μs | 1.8 μs | ExpFromLeft (1.8 μs) | 1.03x | -| sqrt | sorted_arithmetic | 4096 | 256 | 8.7 μs | 7.4 μs | 5.5 μs | 17.5 μs | 11.4 μs | 5.6 μs | 10.1 μs | ExpFromLeft (5.5 μs) | 1.03x | -| sqrt | sorted_arithmetic | 4096 | 1024 | 16.4 μs | 23.9 μs | 18.1 μs | 85.5 μs | 92.4 μs | 16.3 μs | 86.4 μs | Linear (16.4 μs) | 1.00x | -| sqrt | sorted_arithmetic | 4096 | 4096 | 44.0 μs | 73.6 μs | 49.7 μs | 355.0 μs | 306.9 μs | 44.1 μs | 293.1 μs | Linear (44.0 μs) | 1.00x | -| sqrt | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 119 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_arithmetic | 16384 | 4 | 23.4 μs | 270 ns | 220 ns | 250 ns | 180 ns | 250 ns | 170 ns | Binary (180 ns) | 1.39x | -| sqrt | sorted_arithmetic | 16384 | 16 | 23.9 μs | 910 ns | 680 ns | 1.2 μs | 600 ns | 700 ns | 570 ns | Binary (600 ns) | 1.17x | -| sqrt | sorted_arithmetic | 16384 | 64 | 24.5 μs | 3.1 μs | 2.3 μs | 4.9 μs | 2.5 μs | 2.3 μs | 2.3 μs | ExpFromLeft (2.3 μs) | 1.01x | -| sqrt | sorted_arithmetic | 16384 | 256 | 28.9 μs | 10.0 μs | 7.4 μs | 20.1 μs | 15.0 μs | 7.4 μs | 13.9 μs | ExpFromLeft (7.4 μs) | 1.01x | -| sqrt | sorted_arithmetic | 16384 | 1024 | 35.8 μs | 32.0 μs | 23.8 μs | 110.8 μs | 121.2 μs | 24.3 μs | 119.4 μs | ExpFromLeft (23.8 μs) | 1.02x | -| sqrt | sorted_arithmetic | 16384 | 4096 | 65.8 μs | 96.7 μs | 72.0 μs | 477.3 μs | 409.7 μs | 65.8 μs | 395.6 μs | Linear (65.8 μs) | 1.00x | -| sqrt | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | sorted_arithmetic | 65536 | 4 | 93.0 μs | 300 ns | 250 ns | 270 ns | 200 ns | 280 ns | 190 ns | Binary (200 ns) | 1.40x | -| sqrt | sorted_arithmetic | 65536 | 16 | 93.4 μs | 1.4 μs | 1.0 μs | 1.4 μs | 710 ns | 810 ns | 640 ns | Binary (710 ns) | 1.14x | -| sqrt | sorted_arithmetic | 65536 | 64 | 95.2 μs | 3.6 μs | 2.7 μs | 5.7 μs | 2.8 μs | 2.7 μs | 2.7 μs | ExpFromLeft (2.7 μs) | 1.01x | -| sqrt | sorted_arithmetic | 65536 | 256 | 97.8 μs | 13.2 μs | 10.1 μs | 23.9 μs | 15.9 μs | 10.2 μs | 15.6 μs | ExpFromLeft (10.1 μs) | 1.01x | -| sqrt | sorted_arithmetic | 65536 | 1024 | 111.7 μs | 45.2 μs | 34.4 μs | 159.6 μs | 147.9 μs | 34.5 μs | 153.0 μs | ExpFromLeft (34.4 μs) | 1.00x | -| sqrt | sorted_arithmetic | 65536 | 4096 | 142.1 μs | 131.1 μs | 99.8 μs | 643.9 μs | 495.4 μs | 101.4 μs | 499.6 μs | ExpFromLeft (99.8 μs) | 1.02x | -| sqrt | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 60 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| sqrt | sorted_geometric | 16 | 4 | 100 ns | 120 ns | 100 ns | 150 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | -| sqrt | sorted_geometric | 16 | 16 | 190 ns | 290 ns | 220 ns | 510 ns | 240 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| sqrt | sorted_geometric | 16 | 64 | 590 ns | 970 ns | 750 ns | 2.0 μs | 1.0 μs | 790 ns | 840 ns | Linear (590 ns) | 1.34x | -| sqrt | sorted_geometric | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 8.1 μs | 3.3 μs | 2.2 μs | 2.8 μs | Linear (2.2 μs) | 1.02x | -| sqrt | sorted_geometric | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 31.4 μs | 12.2 μs | 8.1 μs | 10.3 μs | Linear (8.1 μs) | 1.00x | -| sqrt | sorted_geometric | 16 | 4096 | 31.1 μs | 55.7 μs | 42.3 μs | 123.1 μs | 47.6 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | -| sqrt | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| sqrt | sorted_geometric | 64 | 4 | 170 ns | 130 ns | 120 ns | 170 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | -| sqrt | sorted_geometric | 64 | 16 | 259 ns | 340 ns | 260 ns | 600 ns | 300 ns | 280 ns | 260 ns | Linear (259 ns) | 1.08x | -| sqrt | sorted_geometric | 64 | 64 | 650 ns | 1.1 μs | 790 ns | 2.4 μs | 1.2 μs | 700 ns | 1.1 μs | Linear (650 ns) | 1.08x | -| sqrt | sorted_geometric | 64 | 256 | 2.3 μs | 3.9 μs | 2.9 μs | 9.9 μs | 4.9 μs | 2.3 μs | 4.3 μs | Linear (2.3 μs) | 1.00x | -| sqrt | sorted_geometric | 64 | 1024 | 8.6 μs | 14.8 μs | 11.4 μs | 38.8 μs | 17.6 μs | 8.6 μs | 16.0 μs | Linear (8.6 μs) | 1.00x | -| sqrt | sorted_geometric | 64 | 4096 | 32.1 μs | 56.4 μs | 43.2 μs | 149.3 μs | 67.0 μs | 32.2 μs | 60.4 μs | Linear (32.1 μs) | 1.00x | -| sqrt | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_geometric | 256 | 4 | 450 ns | 150 ns | 130 ns | 180 ns | 130 ns | 160 ns | 110 ns | ExpFromLeft (130 ns) | 1.23x | -| sqrt | sorted_geometric | 256 | 16 | 640 ns | 470 ns | 420 ns | 730 ns | 400 ns | 440 ns | 350 ns | Binary (400 ns) | 1.10x | -| sqrt | sorted_geometric | 256 | 64 | 920 ns | 1.3 μs | 980 ns | 2.8 μs | 1.5 μs | 960 ns | 1.4 μs | Linear (920 ns) | 1.04x | -| sqrt | sorted_geometric | 256 | 256 | 2.5 μs | 4.3 μs | 3.0 μs | 11.7 μs | 6.1 μs | 2.5 μs | 5.7 μs | Linear (2.5 μs) | 1.01x | -| sqrt | sorted_geometric | 256 | 1024 | 9.2 μs | 15.6 μs | 11.6 μs | 48.8 μs | 25.0 μs | 9.2 μs | 23.7 μs | Linear (9.2 μs) | 1.01x | -| sqrt | sorted_geometric | 256 | 4096 | 34.1 μs | 58.6 μs | 44.8 μs | 187.2 μs | 90.8 μs | 34.0 μs | 84.0 μs | Linear (34.1 μs) | 1.00x | -| sqrt | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_geometric | 1024 | 4 | 1.5 μs | 200 ns | 160 ns | 200 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| sqrt | sorted_geometric | 1024 | 16 | 1.7 μs | 550 ns | 410 ns | 830 ns | 440 ns | 460 ns | 410 ns | ExpFromLeft (410 ns) | 1.12x | -| sqrt | sorted_geometric | 1024 | 64 | 2.1 μs | 1.6 μs | 1.2 μs | 3.4 μs | 1.8 μs | 1.2 μs | 1.7 μs | ExpFromLeft (1.2 μs) | 1.03x | -| sqrt | sorted_geometric | 1024 | 256 | 3.6 μs | 5.2 μs | 3.7 μs | 14.0 μs | 7.3 μs | 3.6 μs | 7.1 μs | Linear (3.6 μs) | 1.01x | -| sqrt | sorted_geometric | 1024 | 1024 | 10.5 μs | 17.8 μs | 12.6 μs | 60.3 μs | 38.4 μs | 10.5 μs | 35.3 μs | Linear (10.5 μs) | 1.00x | -| sqrt | sorted_geometric | 1024 | 4096 | 36.7 μs | 62.4 μs | 46.7 μs | 243.4 μs | 179.3 μs | 36.9 μs | 174.5 μs | Linear (36.7 μs) | 1.00x | -| sqrt | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| sqrt | sorted_geometric | 4096 | 4 | 5.6 μs | 220 ns | 190 ns | 220 ns | 160 ns | 210 ns | 140 ns | Binary (160 ns) | 1.31x | -| sqrt | sorted_geometric | 4096 | 16 | 6.0 μs | 670 ns | 510 ns | 960 ns | 530 ns | 540 ns | 490 ns | ExpFromLeft (510 ns) | 1.06x | -| sqrt | sorted_geometric | 4096 | 64 | 6.7 μs | 2.1 μs | 1.6 μs | 4.0 μs | 2.1 μs | 1.6 μs | 1.9 μs | ExpFromLeft (1.6 μs) | 1.03x | -| sqrt | sorted_geometric | 4096 | 256 | 8.6 μs | 6.6 μs | 4.9 μs | 16.2 μs | 9.9 μs | 5.0 μs | 9.0 μs | ExpFromLeft (4.9 μs) | 1.03x | -| sqrt | sorted_geometric | 4096 | 1024 | 15.7 μs | 21.5 μs | 15.7 μs | 76.2 μs | 67.3 μs | 15.9 μs | 59.4 μs | Linear (15.7 μs) | 1.01x | -| sqrt | sorted_geometric | 4096 | 4096 | 43.8 μs | 72.2 μs | 51.6 μs | 327.5 μs | 254.1 μs | 43.9 μs | 244.7 μs | Linear (43.8 μs) | 1.00x | -| sqrt | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| sqrt | sorted_geometric | 16384 | 4 | 23.4 μs | 250 ns | 220 ns | 230 ns | 180 ns | 240 ns | 170 ns | Binary (180 ns) | 1.33x | -| sqrt | sorted_geometric | 16384 | 16 | 23.7 μs | 810 ns | 600 ns | 1.1 μs | 600 ns | 630 ns | 560 ns | ExpFromLeft (600 ns) | 1.05x | -| sqrt | sorted_geometric | 16384 | 64 | 24.4 μs | 2.7 μs | 2.0 μs | 4.6 μs | 2.8 μs | 2.0 μs | 2.5 μs | ExpFromLeft (2.0 μs) | 1.02x | -| sqrt | sorted_geometric | 16384 | 256 | 26.8 μs | 8.7 μs | 6.4 μs | 19.1 μs | 15.9 μs | 6.3 μs | 14.5 μs | ExpFromLeft (6.4 μs) | 1.00x | -| sqrt | sorted_geometric | 16384 | 1024 | 35.9 μs | 27.2 μs | 20.2 μs | 101.0 μs | 97.0 μs | 20.7 μs | 91.5 μs | ExpFromLeft (20.2 μs) | 1.02x | -| sqrt | sorted_geometric | 16384 | 4096 | 65.3 μs | 89.2 μs | 65.7 μs | 435.2 μs | 347.9 μs | 65.4 μs | 341.0 μs | Linear (65.3 μs) | 1.00x | -| sqrt | sorted_geometric | 65536 | 1 | 80 ns | 79 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | -| sqrt | sorted_geometric | 65536 | 4 | 88.3 μs | 290 ns | 240 ns | 260 ns | 210 ns | 270 ns | 190 ns | Binary (210 ns) | 1.29x | -| sqrt | sorted_geometric | 65536 | 16 | 88.2 μs | 980 ns | 730 ns | 1.3 μs | 680 ns | 730 ns | 650 ns | Binary (680 ns) | 1.07x | -| sqrt | sorted_geometric | 65536 | 64 | 91.0 μs | 3.3 μs | 2.4 μs | 5.4 μs | 3.1 μs | 2.5 μs | 2.8 μs | ExpFromLeft (2.4 μs) | 1.01x | -| sqrt | sorted_geometric | 65536 | 256 | 96.0 μs | 10.9 μs | 8.1 μs | 23.2 μs | 20.0 μs | 8.2 μs | 17.5 μs | ExpFromLeft (8.1 μs) | 1.00x | -| sqrt | sorted_geometric | 65536 | 1024 | 107.7 μs | 41.4 μs | 30.3 μs | 144.0 μs | 124.0 μs | 30.0 μs | 124.0 μs | ExpFromLeft (30.3 μs) | 0.99x | -| sqrt | sorted_geometric | 65536 | 4096 | 142.4 μs | 119.2 μs | 90.8 μs | 578.3 μs | 433.7 μs | 91.4 μs | 424.1 μs | ExpFromLeft (90.8 μs) | 1.01x | -| sqrt | sorted_bimodal | 16 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| sqrt | sorted_bimodal | 16 | 4 | 90 ns | 110 ns | 100 ns | 150 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | -| sqrt | sorted_bimodal | 16 | 16 | 190 ns | 290 ns | 210 ns | 489 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| sqrt | sorted_bimodal | 16 | 64 | 580 ns | 950 ns | 760 ns | 1.9 μs | 860 ns | 610 ns | 760 ns | Linear (580 ns) | 1.05x | -| sqrt | sorted_bimodal | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 7.2 μs | 3.2 μs | 2.1 μs | 2.7 μs | Linear (2.1 μs) | 1.01x | -| sqrt | sorted_bimodal | 16 | 1024 | 7.8 μs | 13.7 μs | 10.6 μs | 28.1 μs | 12.3 μs | 7.8 μs | 10.6 μs | Linear (7.8 μs) | 1.01x | -| sqrt | sorted_bimodal | 16 | 4096 | 30.9 μs | 54.1 μs | 42.1 μs | 111.7 μs | 49.1 μs | 30.9 μs | 42.0 μs | Linear (30.9 μs) | 1.00x | -| sqrt | sorted_bimodal | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| sqrt | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 120 ns | 170 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | -| sqrt | sorted_bimodal | 64 | 16 | 260 ns | 300 ns | 240 ns | 520 ns | 330 ns | 280 ns | 300 ns | ExpFromLeft (240 ns) | 1.17x | -| sqrt | sorted_bimodal | 64 | 64 | 640 ns | 990 ns | 760 ns | 2.1 μs | 1.2 μs | 680 ns | 1.2 μs | Linear (640 ns) | 1.06x | -| sqrt | sorted_bimodal | 64 | 256 | 2.2 μs | 4.9 μs | 3.7 μs | 8.5 μs | 4.3 μs | 2.3 μs | 4.0 μs | Linear (2.2 μs) | 1.01x | -| sqrt | sorted_bimodal | 64 | 1024 | 8.1 μs | 14.0 μs | 10.8 μs | 31.8 μs | 16.9 μs | 8.1 μs | 15.2 μs | Linear (8.1 μs) | 1.01x | -| sqrt | sorted_bimodal | 64 | 4096 | 31.1 μs | 54.9 μs | 42.3 μs | 126.8 μs | 66.6 μs | 31.1 μs | 60.2 μs | Linear (31.1 μs) | 1.00x | -| sqrt | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 80 ns | 80 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | -| sqrt | sorted_bimodal | 256 | 4 | 440 ns | 140 ns | 130 ns | 180 ns | 120 ns | 150 ns | 110 ns | Binary (120 ns) | 1.25x | -| sqrt | sorted_bimodal | 256 | 16 | 540 ns | 360 ns | 280 ns | 660 ns | 390 ns | 370 ns | 350 ns | ExpFromLeft (280 ns) | 1.32x | -| sqrt | sorted_bimodal | 256 | 64 | 920 ns | 1.1 μs | 800 ns | 2.5 μs | 1.7 μs | 940 ns | 1.5 μs | ExpFromLeft (800 ns) | 1.18x | -| sqrt | sorted_bimodal | 256 | 256 | 2.4 μs | 3.9 μs | 2.8 μs | 10.2 μs | 6.4 μs | 2.5 μs | 6.0 μs | Linear (2.4 μs) | 1.02x | -| sqrt | sorted_bimodal | 256 | 1024 | 9.1 μs | 14.7 μs | 11.5 μs | 40.1 μs | 22.6 μs | 9.1 μs | 20.7 μs | Linear (9.1 μs) | 1.00x | -| sqrt | sorted_bimodal | 256 | 4096 | 32.2 μs | 55.9 μs | 43.0 μs | 154.0 μs | 87.0 μs | 32.2 μs | 79.5 μs | Linear (32.2 μs) | 1.00x | -| sqrt | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 80 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_bimodal | 1024 | 4 | 1.4 μs | 150 ns | 140 ns | 220 ns | 140 ns | 160 ns | 120 ns | ExpFromLeft (140 ns) | 1.14x | -| sqrt | sorted_bimodal | 1024 | 16 | 1.6 μs | 420 ns | 330 ns | 750 ns | 500 ns | 350 ns | 440 ns | ExpFromLeft (330 ns) | 1.06x | -| sqrt | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 950 ns | 3.0 μs | 1.9 μs | 980 ns | 1.8 μs | ExpFromLeft (950 ns) | 1.03x | -| sqrt | sorted_bimodal | 1024 | 256 | 3.6 μs | 4.3 μs | 3.0 μs | 12.4 μs | 7.5 μs | 3.6 μs | 7.0 μs | ExpFromLeft (3.0 μs) | 1.21x | -| sqrt | sorted_bimodal | 1024 | 1024 | 9.9 μs | 15.5 μs | 11.7 μs | 49.8 μs | 30.2 μs | 10.3 μs | 28.4 μs | Linear (9.9 μs) | 1.04x | -| sqrt | sorted_bimodal | 1024 | 4096 | 36.5 μs | 58.6 μs | 45.8 μs | 195.3 μs | 108.1 μs | 36.6 μs | 101.5 μs | Linear (36.5 μs) | 1.00x | -| sqrt | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_bimodal | 4096 | 4 | 5.5 μs | 210 ns | 170 ns | 270 ns | 160 ns | 190 ns | 150 ns | Binary (160 ns) | 1.19x | -| sqrt | sorted_bimodal | 4096 | 16 | 5.9 μs | 570 ns | 450 ns | 910 ns | 520 ns | 470 ns | 480 ns | ExpFromLeft (450 ns) | 1.04x | -| sqrt | sorted_bimodal | 4096 | 64 | 5.9 μs | 1.5 μs | 1.1 μs | 3.5 μs | 2.3 μs | 1.2 μs | 2.2 μs | ExpFromLeft (1.1 μs) | 1.03x | -| sqrt | sorted_bimodal | 4096 | 256 | 7.8 μs | 4.8 μs | 3.6 μs | 15.0 μs | 10.5 μs | 3.7 μs | 9.5 μs | ExpFromLeft (3.6 μs) | 1.03x | -| sqrt | sorted_bimodal | 4096 | 1024 | 14.8 μs | 16.8 μs | 12.3 μs | 64.4 μs | 43.8 μs | 14.6 μs | 41.1 μs | ExpFromLeft (12.3 μs) | 1.18x | -| sqrt | sorted_bimodal | 4096 | 4096 | 45.2 μs | 66.3 μs | 49.0 μs | 261.8 μs | 170.5 μs | 44.8 μs | 157.4 μs | Linear (45.2 μs) | 0.99x | -| sqrt | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 80 ns | 110 ns | 70 ns | 70 ns | 60 ns | Binary (70 ns) | 1.00x | -| sqrt | sorted_bimodal | 16384 | 4 | 18.8 μs | 250 ns | 210 ns | 310 ns | 179 ns | 240 ns | 160 ns | Binary (179 ns) | 1.34x | -| sqrt | sorted_bimodal | 16384 | 16 | 22.9 μs | 680 ns | 520 ns | 1.1 μs | 650 ns | 550 ns | 650 ns | ExpFromLeft (520 ns) | 1.06x | -| sqrt | sorted_bimodal | 16384 | 64 | 23.9 μs | 2.0 μs | 1.5 μs | 4.3 μs | 3.1 μs | 1.5 μs | 3.0 μs | ExpFromLeft (1.5 μs) | 1.03x | -| sqrt | sorted_bimodal | 16384 | 256 | 24.1 μs | 6.0 μs | 4.4 μs | 17.3 μs | 14.9 μs | 4.6 μs | 14.8 μs | ExpFromLeft (4.4 μs) | 1.03x | -| sqrt | sorted_bimodal | 16384 | 1024 | 32.8 μs | 20.6 μs | 15.2 μs | 81.5 μs | 77.4 μs | 16.3 μs | 73.8 μs | ExpFromLeft (15.2 μs) | 1.07x | -| sqrt | sorted_bimodal | 16384 | 4096 | 68.2 μs | 75.1 μs | 55.8 μs | 366.4 μs | 246.8 μs | 67.4 μs | 235.8 μs | ExpFromLeft (55.8 μs) | 1.21x | -| sqrt | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | sorted_bimodal | 65536 | 4 | 84.1 μs | 280 ns | 230 ns | 340 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | -| sqrt | sorted_bimodal | 65536 | 16 | 83.5 μs | 780 ns | 600 ns | 1.2 μs | 720 ns | 600 ns | 670 ns | ExpFromLeft (600 ns) | 1.00x | -| sqrt | sorted_bimodal | 65536 | 64 | 92.0 μs | 2.5 μs | 1.9 μs | 4.8 μs | 3.4 μs | 1.9 μs | 3.2 μs | ExpFromLeft (1.9 μs) | 1.03x | -| sqrt | sorted_bimodal | 65536 | 256 | 96.2 μs | 7.9 μs | 5.8 μs | 20.2 μs | 18.6 μs | 5.9 μs | 17.0 μs | ExpFromLeft (5.8 μs) | 1.01x | -| sqrt | sorted_bimodal | 65536 | 1024 | 106.5 μs | 27.1 μs | 20.1 μs | 108.5 μs | 98.3 μs | 21.1 μs | 96.7 μs | ExpFromLeft (20.1 μs) | 1.05x | -| sqrt | sorted_bimodal | 65536 | 4096 | 152.5 μs | 115.3 μs | 88.0 μs | 469.1 μs | 314.1 μs | 85.6 μs | 301.3 μs | ExpFromLeft (88.0 μs) | 0.97x | -| sqrt | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| sqrt | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 160 ns | 90 ns | 100 ns | 80 ns | Linear (80 ns) | 1.25x | -| sqrt | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 210 ns | 560 ns | 220 ns | 190 ns | 180 ns | Linear (170 ns) | 1.12x | -| sqrt | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 690 ns | 2.0 μs | 790 ns | 580 ns | 660 ns | Linear (550 ns) | 1.05x | -| sqrt | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 7.9 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.01x | -| sqrt | sorted_repeated | 16 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 31.4 μs | 11.9 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.00x | -| sqrt | sorted_repeated | 16 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 124.8 μs | 47.2 μs | 30.8 μs | 38.4 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| sqrt | sorted_repeated | 64 | 4 | 80 ns | 100 ns | 90 ns | 200 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| sqrt | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 210 ns | 710 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | -| sqrt | sorted_repeated | 64 | 64 | 550 ns | 920 ns | 710 ns | 2.7 μs | 1.1 μs | 580 ns | 920 ns | Linear (550 ns) | 1.05x | -| sqrt | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 10.6 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.01x | -| sqrt | sorted_repeated | 64 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 42.3 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | -| sqrt | sorted_repeated | 64 | 4096 | 30.8 μs | 54.9 μs | 39.1 μs | 168.3 μs | 66.5 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_repeated | 256 | 1 | 60 ns | 70 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_repeated | 256 | 4 | 80 ns | 100 ns | 100 ns | 230 ns | 130 ns | 120 ns | 110 ns | Linear (80 ns) | 1.50x | -| sqrt | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 830 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| sqrt | sorted_repeated | 256 | 64 | 560 ns | 930 ns | 700 ns | 3.2 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (560 ns) | 1.05x | -| sqrt | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 12.6 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| sqrt | sorted_repeated | 256 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 50.2 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.8 μs) | 1.00x | -| sqrt | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 200.8 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 60 ns | 60 ns | 70 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 90 ns | 270 ns | 140 ns | 110 ns | 120 ns | ExpFromLeft (90 ns) | 1.22x | -| sqrt | sorted_repeated | 1024 | 16 | 179 ns | 280 ns | 230 ns | 990 ns | 450 ns | 210 ns | 420 ns | Linear (179 ns) | 1.17x | -| sqrt | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 700 ns | 3.8 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| sqrt | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 15.1 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | -| sqrt | sorted_repeated | 1024 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 60.4 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.01x | -| sqrt | sorted_repeated | 1024 | 4096 | 30.8 μs | 54.9 μs | 39.0 μs | 241.1 μs | 105.5 μs | 30.8 μs | 95.7 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 330 ns | 160 ns | 120 ns | 140 ns | Linear (90 ns) | 1.33x | -| sqrt | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 1.1 μs | 530 ns | 210 ns | 480 ns | Linear (180 ns) | 1.17x | -| sqrt | sorted_repeated | 4096 | 64 | 560 ns | 930 ns | 710 ns | 4.4 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | -| sqrt | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 17.5 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| sqrt | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 70.0 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 0.99x | -| sqrt | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 279.5 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_repeated | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | sorted_repeated | 16384 | 4 | 100 ns | 110 ns | 110 ns | 360 ns | 180 ns | 120 ns | 170 ns | Linear (100 ns) | 1.20x | -| sqrt | sorted_repeated | 16384 | 16 | 180 ns | 300 ns | 220 ns | 1.3 μs | 610 ns | 220 ns | 570 ns | Linear (180 ns) | 1.22x | -| sqrt | sorted_repeated | 16384 | 64 | 570 ns | 940 ns | 880 ns | 5.2 μs | 2.3 μs | 790 ns | 2.1 μs | Linear (570 ns) | 1.39x | -| sqrt | sorted_repeated | 16384 | 256 | 2.0 μs | 3.6 μs | 2.6 μs | 20.1 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | -| sqrt | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 80.5 μs | 36.0 μs | 7.8 μs | 33.5 μs | Linear (7.8 μs) | 1.00x | -| sqrt | sorted_repeated | 16384 | 4096 | 30.8 μs | 54.9 μs | 39.3 μs | 322.2 μs | 144.1 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | -| sqrt | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 140 ns | 410 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| sqrt | sorted_repeated | 65536 | 16 | 190 ns | 290 ns | 230 ns | 1.5 μs | 680 ns | 210 ns | 650 ns | Linear (190 ns) | 1.11x | -| sqrt | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 720 ns | 5.9 μs | 2.6 μs | 609 ns | 2.4 μs | Linear (570 ns) | 1.07x | -| sqrt | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 23.5 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | -| sqrt | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 94.0 μs | 40.7 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.00x | -| sqrt | sorted_repeated | 65536 | 4096 | 30.8 μs | 54.9 μs | 39.4 μs | 376.3 μs | 163.2 μs | 30.8 μs | 152.6 μs | Linear (30.8 μs) | 1.00x | -| sqrt | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| sqrt | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 90 ns | 90 ns | 100 ns | 70 ns | InterpSearch (90 ns) | 1.11x | -| sqrt | unsorted | 16 | 16 | 210 ns | 210 ns | 200 ns | 200 ns | 210 ns | 210 ns | 190 ns | InterpSearch (200 ns) | 1.05x | -| sqrt | unsorted | 16 | 64 | 700 ns | 700 ns | 690 ns | 690 ns | 690 ns | 710 ns | 680 ns | InterpSearch (690 ns) | 1.03x | -| sqrt | unsorted | 16 | 256 | 4.2 μs | 4.3 μs | 4.2 μs | 4.2 μs | 4.2 μs | 4.1 μs | 4.3 μs | Binary (4.2 μs) | 1.00x | -| sqrt | unsorted | 16 | 1024 | 24.0 μs | 23.6 μs | 23.6 μs | 23.4 μs | 23.5 μs | 23.6 μs | 24.4 μs | InterpSearch (23.4 μs) | 1.01x | -| sqrt | unsorted | 16 | 4096 | 129.6 μs | 128.2 μs | 128.0 μs | 128.4 μs | 127.6 μs | 127.7 μs | 130.1 μs | Binary (127.6 μs) | 1.00x | -| sqrt | unsorted | 64 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| sqrt | unsorted | 64 | 4 | 90 ns | 110 ns | 100 ns | 170 ns | 110 ns | 120 ns | 90 ns | Linear (90 ns) | 1.33x | -| sqrt | unsorted | 64 | 16 | 290 ns | 290 ns | 290 ns | 290 ns | 290 ns | 300 ns | 270 ns | InterpSearch (290 ns) | 1.03x | -| sqrt | unsorted | 64 | 64 | 1.1 μs | 1.0 μs | 1.1 μs | 1.0 μs | 1.0 μs | 1.1 μs | 1.0 μs | Gallop (1.0 μs) | 1.03x | -| sqrt | unsorted | 64 | 256 | 5.9 μs | 6.0 μs | 6.0 μs | 5.9 μs | 5.9 μs | 6.0 μs | 6.2 μs | Linear (5.9 μs) | 1.02x | -| sqrt | unsorted | 64 | 1024 | 40.0 μs | 40.3 μs | 39.6 μs | 39.0 μs | 39.1 μs | 39.2 μs | 39.5 μs | InterpSearch (39.0 μs) | 1.01x | -| sqrt | unsorted | 64 | 4096 | 207.4 μs | 205.8 μs | 205.2 μs | 205.9 μs | 206.1 μs | 205.7 μs | 208.5 μs | ExpFromLeft (205.2 μs) | 1.00x | -| sqrt | unsorted | 256 | 1 | 59 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Linear (59 ns) | 1.02x | -| sqrt | unsorted | 256 | 4 | 120 ns | 120 ns | 130 ns | 120 ns | 130 ns | 130 ns | 110 ns | InterpSearch (120 ns) | 1.08x | -| sqrt | unsorted | 256 | 16 | 350 ns | 340 ns | 340 ns | 350 ns | 350 ns | 360 ns | 340 ns | ExpFromLeft (340 ns) | 1.06x | -| sqrt | unsorted | 256 | 64 | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.5 μs | 1.4 μs | InterpSearch (1.5 μs) | 1.00x | -| sqrt | unsorted | 256 | 256 | 7.3 μs | 7.4 μs | 7.3 μs | 7.3 μs | 7.3 μs | 7.2 μs | 7.5 μs | Linear (7.3 μs) | 0.99x | -| sqrt | unsorted | 256 | 1024 | 49.8 μs | 48.9 μs | 48.4 μs | 47.5 μs | 47.7 μs | 47.9 μs | 50.1 μs | InterpSearch (47.5 μs) | 1.01x | -| sqrt | unsorted | 256 | 4096 | 281.7 μs | 281.6 μs | 281.9 μs | 280.0 μs | 277.8 μs | 278.8 μs | 283.8 μs | Binary (277.8 μs) | 1.00x | -| sqrt | unsorted | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| sqrt | unsorted | 1024 | 4 | 140 ns | 150 ns | 150 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| sqrt | unsorted | 1024 | 16 | 430 ns | 430 ns | 430 ns | 430 ns | 430 ns | 440 ns | 409 ns | InterpSearch (430 ns) | 1.02x | -| sqrt | unsorted | 1024 | 64 | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | 1.8 μs | InterpSearch (1.8 μs) | 1.01x | -| sqrt | unsorted | 1024 | 256 | 8.8 μs | 8.7 μs | 8.6 μs | 8.6 μs | 8.4 μs | 8.5 μs | 8.7 μs | Binary (8.4 μs) | 1.01x | -| sqrt | unsorted | 1024 | 1024 | 73.5 μs | 71.9 μs | 71.3 μs | 71.3 μs | 70.9 μs | 70.4 μs | 73.6 μs | Binary (70.9 μs) | 0.99x | -| sqrt | unsorted | 1024 | 4096 | 369.4 μs | 371.9 μs | 375.4 μs | 376.0 μs | 372.4 μs | 374.0 μs | 373.5 μs | Linear (369.4 μs) | 1.01x | -| sqrt | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | unsorted | 4096 | 4 | 200 ns | 160 ns | 160 ns | 160 ns | 160 ns | 170 ns | 150 ns | InterpSearch (160 ns) | 1.06x | -| sqrt | unsorted | 4096 | 16 | 500 ns | 500 ns | 500 ns | 510 ns | 500 ns | 500 ns | 480 ns | ExpFromLeft (500 ns) | 1.00x | -| sqrt | unsorted | 4096 | 64 | 2.2 μs | 2.1 μs | 2.1 μs | 2.2 μs | 2.2 μs | 2.2 μs | 2.1 μs | ExpFromLeft (2.1 μs) | 1.02x | -| sqrt | unsorted | 4096 | 256 | 10.1 μs | 9.9 μs | 9.8 μs | 9.8 μs | 9.7 μs | 9.7 μs | 10.7 μs | Binary (9.7 μs) | 1.00x | -| sqrt | unsorted | 4096 | 1024 | 93.2 μs | 91.7 μs | 91.1 μs | 90.1 μs | 89.8 μs | 89.9 μs | 94.3 μs | Binary (89.8 μs) | 1.00x | -| sqrt | unsorted | 4096 | 4096 | 458.2 μs | 448.9 μs | 458.8 μs | 458.0 μs | 456.7 μs | 457.4 μs | 457.4 μs | Gallop (448.9 μs) | 1.02x | -| sqrt | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| sqrt | unsorted | 16384 | 4 | 170 ns | 170 ns | 180 ns | 180 ns | 170 ns | 180 ns | 160 ns | Binary (170 ns) | 1.06x | -| sqrt | unsorted | 16384 | 16 | 570 ns | 560 ns | 570 ns | 570 ns | 570 ns | 570 ns | 560 ns | Gallop (560 ns) | 1.02x | -| sqrt | unsorted | 16384 | 64 | 2.4 μs | 2.4 μs | 2.4 μs | 2.3 μs | 2.4 μs | 2.4 μs | 2.3 μs | InterpSearch (2.3 μs) | 1.01x | -| sqrt | unsorted | 16384 | 256 | 11.9 μs | 11.7 μs | 11.6 μs | 11.6 μs | 11.6 μs | 11.6 μs | 13.8 μs | Binary (11.6 μs) | 1.00x | -| sqrt | unsorted | 16384 | 1024 | 130.0 μs | 129.0 μs | 127.7 μs | 127.0 μs | 126.3 μs | 125.7 μs | 131.8 μs | Binary (126.3 μs) | 1.00x | -| sqrt | unsorted | 16384 | 4096 | 615.8 μs | 614.9 μs | 615.8 μs | 617.7 μs | 615.9 μs | 618.0 μs | 617.4 μs | Gallop (614.9 μs) | 1.00x | -| sqrt | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| sqrt | unsorted | 65536 | 4 | 190 ns | 190 ns | 200 ns | 190 ns | 200 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | -| sqrt | unsorted | 65536 | 16 | 670 ns | 660 ns | 660 ns | 670 ns | 670 ns | 670 ns | 650 ns | ExpFromLeft (660 ns) | 1.02x | -| sqrt | unsorted | 65536 | 64 | 3.0 μs | 3.0 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 3.0 μs | Binary (2.9 μs) | 1.00x | -| sqrt | unsorted | 65536 | 256 | 14.6 μs | 14.5 μs | 14.4 μs | 14.4 μs | 14.4 μs | 14.2 μs | 17.3 μs | Binary (14.4 μs) | 0.99x | -| sqrt | unsorted | 65536 | 1024 | 174.2 μs | 171.2 μs | 168.8 μs | 168.5 μs | 167.9 μs | 166.9 μs | 172.8 μs | Binary (167.9 μs) | 0.99x | -| sqrt | unsorted | 65536 | 4096 | 795.6 μs | 794.2 μs | 792.7 μs | 791.6 μs | 792.1 μs | 791.5 μs | 791.8 μs | InterpSearch (791.6 μs) | 1.00x | -| plateau | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| plateau | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 100 ns | 170 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| plateau | sorted_uniform | 16 | 16 | 180 ns | 270 ns | 220 ns | 510 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | -| plateau | sorted_uniform | 16 | 64 | 600 ns | 949 ns | 760 ns | 2.1 μs | 810 ns | 630 ns | 690 ns | Linear (600 ns) | 1.05x | -| plateau | sorted_uniform | 16 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 8.1 μs | 3.0 μs | 2.2 μs | 2.5 μs | Linear (2.1 μs) | 1.01x | -| plateau | sorted_uniform | 16 | 1024 | 8.3 μs | 13.9 μs | 10.6 μs | 31.2 μs | 11.8 μs | 8.3 μs | 10.0 μs | Linear (8.3 μs) | 1.00x | -| plateau | sorted_uniform | 16 | 4096 | 32.9 μs | 55.4 μs | 41.8 μs | 123.4 μs | 47.1 μs | 32.9 μs | 39.8 μs | Linear (32.9 μs) | 1.00x | -| plateau | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| plateau | sorted_uniform | 64 | 4 | 110 ns | 110 ns | 110 ns | 200 ns | 109 ns | 130 ns | 90 ns | Binary (109 ns) | 1.19x | -| plateau | sorted_uniform | 64 | 16 | 200 ns | 270 ns | 230 ns | 680 ns | 310 ns | 230 ns | 270 ns | Linear (200 ns) | 1.15x | -| plateau | sorted_uniform | 64 | 64 | 600 ns | 950 ns | 760 ns | 2.6 μs | 1.1 μs | 640 ns | 970 ns | Linear (600 ns) | 1.07x | -| plateau | sorted_uniform | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 10.4 μs | 4.2 μs | 2.1 μs | 3.7 μs | Linear (2.0 μs) | 1.01x | -| plateau | sorted_uniform | 64 | 1024 | 7.8 μs | 13.8 μs | 10.6 μs | 40.7 μs | 16.6 μs | 7.8 μs | 14.7 μs | Linear (7.8 μs) | 1.00x | -| plateau | sorted_uniform | 64 | 4096 | 30.8 μs | 55.1 μs | 42.0 μs | 158.7 μs | 66.5 μs | 30.8 μs | 58.8 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_uniform | 256 | 4 | 210 ns | 130 ns | 120 ns | 220 ns | 120 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | -| plateau | sorted_uniform | 256 | 16 | 280 ns | 290 ns | 250 ns | 720 ns | 380 ns | 259 ns | 360 ns | ExpFromLeft (250 ns) | 1.04x | -| plateau | sorted_uniform | 256 | 64 | 690 ns | 970 ns | 770 ns | 2.8 μs | 1.4 μs | 720 ns | 1.3 μs | Linear (690 ns) | 1.04x | -| plateau | sorted_uniform | 256 | 256 | 2.1 μs | 3.5 μs | 2.7 μs | 12.3 μs | 5.4 μs | 2.2 μs | 4.9 μs | Linear (2.1 μs) | 1.01x | -| plateau | sorted_uniform | 256 | 1024 | 7.9 μs | 13.8 μs | 10.6 μs | 53.8 μs | 21.5 μs | 7.9 μs | 19.6 μs | Linear (7.9 μs) | 1.01x | -| plateau | sorted_uniform | 256 | 4096 | 30.9 μs | 55.1 μs | 42.0 μs | 195.4 μs | 86.0 μs | 30.9 μs | 78.3 μs | Linear (30.9 μs) | 1.00x | -| plateau | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 90 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_uniform | 1024 | 4 | 550 ns | 140 ns | 130 ns | 250 ns | 150 ns | 160 ns | 130 ns | ExpFromLeft (130 ns) | 1.23x | -| plateau | sorted_uniform | 1024 | 16 | 670 ns | 300 ns | 240 ns | 950 ns | 460 ns | 260 ns | 420 ns | ExpFromLeft (240 ns) | 1.08x | -| plateau | sorted_uniform | 1024 | 64 | 1.1 μs | 980 ns | 780 ns | 3.6 μs | 1.7 μs | 830 ns | 1.6 μs | ExpFromLeft (780 ns) | 1.06x | -| plateau | sorted_uniform | 1024 | 256 | 2.5 μs | 3.5 μs | 2.8 μs | 15.0 μs | 6.5 μs | 2.5 μs | 6.1 μs | Linear (2.5 μs) | 1.01x | -| plateau | sorted_uniform | 1024 | 1024 | 8.2 μs | 13.8 μs | 10.6 μs | 79.9 μs | 26.1 μs | 8.3 μs | 24.4 μs | Linear (8.2 μs) | 1.00x | -| plateau | sorted_uniform | 1024 | 4096 | 31.3 μs | 55.1 μs | 42.1 μs | 296.7 μs | 104.7 μs | 31.3 μs | 97.2 μs | Linear (31.3 μs) | 1.00x | -| plateau | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_uniform | 4096 | 4 | 2.0 μs | 150 ns | 140 ns | 320 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (140 ns) | 1.21x | -| plateau | sorted_uniform | 4096 | 16 | 2.1 μs | 310 ns | 260 ns | 1.0 μs | 550 ns | 290 ns | 510 ns | ExpFromLeft (260 ns) | 1.12x | -| plateau | sorted_uniform | 4096 | 64 | 2.5 μs | 990 ns | 800 ns | 4.2 μs | 2.0 μs | 840 ns | 1.9 μs | ExpFromLeft (800 ns) | 1.05x | -| plateau | sorted_uniform | 4096 | 256 | 3.9 μs | 3.6 μs | 2.8 μs | 18.3 μs | 7.8 μs | 2.9 μs | 7.3 μs | ExpFromLeft (2.8 μs) | 1.04x | -| plateau | sorted_uniform | 4096 | 1024 | 9.7 μs | 13.9 μs | 10.6 μs | 104.6 μs | 31.2 μs | 9.7 μs | 29.1 μs | Linear (9.7 μs) | 1.01x | -| plateau | sorted_uniform | 4096 | 4096 | 32.7 μs | 55.1 μs | 42.1 μs | 438.2 μs | 124.6 μs | 32.7 μs | 116.2 μs | Linear (32.7 μs) | 1.00x | -| plateau | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 80 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_uniform | 16384 | 4 | 7.8 μs | 180 ns | 140 ns | 310 ns | 180 ns | 180 ns | 170 ns | ExpFromLeft (140 ns) | 1.29x | -| plateau | sorted_uniform | 16384 | 16 | 7.9 μs | 330 ns | 270 ns | 1.2 μs | 600 ns | 290 ns | 580 ns | ExpFromLeft (270 ns) | 1.07x | -| plateau | sorted_uniform | 16384 | 64 | 8.3 μs | 1.0 μs | 1.0 μs | 5.2 μs | 2.3 μs | 850 ns | 2.2 μs | ExpFromLeft (1.0 μs) | 0.85x | -| plateau | sorted_uniform | 16384 | 256 | 9.7 μs | 3.6 μs | 2.8 μs | 21.7 μs | 9.0 μs | 2.9 μs | 8.6 μs | ExpFromLeft (2.8 μs) | 1.04x | -| plateau | sorted_uniform | 16384 | 1024 | 15.4 μs | 13.9 μs | 10.7 μs | 135.4 μs | 36.0 μs | 11.0 μs | 34.3 μs | ExpFromLeft (10.7 μs) | 1.04x | -| plateau | sorted_uniform | 16384 | 4096 | 38.4 μs | 55.2 μs | 42.1 μs | 556.4 μs | 144.0 μs | 38.4 μs | 136.9 μs | Linear (38.4 μs) | 1.00x | -| plateau | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| plateau | sorted_uniform | 65536 | 4 | 30.8 μs | 180 ns | 170 ns | 390 ns | 200 ns | 180 ns | 180 ns | ExpFromLeft (170 ns) | 1.06x | -| plateau | sorted_uniform | 65536 | 16 | 31.1 μs | 340 ns | 300 ns | 1.4 μs | 680 ns | 290 ns | 670 ns | ExpFromLeft (300 ns) | 0.97x | -| plateau | sorted_uniform | 65536 | 64 | 29.9 μs | 1.0 μs | 820 ns | 5.7 μs | 2.6 μs | 860 ns | 2.5 μs | ExpFromLeft (820 ns) | 1.05x | -| plateau | sorted_uniform | 65536 | 256 | 32.9 μs | 3.6 μs | 2.8 μs | 24.1 μs | 10.2 μs | 2.9 μs | 9.8 μs | ExpFromLeft (2.8 μs) | 1.05x | -| plateau | sorted_uniform | 65536 | 1024 | 38.6 μs | 13.9 μs | 10.7 μs | 178.2 μs | 40.6 μs | 11.1 μs | 38.7 μs | ExpFromLeft (10.7 μs) | 1.04x | -| plateau | sorted_uniform | 65536 | 4096 | 61.7 μs | 55.2 μs | 42.1 μs | 694.6 μs | 162.8 μs | 43.8 μs | 154.7 μs | ExpFromLeft (42.1 μs) | 1.04x | -| plateau | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| plateau | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 110 ns | 70 ns | Linear (80 ns) | 1.38x | -| plateau | sorted_dense_burst | 16 | 16 | 170 ns | 280 ns | 200 ns | 500 ns | 220 ns | 190 ns | 190 ns | Linear (170 ns) | 1.12x | -| plateau | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 690 ns | 1.9 μs | 780 ns | 579 ns | 670 ns | Linear (550 ns) | 1.05x | -| plateau | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 7.2 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.02x | -| plateau | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 28.8 μs | 11.8 μs | 7.8 μs | 10.0 μs | Linear (7.7 μs) | 1.00x | -| plateau | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.8 μs | 39.5 μs | 115.3 μs | 47.1 μs | 30.8 μs | 39.8 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_dense_burst | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| plateau | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 90 ns | 190 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| plateau | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 210 ns | 680 ns | 320 ns | 200 ns | 260 ns | Linear (170 ns) | 1.18x | -| plateau | sorted_dense_burst | 64 | 64 | 550 ns | 920 ns | 690 ns | 2.5 μs | 1.1 μs | 580 ns | 920 ns | Linear (550 ns) | 1.05x | -| plateau | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 10.1 μs | 4.2 μs | 2.0 μs | 3.9 μs | Linear (2.0 μs) | 1.03x | -| plateau | sorted_dense_burst | 64 | 1024 | 7.9 μs | 13.7 μs | 10.0 μs | 40.4 μs | 16.8 μs | 7.9 μs | 14.2 μs | Linear (7.9 μs) | 1.00x | -| plateau | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.0 μs | 39.2 μs | 159.9 μs | 66.8 μs | 30.8 μs | 57.0 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 90 ns | 230 ns | 120 ns | 110 ns | 110 ns | ExpFromLeft (90 ns) | 1.22x | -| plateau | sorted_dense_burst | 256 | 16 | 180 ns | 280 ns | 210 ns | 840 ns | 400 ns | 200 ns | 340 ns | Linear (180 ns) | 1.11x | -| plateau | sorted_dense_burst | 256 | 64 | 560 ns | 930 ns | 700 ns | 3.2 μs | 1.4 μs | 590 ns | 1.3 μs | Linear (560 ns) | 1.05x | -| plateau | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 12.5 μs | 5.4 μs | 2.0 μs | 4.9 μs | Linear (2.0 μs) | 1.02x | -| plateau | sorted_dense_burst | 256 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 50.1 μs | 21.4 μs | 7.8 μs | 19.5 μs | Linear (7.7 μs) | 1.01x | -| plateau | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.0 μs | 39.5 μs | 199.3 μs | 85.6 μs | 30.8 μs | 78.1 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_dense_burst | 1024 | 4 | 90 ns | 100 ns | 100 ns | 270 ns | 150 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | -| plateau | sorted_dense_burst | 1024 | 16 | 190 ns | 290 ns | 220 ns | 1.0 μs | 460 ns | 210 ns | 420 ns | Linear (190 ns) | 1.11x | -| plateau | sorted_dense_burst | 1024 | 64 | 559 ns | 930 ns | 700 ns | 3.9 μs | 1.7 μs | 600 ns | 1.6 μs | Linear (559 ns) | 1.07x | -| plateau | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 14.9 μs | 6.6 μs | 2.0 μs | 6.2 μs | Linear (2.0 μs) | 1.02x | -| plateau | sorted_dense_burst | 1024 | 1024 | 7.8 μs | 13.8 μs | 10.0 μs | 59.9 μs | 26.4 μs | 7.8 μs | 24.3 μs | Linear (7.8 μs) | 1.00x | -| plateau | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.0 μs | 39.1 μs | 239.9 μs | 105.4 μs | 30.8 μs | 96.8 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_dense_burst | 4096 | 4 | 90 ns | 110 ns | 100 ns | 310 ns | 170 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | -| plateau | sorted_dense_burst | 4096 | 16 | 180 ns | 290 ns | 240 ns | 1.1 μs | 540 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | -| plateau | sorted_dense_burst | 4096 | 64 | 560 ns | 940 ns | 720 ns | 4.5 μs | 2.0 μs | 590 ns | 1.9 μs | Linear (560 ns) | 1.05x | -| plateau | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 17.7 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| plateau | sorted_dense_burst | 4096 | 1024 | 7.7 μs | 13.9 μs | 10.0 μs | 70.4 μs | 31.3 μs | 7.8 μs | 28.9 μs | Linear (7.7 μs) | 1.01x | -| plateau | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.4 μs | 39.8 μs | 281.4 μs | 125.0 μs | 30.8 μs | 115.5 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_dense_burst | 16384 | 4 | 100 ns | 120 ns | 110 ns | 370 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | -| plateau | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 220 ns | 1.3 μs | 600 ns | 220 ns | 570 ns | Linear (190 ns) | 1.16x | -| plateau | sorted_dense_burst | 16384 | 64 | 570 ns | 950 ns | 720 ns | 5.1 μs | 2.3 μs | 600 ns | 2.2 μs | Linear (570 ns) | 1.05x | -| plateau | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 20.1 μs | 9.0 μs | 2.0 μs | 8.6 μs | Linear (2.0 μs) | 1.02x | -| plateau | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 80.4 μs | 36.7 μs | 11.2 μs | 34.1 μs | Linear (7.8 μs) | 1.44x | -| plateau | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 54.7 μs | 39.4 μs | 322.2 μs | 143.5 μs | 30.8 μs | 136.4 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| plateau | sorted_dense_burst | 65536 | 4 | 110 ns | 120 ns | 120 ns | 410 ns | 200 ns | 130 ns | 180 ns | Linear (110 ns) | 1.18x | -| plateau | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 230 ns | 1.5 μs | 690 ns | 220 ns | 650 ns | Linear (190 ns) | 1.16x | -| plateau | sorted_dense_burst | 65536 | 64 | 580 ns | 949 ns | 710 ns | 5.8 μs | 2.6 μs | 610 ns | 2.5 μs | Linear (580 ns) | 1.05x | -| plateau | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 23.1 μs | 10.2 μs | 2.0 μs | 9.7 μs | Linear (2.0 μs) | 1.01x | -| plateau | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 92.4 μs | 40.9 μs | 7.8 μs | 38.6 μs | Linear (7.8 μs) | 1.00x | -| plateau | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.1 μs | 39.3 μs | 369.5 μs | 163.3 μs | 30.8 μs | 154.5 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| plateau | sorted_near_start | 16 | 4 | 90 ns | 110 ns | 100 ns | 190 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| plateau | sorted_near_start | 16 | 16 | 170 ns | 280 ns | 210 ns | 630 ns | 220 ns | 200 ns | 190 ns | Linear (170 ns) | 1.18x | -| plateau | sorted_near_start | 16 | 64 | 560 ns | 930 ns | 700 ns | 2.3 μs | 780 ns | 589 ns | 680 ns | Linear (560 ns) | 1.05x | -| plateau | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 9.0 μs | 3.0 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | -| plateau | sorted_near_start | 16 | 1024 | 7.8 μs | 13.8 μs | 10.1 μs | 36.3 μs | 11.8 μs | 7.8 μs | 10.1 μs | Linear (7.8 μs) | 1.00x | -| plateau | sorted_near_start | 16 | 4096 | 30.8 μs | 55.0 μs | 39.4 μs | 144.2 μs | 46.9 μs | 30.8 μs | 40.2 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_near_start | 64 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| plateau | sorted_near_start | 64 | 4 | 110 ns | 110 ns | 110 ns | 210 ns | 110 ns | 130 ns | 90 ns | ExpFromLeft (110 ns) | 1.18x | -| plateau | sorted_near_start | 64 | 16 | 200 ns | 290 ns | 220 ns | 750 ns | 310 ns | 230 ns | 290 ns | Linear (200 ns) | 1.15x | -| plateau | sorted_near_start | 64 | 64 | 590 ns | 940 ns | 710 ns | 2.8 μs | 1.1 μs | 620 ns | 1.0 μs | Linear (590 ns) | 1.05x | -| plateau | sorted_near_start | 64 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 11.1 μs | 4.2 μs | 2.0 μs | 3.8 μs | Linear (2.0 μs) | 1.01x | -| plateau | sorted_near_start | 64 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 44.3 μs | 16.6 μs | 7.8 μs | 15.0 μs | Linear (7.8 μs) | 1.00x | -| plateau | sorted_near_start | 64 | 4096 | 30.8 μs | 54.9 μs | 39.5 μs | 178.0 μs | 66.0 μs | 30.9 μs | 60.0 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_near_start | 256 | 4 | 200 ns | 120 ns | 150 ns | 310 ns | 120 ns | 140 ns | 110 ns | Binary (120 ns) | 1.17x | -| plateau | sorted_near_start | 256 | 16 | 300 ns | 300 ns | 240 ns | 920 ns | 390 ns | 250 ns | 350 ns | ExpFromLeft (240 ns) | 1.04x | -| plateau | sorted_near_start | 256 | 64 | 680 ns | 950 ns | 730 ns | 3.5 μs | 1.4 μs | 710 ns | 1.3 μs | Linear (680 ns) | 1.04x | -| plateau | sorted_near_start | 256 | 256 | 2.3 μs | 3.5 μs | 2.6 μs | 13.8 μs | 5.4 μs | 2.1 μs | 5.0 μs | Linear (2.3 μs) | 0.92x | -| plateau | sorted_near_start | 256 | 1024 | 7.9 μs | 13.8 μs | 10.0 μs | 55.0 μs | 21.6 μs | 7.9 μs | 19.7 μs | Linear (7.9 μs) | 1.00x | -| plateau | sorted_near_start | 256 | 4096 | 30.9 μs | 55.1 μs | 39.6 μs | 222.1 μs | 86.6 μs | 30.9 μs | 78.6 μs | Linear (30.9 μs) | 1.00x | -| plateau | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_near_start | 1024 | 4 | 90 ns | 100 ns | 100 ns | 280 ns | 150 ns | 130 ns | 130 ns | Linear (90 ns) | 1.44x | -| plateau | sorted_near_start | 1024 | 16 | 180 ns | 290 ns | 220 ns | 1.1 μs | 440 ns | 230 ns | 420 ns | Linear (180 ns) | 1.28x | -| plateau | sorted_near_start | 1024 | 64 | 1.1 μs | 970 ns | 740 ns | 4.1 μs | 1.7 μs | 770 ns | 1.6 μs | ExpFromLeft (740 ns) | 1.04x | -| plateau | sorted_near_start | 1024 | 256 | 2.5 μs | 3.5 μs | 2.6 μs | 16.6 μs | 6.9 μs | 3.4 μs | 6.3 μs | Linear (2.5 μs) | 1.37x | -| plateau | sorted_near_start | 1024 | 1024 | 8.3 μs | 13.8 μs | 10.1 μs | 64.6 μs | 25.9 μs | 8.3 μs | 24.4 μs | Linear (8.3 μs) | 1.00x | -| plateau | sorted_near_start | 1024 | 4096 | 31.3 μs | 55.1 μs | 39.7 μs | 264.4 μs | 103.9 μs | 31.3 μs | 97.7 μs | Linear (31.3 μs) | 1.00x | -| plateau | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_near_start | 4096 | 4 | 2.0 μs | 150 ns | 150 ns | 320 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (150 ns) | 1.13x | -| plateau | sorted_near_start | 4096 | 16 | 2.1 μs | 320 ns | 270 ns | 1.2 μs | 540 ns | 270 ns | 510 ns | ExpFromLeft (270 ns) | 1.00x | -| plateau | sorted_near_start | 4096 | 64 | 3.0 μs | 1.3 μs | 920 ns | 4.8 μs | 2.1 μs | 940 ns | 1.9 μs | ExpFromLeft (920 ns) | 1.02x | -| plateau | sorted_near_start | 4096 | 256 | 4.0 μs | 3.6 μs | 2.6 μs | 18.9 μs | 7.8 μs | 2.7 μs | 7.4 μs | ExpFromLeft (2.6 μs) | 1.06x | -| plateau | sorted_near_start | 4096 | 1024 | 9.7 μs | 13.9 μs | 10.0 μs | 75.1 μs | 31.1 μs | 9.7 μs | 29.2 μs | Linear (9.7 μs) | 1.00x | -| plateau | sorted_near_start | 4096 | 4096 | 32.8 μs | 55.1 μs | 39.8 μs | 303.3 μs | 124.1 μs | 32.8 μs | 116.8 μs | Linear (32.8 μs) | 1.00x | -| plateau | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 80 ns | 120 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | -| plateau | sorted_near_start | 16384 | 4 | 100 ns | 110 ns | 110 ns | 360 ns | 180 ns | 130 ns | 160 ns | Linear (100 ns) | 1.30x | -| plateau | sorted_near_start | 16384 | 16 | 7.9 μs | 350 ns | 280 ns | 1.4 μs | 620 ns | 280 ns | 580 ns | ExpFromLeft (280 ns) | 1.00x | -| plateau | sorted_near_start | 16384 | 64 | 8.3 μs | 1.0 μs | 770 ns | 5.3 μs | 2.3 μs | 790 ns | 2.2 μs | ExpFromLeft (770 ns) | 1.03x | -| plateau | sorted_near_start | 16384 | 256 | 9.7 μs | 3.6 μs | 2.6 μs | 21.1 μs | 9.0 μs | 2.8 μs | 8.7 μs | ExpFromLeft (2.6 μs) | 1.05x | -| plateau | sorted_near_start | 16384 | 1024 | 15.4 μs | 13.9 μs | 10.0 μs | 84.8 μs | 36.1 μs | 10.4 μs | 34.3 μs | ExpFromLeft (10.0 μs) | 1.04x | -| plateau | sorted_near_start | 16384 | 4096 | 38.4 μs | 55.1 μs | 39.7 μs | 343.4 μs | 144.4 μs | 38.4 μs | 137.5 μs | Linear (38.4 μs) | 1.00x | -| plateau | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| plateau | sorted_near_start | 65536 | 4 | 31.1 μs | 180 ns | 170 ns | 400 ns | 190 ns | 190 ns | 180 ns | ExpFromLeft (170 ns) | 1.12x | -| plateau | sorted_near_start | 65536 | 16 | 31.1 μs | 350 ns | 280 ns | 1.5 μs | 690 ns | 290 ns | 679 ns | ExpFromLeft (280 ns) | 1.04x | -| plateau | sorted_near_start | 65536 | 64 | 31.5 μs | 1.0 μs | 780 ns | 6.0 μs | 2.6 μs | 800 ns | 2.5 μs | ExpFromLeft (780 ns) | 1.03x | -| plateau | sorted_near_start | 65536 | 256 | 32.9 μs | 3.6 μs | 2.6 μs | 23.9 μs | 10.2 μs | 2.8 μs | 9.7 μs | ExpFromLeft (2.6 μs) | 1.04x | -| plateau | sorted_near_start | 65536 | 1024 | 38.6 μs | 13.9 μs | 10.1 μs | 96.1 μs | 40.6 μs | 10.5 μs | 38.8 μs | ExpFromLeft (10.1 μs) | 1.03x | -| plateau | sorted_near_start | 65536 | 4096 | 61.7 μs | 55.2 μs | 38.8 μs | 395.4 μs | 162.2 μs | 41.1 μs | 154.7 μs | ExpFromLeft (38.8 μs) | 1.06x | -| plateau | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| plateau | sorted_arithmetic | 16 | 4 | 90 ns | 120 ns | 100 ns | 160 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | -| plateau | sorted_arithmetic | 16 | 16 | 180 ns | 280 ns | 220 ns | 520 ns | 220 ns | 210 ns | 200 ns | Linear (180 ns) | 1.17x | -| plateau | sorted_arithmetic | 16 | 64 | 610 ns | 1.0 μs | 760 ns | 2.0 μs | 820 ns | 630 ns | 690 ns | Linear (610 ns) | 1.03x | -| plateau | sorted_arithmetic | 16 | 256 | 2.1 μs | 3.7 μs | 2.7 μs | 8.3 μs | 3.0 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.01x | -| plateau | sorted_arithmetic | 16 | 1024 | 9.5 μs | 14.5 μs | 10.6 μs | 31.8 μs | 11.9 μs | 7.9 μs | 10.2 μs | Linear (9.5 μs) | 0.84x | -| plateau | sorted_arithmetic | 16 | 4096 | 30.8 μs | 55.2 μs | 42.0 μs | 123.7 μs | 55.8 μs | 34.5 μs | 39.9 μs | Linear (30.8 μs) | 1.12x | -| plateau | sorted_arithmetic | 64 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_arithmetic | 64 | 4 | 140 ns | 130 ns | 110 ns | 170 ns | 110 ns | 130 ns | 100 ns | ExpFromLeft (110 ns) | 1.18x | -| plateau | sorted_arithmetic | 64 | 16 | 230 ns | 300 ns | 240 ns | 650 ns | 330 ns | 260 ns | 290 ns | Linear (230 ns) | 1.13x | -| plateau | sorted_arithmetic | 64 | 64 | 650 ns | 1.0 μs | 760 ns | 2.5 μs | 1.1 μs | 690 ns | 1.1 μs | Linear (650 ns) | 1.06x | -| plateau | sorted_arithmetic | 64 | 256 | 2.6 μs | 3.8 μs | 2.7 μs | 9.6 μs | 4.3 μs | 2.1 μs | 3.8 μs | Linear (2.6 μs) | 0.82x | -| plateau | sorted_arithmetic | 64 | 1024 | 7.9 μs | 14.7 μs | 10.6 μs | 39.5 μs | 16.7 μs | 8.0 μs | 14.7 μs | Linear (7.9 μs) | 1.01x | -| plateau | sorted_arithmetic | 64 | 4096 | 30.9 μs | 54.9 μs | 42.0 μs | 152.5 μs | 66.4 μs | 30.9 μs | 59.4 μs | Linear (30.9 μs) | 1.00x | -| plateau | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_arithmetic | 256 | 4 | 330 ns | 150 ns | 120 ns | 170 ns | 130 ns | 150 ns | 110 ns | ExpFromLeft (120 ns) | 1.25x | -| plateau | sorted_arithmetic | 256 | 16 | 440 ns | 329 ns | 250 ns | 790 ns | 400 ns | 260 ns | 370 ns | ExpFromLeft (250 ns) | 1.04x | -| plateau | sorted_arithmetic | 256 | 64 | 850 ns | 1.1 μs | 780 ns | 3.0 μs | 1.4 μs | 900 ns | 1.3 μs | ExpFromLeft (780 ns) | 1.15x | -| plateau | sorted_arithmetic | 256 | 256 | 2.3 μs | 3.8 μs | 2.7 μs | 12.0 μs | 5.5 μs | 2.3 μs | 5.0 μs | Linear (2.3 μs) | 1.01x | -| plateau | sorted_arithmetic | 256 | 1024 | 8.1 μs | 14.7 μs | 10.6 μs | 51.3 μs | 21.6 μs | 8.2 μs | 19.7 μs | Linear (8.1 μs) | 1.00x | -| plateau | sorted_arithmetic | 256 | 4096 | 31.5 μs | 58.4 μs | 42.1 μs | 194.5 μs | 86.1 μs | 31.1 μs | 82.0 μs | Linear (31.5 μs) | 0.99x | -| plateau | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_arithmetic | 1024 | 4 | 1.1 μs | 180 ns | 130 ns | 180 ns | 140 ns | 160 ns | 130 ns | ExpFromLeft (130 ns) | 1.23x | -| plateau | sorted_arithmetic | 1024 | 16 | 1.2 μs | 340 ns | 260 ns | 910 ns | 470 ns | 270 ns | 439 ns | ExpFromLeft (260 ns) | 1.04x | -| plateau | sorted_arithmetic | 1024 | 64 | 1.5 μs | 1.0 μs | 770 ns | 3.6 μs | 1.7 μs | 830 ns | 1.6 μs | ExpFromLeft (770 ns) | 1.08x | -| plateau | sorted_arithmetic | 1024 | 256 | 3.0 μs | 3.8 μs | 3.6 μs | 14.9 μs | 7.0 μs | 4.0 μs | 6.2 μs | Linear (3.0 μs) | 1.33x | -| plateau | sorted_arithmetic | 1024 | 1024 | 8.8 μs | 13.9 μs | 10.6 μs | 70.0 μs | 26.2 μs | 8.8 μs | 24.4 μs | Linear (8.8 μs) | 1.00x | -| plateau | sorted_arithmetic | 1024 | 4096 | 31.8 μs | 55.1 μs | 42.1 μs | 306.3 μs | 104.7 μs | 45.5 μs | 97.2 μs | Linear (31.8 μs) | 1.43x | -| plateau | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_arithmetic | 4096 | 4 | 4.0 μs | 190 ns | 140 ns | 190 ns | 170 ns | 160 ns | 140 ns | ExpFromLeft (140 ns) | 1.14x | -| plateau | sorted_arithmetic | 4096 | 16 | 4.0 μs | 370 ns | 260 ns | 1.0 μs | 550 ns | 280 ns | 520 ns | ExpFromLeft (260 ns) | 1.08x | -| plateau | sorted_arithmetic | 4096 | 64 | 4.5 μs | 1.0 μs | 790 ns | 4.2 μs | 2.0 μs | 840 ns | 1.9 μs | ExpFromLeft (790 ns) | 1.06x | -| plateau | sorted_arithmetic | 4096 | 256 | 5.8 μs | 3.6 μs | 2.8 μs | 17.0 μs | 7.8 μs | 2.9 μs | 7.3 μs | ExpFromLeft (2.8 μs) | 1.05x | -| plateau | sorted_arithmetic | 4096 | 1024 | 11.7 μs | 13.9 μs | 10.6 μs | 82.2 μs | 31.3 μs | 11.6 μs | 29.1 μs | ExpFromLeft (10.6 μs) | 1.09x | -| plateau | sorted_arithmetic | 4096 | 4096 | 34.7 μs | 55.1 μs | 42.1 μs | 471.8 μs | 124.7 μs | 34.7 μs | 116.2 μs | Linear (34.7 μs) | 1.00x | -| plateau | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_arithmetic | 16384 | 4 | 15.3 μs | 230 ns | 150 ns | 200 ns | 180 ns | 180 ns | 170 ns | ExpFromLeft (150 ns) | 1.20x | -| plateau | sorted_arithmetic | 16384 | 16 | 15.6 μs | 390 ns | 280 ns | 1.2 μs | 650 ns | 300 ns | 600 ns | ExpFromLeft (280 ns) | 1.07x | -| plateau | sorted_arithmetic | 16384 | 64 | 15.3 μs | 1.1 μs | 800 ns | 4.8 μs | 2.3 μs | 850 ns | 2.2 μs | ExpFromLeft (800 ns) | 1.06x | -| plateau | sorted_arithmetic | 16384 | 256 | 17.0 μs | 3.6 μs | 2.8 μs | 19.6 μs | 9.1 μs | 2.9 μs | 8.7 μs | ExpFromLeft (2.8 μs) | 1.05x | -| plateau | sorted_arithmetic | 16384 | 1024 | 23.0 μs | 13.9 μs | 10.6 μs | 99.8 μs | 36.0 μs | 11.1 μs | 34.3 μs | ExpFromLeft (10.6 μs) | 1.04x | -| plateau | sorted_arithmetic | 16384 | 4096 | 46.2 μs | 55.9 μs | 42.1 μs | 564.2 μs | 144.0 μs | 46.2 μs | 137.1 μs | ExpFromLeft (42.1 μs) | 1.10x | -| plateau | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| plateau | sorted_arithmetic | 65536 | 4 | 63.5 μs | 240 ns | 150 ns | 210 ns | 200 ns | 180 ns | 189 ns | ExpFromLeft (150 ns) | 1.20x | -| plateau | sorted_arithmetic | 65536 | 16 | 62.1 μs | 410 ns | 280 ns | 1.4 μs | 710 ns | 300 ns | 670 ns | ExpFromLeft (280 ns) | 1.07x | -| plateau | sorted_arithmetic | 65536 | 64 | 62.0 μs | 1.1 μs | 820 ns | 5.5 μs | 2.6 μs | 860 ns | 2.5 μs | ExpFromLeft (820 ns) | 1.05x | -| plateau | sorted_arithmetic | 65536 | 256 | 64.0 μs | 3.7 μs | 2.8 μs | 22.5 μs | 10.2 μs | 2.9 μs | 9.7 μs | ExpFromLeft (2.8 μs) | 1.04x | -| plateau | sorted_arithmetic | 65536 | 1024 | 69.4 μs | 14.2 μs | 10.7 μs | 127.0 μs | 40.7 μs | 11.1 μs | 38.7 μs | ExpFromLeft (10.7 μs) | 1.04x | -| plateau | sorted_arithmetic | 65536 | 4096 | 92.3 μs | 55.8 μs | 42.1 μs | 666.5 μs | 162.8 μs | 43.8 μs | 154.7 μs | ExpFromLeft (42.1 μs) | 1.04x | -| plateau | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| plateau | sorted_geometric | 16 | 4 | 90 ns | 110 ns | 100 ns | 160 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | -| plateau | sorted_geometric | 16 | 16 | 180 ns | 280 ns | 220 ns | 520 ns | 220 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | -| plateau | sorted_geometric | 16 | 64 | 570 ns | 980 ns | 780 ns | 2.1 μs | 810 ns | 590 ns | 700 ns | Linear (570 ns) | 1.04x | -| plateau | sorted_geometric | 16 | 256 | 2.0 μs | 3.6 μs | 2.8 μs | 8.2 μs | 3.0 μs | 2.1 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | -| plateau | sorted_geometric | 16 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 31.4 μs | 11.8 μs | 7.8 μs | 10.0 μs | Linear (7.8 μs) | 0.99x | -| plateau | sorted_geometric | 16 | 4096 | 30.8 μs | 55.6 μs | 42.1 μs | 124.3 μs | 47.0 μs | 30.9 μs | 39.9 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| plateau | sorted_geometric | 64 | 4 | 140 ns | 120 ns | 110 ns | 190 ns | 110 ns | 120 ns | 90 ns | ExpFromLeft (110 ns) | 1.09x | -| plateau | sorted_geometric | 64 | 16 | 230 ns | 290 ns | 240 ns | 640 ns | 310 ns | 250 ns | 280 ns | Linear (230 ns) | 1.09x | -| plateau | sorted_geometric | 64 | 64 | 640 ns | 990 ns | 790 ns | 2.5 μs | 1.1 μs | 660 ns | 990 ns | Linear (640 ns) | 1.03x | -| plateau | sorted_geometric | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 10.5 μs | 4.2 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | -| plateau | sorted_geometric | 64 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 40.5 μs | 16.6 μs | 7.9 μs | 14.9 μs | Linear (7.8 μs) | 1.02x | -| plateau | sorted_geometric | 64 | 4096 | 30.9 μs | 55.8 μs | 42.2 μs | 157.0 μs | 66.2 μs | 30.9 μs | 59.4 μs | Linear (30.9 μs) | 1.00x | -| plateau | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_geometric | 256 | 4 | 340 ns | 130 ns | 110 ns | 210 ns | 130 ns | 130 ns | 110 ns | ExpFromLeft (110 ns) | 1.18x | -| plateau | sorted_geometric | 256 | 16 | 430 ns | 310 ns | 250 ns | 770 ns | 420 ns | 270 ns | 370 ns | ExpFromLeft (250 ns) | 1.08x | -| plateau | sorted_geometric | 256 | 64 | 820 ns | 1.0 μs | 830 ns | 3.1 μs | 1.4 μs | 850 ns | 1.3 μs | Linear (820 ns) | 1.04x | -| plateau | sorted_geometric | 256 | 256 | 2.3 μs | 3.6 μs | 2.8 μs | 12.6 μs | 5.5 μs | 2.3 μs | 5.0 μs | Linear (2.3 μs) | 1.01x | -| plateau | sorted_geometric | 256 | 1024 | 8.0 μs | 14.1 μs | 10.6 μs | 54.5 μs | 21.6 μs | 8.0 μs | 19.6 μs | Linear (8.0 μs) | 1.01x | -| plateau | sorted_geometric | 256 | 4096 | 31.1 μs | 55.7 μs | 42.1 μs | 200.6 μs | 86.3 μs | 31.1 μs | 78.5 μs | Linear (31.1 μs) | 1.00x | -| plateau | sorted_geometric | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_geometric | 1024 | 4 | 1.1 μs | 150 ns | 120 ns | 240 ns | 150 ns | 159 ns | 130 ns | ExpFromLeft (120 ns) | 1.32x | -| plateau | sorted_geometric | 1024 | 16 | 1.2 μs | 350 ns | 270 ns | 910 ns | 480 ns | 289 ns | 460 ns | ExpFromLeft (270 ns) | 1.07x | -| plateau | sorted_geometric | 1024 | 64 | 1.6 μs | 1.0 μs | 840 ns | 3.7 μs | 1.7 μs | 870 ns | 1.6 μs | ExpFromLeft (840 ns) | 1.04x | -| plateau | sorted_geometric | 1024 | 256 | 3.0 μs | 3.6 μs | 2.8 μs | 15.6 μs | 6.6 μs | 3.0 μs | 6.2 μs | ExpFromLeft (2.8 μs) | 1.09x | -| plateau | sorted_geometric | 1024 | 1024 | 8.8 μs | 14.1 μs | 10.7 μs | 79.2 μs | 26.1 μs | 8.8 μs | 24.4 μs | Linear (8.8 μs) | 1.00x | -| plateau | sorted_geometric | 1024 | 4096 | 31.8 μs | 55.8 μs | 42.1 μs | 302.9 μs | 104.3 μs | 31.8 μs | 97.5 μs | Linear (31.8 μs) | 1.00x | -| plateau | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_geometric | 4096 | 4 | 3.9 μs | 160 ns | 150 ns | 270 ns | 160 ns | 160 ns | 150 ns | ExpFromLeft (150 ns) | 1.07x | -| plateau | sorted_geometric | 4096 | 16 | 4.0 μs | 360 ns | 290 ns | 1.1 μs | 540 ns | 310 ns | 530 ns | ExpFromLeft (290 ns) | 1.07x | -| plateau | sorted_geometric | 4096 | 64 | 4.5 μs | 1.1 μs | 840 ns | 4.3 μs | 2.0 μs | 890 ns | 1.9 μs | ExpFromLeft (840 ns) | 1.06x | -| plateau | sorted_geometric | 4096 | 256 | 5.6 μs | 3.7 μs | 2.8 μs | 18.2 μs | 7.8 μs | 2.9 μs | 7.3 μs | ExpFromLeft (2.8 μs) | 1.05x | -| plateau | sorted_geometric | 4096 | 1024 | 11.6 μs | 14.1 μs | 10.7 μs | 111.8 μs | 31.1 μs | 11.7 μs | 29.1 μs | ExpFromLeft (10.7 μs) | 1.10x | -| plateau | sorted_geometric | 4096 | 4096 | 34.7 μs | 55.8 μs | 42.2 μs | 453.2 μs | 124.3 μs | 34.7 μs | 116.5 μs | Linear (34.7 μs) | 1.00x | -| plateau | sorted_geometric | 16384 | 1 | 80 ns | 70 ns | 80 ns | 119 ns | 70 ns | 70 ns | 70 ns | Binary (70 ns) | 1.00x | -| plateau | sorted_geometric | 16384 | 4 | 15.4 μs | 170 ns | 160 ns | 290 ns | 180 ns | 170 ns | 169 ns | ExpFromLeft (160 ns) | 1.06x | -| plateau | sorted_geometric | 16384 | 16 | 15.6 μs | 390 ns | 310 ns | 1.2 μs | 640 ns | 330 ns | 600 ns | ExpFromLeft (310 ns) | 1.06x | -| plateau | sorted_geometric | 16384 | 64 | 16.0 μs | 1.1 μs | 850 ns | 5.1 μs | 2.3 μs | 900 ns | 2.2 μs | ExpFromLeft (850 ns) | 1.06x | -| plateau | sorted_geometric | 16384 | 256 | 17.4 μs | 3.7 μs | 2.8 μs | 21.8 μs | 9.1 μs | 3.0 μs | 8.6 μs | ExpFromLeft (2.8 μs) | 1.04x | -| plateau | sorted_geometric | 16384 | 1024 | 22.6 μs | 14.2 μs | 10.7 μs | 143.0 μs | 36.0 μs | 11.1 μs | 34.4 μs | ExpFromLeft (10.7 μs) | 1.04x | -| plateau | sorted_geometric | 16384 | 4096 | 46.1 μs | 55.8 μs | 42.1 μs | 570.7 μs | 144.0 μs | 46.2 μs | 137.3 μs | ExpFromLeft (42.1 μs) | 1.10x | -| plateau | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| plateau | sorted_geometric | 65536 | 4 | 61.4 μs | 180 ns | 160 ns | 330 ns | 210 ns | 190 ns | 180 ns | ExpFromLeft (160 ns) | 1.19x | -| plateau | sorted_geometric | 65536 | 16 | 62.3 μs | 420 ns | 320 ns | 1.4 μs | 710 ns | 350 ns | 660 ns | ExpFromLeft (320 ns) | 1.09x | -| plateau | sorted_geometric | 65536 | 64 | 63.0 μs | 1.1 μs | 870 ns | 5.7 μs | 2.6 μs | 920 ns | 2.5 μs | ExpFromLeft (870 ns) | 1.06x | -| plateau | sorted_geometric | 65536 | 256 | 63.2 μs | 3.7 μs | 2.9 μs | 24.9 μs | 10.2 μs | 3.0 μs | 9.7 μs | ExpFromLeft (2.9 μs) | 1.05x | -| plateau | sorted_geometric | 65536 | 1024 | 70.0 μs | 14.1 μs | 10.7 μs | 182.2 μs | 40.6 μs | 11.2 μs | 38.7 μs | ExpFromLeft (10.7 μs) | 1.04x | -| plateau | sorted_geometric | 65536 | 4096 | 92.0 μs | 55.9 μs | 42.2 μs | 709.1 μs | 162.6 μs | 43.9 μs | 154.8 μs | ExpFromLeft (42.2 μs) | 1.04x | -| plateau | sorted_bimodal | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| plateau | sorted_bimodal | 16 | 4 | 90 ns | 100 ns | 100 ns | 170 ns | 90 ns | 100 ns | 70 ns | Binary (90 ns) | 1.11x | -| plateau | sorted_bimodal | 16 | 16 | 180 ns | 270 ns | 230 ns | 610 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | -| plateau | sorted_bimodal | 16 | 64 | 570 ns | 950 ns | 760 ns | 2.3 μs | 809 ns | 600 ns | 730 ns | Linear (570 ns) | 1.05x | -| plateau | sorted_bimodal | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.6 μs | 3.0 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.00x | -| plateau | sorted_bimodal | 16 | 1024 | 7.8 μs | 13.9 μs | 10.6 μs | 34.1 μs | 11.8 μs | 7.8 μs | 10.0 μs | Linear (7.8 μs) | 1.00x | -| plateau | sorted_bimodal | 16 | 4096 | 30.8 μs | 55.5 μs | 42.0 μs | 135.9 μs | 47.1 μs | 30.8 μs | 40.1 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_bimodal | 64 | 1 | 60 ns | 50 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| plateau | sorted_bimodal | 64 | 4 | 110 ns | 110 ns | 110 ns | 210 ns | 100 ns | 130 ns | 90 ns | Binary (100 ns) | 1.30x | -| plateau | sorted_bimodal | 64 | 16 | 210 ns | 270 ns | 220 ns | 740 ns | 320 ns | 230 ns | 270 ns | Linear (210 ns) | 1.10x | -| plateau | sorted_bimodal | 64 | 64 | 600 ns | 950 ns | 760 ns | 2.9 μs | 1.1 μs | 630 ns | 960 ns | Linear (600 ns) | 1.05x | -| plateau | sorted_bimodal | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 11.4 μs | 4.2 μs | 2.1 μs | 3.7 μs | Linear (2.0 μs) | 1.01x | -| plateau | sorted_bimodal | 64 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 44.4 μs | 16.6 μs | 7.8 μs | 14.8 μs | Linear (7.8 μs) | 1.00x | -| plateau | sorted_bimodal | 64 | 4096 | 30.8 μs | 55.7 μs | 42.0 μs | 176.1 μs | 66.4 μs | 30.9 μs | 58.7 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_bimodal | 256 | 4 | 200 ns | 120 ns | 110 ns | 250 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (110 ns) | 1.27x | -| plateau | sorted_bimodal | 256 | 16 | 290 ns | 290 ns | 250 ns | 910 ns | 380 ns | 250 ns | 350 ns | ExpFromLeft (250 ns) | 1.00x | -| plateau | sorted_bimodal | 256 | 64 | 690 ns | 970 ns | 780 ns | 3.6 μs | 1.4 μs | 710 ns | 1.3 μs | Linear (690 ns) | 1.03x | -| plateau | sorted_bimodal | 256 | 256 | 2.1 μs | 3.6 μs | 2.7 μs | 14.7 μs | 5.4 μs | 2.2 μs | 4.9 μs | Linear (2.1 μs) | 1.01x | -| plateau | sorted_bimodal | 256 | 1024 | 7.9 μs | 14.0 μs | 10.6 μs | 56.3 μs | 21.6 μs | 7.9 μs | 19.6 μs | Linear (7.9 μs) | 1.00x | -| plateau | sorted_bimodal | 256 | 4096 | 30.9 μs | 55.6 μs | 42.1 μs | 220.8 μs | 86.1 μs | 30.9 μs | 78.2 μs | Linear (30.9 μs) | 1.00x | -| plateau | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 70 ns | 100 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | -| plateau | sorted_bimodal | 1024 | 4 | 560 ns | 150 ns | 120 ns | 290 ns | 150 ns | 160 ns | 130 ns | ExpFromLeft (120 ns) | 1.33x | -| plateau | sorted_bimodal | 1024 | 16 | 670 ns | 310 ns | 250 ns | 1.0 μs | 470 ns | 260 ns | 430 ns | ExpFromLeft (250 ns) | 1.04x | -| plateau | sorted_bimodal | 1024 | 64 | 1.1 μs | 989 ns | 990 ns | 4.2 μs | 1.8 μs | 820 ns | 1.6 μs | Gallop (989 ns) | 0.83x | -| plateau | sorted_bimodal | 1024 | 256 | 2.5 μs | 4.7 μs | 3.6 μs | 17.2 μs | 6.6 μs | 2.5 μs | 6.1 μs | Linear (2.5 μs) | 1.01x | -| plateau | sorted_bimodal | 1024 | 1024 | 8.2 μs | 14.0 μs | 10.6 μs | 71.8 μs | 26.2 μs | 8.3 μs | 24.4 μs | Linear (8.2 μs) | 1.00x | -| plateau | sorted_bimodal | 1024 | 4096 | 31.3 μs | 55.6 μs | 42.1 μs | 264.7 μs | 104.6 μs | 31.3 μs | 97.2 μs | Linear (31.3 μs) | 1.00x | -| plateau | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_bimodal | 4096 | 4 | 2.0 μs | 150 ns | 130 ns | 330 ns | 160 ns | 170 ns | 150 ns | ExpFromLeft (130 ns) | 1.31x | -| plateau | sorted_bimodal | 4096 | 16 | 2.1 μs | 320 ns | 260 ns | 1.2 μs | 540 ns | 280 ns | 510 ns | ExpFromLeft (260 ns) | 1.08x | -| plateau | sorted_bimodal | 4096 | 64 | 2.5 μs | 999 ns | 790 ns | 4.7 μs | 2.0 μs | 830 ns | 1.9 μs | ExpFromLeft (790 ns) | 1.05x | -| plateau | sorted_bimodal | 4096 | 256 | 3.9 μs | 3.6 μs | 2.8 μs | 19.7 μs | 7.8 μs | 2.9 μs | 7.3 μs | ExpFromLeft (2.8 μs) | 1.04x | -| plateau | sorted_bimodal | 4096 | 1024 | 9.7 μs | 14.1 μs | 10.6 μs | 91.5 μs | 31.2 μs | 9.7 μs | 29.1 μs | Linear (9.7 μs) | 1.00x | -| plateau | sorted_bimodal | 4096 | 4096 | 32.7 μs | 55.6 μs | 42.1 μs | 358.4 μs | 124.6 μs | 32.7 μs | 116.2 μs | Linear (32.7 μs) | 1.00x | -| plateau | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_bimodal | 16384 | 4 | 7.6 μs | 160 ns | 150 ns | 370 ns | 180 ns | 170 ns | 170 ns | ExpFromLeft (150 ns) | 1.13x | -| plateau | sorted_bimodal | 16384 | 16 | 7.9 μs | 330 ns | 270 ns | 1.4 μs | 610 ns | 290 ns | 590 ns | ExpFromLeft (270 ns) | 1.07x | -| plateau | sorted_bimodal | 16384 | 64 | 8.3 μs | 1.0 μs | 810 ns | 5.5 μs | 2.3 μs | 840 ns | 2.2 μs | ExpFromLeft (810 ns) | 1.04x | -| plateau | sorted_bimodal | 16384 | 256 | 9.7 μs | 3.6 μs | 2.8 μs | 23.1 μs | 9.0 μs | 2.9 μs | 8.6 μs | ExpFromLeft (2.8 μs) | 1.04x | -| plateau | sorted_bimodal | 16384 | 1024 | 15.4 μs | 13.9 μs | 10.7 μs | 119.1 μs | 36.0 μs | 11.1 μs | 34.2 μs | ExpFromLeft (10.7 μs) | 1.04x | -| plateau | sorted_bimodal | 16384 | 4096 | 38.5 μs | 55.8 μs | 42.1 μs | 501.1 μs | 143.9 μs | 38.4 μs | 137.0 μs | Linear (38.5 μs) | 1.00x | -| plateau | sorted_bimodal | 65536 | 1 | 80 ns | 70 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | Gallop (70 ns) | 1.14x | -| plateau | sorted_bimodal | 65536 | 4 | 29.8 μs | 180 ns | 160 ns | 410 ns | 200 ns | 190 ns | 190 ns | ExpFromLeft (160 ns) | 1.19x | -| plateau | sorted_bimodal | 65536 | 16 | 30.9 μs | 350 ns | 280 ns | 1.6 μs | 710 ns | 300 ns | 660 ns | ExpFromLeft (280 ns) | 1.07x | -| plateau | sorted_bimodal | 65536 | 64 | 31.6 μs | 1.0 μs | 820 ns | 6.1 μs | 2.6 μs | 850 ns | 2.5 μs | ExpFromLeft (820 ns) | 1.04x | -| plateau | sorted_bimodal | 65536 | 256 | 32.6 μs | 3.6 μs | 2.8 μs | 26.9 μs | 10.2 μs | 2.9 μs | 9.7 μs | ExpFromLeft (2.8 μs) | 1.04x | -| plateau | sorted_bimodal | 65536 | 1024 | 38.7 μs | 14.1 μs | 10.6 μs | 175.2 μs | 40.7 μs | 11.1 μs | 38.7 μs | ExpFromLeft (10.6 μs) | 1.04x | -| plateau | sorted_bimodal | 65536 | 4096 | 61.7 μs | 55.7 μs | 42.1 μs | 678.9 μs | 162.7 μs | 43.8 μs | 154.9 μs | ExpFromLeft (42.1 μs) | 1.04x | -| plateau | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| plateau | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 160 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| plateau | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 200 ns | 500 ns | 230 ns | 190 ns | 190 ns | Linear (170 ns) | 1.12x | -| plateau | sorted_repeated | 16 | 64 | 550 ns | 920 ns | 690 ns | 1.9 μs | 790 ns | 580 ns | 680 ns | Linear (550 ns) | 1.05x | -| plateau | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 7.2 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.01x | -| plateau | sorted_repeated | 16 | 1024 | 7.7 μs | 13.9 μs | 9.8 μs | 28.8 μs | 11.8 μs | 7.8 μs | 10.3 μs | Linear (7.7 μs) | 1.00x | -| plateau | sorted_repeated | 16 | 4096 | 30.8 μs | 54.9 μs | 39.0 μs | 115.1 μs | 47.1 μs | 30.8 μs | 40.0 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| plateau | sorted_repeated | 64 | 4 | 80 ns | 90 ns | 90 ns | 190 ns | 100 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| plateau | sorted_repeated | 64 | 16 | 170 ns | 279 ns | 200 ns | 670 ns | 310 ns | 190 ns | 260 ns | Linear (170 ns) | 1.12x | -| plateau | sorted_repeated | 64 | 64 | 550 ns | 920 ns | 690 ns | 2.5 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | -| plateau | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 10.1 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | -| plateau | sorted_repeated | 64 | 1024 | 7.8 μs | 13.8 μs | 9.8 μs | 40.0 μs | 16.7 μs | 7.8 μs | 14.3 μs | Linear (7.8 μs) | 1.00x | -| plateau | sorted_repeated | 64 | 4096 | 30.8 μs | 54.9 μs | 39.1 μs | 159.7 μs | 67.1 μs | 30.8 μs | 57.1 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 110 ns | 230 ns | 120 ns | 110 ns | 120 ns | Linear (90 ns) | 1.22x | -| plateau | sorted_repeated | 256 | 16 | 180 ns | 280 ns | 220 ns | 830 ns | 390 ns | 200 ns | 350 ns | Linear (180 ns) | 1.11x | -| plateau | sorted_repeated | 256 | 64 | 550 ns | 920 ns | 710 ns | 3.2 μs | 1.4 μs | 580 ns | 1.3 μs | Linear (550 ns) | 1.05x | -| plateau | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 12.6 μs | 5.4 μs | 2.0 μs | 4.9 μs | Linear (2.0 μs) | 1.02x | -| plateau | sorted_repeated | 256 | 1024 | 7.7 μs | 13.8 μs | 9.9 μs | 49.7 μs | 21.4 μs | 7.8 μs | 19.5 μs | Linear (7.7 μs) | 1.00x | -| plateau | sorted_repeated | 256 | 4096 | 30.8 μs | 55.0 μs | 39.0 μs | 198.9 μs | 85.6 μs | 30.8 μs | 78.0 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | sorted_repeated | 1024 | 4 | 90 ns | 110 ns | 100 ns | 270 ns | 150 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | -| plateau | sorted_repeated | 1024 | 16 | 189 ns | 290 ns | 220 ns | 1.0 μs | 470 ns | 200 ns | 430 ns | Linear (189 ns) | 1.06x | -| plateau | sorted_repeated | 1024 | 64 | 560 ns | 930 ns | 690 ns | 3.9 μs | 1.7 μs | 600 ns | 1.6 μs | Linear (560 ns) | 1.07x | -| plateau | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 15.1 μs | 6.6 μs | 2.0 μs | 6.1 μs | Linear (2.0 μs) | 1.02x | -| plateau | sorted_repeated | 1024 | 1024 | 7.7 μs | 13.8 μs | 9.8 μs | 60.2 μs | 26.3 μs | 7.8 μs | 24.2 μs | Linear (7.7 μs) | 1.01x | -| plateau | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.1 μs | 39.1 μs | 239.4 μs | 105.3 μs | 30.8 μs | 96.9 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_repeated | 4096 | 4 | 90 ns | 120 ns | 100 ns | 310 ns | 160 ns | 130 ns | 150 ns | Linear (90 ns) | 1.44x | -| plateau | sorted_repeated | 4096 | 16 | 230 ns | 360 ns | 260 ns | 1.2 μs | 550 ns | 250 ns | 500 ns | Linear (230 ns) | 1.09x | -| plateau | sorted_repeated | 4096 | 64 | 560 ns | 940 ns | 700 ns | 4.5 μs | 2.0 μs | 600 ns | 1.9 μs | Linear (560 ns) | 1.07x | -| plateau | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 17.6 μs | 7.8 μs | 2.1 μs | 7.3 μs | Linear (2.0 μs) | 1.04x | -| plateau | sorted_repeated | 4096 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 70.4 μs | 31.3 μs | 7.8 μs | 28.9 μs | Linear (7.7 μs) | 1.01x | -| plateau | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.1 μs | 39.0 μs | 281.2 μs | 124.9 μs | 30.8 μs | 115.5 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | sorted_repeated | 16384 | 4 | 100 ns | 110 ns | 110 ns | 370 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | -| plateau | sorted_repeated | 16384 | 16 | 190 ns | 290 ns | 240 ns | 1.3 μs | 610 ns | 220 ns | 580 ns | Linear (190 ns) | 1.16x | -| plateau | sorted_repeated | 16384 | 64 | 560 ns | 940 ns | 720 ns | 5.1 μs | 2.3 μs | 600 ns | 2.2 μs | Linear (560 ns) | 1.07x | -| plateau | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 20.2 μs | 9.0 μs | 2.0 μs | 8.6 μs | Linear (2.0 μs) | 1.02x | -| plateau | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.8 μs | 9.9 μs | 80.5 μs | 35.8 μs | 7.8 μs | 34.2 μs | Linear (7.8 μs) | 1.00x | -| plateau | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.0 μs | 39.3 μs | 321.0 μs | 143.6 μs | 30.8 μs | 136.5 μs | Linear (30.8 μs) | 1.00x | -| plateau | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| plateau | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 420 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| plateau | sorted_repeated | 65536 | 16 | 200 ns | 300 ns | 230 ns | 1.5 μs | 690 ns | 220 ns | 650 ns | Linear (200 ns) | 1.10x | -| plateau | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 710 ns | 6.0 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| plateau | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 23.9 μs | 10.2 μs | 2.0 μs | 9.7 μs | Linear (2.0 μs) | 1.01x | -| plateau | sorted_repeated | 65536 | 1024 | 7.7 μs | 13.8 μs | 10.0 μs | 95.7 μs | 40.8 μs | 7.8 μs | 38.7 μs | Linear (7.7 μs) | 1.01x | -| plateau | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.1 μs | 39.1 μs | 382.4 μs | 163.2 μs | 30.8 μs | 154.4 μs | Linear (30.8 μs) | 1.00x | -| plateau | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| plateau | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 90 ns | 90 ns | 100 ns | 70 ns | InterpSearch (90 ns) | 1.11x | -| plateau | unsorted | 16 | 16 | 220 ns | 200 ns | 210 ns | 210 ns | 210 ns | 220 ns | 190 ns | Gallop (200 ns) | 1.10x | -| plateau | unsorted | 16 | 64 | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | 1.0 μs | Binary (1.0 μs) | 1.01x | -| plateau | unsorted | 16 | 256 | 4.6 μs | 4.6 μs | 4.6 μs | 4.5 μs | 4.6 μs | 4.5 μs | 4.6 μs | InterpSearch (4.5 μs) | 1.00x | -| plateau | unsorted | 16 | 1024 | 18.3 μs | 18.3 μs | 18.3 μs | 18.2 μs | 18.3 μs | 18.3 μs | 18.4 μs | InterpSearch (18.2 μs) | 1.00x | -| plateau | unsorted | 16 | 4096 | 74.4 μs | 74.5 μs | 74.4 μs | 74.0 μs | 74.5 μs | 74.2 μs | 74.5 μs | InterpSearch (74.0 μs) | 1.00x | -| plateau | unsorted | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 60 ns | 49 ns | ExpFromLeft (50 ns) | 1.20x | -| plateau | unsorted | 64 | 4 | 100 ns | 110 ns | 110 ns | 110 ns | 110 ns | 120 ns | 90 ns | Linear (100 ns) | 1.20x | -| plateau | unsorted | 64 | 16 | 300 ns | 290 ns | 300 ns | 290 ns | 300 ns | 310 ns | 280 ns | InterpSearch (290 ns) | 1.07x | -| plateau | unsorted | 64 | 64 | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | 1.4 μs | InterpSearch (1.4 μs) | 1.01x | -| plateau | unsorted | 64 | 256 | 5.6 μs | 5.7 μs | 5.7 μs | 5.7 μs | 5.7 μs | 5.7 μs | 5.7 μs | Linear (5.6 μs) | 1.01x | -| plateau | unsorted | 64 | 1024 | 22.8 μs | 22.6 μs | 22.7 μs | 22.7 μs | 22.8 μs | 23.1 μs | 22.8 μs | Gallop (22.6 μs) | 1.02x | -| plateau | unsorted | 64 | 4096 | 89.8 μs | 90.0 μs | 89.9 μs | 90.0 μs | 89.8 μs | 89.7 μs | 89.3 μs | Binary (89.8 μs) | 1.00x | -| plateau | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | unsorted | 256 | 4 | 120 ns | 120 ns | 130 ns | 130 ns | 130 ns | 140 ns | 110 ns | Gallop (120 ns) | 1.17x | -| plateau | unsorted | 256 | 16 | 390 ns | 390 ns | 380 ns | 380 ns | 390 ns | 400 ns | 360 ns | InterpSearch (380 ns) | 1.05x | -| plateau | unsorted | 256 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | InterpSearch (1.6 μs) | 1.01x | -| plateau | unsorted | 256 | 256 | 6.5 μs | 6.5 μs | 6.5 μs | 6.5 μs | 6.5 μs | 6.5 μs | 6.5 μs | InterpSearch (6.5 μs) | 1.00x | -| plateau | unsorted | 256 | 1024 | 27.0 μs | 27.1 μs | 27.1 μs | 27.1 μs | 27.1 μs | 27.1 μs | 26.8 μs | Linear (27.0 μs) | 1.00x | -| plateau | unsorted | 256 | 4096 | 108.6 μs | 108.7 μs | 108.6 μs | 111.7 μs | 111.9 μs | 111.9 μs | 108.1 μs | Linear (108.6 μs) | 1.03x | -| plateau | unsorted | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| plateau | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| plateau | unsorted | 1024 | 16 | 480 ns | 480 ns | 470 ns | 470 ns | 480 ns | 479 ns | 460 ns | InterpSearch (470 ns) | 1.02x | -| plateau | unsorted | 1024 | 64 | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | 2.0 μs | Gallop (2.0 μs) | 1.02x | -| plateau | unsorted | 1024 | 256 | 8.4 μs | 8.2 μs | 8.3 μs | 8.2 μs | 8.3 μs | 8.3 μs | 8.4 μs | InterpSearch (8.2 μs) | 1.02x | -| plateau | unsorted | 1024 | 1024 | 32.3 μs | 32.4 μs | 32.5 μs | 32.4 μs | 32.5 μs | 32.3 μs | 32.4 μs | Linear (32.3 μs) | 1.00x | -| plateau | unsorted | 1024 | 4096 | 130.2 μs | 130.5 μs | 131.5 μs | 129.4 μs | 130.0 μs | 129.9 μs | 130.3 μs | InterpSearch (129.4 μs) | 1.00x | -| plateau | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | unsorted | 4096 | 4 | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 150 ns | InterpSearch (160 ns) | 1.00x | -| plateau | unsorted | 4096 | 16 | 560 ns | 540 ns | 550 ns | 550 ns | 550 ns | 550 ns | 540 ns | Gallop (540 ns) | 1.02x | -| plateau | unsorted | 4096 | 64 | 2.3 μs | 2.4 μs | 2.4 μs | 2.4 μs | 2.4 μs | 2.4 μs | 2.3 μs | Linear (2.3 μs) | 1.03x | -| plateau | unsorted | 4096 | 256 | 9.5 μs | 9.4 μs | 9.5 μs | 9.5 μs | 9.5 μs | 9.5 μs | 9.4 μs | Gallop (9.4 μs) | 1.00x | -| plateau | unsorted | 4096 | 1024 | 36.6 μs | 36.6 μs | 36.6 μs | 36.6 μs | 36.5 μs | 36.5 μs | 36.6 μs | Binary (36.5 μs) | 1.00x | -| plateau | unsorted | 4096 | 4096 | 148.7 μs | 147.9 μs | 147.8 μs | 148.7 μs | 148.1 μs | 148.8 μs | 148.3 μs | ExpFromLeft (147.8 μs) | 1.01x | -| plateau | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| plateau | unsorted | 16384 | 4 | 180 ns | 170 ns | 170 ns | 210 ns | 179 ns | 180 ns | 170 ns | ExpFromLeft (170 ns) | 1.06x | -| plateau | unsorted | 16384 | 16 | 630 ns | 630 ns | 630 ns | 630 ns | 640 ns | 650 ns | 630 ns | InterpSearch (630 ns) | 1.03x | -| plateau | unsorted | 16384 | 64 | 2.6 μs | 2.5 μs | 2.5 μs | 2.5 μs | 2.6 μs | 2.6 μs | 2.5 μs | InterpSearch (2.5 μs) | 1.01x | -| plateau | unsorted | 16384 | 256 | 10.5 μs | 10.5 μs | 10.6 μs | 10.6 μs | 10.6 μs | 10.6 μs | 10.4 μs | Linear (10.5 μs) | 1.01x | -| plateau | unsorted | 16384 | 1024 | 41.8 μs | 41.9 μs | 41.8 μs | 42.0 μs | 42.1 μs | 41.8 μs | 41.9 μs | Linear (41.8 μs) | 1.00x | -| plateau | unsorted | 16384 | 4096 | 168.3 μs | 168.2 μs | 168.2 μs | 168.2 μs | 168.2 μs | 168.2 μs | 167.4 μs | Binary (168.2 μs) | 1.00x | -| plateau | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| plateau | unsorted | 65536 | 4 | 200 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | -| plateau | unsorted | 65536 | 16 | 730 ns | 730 ns | 720 ns | 720 ns | 740 ns | 740 ns | 720 ns | InterpSearch (720 ns) | 1.03x | -| plateau | unsorted | 65536 | 64 | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | 2.9 μs | InterpSearch (2.9 μs) | 1.01x | -| plateau | unsorted | 65536 | 256 | 12.0 μs | 12.0 μs | 12.1 μs | 12.0 μs | 12.0 μs | 12.0 μs | 12.0 μs | Binary (12.0 μs) | 1.00x | -| plateau | unsorted | 65536 | 1024 | 47.8 μs | 48.0 μs | 48.0 μs | 47.9 μs | 47.8 μs | 47.9 μs | 47.9 μs | Linear (47.8 μs) | 1.00x | -| plateau | unsorted | 65536 | 4096 | 194.3 μs | 194.5 μs | 193.9 μs | 193.8 μs | 194.1 μs | 194.3 μs | 193.7 μs | InterpSearch (193.8 μs) | 1.00x | -| bimodal | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | sorted_uniform | 16 | 4 | 80 ns | 100 ns | 90 ns | 170 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| bimodal | sorted_uniform | 16 | 16 | 190 ns | 280 ns | 240 ns | 570 ns | 230 ns | 200 ns | 180 ns | Linear (190 ns) | 1.05x | -| bimodal | sorted_uniform | 16 | 64 | 570 ns | 950 ns | 750 ns | 2.2 μs | 840 ns | 600 ns | 710 ns | Linear (570 ns) | 1.05x | -| bimodal | sorted_uniform | 16 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 8.6 μs | 3.1 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.02x | -| bimodal | sorted_uniform | 16 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 33.6 μs | 12.0 μs | 7.9 μs | 9.9 μs | Linear (7.9 μs) | 1.00x | -| bimodal | sorted_uniform | 16 | 4096 | 31.0 μs | 55.1 μs | 42.3 μs | 132.4 μs | 47.5 μs | 31.0 μs | 41.1 μs | Linear (31.0 μs) | 1.00x | -| bimodal | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | sorted_uniform | 64 | 4 | 120 ns | 120 ns | 120 ns | 180 ns | 110 ns | 130 ns | 90 ns | Binary (110 ns) | 1.18x | -| bimodal | sorted_uniform | 64 | 16 | 190 ns | 290 ns | 220 ns | 640 ns | 320 ns | 210 ns | 280 ns | Linear (190 ns) | 1.11x | -| bimodal | sorted_uniform | 64 | 64 | 650 ns | 980 ns | 770 ns | 2.5 μs | 1.1 μs | 680 ns | 940 ns | Linear (650 ns) | 1.05x | -| bimodal | sorted_uniform | 64 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 10.7 μs | 4.4 μs | 2.1 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | -| bimodal | sorted_uniform | 64 | 1024 | 7.9 μs | 14.1 μs | 10.7 μs | 42.1 μs | 17.3 μs | 7.9 μs | 15.0 μs | Linear (7.9 μs) | 1.00x | -| bimodal | sorted_uniform | 64 | 4096 | 31.9 μs | 55.9 μs | 43.0 μs | 164.1 μs | 67.5 μs | 31.9 μs | 58.4 μs | Linear (31.9 μs) | 1.00x | -| bimodal | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | sorted_uniform | 256 | 4 | 80 ns | 100 ns | 100 ns | 250 ns | 120 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | -| bimodal | sorted_uniform | 256 | 16 | 500 ns | 320 ns | 260 ns | 760 ns | 390 ns | 280 ns | 350 ns | ExpFromLeft (260 ns) | 1.08x | -| bimodal | sorted_uniform | 256 | 64 | 930 ns | 1.1 μs | 860 ns | 3.1 μs | 1.4 μs | 940 ns | 1.2 μs | ExpFromLeft (860 ns) | 1.09x | -| bimodal | sorted_uniform | 256 | 256 | 2.5 μs | 3.8 μs | 2.9 μs | 12.9 μs | 5.5 μs | 2.5 μs | 5.0 μs | Linear (2.5 μs) | 1.01x | -| bimodal | sorted_uniform | 256 | 1024 | 8.2 μs | 14.4 μs | 10.8 μs | 57.7 μs | 22.9 μs | 8.2 μs | 20.7 μs | Linear (8.2 μs) | 1.00x | -| bimodal | sorted_uniform | 256 | 4096 | 31.9 μs | 57.1 μs | 43.5 μs | 212.3 μs | 89.4 μs | 31.9 μs | 80.2 μs | Linear (31.9 μs) | 1.00x | -| bimodal | sorted_uniform | 1024 | 1 | 60 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | sorted_uniform | 1024 | 4 | 520 ns | 140 ns | 130 ns | 290 ns | 140 ns | 170 ns | 130 ns | ExpFromLeft (130 ns) | 1.31x | -| bimodal | sorted_uniform | 1024 | 16 | 1.2 μs | 380 ns | 310 ns | 1.0 μs | 460 ns | 330 ns | 430 ns | ExpFromLeft (310 ns) | 1.06x | -| bimodal | sorted_uniform | 1024 | 64 | 2.0 μs | 1.2 μs | 970 ns | 3.8 μs | 1.7 μs | 1.0 μs | 1.5 μs | ExpFromLeft (970 ns) | 1.05x | -| bimodal | sorted_uniform | 1024 | 256 | 3.7 μs | 4.3 μs | 3.3 μs | 15.7 μs | 6.8 μs | 3.7 μs | 6.1 μs | ExpFromLeft (3.3 μs) | 1.14x | -| bimodal | sorted_uniform | 1024 | 1024 | 9.7 μs | 15.7 μs | 11.6 μs | 79.7 μs | 28.0 μs | 9.8 μs | 25.7 μs | Linear (9.7 μs) | 1.01x | -| bimodal | sorted_uniform | 1024 | 4096 | 33.5 μs | 58.3 μs | 44.0 μs | 324.0 μs | 118.6 μs | 33.3 μs | 113.4 μs | Linear (33.5 μs) | 1.00x | -| bimodal | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 90 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (70 ns) | 0.86x | -| bimodal | sorted_uniform | 4096 | 4 | 90 ns | 110 ns | 120 ns | 309 ns | 160 ns | 130 ns | 140 ns | Linear (90 ns) | 1.44x | -| bimodal | sorted_uniform | 4096 | 16 | 1.9 μs | 400 ns | 310 ns | 1.1 μs | 540 ns | 330 ns | 490 ns | ExpFromLeft (310 ns) | 1.06x | -| bimodal | sorted_uniform | 4096 | 64 | 6.2 μs | 1.4 μs | 1.1 μs | 4.4 μs | 2.0 μs | 1.1 μs | 1.8 μs | ExpFromLeft (1.1 μs) | 1.04x | -| bimodal | sorted_uniform | 4096 | 256 | 8.4 μs | 4.6 μs | 3.5 μs | 18.4 μs | 7.9 μs | 3.7 μs | 7.2 μs | ExpFromLeft (3.5 μs) | 1.03x | -| bimodal | sorted_uniform | 4096 | 1024 | 15.0 μs | 16.8 μs | 12.7 μs | 109.1 μs | 33.9 μs | 15.3 μs | 30.0 μs | ExpFromLeft (12.7 μs) | 1.20x | -| bimodal | sorted_uniform | 4096 | 4096 | 39.4 μs | 63.7 μs | 47.7 μs | 452.0 μs | 163.7 μs | 40.2 μs | 147.5 μs | Linear (39.4 μs) | 1.02x | -| bimodal | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 130 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | sorted_uniform | 16384 | 4 | 4.6 μs | 200 ns | 180 ns | 370 ns | 180 ns | 200 ns | 170 ns | ExpFromLeft (180 ns) | 1.11x | -| bimodal | sorted_uniform | 16384 | 16 | 18.5 μs | 550 ns | 430 ns | 1.3 μs | 610 ns | 450 ns | 560 ns | ExpFromLeft (430 ns) | 1.05x | -| bimodal | sorted_uniform | 16384 | 64 | 20.5 μs | 1.5 μs | 1.2 μs | 5.2 μs | 2.3 μs | 1.2 μs | 2.1 μs | ExpFromLeft (1.2 μs) | 1.03x | -| bimodal | sorted_uniform | 16384 | 256 | 26.6 μs | 5.1 μs | 3.9 μs | 21.7 μs | 9.2 μs | 4.1 μs | 8.5 μs | ExpFromLeft (3.9 μs) | 1.03x | -| bimodal | sorted_uniform | 16384 | 1024 | 35.0 μs | 19.1 μs | 14.6 μs | 140.4 μs | 38.4 μs | 15.0 μs | 35.7 μs | ExpFromLeft (14.6 μs) | 1.03x | -| bimodal | sorted_uniform | 16384 | 4096 | 63.6 μs | 71.5 μs | 56.6 μs | 571.5 μs | 206.6 μs | 63.3 μs | 199.3 μs | ExpFromLeft (56.6 μs) | 1.12x | -| bimodal | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 79 ns | 140 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (79 ns) | 1.01x | -| bimodal | sorted_uniform | 65536 | 4 | 100 ns | 120 ns | 110 ns | 400 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| bimodal | sorted_uniform | 65536 | 16 | 46.0 μs | 370 ns | 300 ns | 1.5 μs | 680 ns | 320 ns | 640 ns | ExpFromLeft (300 ns) | 1.07x | -| bimodal | sorted_uniform | 65536 | 64 | 90.2 μs | 1.7 μs | 1.3 μs | 5.7 μs | 2.6 μs | 1.3 μs | 2.5 μs | ExpFromLeft (1.3 μs) | 1.03x | -| bimodal | sorted_uniform | 65536 | 256 | 95.1 μs | 6.0 μs | 4.6 μs | 26.8 μs | 10.8 μs | 4.6 μs | 9.9 μs | ExpFromLeft (4.6 μs) | 0.99x | -| bimodal | sorted_uniform | 65536 | 1024 | 107.1 μs | 21.4 μs | 16.8 μs | 189.8 μs | 43.2 μs | 17.0 μs | 41.2 μs | ExpFromLeft (16.8 μs) | 1.01x | -| bimodal | sorted_uniform | 65536 | 4096 | 136.7 μs | 88.7 μs | 67.5 μs | 730.4 μs | 251.0 μs | 66.9 μs | 251.5 μs | ExpFromLeft (67.5 μs) | 0.99x | -| bimodal | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | sorted_dense_burst | 16 | 4 | 80 ns | 90 ns | 90 ns | 160 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| bimodal | sorted_dense_burst | 16 | 16 | 170 ns | 270 ns | 220 ns | 570 ns | 230 ns | 190 ns | 190 ns | Linear (170 ns) | 1.12x | -| bimodal | sorted_dense_burst | 16 | 64 | 550 ns | 920 ns | 720 ns | 2.2 μs | 790 ns | 570 ns | 649 ns | Linear (550 ns) | 1.04x | -| bimodal | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 8.4 μs | 3.0 μs | 2.0 μs | 2.5 μs | Linear (2.0 μs) | 1.01x | -| bimodal | sorted_dense_burst | 16 | 1024 | 7.7 μs | 13.8 μs | 10.5 μs | 33.1 μs | 11.8 μs | 7.8 μs | 9.6 μs | Linear (7.7 μs) | 1.01x | -| bimodal | sorted_dense_burst | 16 | 4096 | 30.8 μs | 54.8 μs | 42.0 μs | 130.4 μs | 47.0 μs | 32.9 μs | 38.5 μs | Linear (30.8 μs) | 1.07x | -| bimodal | sorted_dense_burst | 64 | 1 | 50 ns | 90 ns | 50 ns | 80 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | sorted_dense_burst | 64 | 4 | 80 ns | 100 ns | 90 ns | 190 ns | 110 ns | 110 ns | 80 ns | Linear (80 ns) | 1.38x | -| bimodal | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 220 ns | 670 ns | 310 ns | 200 ns | 270 ns | Linear (170 ns) | 1.18x | -| bimodal | sorted_dense_burst | 64 | 64 | 550 ns | 930 ns | 730 ns | 2.6 μs | 1.1 μs | 580 ns | 910 ns | Linear (550 ns) | 1.05x | -| bimodal | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 10.8 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | -| bimodal | sorted_dense_burst | 64 | 1024 | 8.3 μs | 13.9 μs | 10.5 μs | 41.6 μs | 17.1 μs | 7.8 μs | 14.1 μs | Linear (8.3 μs) | 0.94x | -| bimodal | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.4 μs | 41.9 μs | 162.9 μs | 66.6 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 80 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | sorted_dense_burst | 256 | 4 | 80 ns | 100 ns | 100 ns | 200 ns | 120 ns | 110 ns | 110 ns | Linear (80 ns) | 1.38x | -| bimodal | sorted_dense_burst | 256 | 16 | 180 ns | 280 ns | 230 ns | 780 ns | 380 ns | 250 ns | 350 ns | Linear (180 ns) | 1.39x | -| bimodal | sorted_dense_burst | 256 | 64 | 550 ns | 930 ns | 730 ns | 3.2 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | -| bimodal | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 12.9 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| bimodal | sorted_dense_burst | 256 | 1024 | 7.8 μs | 13.9 μs | 10.6 μs | 56.1 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | -| bimodal | sorted_dense_burst | 256 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 205.3 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_dense_burst | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | sorted_dense_burst | 1024 | 4 | 100 ns | 100 ns | 110 ns | 290 ns | 140 ns | 130 ns | 120 ns | Gallop (100 ns) | 1.30x | -| bimodal | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 250 ns | 999 ns | 460 ns | 250 ns | 420 ns | Linear (180 ns) | 1.39x | -| bimodal | sorted_dense_burst | 1024 | 64 | 560 ns | 939 ns | 730 ns | 3.9 μs | 1.7 μs | 790 ns | 1.5 μs | Linear (560 ns) | 1.41x | -| bimodal | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 16.1 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.01x | -| bimodal | sorted_dense_burst | 1024 | 1024 | 8.3 μs | 14.0 μs | 10.6 μs | 78.8 μs | 26.3 μs | 7.8 μs | 24.0 μs | Linear (8.3 μs) | 0.94x | -| bimodal | sorted_dense_burst | 1024 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 312.8 μs | 105.5 μs | 30.9 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 100 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | sorted_dense_burst | 4096 | 4 | 100 ns | 110 ns | 110 ns | 400 ns | 200 ns | 130 ns | 150 ns | Linear (100 ns) | 1.30x | -| bimodal | sorted_dense_burst | 4096 | 16 | 180 ns | 290 ns | 260 ns | 1.1 μs | 520 ns | 270 ns | 489 ns | Linear (180 ns) | 1.50x | -| bimodal | sorted_dense_burst | 4096 | 64 | 560 ns | 950 ns | 750 ns | 4.3 μs | 2.0 μs | 780 ns | 1.8 μs | Linear (560 ns) | 1.39x | -| bimodal | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 19.0 μs | 7.8 μs | 2.8 μs | 7.2 μs | Linear (2.0 μs) | 1.40x | -| bimodal | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 14.0 μs | 10.4 μs | 101.8 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | -| bimodal | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 56.0 μs | 41.8 μs | 441.0 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 110 ns | 80 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | sorted_dense_burst | 16384 | 4 | 100 ns | 110 ns | 110 ns | 360 ns | 179 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | -| bimodal | sorted_dense_burst | 16384 | 16 | 200 ns | 290 ns | 240 ns | 1.3 μs | 610 ns | 270 ns | 560 ns | Linear (200 ns) | 1.35x | -| bimodal | sorted_dense_burst | 16384 | 64 | 570 ns | 950 ns | 750 ns | 5.1 μs | 2.3 μs | 790 ns | 2.1 μs | Linear (570 ns) | 1.39x | -| bimodal | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 22.3 μs | 9.0 μs | 2.8 μs | 8.4 μs | Linear (2.0 μs) | 1.41x | -| bimodal | sorted_dense_burst | 16384 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 136.3 μs | 36.0 μs | 11.0 μs | 33.4 μs | Linear (7.8 μs) | 1.41x | -| bimodal | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.7 μs | 42.0 μs | 556.4 μs | 144.2 μs | 30.8 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 120 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| bimodal | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 110 ns | 370 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| bimodal | sorted_dense_burst | 65536 | 16 | 190 ns | 300 ns | 250 ns | 1.5 μs | 690 ns | 260 ns | 640 ns | Linear (190 ns) | 1.37x | -| bimodal | sorted_dense_burst | 65536 | 64 | 780 ns | 960 ns | 750 ns | 5.9 μs | 2.6 μs | 820 ns | 2.4 μs | ExpFromLeft (750 ns) | 1.09x | -| bimodal | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 24.8 μs | 10.2 μs | 2.8 μs | 9.5 μs | Linear (2.0 μs) | 1.42x | -| bimodal | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 181.4 μs | 40.8 μs | 11.0 μs | 38.2 μs | Linear (7.8 μs) | 1.41x | -| bimodal | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 707.9 μs | 163.2 μs | 43.7 μs | 152.6 μs | Linear (30.8 μs) | 1.42x | -| bimodal | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | sorted_near_start | 16 | 4 | 90 ns | 100 ns | 100 ns | 160 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | -| bimodal | sorted_near_start | 16 | 16 | 180 ns | 280 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | -| bimodal | sorted_near_start | 16 | 64 | 570 ns | 960 ns | 740 ns | 1.8 μs | 810 ns | 590 ns | 690 ns | Linear (570 ns) | 1.04x | -| bimodal | sorted_near_start | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 6.8 μs | 3.0 μs | 2.1 μs | 2.6 μs | Linear (2.1 μs) | 1.01x | -| bimodal | sorted_near_start | 16 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 27.2 μs | 11.9 μs | 7.8 μs | 10.1 μs | Linear (7.8 μs) | 1.00x | -| bimodal | sorted_near_start | 16 | 4096 | 30.9 μs | 55.7 μs | 42.1 μs | 107.6 μs | 47.6 μs | 30.9 μs | 40.2 μs | Linear (30.9 μs) | 1.00x | -| bimodal | sorted_near_start | 64 | 1 | 60 ns | 50 ns | 50 ns | 69 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| bimodal | sorted_near_start | 64 | 4 | 130 ns | 110 ns | 110 ns | 200 ns | 130 ns | 120 ns | 90 ns | ExpFromLeft (110 ns) | 1.09x | -| bimodal | sorted_near_start | 64 | 16 | 220 ns | 280 ns | 230 ns | 520 ns | 320 ns | 240 ns | 280 ns | Linear (220 ns) | 1.09x | -| bimodal | sorted_near_start | 64 | 64 | 600 ns | 960 ns | 750 ns | 1.8 μs | 1.1 μs | 630 ns | 1.0 μs | Linear (600 ns) | 1.05x | -| bimodal | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.1 μs | 4.2 μs | 2.2 μs | 3.8 μs | Linear (2.1 μs) | 1.01x | -| bimodal | sorted_near_start | 64 | 1024 | 7.9 μs | 14.1 μs | 10.7 μs | 28.1 μs | 16.6 μs | 7.9 μs | 14.9 μs | Linear (7.9 μs) | 1.00x | -| bimodal | sorted_near_start | 64 | 4096 | 31.0 μs | 55.9 μs | 42.1 μs | 113.3 μs | 66.4 μs | 31.0 μs | 59.9 μs | Linear (31.0 μs) | 1.00x | -| bimodal | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | sorted_near_start | 256 | 4 | 360 ns | 150 ns | 130 ns | 210 ns | 130 ns | 150 ns | 110 ns | ExpFromLeft (130 ns) | 1.15x | -| bimodal | sorted_near_start | 256 | 16 | 470 ns | 320 ns | 260 ns | 630 ns | 450 ns | 270 ns | 390 ns | ExpFromLeft (260 ns) | 1.04x | -| bimodal | sorted_near_start | 256 | 64 | 930 ns | 1.1 μs | 830 ns | 2.4 μs | 1.5 μs | 1.0 μs | 1.4 μs | ExpFromLeft (830 ns) | 1.20x | -| bimodal | sorted_near_start | 256 | 256 | 2.4 μs | 3.8 μs | 3.0 μs | 9.5 μs | 5.6 μs | 2.5 μs | 5.1 μs | Linear (2.4 μs) | 1.02x | -| bimodal | sorted_near_start | 256 | 1024 | 8.8 μs | 14.4 μs | 10.9 μs | 36.9 μs | 21.7 μs | 8.4 μs | 19.8 μs | Linear (8.8 μs) | 0.96x | -| bimodal | sorted_near_start | 256 | 4096 | 31.6 μs | 56.3 μs | 42.6 μs | 149.5 μs | 86.2 μs | 31.7 μs | 78.7 μs | Linear (31.6 μs) | 1.00x | -| bimodal | sorted_near_start | 1024 | 1 | 60 ns | 60 ns | 70 ns | 90 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| bimodal | sorted_near_start | 1024 | 4 | 820 ns | 160 ns | 160 ns | 240 ns | 140 ns | 180 ns | 120 ns | Binary (140 ns) | 1.29x | -| bimodal | sorted_near_start | 1024 | 16 | 950 ns | 410 ns | 310 ns | 800 ns | 460 ns | 340 ns | 430 ns | ExpFromLeft (310 ns) | 1.10x | -| bimodal | sorted_near_start | 1024 | 64 | 1.8 μs | 1.1 μs | 810 ns | 3.1 μs | 2.0 μs | 850 ns | 1.8 μs | ExpFromLeft (810 ns) | 1.05x | -| bimodal | sorted_near_start | 1024 | 256 | 3.3 μs | 4.0 μs | 3.0 μs | 12.4 μs | 7.3 μs | 3.4 μs | 6.8 μs | ExpFromLeft (3.0 μs) | 1.10x | -| bimodal | sorted_near_start | 1024 | 1024 | 10.3 μs | 15.2 μs | 11.8 μs | 47.6 μs | 27.0 μs | 10.3 μs | 25.2 μs | Linear (10.3 μs) | 1.00x | -| bimodal | sorted_near_start | 1024 | 4096 | 33.6 μs | 57.4 μs | 43.8 μs | 189.3 μs | 105.5 μs | 33.6 μs | 98.5 μs | Linear (33.6 μs) | 1.00x | -| bimodal | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 69 ns | 90 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (69 ns) | 1.01x | -| bimodal | sorted_near_start | 4096 | 4 | 5.7 μs | 200 ns | 180 ns | 250 ns | 160 ns | 200 ns | 150 ns | Binary (160 ns) | 1.25x | -| bimodal | sorted_near_start | 4096 | 16 | 3.1 μs | 450 ns | 370 ns | 880 ns | 570 ns | 380 ns | 530 ns | ExpFromLeft (370 ns) | 1.03x | -| bimodal | sorted_near_start | 4096 | 64 | 3.5 μs | 1.3 μs | 920 ns | 3.6 μs | 2.6 μs | 960 ns | 2.5 μs | ExpFromLeft (920 ns) | 1.04x | -| bimodal | sorted_near_start | 4096 | 256 | 5.9 μs | 4.3 μs | 3.0 μs | 14.5 μs | 10.7 μs | 3.1 μs | 9.7 μs | ExpFromLeft (3.0 μs) | 1.03x | -| bimodal | sorted_near_start | 4096 | 1024 | 15.5 μs | 17.1 μs | 13.0 μs | 60.1 μs | 38.7 μs | 15.3 μs | 34.8 μs | ExpFromLeft (13.0 μs) | 1.18x | -| bimodal | sorted_near_start | 4096 | 4096 | 41.5 μs | 60.7 μs | 46.9 μs | 236.7 μs | 137.5 μs | 41.6 μs | 123.7 μs | Linear (41.5 μs) | 1.00x | -| bimodal | sorted_near_start | 16384 | 1 | 80 ns | 70 ns | 70 ns | 100 ns | 70 ns | 80 ns | 69 ns | ExpFromLeft (70 ns) | 1.14x | -| bimodal | sorted_near_start | 16384 | 4 | 11.5 μs | 220 ns | 180 ns | 290 ns | 180 ns | 210 ns | 170 ns | ExpFromLeft (180 ns) | 1.17x | -| bimodal | sorted_near_start | 16384 | 16 | 17.9 μs | 649 ns | 500 ns | 989 ns | 600 ns | 510 ns | 560 ns | ExpFromLeft (500 ns) | 1.02x | -| bimodal | sorted_near_start | 16384 | 64 | 12.1 μs | 1.8 μs | 1.3 μs | 4.1 μs | 3.0 μs | 1.3 μs | 2.8 μs | ExpFromLeft (1.3 μs) | 1.03x | -| bimodal | sorted_near_start | 16384 | 256 | 13.7 μs | 5.1 μs | 3.9 μs | 17.3 μs | 16.2 μs | 3.9 μs | 15.3 μs | ExpFromLeft (3.9 μs) | 1.00x | -| bimodal | sorted_near_start | 16384 | 1024 | 30.8 μs | 18.0 μs | 12.7 μs | 78.3 μs | 69.2 μs | 13.2 μs | 62.2 μs | ExpFromLeft (12.7 μs) | 1.04x | -| bimodal | sorted_near_start | 16384 | 4096 | 64.5 μs | 69.7 μs | 54.5 μs | 332.8 μs | 223.2 μs | 64.4 μs | 202.5 μs | ExpFromLeft (54.5 μs) | 1.18x | -| bimodal | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 110 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| bimodal | sorted_near_start | 65536 | 4 | 45.4 μs | 280 ns | 220 ns | 340 ns | 200 ns | 250 ns | 180 ns | Binary (200 ns) | 1.25x | -| bimodal | sorted_near_start | 65536 | 16 | 46.9 μs | 720 ns | 550 ns | 1.2 μs | 690 ns | 580 ns | 690 ns | ExpFromLeft (550 ns) | 1.05x | -| bimodal | sorted_near_start | 65536 | 64 | 91.7 μs | 2.4 μs | 1.8 μs | 4.7 μs | 3.4 μs | 1.8 μs | 3.2 μs | ExpFromLeft (1.8 μs) | 1.01x | -| bimodal | sorted_near_start | 65536 | 256 | 76.7 μs | 7.6 μs | 6.6 μs | 20.2 μs | 19.7 μs | 5.1 μs | 18.7 μs | ExpFromLeft (6.6 μs) | 0.78x | -| bimodal | sorted_near_start | 65536 | 1024 | 102.3 μs | 23.6 μs | 16.1 μs | 109.6 μs | 84.7 μs | 16.8 μs | 78.7 μs | ExpFromLeft (16.1 μs) | 1.04x | -| bimodal | sorted_near_start | 65536 | 4096 | 149.5 μs | 96.5 μs | 76.4 μs | 465.1 μs | 281.7 μs | 76.3 μs | 241.3 μs | ExpFromLeft (76.4 μs) | 1.00x | -| bimodal | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | sorted_arithmetic | 16 | 4 | 110 ns | 120 ns | 120 ns | 160 ns | 100 ns | 120 ns | 80 ns | Binary (100 ns) | 1.20x | -| bimodal | sorted_arithmetic | 16 | 16 | 190 ns | 280 ns | 220 ns | 540 ns | 240 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | -| bimodal | sorted_arithmetic | 16 | 64 | 570 ns | 960 ns | 740 ns | 2.1 μs | 800 ns | 600 ns | 660 ns | Linear (570 ns) | 1.05x | -| bimodal | sorted_arithmetic | 16 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 8.7 μs | 3.1 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.01x | -| bimodal | sorted_arithmetic | 16 | 1024 | 8.0 μs | 14.2 μs | 10.8 μs | 33.5 μs | 12.0 μs | 8.0 μs | 9.9 μs | Linear (8.0 μs) | 1.00x | -| bimodal | sorted_arithmetic | 16 | 4096 | 31.1 μs | 55.7 μs | 42.3 μs | 131.7 μs | 47.6 μs | 44.5 μs | 44.9 μs | Linear (31.1 μs) | 1.43x | -| bimodal | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| bimodal | sorted_arithmetic | 64 | 4 | 160 ns | 140 ns | 120 ns | 170 ns | 110 ns | 140 ns | 90 ns | Binary (110 ns) | 1.27x | -| bimodal | sorted_arithmetic | 64 | 16 | 250 ns | 320 ns | 260 ns | 650 ns | 330 ns | 270 ns | 270 ns | Linear (250 ns) | 1.08x | -| bimodal | sorted_arithmetic | 64 | 64 | 650 ns | 1.0 μs | 830 ns | 2.5 μs | 1.1 μs | 700 ns | 940 ns | Linear (650 ns) | 1.08x | -| bimodal | sorted_arithmetic | 64 | 256 | 2.1 μs | 3.7 μs | 2.7 μs | 10.5 μs | 4.4 μs | 2.1 μs | 3.9 μs | Linear (2.1 μs) | 1.01x | -| bimodal | sorted_arithmetic | 64 | 1024 | 7.9 μs | 14.3 μs | 10.8 μs | 42.4 μs | 17.5 μs | 8.0 μs | 15.2 μs | Linear (7.9 μs) | 1.01x | -| bimodal | sorted_arithmetic | 64 | 4096 | 32.0 μs | 56.4 μs | 43.0 μs | 163.8 μs | 67.6 μs | 32.0 μs | 58.3 μs | Linear (32.0 μs) | 1.00x | -| bimodal | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | sorted_arithmetic | 256 | 4 | 490 ns | 150 ns | 140 ns | 190 ns | 130 ns | 160 ns | 110 ns | Binary (130 ns) | 1.23x | -| bimodal | sorted_arithmetic | 256 | 16 | 530 ns | 370 ns | 300 ns | 780 ns | 400 ns | 320 ns | 350 ns | ExpFromLeft (300 ns) | 1.07x | -| bimodal | sorted_arithmetic | 256 | 64 | 929 ns | 1.2 μs | 920 ns | 3.1 μs | 1.4 μs | 950 ns | 1.2 μs | ExpFromLeft (920 ns) | 1.03x | -| bimodal | sorted_arithmetic | 256 | 256 | 2.5 μs | 4.0 μs | 3.0 μs | 12.8 μs | 5.4 μs | 2.5 μs | 4.8 μs | Linear (2.5 μs) | 1.02x | -| bimodal | sorted_arithmetic | 256 | 1024 | 11.6 μs | 14.6 μs | 10.7 μs | 59.6 μs | 22.6 μs | 8.2 μs | 20.3 μs | ExpFromLeft (10.7 μs) | 0.77x | -| bimodal | sorted_arithmetic | 256 | 4096 | 32.0 μs | 57.9 μs | 43.5 μs | 212.7 μs | 89.7 μs | 32.0 μs | 81.0 μs | Linear (32.0 μs) | 1.00x | -| bimodal | sorted_arithmetic | 1024 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (60 ns) | 1.17x | -| bimodal | sorted_arithmetic | 1024 | 4 | 1.6 μs | 180 ns | 150 ns | 210 ns | 150 ns | 190 ns | 130 ns | ExpFromLeft (150 ns) | 1.27x | -| bimodal | sorted_arithmetic | 1024 | 16 | 1.7 μs | 400 ns | 320 ns | 920 ns | 480 ns | 350 ns | 430 ns | ExpFromLeft (320 ns) | 1.09x | -| bimodal | sorted_arithmetic | 1024 | 64 | 2.3 μs | 1.3 μs | 1.0 μs | 3.7 μs | 1.7 μs | 1.1 μs | 1.6 μs | ExpFromLeft (1.0 μs) | 1.04x | -| bimodal | sorted_arithmetic | 1024 | 256 | 3.7 μs | 4.5 μs | 3.4 μs | 16.0 μs | 6.6 μs | 3.7 μs | 6.1 μs | ExpFromLeft (3.4 μs) | 1.10x | -| bimodal | sorted_arithmetic | 1024 | 1024 | 9.7 μs | 15.9 μs | 12.0 μs | 89.3 μs | 26.7 μs | 9.8 μs | 24.5 μs | Linear (9.7 μs) | 1.00x | -| bimodal | sorted_arithmetic | 1024 | 4096 | 32.7 μs | 59.0 μs | 43.3 μs | 340.3 μs | 125.8 μs | 33.5 μs | 116.7 μs | Linear (32.7 μs) | 1.03x | -| bimodal | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | InterpSearch (70 ns) | 0.86x | -| bimodal | sorted_arithmetic | 4096 | 4 | 5.9 μs | 200 ns | 170 ns | 230 ns | 170 ns | 200 ns | 140 ns | ExpFromLeft (170 ns) | 1.18x | -| bimodal | sorted_arithmetic | 4096 | 16 | 5.9 μs | 440 ns | 340 ns | 1.1 μs | 540 ns | 390 ns | 500 ns | ExpFromLeft (340 ns) | 1.15x | -| bimodal | sorted_arithmetic | 4096 | 64 | 6.8 μs | 1.4 μs | 1.1 μs | 4.3 μs | 2.0 μs | 1.1 μs | 1.8 μs | ExpFromLeft (1.1 μs) | 1.06x | -| bimodal | sorted_arithmetic | 4096 | 256 | 8.9 μs | 4.9 μs | 3.8 μs | 18.6 μs | 7.8 μs | 3.9 μs | 7.2 μs | ExpFromLeft (3.8 μs) | 1.03x | -| bimodal | sorted_arithmetic | 4096 | 1024 | 15.3 μs | 17.5 μs | 13.3 μs | 112.8 μs | 32.3 μs | 15.2 μs | 30.6 μs | ExpFromLeft (13.3 μs) | 1.14x | -| bimodal | sorted_arithmetic | 4096 | 4096 | 39.9 μs | 64.3 μs | 49.4 μs | 487.6 μs | 173.5 μs | 39.8 μs | 165.3 μs | Linear (39.9 μs) | 1.00x | -| bimodal | sorted_arithmetic | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| bimodal | sorted_arithmetic | 16384 | 4 | 26.4 μs | 240 ns | 190 ns | 260 ns | 180 ns | 280 ns | 170 ns | Binary (180 ns) | 1.56x | -| bimodal | sorted_arithmetic | 16384 | 16 | 22.8 μs | 480 ns | 370 ns | 1.2 μs | 620 ns | 420 ns | 580 ns | ExpFromLeft (370 ns) | 1.14x | -| bimodal | sorted_arithmetic | 16384 | 64 | 24.8 μs | 1.6 μs | 1.2 μs | 5.1 μs | 2.3 μs | 1.2 μs | 2.1 μs | ExpFromLeft (1.2 μs) | 1.05x | -| bimodal | sorted_arithmetic | 16384 | 256 | 26.9 μs | 5.5 μs | 4.1 μs | 22.4 μs | 9.2 μs | 4.2 μs | 8.6 μs | ExpFromLeft (4.1 μs) | 1.03x | -| bimodal | sorted_arithmetic | 16384 | 1024 | 35.4 μs | 19.7 μs | 14.9 μs | 150.1 μs | 37.2 μs | 15.4 μs | 35.2 μs | ExpFromLeft (14.9 μs) | 1.03x | -| bimodal | sorted_arithmetic | 16384 | 4096 | 78.7 μs | 88.3 μs | 55.3 μs | 585.1 μs | 213.1 μs | 68.6 μs | 207.7 μs | ExpFromLeft (55.3 μs) | 1.24x | -| bimodal | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| bimodal | sorted_arithmetic | 65536 | 4 | 90.8 μs | 250 ns | 210 ns | 270 ns | 200 ns | 240 ns | 190 ns | Binary (200 ns) | 1.20x | -| bimodal | sorted_arithmetic | 65536 | 16 | 92.9 μs | 540 ns | 420 ns | 1.4 μs | 700 ns | 450 ns | 650 ns | ExpFromLeft (420 ns) | 1.07x | -| bimodal | sorted_arithmetic | 65536 | 64 | 96.1 μs | 1.7 μs | 1.3 μs | 5.8 μs | 2.6 μs | 1.3 μs | 2.5 μs | ExpFromLeft (1.3 μs) | 1.02x | -| bimodal | sorted_arithmetic | 65536 | 256 | 99.3 μs | 6.0 μs | 4.4 μs | 25.2 μs | 10.6 μs | 4.5 μs | 9.8 μs | ExpFromLeft (4.4 μs) | 1.03x | -| bimodal | sorted_arithmetic | 65536 | 1024 | 108.3 μs | 22.2 μs | 16.6 μs | 195.5 μs | 42.4 μs | 16.9 μs | 40.6 μs | ExpFromLeft (16.6 μs) | 1.02x | -| bimodal | sorted_arithmetic | 65536 | 4096 | 139.6 μs | 84.7 μs | 65.7 μs | 710.7 μs | 257.7 μs | 64.5 μs | 259.7 μs | ExpFromLeft (65.7 μs) | 0.98x | -| bimodal | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 110 ns | 160 ns | 90 ns | 120 ns | 80 ns | Binary (90 ns) | 1.33x | -| bimodal | sorted_geometric | 16 | 16 | 190 ns | 280 ns | 220 ns | 540 ns | 220 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | -| bimodal | sorted_geometric | 16 | 64 | 580 ns | 950 ns | 750 ns | 2.2 μs | 800 ns | 610 ns | 660 ns | Linear (580 ns) | 1.05x | -| bimodal | sorted_geometric | 16 | 256 | 2.1 μs | 3.6 μs | 2.8 μs | 8.7 μs | 3.1 μs | 2.1 μs | 2.5 μs | Linear (2.1 μs) | 1.02x | -| bimodal | sorted_geometric | 16 | 1024 | 7.9 μs | 14.0 μs | 10.7 μs | 33.4 μs | 12.1 μs | 8.0 μs | 10.0 μs | Linear (7.9 μs) | 1.01x | -| bimodal | sorted_geometric | 16 | 4096 | 31.1 μs | 55.3 μs | 42.3 μs | 130.8 μs | 47.3 μs | 31.1 μs | 39.1 μs | Linear (31.1 μs) | 1.00x | -| bimodal | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| bimodal | sorted_geometric | 64 | 4 | 170 ns | 130 ns | 120 ns | 170 ns | 110 ns | 150 ns | 100 ns | Binary (110 ns) | 1.36x | -| bimodal | sorted_geometric | 64 | 16 | 250 ns | 320 ns | 280 ns | 650 ns | 330 ns | 280 ns | 270 ns | Linear (250 ns) | 1.12x | -| bimodal | sorted_geometric | 64 | 64 | 660 ns | 1.0 μs | 790 ns | 2.6 μs | 1.1 μs | 660 ns | 950 ns | Linear (660 ns) | 1.00x | -| bimodal | sorted_geometric | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 10.8 μs | 4.6 μs | 2.1 μs | 4.0 μs | Linear (2.1 μs) | 1.01x | -| bimodal | sorted_geometric | 64 | 1024 | 8.2 μs | 14.3 μs | 10.9 μs | 42.8 μs | 17.4 μs | 8.2 μs | 15.1 μs | Linear (8.2 μs) | 1.00x | -| bimodal | sorted_geometric | 64 | 4096 | 31.6 μs | 55.9 μs | 42.9 μs | 165.3 μs | 67.3 μs | 31.6 μs | 59.2 μs | Linear (31.6 μs) | 1.00x | -| bimodal | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 59 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (59 ns) | 1.02x | -| bimodal | sorted_geometric | 256 | 4 | 480 ns | 160 ns | 120 ns | 190 ns | 130 ns | 160 ns | 110 ns | ExpFromLeft (120 ns) | 1.33x | -| bimodal | sorted_geometric | 256 | 16 | 560 ns | 380 ns | 310 ns | 770 ns | 410 ns | 320 ns | 350 ns | ExpFromLeft (310 ns) | 1.03x | -| bimodal | sorted_geometric | 256 | 64 | 940 ns | 1.2 μs | 939 ns | 3.2 μs | 1.4 μs | 1.0 μs | 1.3 μs | ExpFromLeft (939 ns) | 1.09x | -| bimodal | sorted_geometric | 256 | 256 | 2.4 μs | 3.9 μs | 2.9 μs | 13.3 μs | 5.8 μs | 2.4 μs | 5.2 μs | Linear (2.4 μs) | 1.00x | -| bimodal | sorted_geometric | 256 | 1024 | 8.2 μs | 14.6 μs | 11.0 μs | 58.0 μs | 23.1 μs | 8.2 μs | 20.9 μs | Linear (8.2 μs) | 1.00x | -| bimodal | sorted_geometric | 256 | 4096 | 33.1 μs | 57.3 μs | 44.0 μs | 214.8 μs | 89.3 μs | 33.2 μs | 80.1 μs | Linear (33.1 μs) | 1.00x | -| bimodal | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | -| bimodal | sorted_geometric | 1024 | 4 | 1.6 μs | 180 ns | 150 ns | 210 ns | 150 ns | 180 ns | 130 ns | ExpFromLeft (150 ns) | 1.20x | -| bimodal | sorted_geometric | 1024 | 16 | 1.8 μs | 450 ns | 360 ns | 910 ns | 480 ns | 370 ns | 420 ns | ExpFromLeft (360 ns) | 1.03x | -| bimodal | sorted_geometric | 1024 | 64 | 2.5 μs | 1.6 μs | 1.4 μs | 3.8 μs | 1.8 μs | 1.4 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.01x | -| bimodal | sorted_geometric | 1024 | 256 | 3.7 μs | 4.6 μs | 3.5 μs | 15.8 μs | 6.7 μs | 3.6 μs | 6.1 μs | ExpFromLeft (3.5 μs) | 1.03x | -| bimodal | sorted_geometric | 1024 | 1024 | 9.4 μs | 15.7 μs | 11.6 μs | 82.8 μs | 29.6 μs | 9.6 μs | 26.8 μs | Linear (9.4 μs) | 1.02x | -| bimodal | sorted_geometric | 1024 | 4096 | 34.7 μs | 60.1 μs | 45.9 μs | 328.2 μs | 127.2 μs | 35.1 μs | 122.4 μs | Linear (34.7 μs) | 1.01x | -| bimodal | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| bimodal | sorted_geometric | 4096 | 4 | 6.0 μs | 200 ns | 150 ns | 230 ns | 160 ns | 190 ns | 150 ns | ExpFromLeft (150 ns) | 1.27x | -| bimodal | sorted_geometric | 4096 | 16 | 6.3 μs | 500 ns | 370 ns | 1.1 μs | 550 ns | 399 ns | 510 ns | ExpFromLeft (370 ns) | 1.08x | -| bimodal | sorted_geometric | 4096 | 64 | 7.6 μs | 1.8 μs | 1.3 μs | 4.4 μs | 2.0 μs | 1.3 μs | 1.8 μs | ExpFromLeft (1.3 μs) | 0.99x | -| bimodal | sorted_geometric | 4096 | 256 | 9.0 μs | 5.3 μs | 4.1 μs | 18.6 μs | 7.9 μs | 4.2 μs | 7.4 μs | ExpFromLeft (4.1 μs) | 1.02x | -| bimodal | sorted_geometric | 4096 | 1024 | 15.2 μs | 18.3 μs | 13.9 μs | 111.4 μs | 36.6 μs | 14.6 μs | 34.5 μs | ExpFromLeft (13.9 μs) | 1.05x | -| bimodal | sorted_geometric | 4096 | 4096 | 39.7 μs | 65.2 μs | 48.0 μs | 473.1 μs | 195.0 μs | 39.2 μs | 179.4 μs | Linear (39.7 μs) | 0.99x | -| bimodal | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| bimodal | sorted_geometric | 16384 | 4 | 23.4 μs | 230 ns | 170 ns | 250 ns | 180 ns | 200 ns | 170 ns | ExpFromLeft (170 ns) | 1.18x | -| bimodal | sorted_geometric | 16384 | 16 | 23.2 μs | 560 ns | 400 ns | 1.2 μs | 620 ns | 440 ns | 580 ns | ExpFromLeft (400 ns) | 1.10x | -| bimodal | sorted_geometric | 16384 | 64 | 24.7 μs | 1.8 μs | 1.4 μs | 5.0 μs | 2.3 μs | 1.4 μs | 2.1 μs | ExpFromLeft (1.4 μs) | 1.00x | -| bimodal | sorted_geometric | 16384 | 256 | 27.9 μs | 6.2 μs | 4.7 μs | 21.4 μs | 9.3 μs | 4.9 μs | 8.7 μs | ExpFromLeft (4.7 μs) | 1.03x | -| bimodal | sorted_geometric | 16384 | 1024 | 36.8 μs | 21.5 μs | 16.2 μs | 146.3 μs | 43.9 μs | 16.8 μs | 42.4 μs | ExpFromLeft (16.2 μs) | 1.04x | -| bimodal | sorted_geometric | 16384 | 4096 | 65.0 μs | 79.7 μs | 61.5 μs | 582.8 μs | 249.9 μs | 60.4 μs | 244.3 μs | ExpFromLeft (61.5 μs) | 0.98x | -| bimodal | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| bimodal | sorted_geometric | 65536 | 4 | 93.3 μs | 250 ns | 210 ns | 260 ns | 200 ns | 240 ns | 180 ns | Binary (200 ns) | 1.20x | -| bimodal | sorted_geometric | 65536 | 16 | 94.6 μs | 630 ns | 480 ns | 1.4 μs | 710 ns | 490 ns | 650 ns | ExpFromLeft (480 ns) | 1.02x | -| bimodal | sorted_geometric | 65536 | 64 | 95.0 μs | 2.1 μs | 1.6 μs | 5.8 μs | 2.6 μs | 1.6 μs | 2.5 μs | ExpFromLeft (1.6 μs) | 1.03x | -| bimodal | sorted_geometric | 65536 | 256 | 99.5 μs | 7.0 μs | 5.3 μs | 26.4 μs | 10.9 μs | 5.4 μs | 10.2 μs | ExpFromLeft (5.3 μs) | 1.02x | -| bimodal | sorted_geometric | 65536 | 1024 | 109.8 μs | 25.9 μs | 19.7 μs | 192.0 μs | 50.6 μs | 20.4 μs | 52.5 μs | ExpFromLeft (19.7 μs) | 1.03x | -| bimodal | sorted_geometric | 65536 | 4096 | 149.4 μs | 104.0 μs | 81.0 μs | 739.1 μs | 299.0 μs | 76.0 μs | 295.3 μs | ExpFromLeft (81.0 μs) | 0.94x | -| bimodal | sorted_bimodal | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | sorted_bimodal | 16 | 4 | 80 ns | 100 ns | 90 ns | 170 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| bimodal | sorted_bimodal | 16 | 16 | 190 ns | 270 ns | 210 ns | 589 ns | 230 ns | 200 ns | 190 ns | Linear (190 ns) | 1.05x | -| bimodal | sorted_bimodal | 16 | 64 | 560 ns | 990 ns | 770 ns | 2.2 μs | 920 ns | 580 ns | 790 ns | Linear (560 ns) | 1.04x | -| bimodal | sorted_bimodal | 16 | 256 | 2.2 μs | 3.7 μs | 2.9 μs | 8.7 μs | 3.2 μs | 2.3 μs | 2.7 μs | Linear (2.2 μs) | 1.01x | -| bimodal | sorted_bimodal | 16 | 1024 | 8.1 μs | 14.1 μs | 10.8 μs | 33.7 μs | 12.1 μs | 8.0 μs | 10.3 μs | Linear (8.1 μs) | 1.00x | -| bimodal | sorted_bimodal | 16 | 4096 | 31.0 μs | 55.1 μs | 42.3 μs | 132.7 μs | 47.5 μs | 31.1 μs | 40.1 μs | Linear (31.0 μs) | 1.00x | -| bimodal | sorted_bimodal | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| bimodal | sorted_bimodal | 64 | 4 | 140 ns | 130 ns | 140 ns | 200 ns | 110 ns | 150 ns | 90 ns | Binary (110 ns) | 1.36x | -| bimodal | sorted_bimodal | 64 | 16 | 230 ns | 350 ns | 260 ns | 710 ns | 300 ns | 260 ns | 270 ns | Linear (230 ns) | 1.13x | -| bimodal | sorted_bimodal | 64 | 64 | 630 ns | 1.0 μs | 760 ns | 2.6 μs | 1.3 μs | 660 ns | 1.3 μs | Linear (630 ns) | 1.05x | -| bimodal | sorted_bimodal | 64 | 256 | 2.2 μs | 4.0 μs | 3.0 μs | 10.8 μs | 5.0 μs | 2.3 μs | 4.6 μs | Linear (2.2 μs) | 1.01x | -| bimodal | sorted_bimodal | 64 | 1024 | 9.0 μs | 14.8 μs | 11.6 μs | 43.1 μs | 17.5 μs | 9.0 μs | 15.7 μs | Linear (9.0 μs) | 1.00x | -| bimodal | sorted_bimodal | 64 | 4096 | 32.2 μs | 56.0 μs | 43.2 μs | 166.6 μs | 67.4 μs | 32.1 μs | 59.9 μs | Linear (32.2 μs) | 1.00x | -| bimodal | sorted_bimodal | 256 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 70 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | sorted_bimodal | 256 | 4 | 280 ns | 160 ns | 140 ns | 240 ns | 120 ns | 160 ns | 110 ns | Binary (120 ns) | 1.33x | -| bimodal | sorted_bimodal | 256 | 16 | 500 ns | 450 ns | 370 ns | 830 ns | 370 ns | 390 ns | 340 ns | ExpFromLeft (370 ns) | 1.05x | -| bimodal | sorted_bimodal | 256 | 64 | 910 ns | 1.4 μs | 1.0 μs | 3.2 μs | 1.6 μs | 920 ns | 1.5 μs | Linear (910 ns) | 1.01x | -| bimodal | sorted_bimodal | 256 | 256 | 2.4 μs | 4.1 μs | 2.9 μs | 13.2 μs | 6.8 μs | 2.4 μs | 6.5 μs | Linear (2.4 μs) | 1.01x | -| bimodal | sorted_bimodal | 256 | 1024 | 9.6 μs | 16.7 μs | 12.6 μs | 54.3 μs | 25.2 μs | 9.6 μs | 23.3 μs | Linear (9.6 μs) | 1.00x | -| bimodal | sorted_bimodal | 256 | 4096 | 36.0 μs | 59.2 μs | 46.3 μs | 209.0 μs | 90.6 μs | 36.1 μs | 82.9 μs | Linear (36.0 μs) | 1.00x | -| bimodal | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | sorted_bimodal | 1024 | 4 | 1.3 μs | 210 ns | 180 ns | 270 ns | 140 ns | 260 ns | 120 ns | Binary (140 ns) | 1.86x | -| bimodal | sorted_bimodal | 1024 | 16 | 1.7 μs | 610 ns | 460 ns | 939 ns | 450 ns | 490 ns | 420 ns | Binary (450 ns) | 1.09x | -| bimodal | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.6 μs | 1.3 μs | 3.7 μs | 1.9 μs | 1.3 μs | 1.8 μs | ExpFromLeft (1.3 μs) | 1.03x | -| bimodal | sorted_bimodal | 1024 | 256 | 3.7 μs | 5.1 μs | 3.8 μs | 15.9 μs | 8.2 μs | 3.5 μs | 7.7 μs | Linear (3.7 μs) | 0.96x | -| bimodal | sorted_bimodal | 1024 | 1024 | 13.4 μs | 21.8 μs | 16.6 μs | 75.3 μs | 44.2 μs | 10.5 μs | 42.6 μs | Linear (13.4 μs) | 0.79x | -| bimodal | sorted_bimodal | 1024 | 4096 | 43.6 μs | 69.0 μs | 54.2 μs | 284.5 μs | 164.4 μs | 43.4 μs | 161.0 μs | Linear (43.6 μs) | 1.00x | -| bimodal | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | sorted_bimodal | 4096 | 4 | 2.7 μs | 220 ns | 180 ns | 320 ns | 170 ns | 210 ns | 150 ns | Binary (170 ns) | 1.24x | -| bimodal | sorted_bimodal | 4096 | 16 | 6.5 μs | 740 ns | 570 ns | 1.1 μs | 530 ns | 580 ns | 490 ns | Binary (530 ns) | 1.09x | -| bimodal | sorted_bimodal | 4096 | 64 | 7.4 μs | 2.3 μs | 1.8 μs | 4.3 μs | 2.0 μs | 1.8 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.01x | -| bimodal | sorted_bimodal | 4096 | 256 | 8.8 μs | 6.9 μs | 5.2 μs | 18.2 μs | 11.3 μs | 5.3 μs | 10.3 μs | ExpFromLeft (5.2 μs) | 1.02x | -| bimodal | sorted_bimodal | 4096 | 1024 | 16.1 μs | 24.0 μs | 17.9 μs | 97.4 μs | 88.5 μs | 15.4 μs | 83.4 μs | Linear (16.1 μs) | 0.95x | -| bimodal | sorted_bimodal | 4096 | 4096 | 77.7 μs | 100.0 μs | 79.2 μs | 415.1 μs | 279.4 μs | 73.0 μs | 273.3 μs | Linear (77.7 μs) | 0.94x | -| bimodal | sorted_bimodal | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | sorted_bimodal | 16384 | 4 | 16.7 μs | 260 ns | 220 ns | 350 ns | 190 ns | 250 ns | 170 ns | Binary (190 ns) | 1.32x | -| bimodal | sorted_bimodal | 16384 | 16 | 23.0 μs | 880 ns | 660 ns | 1.3 μs | 600 ns | 670 ns | 550 ns | Binary (600 ns) | 1.12x | -| bimodal | sorted_bimodal | 16384 | 64 | 24.2 μs | 3.0 μs | 2.3 μs | 5.0 μs | 2.4 μs | 2.3 μs | 2.3 μs | ExpFromLeft (2.3 μs) | 1.00x | -| bimodal | sorted_bimodal | 16384 | 256 | 32.1 μs | 10.0 μs | 7.5 μs | 22.1 μs | 13.8 μs | 7.3 μs | 13.9 μs | ExpFromLeft (7.5 μs) | 0.97x | -| bimodal | sorted_bimodal | 16384 | 1024 | 41.1 μs | 35.2 μs | 25.7 μs | 132.9 μs | 124.0 μs | 25.2 μs | 123.8 μs | ExpFromLeft (25.7 μs) | 0.98x | -| bimodal | sorted_bimodal | 16384 | 4096 | 115.1 μs | 161.4 μs | 120.2 μs | 542.9 μs | 390.5 μs | 112.8 μs | 384.1 μs | Linear (115.1 μs) | 0.98x | -| bimodal | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| bimodal | sorted_bimodal | 65536 | 4 | 85.1 μs | 300 ns | 250 ns | 380 ns | 200 ns | 280 ns | 180 ns | Binary (200 ns) | 1.40x | -| bimodal | sorted_bimodal | 65536 | 16 | 64.6 μs | 920 ns | 690 ns | 1.5 μs | 720 ns | 700 ns | 680 ns | ExpFromLeft (690 ns) | 1.01x | -| bimodal | sorted_bimodal | 65536 | 64 | 89.8 μs | 3.6 μs | 2.6 μs | 5.9 μs | 3.0 μs | 2.6 μs | 2.8 μs | ExpFromLeft (2.6 μs) | 1.02x | -| bimodal | sorted_bimodal | 65536 | 256 | 101.1 μs | 12.6 μs | 9.6 μs | 26.9 μs | 19.5 μs | 9.7 μs | 17.7 μs | ExpFromLeft (9.6 μs) | 1.01x | -| bimodal | sorted_bimodal | 65536 | 1024 | 116.6 μs | 59.8 μs | 43.0 μs | 182.1 μs | 155.1 μs | 39.4 μs | 161.8 μs | ExpFromLeft (43.0 μs) | 0.92x | -| bimodal | sorted_bimodal | 65536 | 4096 | 196.6 μs | 250.0 μs | 199.5 μs | 702.2 μs | 487.5 μs | 201.9 μs | 480.8 μs | Linear (196.6 μs) | 1.03x | -| bimodal | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 170 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| bimodal | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 200 ns | 580 ns | 220 ns | 200 ns | 180 ns | Linear (170 ns) | 1.18x | -| bimodal | sorted_repeated | 16 | 64 | 550 ns | 930 ns | 700 ns | 2.1 μs | 790 ns | 570 ns | 640 ns | Linear (550 ns) | 1.04x | -| bimodal | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 8.5 μs | 3.0 μs | 2.0 μs | 2.7 μs | Linear (2.0 μs) | 1.01x | -| bimodal | sorted_repeated | 16 | 1024 | 7.7 μs | 13.9 μs | 9.8 μs | 33.8 μs | 11.8 μs | 7.8 μs | 9.7 μs | Linear (7.7 μs) | 1.01x | -| bimodal | sorted_repeated | 16 | 4096 | 30.8 μs | 55.5 μs | 39.2 μs | 135.2 μs | 47.3 μs | 30.8 μs | 39.7 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_repeated | 64 | 1 | 70 ns | 50 ns | 60 ns | 80 ns | 60 ns | 70 ns | 50 ns | Gallop (50 ns) | 1.40x | -| bimodal | sorted_repeated | 64 | 4 | 80 ns | 90 ns | 90 ns | 210 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| bimodal | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 200 ns | 760 ns | 310 ns | 200 ns | 260 ns | Linear (170 ns) | 1.18x | -| bimodal | sorted_repeated | 64 | 64 | 550 ns | 930 ns | 700 ns | 2.9 μs | 1.1 μs | 580 ns | 930 ns | Linear (550 ns) | 1.05x | -| bimodal | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 11.2 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | -| bimodal | sorted_repeated | 64 | 1024 | 7.7 μs | 14.0 μs | 9.8 μs | 44.6 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | -| bimodal | sorted_repeated | 64 | 4096 | 30.8 μs | 55.6 μs | 39.2 μs | 179.1 μs | 66.6 μs | 30.9 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 80 ns | 120 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | -| bimodal | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 100 ns | 260 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| bimodal | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 930 ns | 390 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| bimodal | sorted_repeated | 256 | 64 | 550 ns | 930 ns | 710 ns | 3.5 μs | 1.4 μs | 580 ns | 1.2 μs | Linear (550 ns) | 1.05x | -| bimodal | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 14.0 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.01x | -| bimodal | sorted_repeated | 256 | 1024 | 7.7 μs | 14.0 μs | 9.8 μs | 55.9 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.7 μs) | 1.00x | -| bimodal | sorted_repeated | 256 | 4096 | 30.8 μs | 55.6 μs | 39.3 μs | 222.7 μs | 86.0 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_repeated | 1024 | 1 | 70 ns | 70 ns | 60 ns | 100 ns | 70 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | sorted_repeated | 1024 | 4 | 90 ns | 110 ns | 100 ns | 290 ns | 140 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | -| bimodal | sorted_repeated | 1024 | 16 | 230 ns | 440 ns | 250 ns | 1.1 μs | 470 ns | 240 ns | 410 ns | Linear (230 ns) | 1.04x | -| bimodal | sorted_repeated | 1024 | 64 | 560 ns | 940 ns | 700 ns | 4.2 μs | 1.7 μs | 590 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| bimodal | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 16.3 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | -| bimodal | sorted_repeated | 1024 | 1024 | 7.8 μs | 14.0 μs | 9.9 μs | 65.2 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.8 μs) | 1.00x | -| bimodal | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.6 μs | 39.3 μs | 260.4 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | sorted_repeated | 4096 | 4 | 100 ns | 109 ns | 110 ns | 350 ns | 160 ns | 120 ns | 150 ns | Linear (100 ns) | 1.20x | -| bimodal | sorted_repeated | 4096 | 16 | 190 ns | 280 ns | 230 ns | 1.2 μs | 540 ns | 210 ns | 490 ns | Linear (190 ns) | 1.11x | -| bimodal | sorted_repeated | 4096 | 64 | 560 ns | 950 ns | 710 ns | 4.8 μs | 2.0 μs | 590 ns | 1.8 μs | Linear (560 ns) | 1.05x | -| bimodal | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 19.1 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.02x | -| bimodal | sorted_repeated | 4096 | 1024 | 7.8 μs | 13.9 μs | 10.0 μs | 76.0 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.01x | -| bimodal | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.5 μs | 39.4 μs | 300.6 μs | 127.4 μs | 44.3 μs | 113.3 μs | Linear (30.8 μs) | 1.44x | -| bimodal | sorted_repeated | 16384 | 1 | 70 ns | 70 ns | 70 ns | 120 ns | 70 ns | 70 ns | 70 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | sorted_repeated | 16384 | 4 | 100 ns | 120 ns | 110 ns | 380 ns | 180 ns | 130 ns | 170 ns | Linear (100 ns) | 1.30x | -| bimodal | sorted_repeated | 16384 | 16 | 190 ns | 290 ns | 230 ns | 1.4 μs | 610 ns | 210 ns | 560 ns | Linear (190 ns) | 1.11x | -| bimodal | sorted_repeated | 16384 | 64 | 570 ns | 950 ns | 710 ns | 5.4 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (570 ns) | 1.05x | -| bimodal | sorted_repeated | 16384 | 256 | 2.0 μs | 3.6 μs | 2.6 μs | 21.4 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | -| bimodal | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.9 μs | 9.9 μs | 85.7 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | -| bimodal | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.6 μs | 39.6 μs | 342.5 μs | 144.1 μs | 30.9 μs | 133.9 μs | Linear (30.8 μs) | 1.00x | -| bimodal | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 70 ns | ExpFromLeft (80 ns) | 1.00x | -| bimodal | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 430 ns | 200 ns | 130 ns | 180 ns | Linear (100 ns) | 1.30x | -| bimodal | sorted_repeated | 65536 | 16 | 190 ns | 290 ns | 230 ns | 1.6 μs | 670 ns | 210 ns | 639 ns | Linear (190 ns) | 1.11x | -| bimodal | sorted_repeated | 65536 | 64 | 570 ns | 950 ns | 710 ns | 6.1 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| bimodal | sorted_repeated | 65536 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 24.2 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.02x | -| bimodal | sorted_repeated | 65536 | 1024 | 7.8 μs | 14.0 μs | 9.9 μs | 96.6 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.00x | -| bimodal | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.5 μs | 39.4 μs | 387.7 μs | 163.2 μs | 30.9 μs | 152.4 μs | Linear (30.8 μs) | 1.00x | -| bimodal | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| bimodal | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 90 ns | 90 ns | 100 ns | 70 ns | InterpSearch (90 ns) | 1.11x | -| bimodal | unsorted | 16 | 16 | 210 ns | 200 ns | 200 ns | 190 ns | 210 ns | 210 ns | 190 ns | InterpSearch (190 ns) | 1.11x | -| bimodal | unsorted | 16 | 64 | 820 ns | 800 ns | 810 ns | 810 ns | 820 ns | 820 ns | 790 ns | Gallop (800 ns) | 1.02x | -| bimodal | unsorted | 16 | 256 | 3.4 μs | 3.4 μs | 3.4 μs | 3.4 μs | 3.4 μs | 3.4 μs | 3.3 μs | ExpFromLeft (3.4 μs) | 1.00x | -| bimodal | unsorted | 16 | 1024 | 13.9 μs | 13.9 μs | 13.9 μs | 13.9 μs | 13.9 μs | 13.9 μs | 13.8 μs | InterpSearch (13.9 μs) | 1.00x | -| bimodal | unsorted | 16 | 4096 | 57.0 μs | 57.2 μs | 57.2 μs | 57.2 μs | 57.6 μs | 60.7 μs | 60.9 μs | Linear (57.0 μs) | 1.06x | -| bimodal | unsorted | 64 | 1 | 50 ns | 50 ns | 60 ns | 80 ns | 60 ns | 50 ns | 50 ns | Gallop (50 ns) | 1.00x | -| bimodal | unsorted | 64 | 4 | 100 ns | 110 ns | 110 ns | 100 ns | 110 ns | 120 ns | 90 ns | InterpSearch (100 ns) | 1.20x | -| bimodal | unsorted | 64 | 16 | 290 ns | 290 ns | 300 ns | 290 ns | 290 ns | 300 ns | 260 ns | InterpSearch (290 ns) | 1.03x | -| bimodal | unsorted | 64 | 64 | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.2 μs | 1.1 μs | InterpSearch (1.2 μs) | 1.02x | -| bimodal | unsorted | 64 | 256 | 5.4 μs | 5.4 μs | 5.4 μs | 5.4 μs | 5.5 μs | 5.5 μs | 5.4 μs | InterpSearch (5.4 μs) | 1.02x | -| bimodal | unsorted | 64 | 1024 | 21.7 μs | 21.7 μs | 21.7 μs | 21.7 μs | 21.7 μs | 21.7 μs | 21.4 μs | InterpSearch (21.7 μs) | 1.00x | -| bimodal | unsorted | 64 | 4096 | 86.7 μs | 86.3 μs | 86.3 μs | 86.1 μs | 86.2 μs | 86.3 μs | 85.8 μs | InterpSearch (86.1 μs) | 1.00x | -| bimodal | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 90 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| bimodal | unsorted | 256 | 4 | 120 ns | 110 ns | 120 ns | 120 ns | 120 ns | 130 ns | 110 ns | Gallop (110 ns) | 1.18x | -| bimodal | unsorted | 256 | 16 | 430 ns | 440 ns | 430 ns | 430 ns | 430 ns | 450 ns | 410 ns | InterpSearch (430 ns) | 1.05x | -| bimodal | unsorted | 256 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | Gallop (1.6 μs) | 1.01x | -| bimodal | unsorted | 256 | 256 | 6.9 μs | 6.9 μs | 6.9 μs | 6.9 μs | 6.9 μs | 6.9 μs | 6.8 μs | Binary (6.9 μs) | 1.01x | -| bimodal | unsorted | 256 | 1024 | 28.1 μs | 28.1 μs | 28.1 μs | 28.1 μs | 28.1 μs | 28.1 μs | 27.9 μs | Binary (28.1 μs) | 1.00x | -| bimodal | unsorted | 256 | 4096 | 113.6 μs | 113.7 μs | 113.5 μs | 113.5 μs | 113.6 μs | 112.5 μs | 113.3 μs | ExpFromLeft (113.5 μs) | 0.99x | -| bimodal | unsorted | 1024 | 1 | 70 ns | 60 ns | 70 ns | 90 ns | 60 ns | 60 ns | 60 ns | Binary (60 ns) | 1.00x | -| bimodal | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| bimodal | unsorted | 1024 | 16 | 430 ns | 430 ns | 420 ns | 440 ns | 420 ns | 440 ns | 420 ns | ExpFromLeft (420 ns) | 1.05x | -| bimodal | unsorted | 1024 | 64 | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | 1.6 μs | Binary (1.6 μs) | 1.01x | -| bimodal | unsorted | 1024 | 256 | 7.9 μs | 7.9 μs | 7.9 μs | 8.0 μs | 7.9 μs | 7.9 μs | 7.9 μs | Gallop (7.9 μs) | 1.01x | -| bimodal | unsorted | 1024 | 1024 | 34.3 μs | 34.4 μs | 34.4 μs | 34.4 μs | 34.4 μs | 34.4 μs | 34.2 μs | Linear (34.3 μs) | 1.00x | -| bimodal | unsorted | 1024 | 4096 | 142.0 μs | 142.5 μs | 142.4 μs | 141.6 μs | 142.1 μs | 142.0 μs | 142.3 μs | InterpSearch (141.6 μs) | 1.00x | -| bimodal | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 110 ns | 70 ns | 70 ns | 60 ns | ExpFromLeft (70 ns) | 1.00x | -| bimodal | unsorted | 4096 | 4 | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 160 ns | 140 ns | InterpSearch (160 ns) | 1.00x | -| bimodal | unsorted | 4096 | 16 | 510 ns | 490 ns | 510 ns | 500 ns | 500 ns | 510 ns | 480 ns | Gallop (490 ns) | 1.04x | -| bimodal | unsorted | 4096 | 64 | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | 2.1 μs | InterpSearch (2.1 μs) | 1.01x | -| bimodal | unsorted | 4096 | 256 | 8.7 μs | 8.7 μs | 8.7 μs | 8.7 μs | 8.7 μs | 8.7 μs | 8.6 μs | Gallop (8.7 μs) | 1.00x | -| bimodal | unsorted | 4096 | 1024 | 38.3 μs | 38.4 μs | 38.4 μs | 38.3 μs | 38.4 μs | 38.4 μs | 38.3 μs | InterpSearch (38.3 μs) | 1.00x | -| bimodal | unsorted | 4096 | 4096 | 171.2 μs | 170.3 μs | 169.6 μs | 169.3 μs | 169.5 μs | 169.1 μs | 171.6 μs | InterpSearch (169.3 μs) | 1.00x | -| bimodal | unsorted | 16384 | 1 | 70 ns | 70 ns | 80 ns | 120 ns | 80 ns | 70 ns | 70 ns | Gallop (70 ns) | 1.00x | -| bimodal | unsorted | 16384 | 4 | 170 ns | 170 ns | 170 ns | 170 ns | 180 ns | 170 ns | 170 ns | InterpSearch (170 ns) | 1.00x | -| bimodal | unsorted | 16384 | 16 | 640 ns | 650 ns | 650 ns | 640 ns | 650 ns | 660 ns | 650 ns | InterpSearch (640 ns) | 1.03x | -| bimodal | unsorted | 16384 | 64 | 2.7 μs | 2.7 μs | 2.7 μs | 2.8 μs | 2.7 μs | 2.7 μs | 2.8 μs | ExpFromLeft (2.7 μs) | 1.01x | -| bimodal | unsorted | 16384 | 256 | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | 10.9 μs | Binary (10.9 μs) | 1.00x | -| bimodal | unsorted | 16384 | 1024 | 46.1 μs | 45.9 μs | 46.0 μs | 46.0 μs | 46.0 μs | 46.2 μs | 46.3 μs | Gallop (45.9 μs) | 1.00x | -| bimodal | unsorted | 16384 | 4096 | 220.6 μs | 218.2 μs | 217.0 μs | 216.5 μs | 216.3 μs | 216.1 μs | 220.1 μs | Binary (216.3 μs) | 1.00x | -| bimodal | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 130 ns | 80 ns | 80 ns | 80 ns | ExpFromLeft (80 ns) | 1.00x | -| bimodal | unsorted | 65536 | 4 | 190 ns | 190 ns | 190 ns | 200 ns | 190 ns | 200 ns | 180 ns | ExpFromLeft (190 ns) | 1.05x | -| bimodal | unsorted | 65536 | 16 | 700 ns | 700 ns | 700 ns | 700 ns | 700 ns | 710 ns | 700 ns | InterpSearch (700 ns) | 1.01x | -| bimodal | unsorted | 65536 | 64 | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.8 μs | 2.8 μs | ExpFromLeft (2.7 μs) | 1.01x | -| bimodal | unsorted | 65536 | 256 | 11.1 μs | 11.1 μs | 11.2 μs | 11.2 μs | 11.2 μs | 11.2 μs | 11.2 μs | Linear (11.1 μs) | 1.01x | -| bimodal | unsorted | 65536 | 1024 | 54.9 μs | 54.8 μs | 54.7 μs | 54.7 μs | 54.6 μs | 54.5 μs | 55.5 μs | Binary (54.6 μs) | 1.00x | -| bimodal | unsorted | 65536 | 4096 | 270.2 μs | 266.2 μs | 264.6 μs | 263.2 μs | 262.5 μs | 262.1 μs | 269.0 μs | Binary (262.5 μs) | 1.00x | -| near_linear | sorted_uniform | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| near_linear | sorted_uniform | 16 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 90 ns | 100 ns | 90 ns | Binary (90 ns) | 1.11x | -| near_linear | sorted_uniform | 16 | 16 | 290 ns | 380 ns | 280 ns | 670 ns | 290 ns | 210 ns | 200 ns | ExpFromLeft (280 ns) | 0.75x | -| near_linear | sorted_uniform | 16 | 64 | 750 ns | 1.0 μs | 960 ns | 2.6 μs | 940 ns | 600 ns | 850 ns | Linear (750 ns) | 0.80x | -| near_linear | sorted_uniform | 16 | 256 | 2.3 μs | 3.9 μs | 2.9 μs | 8.0 μs | 3.3 μs | 2.3 μs | 2.9 μs | Linear (2.3 μs) | 1.02x | -| near_linear | sorted_uniform | 16 | 1024 | 8.1 μs | 14.7 μs | 10.8 μs | 28.9 μs | 12.4 μs | 8.2 μs | 10.4 μs | Linear (8.1 μs) | 1.01x | -| near_linear | sorted_uniform | 16 | 4096 | 31.5 μs | 58.1 μs | 42.4 μs | 109.2 μs | 48.0 μs | 31.1 μs | 40.8 μs | Linear (31.5 μs) | 0.99x | -| near_linear | sorted_uniform | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| near_linear | sorted_uniform | 64 | 4 | 140 ns | 140 ns | 120 ns | 150 ns | 110 ns | 120 ns | 90 ns | Binary (110 ns) | 1.09x | -| near_linear | sorted_uniform | 64 | 16 | 260 ns | 350 ns | 280 ns | 520 ns | 300 ns | 280 ns | 270 ns | Linear (260 ns) | 1.08x | -| near_linear | sorted_uniform | 64 | 64 | 630 ns | 1.1 μs | 750 ns | 2.0 μs | 1.4 μs | 660 ns | 1.3 μs | Linear (630 ns) | 1.05x | -| near_linear | sorted_uniform | 64 | 256 | 2.2 μs | 4.1 μs | 3.1 μs | 9.1 μs | 5.3 μs | 2.2 μs | 4.8 μs | Linear (2.2 μs) | 1.00x | -| near_linear | sorted_uniform | 64 | 1024 | 9.2 μs | 14.9 μs | 11.7 μs | 31.0 μs | 17.8 μs | 9.2 μs | 16.0 μs | Linear (9.2 μs) | 1.00x | -| near_linear | sorted_uniform | 64 | 4096 | 32.1 μs | 56.6 μs | 43.2 μs | 112.4 μs | 67.1 μs | 32.1 μs | 60.3 μs | Linear (32.1 μs) | 1.00x | -| near_linear | sorted_uniform | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_uniform | 256 | 4 | 330 ns | 170 ns | 150 ns | 150 ns | 120 ns | 170 ns | 110 ns | Binary (120 ns) | 1.42x | -| near_linear | sorted_uniform | 256 | 16 | 480 ns | 450 ns | 380 ns | 460 ns | 410 ns | 380 ns | 370 ns | ExpFromLeft (380 ns) | 1.00x | -| near_linear | sorted_uniform | 256 | 64 | 910 ns | 1.3 μs | 980 ns | 2.0 μs | 1.6 μs | 930 ns | 1.4 μs | Linear (910 ns) | 1.02x | -| near_linear | sorted_uniform | 256 | 256 | 2.5 μs | 4.1 μs | 2.8 μs | 9.0 μs | 7.3 μs | 2.5 μs | 6.8 μs | Linear (2.5 μs) | 1.03x | -| near_linear | sorted_uniform | 256 | 1024 | 10.1 μs | 17.5 μs | 13.5 μs | 38.7 μs | 26.2 μs | 10.2 μs | 24.8 μs | Linear (10.1 μs) | 1.01x | -| near_linear | sorted_uniform | 256 | 4096 | 36.6 μs | 59.6 μs | 46.7 μs | 125.0 μs | 90.5 μs | 36.7 μs | 83.9 μs | Linear (36.6 μs) | 1.00x | -| near_linear | sorted_uniform | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 70 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_uniform | 1024 | 4 | 210 ns | 150 ns | 140 ns | 150 ns | 140 ns | 190 ns | 130 ns | ExpFromLeft (140 ns) | 1.36x | -| near_linear | sorted_uniform | 1024 | 16 | 1.8 μs | 580 ns | 470 ns | 520 ns | 450 ns | 580 ns | 399 ns | Binary (450 ns) | 1.29x | -| near_linear | sorted_uniform | 1024 | 64 | 2.0 μs | 1.8 μs | 1.3 μs | 2.0 μs | 1.7 μs | 2.1 μs | 1.6 μs | ExpFromLeft (1.3 μs) | 1.61x | -| near_linear | sorted_uniform | 1024 | 256 | 3.6 μs | 5.4 μs | 3.8 μs | 8.7 μs | 7.8 μs | 3.6 μs | 7.4 μs | Linear (3.6 μs) | 0.99x | -| near_linear | sorted_uniform | 1024 | 1024 | 10.2 μs | 17.4 μs | 12.2 μs | 39.0 μs | 57.0 μs | 10.6 μs | 56.6 μs | Linear (10.2 μs) | 1.04x | -| near_linear | sorted_uniform | 1024 | 4096 | 48.4 μs | 72.7 μs | 57.7 μs | 154.5 μs | 194.2 μs | 48.6 μs | 191.3 μs | Linear (48.4 μs) | 1.00x | -| near_linear | sorted_uniform | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_uniform | 4096 | 4 | 4.5 μs | 230 ns | 190 ns | 150 ns | 170 ns | 190 ns | 150 ns | InterpSearch (150 ns) | 1.27x | -| near_linear | sorted_uniform | 4096 | 16 | 6.0 μs | 710 ns | 540 ns | 490 ns | 510 ns | 560 ns | 480 ns | InterpSearch (490 ns) | 1.14x | -| near_linear | sorted_uniform | 4096 | 64 | 7.4 μs | 2.3 μs | 1.8 μs | 1.9 μs | 2.1 μs | 2.1 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.19x | -| near_linear | sorted_uniform | 4096 | 256 | 8.4 μs | 7.1 μs | 5.4 μs | 9.0 μs | 10.0 μs | 9.6 μs | 10.3 μs | ExpFromLeft (5.4 μs) | 1.76x | -| near_linear | sorted_uniform | 4096 | 1024 | 16.1 μs | 23.8 μs | 17.4 μs | 38.3 μs | 96.1 μs | 14.9 μs | 93.8 μs | Linear (16.1 μs) | 0.93x | -| near_linear | sorted_uniform | 4096 | 4096 | 66.3 μs | 107.8 μs | 82.1 μs | 168.7 μs | 299.9 μs | 67.9 μs | 295.4 μs | Linear (66.3 μs) | 1.02x | -| near_linear | sorted_uniform | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_uniform | 16384 | 4 | 13.7 μs | 250 ns | 200 ns | 150 ns | 180 ns | 190 ns | 160 ns | InterpSearch (150 ns) | 1.27x | -| near_linear | sorted_uniform | 16384 | 16 | 22.0 μs | 890 ns | 660 ns | 530 ns | 620 ns | 570 ns | 560 ns | InterpSearch (530 ns) | 1.08x | -| near_linear | sorted_uniform | 16384 | 64 | 24.0 μs | 2.9 μs | 2.2 μs | 2.0 μs | 2.4 μs | 2.1 μs | 2.3 μs | InterpSearch (2.0 μs) | 1.07x | -| near_linear | sorted_uniform | 16384 | 256 | 28.6 μs | 9.5 μs | 7.2 μs | 9.4 μs | 13.1 μs | 9.8 μs | 13.1 μs | ExpFromLeft (7.2 μs) | 1.36x | -| near_linear | sorted_uniform | 16384 | 1024 | 40.8 μs | 34.4 μs | 26.2 μs | 39.7 μs | 126.4 μs | 40.7 μs | 125.5 μs | ExpFromLeft (26.2 μs) | 1.55x | -| near_linear | sorted_uniform | 16384 | 4096 | 113.3 μs | 160.2 μs | 120.0 μs | 164.0 μs | 400.1 μs | 110.8 μs | 399.8 μs | Linear (113.3 μs) | 0.98x | -| near_linear | sorted_uniform | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | sorted_uniform | 65536 | 4 | 63.1 μs | 300 ns | 240 ns | 150 ns | 200 ns | 200 ns | 180 ns | InterpSearch (150 ns) | 1.33x | -| near_linear | sorted_uniform | 65536 | 16 | 89.4 μs | 1.1 μs | 770 ns | 470 ns | 690 ns | 549 ns | 650 ns | InterpSearch (470 ns) | 1.17x | -| near_linear | sorted_uniform | 65536 | 64 | 93.3 μs | 3.6 μs | 2.7 μs | 2.0 μs | 2.9 μs | 2.2 μs | 2.7 μs | InterpSearch (2.0 μs) | 1.07x | -| near_linear | sorted_uniform | 65536 | 256 | 100.4 μs | 12.6 μs | 9.5 μs | 9.5 μs | 16.6 μs | 10.0 μs | 16.8 μs | ExpFromLeft (9.5 μs) | 1.05x | -| near_linear | sorted_uniform | 65536 | 1024 | 119.6 μs | 61.2 μs | 42.6 μs | 40.8 μs | 157.1 μs | 42.5 μs | 162.9 μs | InterpSearch (40.8 μs) | 1.04x | -| near_linear | sorted_uniform | 65536 | 4096 | 192.9 μs | 250.6 μs | 199.5 μs | 164.0 μs | 494.3 μs | 170.6 μs | 493.4 μs | InterpSearch (164.0 μs) | 1.04x | -| near_linear | sorted_dense_burst | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| near_linear | sorted_dense_burst | 16 | 4 | 80 ns | 100 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| near_linear | sorted_dense_burst | 16 | 16 | 170 ns | 340 ns | 230 ns | 490 ns | 230 ns | 180 ns | 190 ns | Linear (170 ns) | 1.06x | -| near_linear | sorted_dense_burst | 16 | 64 | 540 ns | 930 ns | 730 ns | 1.8 μs | 790 ns | 580 ns | 780 ns | Linear (540 ns) | 1.07x | -| near_linear | sorted_dense_burst | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 3.0 μs | 2.0 μs | 3.0 μs | Linear (2.0 μs) | 1.01x | -| near_linear | sorted_dense_burst | 16 | 1024 | 7.7 μs | 14.0 μs | 10.5 μs | 27.6 μs | 11.8 μs | 7.8 μs | 12.3 μs | Linear (7.7 μs) | 1.00x | -| near_linear | sorted_dense_burst | 16 | 4096 | 30.8 μs | 55.6 μs | 41.9 μs | 109.0 μs | 47.3 μs | 30.8 μs | 38.5 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_dense_burst | 64 | 1 | 50 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| near_linear | sorted_dense_burst | 64 | 4 | 90 ns | 90 ns | 90 ns | 150 ns | 100 ns | 110 ns | 90 ns | ExpFromLeft (90 ns) | 1.22x | -| near_linear | sorted_dense_burst | 64 | 16 | 170 ns | 270 ns | 220 ns | 500 ns | 310 ns | 190 ns | 260 ns | Linear (170 ns) | 1.12x | -| near_linear | sorted_dense_burst | 64 | 64 | 680 ns | 1.2 μs | 730 ns | 1.8 μs | 1.1 μs | 579 ns | 929 ns | Linear (680 ns) | 0.85x | -| near_linear | sorted_dense_burst | 64 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | -| near_linear | sorted_dense_burst | 64 | 1024 | 7.7 μs | 13.9 μs | 10.6 μs | 27.4 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | -| near_linear | sorted_dense_burst | 64 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 108.7 μs | 66.6 μs | 30.8 μs | 56.8 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_dense_burst | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_dense_burst | 256 | 4 | 90 ns | 100 ns | 110 ns | 150 ns | 120 ns | 110 ns | 110 ns | Linear (90 ns) | 1.22x | -| near_linear | sorted_dense_burst | 256 | 16 | 170 ns | 280 ns | 230 ns | 510 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| near_linear | sorted_dense_burst | 256 | 64 | 760 ns | 1.2 μs | 940 ns | 2.0 μs | 1.4 μs | 780 ns | 1.2 μs | Linear (760 ns) | 1.03x | -| near_linear | sorted_dense_burst | 256 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.0 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| near_linear | sorted_dense_burst | 256 | 1024 | 7.8 μs | 14.0 μs | 10.5 μs | 27.3 μs | 21.5 μs | 7.8 μs | 19.1 μs | Linear (7.8 μs) | 1.00x | -| near_linear | sorted_dense_burst | 256 | 4096 | 44.3 μs | 73.8 μs | 55.8 μs | 119.8 μs | 88.3 μs | 44.3 μs | 76.5 μs | Linear (44.3 μs) | 1.00x | -| near_linear | sorted_dense_burst | 1024 | 1 | 70 ns | 70 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_dense_burst | 1024 | 4 | 90 ns | 110 ns | 100 ns | 140 ns | 140 ns | 120 ns | 120 ns | Linear (90 ns) | 1.33x | -| near_linear | sorted_dense_burst | 1024 | 16 | 180 ns | 280 ns | 250 ns | 490 ns | 450 ns | 220 ns | 410 ns | Linear (180 ns) | 1.22x | -| near_linear | sorted_dense_burst | 1024 | 64 | 560 ns | 930 ns | 740 ns | 1.8 μs | 1.7 μs | 589 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| near_linear | sorted_dense_burst | 1024 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 6.7 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | -| near_linear | sorted_dense_burst | 1024 | 1024 | 7.7 μs | 13.9 μs | 10.5 μs | 27.3 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.01x | -| near_linear | sorted_dense_burst | 1024 | 4096 | 31.3 μs | 55.5 μs | 42.1 μs | 109.1 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (31.3 μs) | 0.98x | -| near_linear | sorted_dense_burst | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_dense_burst | 4096 | 4 | 90 ns | 120 ns | 110 ns | 150 ns | 160 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | -| near_linear | sorted_dense_burst | 4096 | 16 | 180 ns | 280 ns | 240 ns | 510 ns | 530 ns | 210 ns | 490 ns | Linear (180 ns) | 1.17x | -| near_linear | sorted_dense_burst | 4096 | 64 | 770 ns | 1.2 μs | 950 ns | 2.0 μs | 2.1 μs | 780 ns | 1.8 μs | Linear (770 ns) | 1.01x | -| near_linear | sorted_dense_burst | 4096 | 256 | 2.0 μs | 3.6 μs | 2.7 μs | 6.9 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| near_linear | sorted_dense_burst | 4096 | 1024 | 7.8 μs | 13.9 μs | 10.6 μs | 27.5 μs | 31.2 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 0.99x | -| near_linear | sorted_dense_burst | 4096 | 4096 | 30.8 μs | 55.6 μs | 41.9 μs | 109.1 μs | 124.6 μs | 30.8 μs | 114.2 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_dense_burst | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_dense_burst | 16384 | 4 | 99 ns | 110 ns | 110 ns | 150 ns | 180 ns | 130 ns | 160 ns | Linear (99 ns) | 1.31x | -| near_linear | sorted_dense_burst | 16384 | 16 | 190 ns | 290 ns | 250 ns | 510 ns | 610 ns | 210 ns | 570 ns | Linear (190 ns) | 1.11x | -| near_linear | sorted_dense_burst | 16384 | 64 | 560 ns | 950 ns | 740 ns | 1.8 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | -| near_linear | sorted_dense_burst | 16384 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.9 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | -| near_linear | sorted_dense_burst | 16384 | 1024 | 7.7 μs | 14.0 μs | 10.5 μs | 27.4 μs | 36.0 μs | 7.8 μs | 33.4 μs | Linear (7.7 μs) | 1.01x | -| near_linear | sorted_dense_burst | 16384 | 4096 | 30.8 μs | 55.6 μs | 42.0 μs | 108.9 μs | 143.9 μs | 30.8 μs | 133.8 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_dense_burst | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | sorted_dense_burst | 65536 | 4 | 100 ns | 120 ns | 120 ns | 150 ns | 200 ns | 129 ns | 190 ns | Linear (100 ns) | 1.29x | -| near_linear | sorted_dense_burst | 65536 | 16 | 190 ns | 299 ns | 250 ns | 500 ns | 690 ns | 220 ns | 630 ns | Linear (190 ns) | 1.16x | -| near_linear | sorted_dense_burst | 65536 | 64 | 570 ns | 949 ns | 750 ns | 1.9 μs | 2.6 μs | 610 ns | 2.4 μs | Linear (570 ns) | 1.07x | -| near_linear | sorted_dense_burst | 65536 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 7.2 μs | 10.2 μs | 2.0 μs | 9.5 μs | Linear (2.0 μs) | 1.01x | -| near_linear | sorted_dense_burst | 65536 | 1024 | 7.8 μs | 14.0 μs | 10.6 μs | 28.4 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.00x | -| near_linear | sorted_dense_burst | 65536 | 4096 | 30.8 μs | 55.5 μs | 42.0 μs | 113.7 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_near_start | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| near_linear | sorted_near_start | 16 | 4 | 90 ns | 110 ns | 110 ns | 150 ns | 90 ns | 120 ns | 70 ns | Binary (90 ns) | 1.33x | -| near_linear | sorted_near_start | 16 | 16 | 180 ns | 290 ns | 220 ns | 480 ns | 230 ns | 200 ns | 190 ns | Linear (180 ns) | 1.11x | -| near_linear | sorted_near_start | 16 | 64 | 579 ns | 970 ns | 770 ns | 1.8 μs | 840 ns | 600 ns | 710 ns | Linear (579 ns) | 1.04x | -| near_linear | sorted_near_start | 16 | 256 | 2.0 μs | 3.5 μs | 2.7 μs | 6.8 μs | 3.1 μs | 2.0 μs | 2.7 μs | Linear (2.0 μs) | 1.01x | -| near_linear | sorted_near_start | 16 | 1024 | 7.9 μs | 14.2 μs | 10.8 μs | 27.3 μs | 12.2 μs | 7.9 μs | 10.3 μs | Linear (7.9 μs) | 1.00x | -| near_linear | sorted_near_start | 16 | 4096 | 31.1 μs | 55.6 μs | 42.2 μs | 106.9 μs | 47.9 μs | 31.1 μs | 40.4 μs | Linear (31.1 μs) | 1.00x | -| near_linear | sorted_near_start | 64 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 50 ns | 50 ns | ExpFromLeft (60 ns) | 0.83x | -| near_linear | sorted_near_start | 64 | 4 | 100 ns | 110 ns | 110 ns | 150 ns | 100 ns | 120 ns | 90 ns | Binary (100 ns) | 1.20x | -| near_linear | sorted_near_start | 64 | 16 | 250 ns | 310 ns | 240 ns | 460 ns | 320 ns | 270 ns | 290 ns | ExpFromLeft (240 ns) | 1.12x | -| near_linear | sorted_near_start | 64 | 64 | 680 ns | 1.0 μs | 819 ns | 1.8 μs | 1.1 μs | 730 ns | 980 ns | Linear (680 ns) | 1.07x | -| near_linear | sorted_near_start | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 7.0 μs | 4.3 μs | 2.3 μs | 3.8 μs | Linear (2.1 μs) | 1.07x | -| near_linear | sorted_near_start | 64 | 1024 | 7.9 μs | 14.1 μs | 10.6 μs | 27.9 μs | 17.1 μs | 7.9 μs | 15.4 μs | Linear (7.9 μs) | 1.00x | -| near_linear | sorted_near_start | 64 | 4096 | 31.8 μs | 56.5 μs | 42.8 μs | 111.0 μs | 67.2 μs | 31.8 μs | 60.4 μs | Linear (31.8 μs) | 1.00x | -| near_linear | sorted_near_start | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_near_start | 256 | 4 | 300 ns | 150 ns | 120 ns | 150 ns | 130 ns | 140 ns | 110 ns | ExpFromLeft (120 ns) | 1.17x | -| near_linear | sorted_near_start | 256 | 16 | 540 ns | 340 ns | 260 ns | 490 ns | 400 ns | 290 ns | 360 ns | ExpFromLeft (260 ns) | 1.12x | -| near_linear | sorted_near_start | 256 | 64 | 869 ns | 1.1 μs | 870 ns | 1.9 μs | 1.6 μs | 910 ns | 1.4 μs | Linear (869 ns) | 1.05x | -| near_linear | sorted_near_start | 256 | 256 | 2.5 μs | 4.0 μs | 3.1 μs | 7.5 μs | 5.7 μs | 2.7 μs | 5.2 μs | Linear (2.5 μs) | 1.04x | -| near_linear | sorted_near_start | 256 | 1024 | 8.4 μs | 14.6 μs | 11.0 μs | 28.6 μs | 22.3 μs | 8.4 μs | 20.4 μs | Linear (8.4 μs) | 1.00x | -| near_linear | sorted_near_start | 256 | 4096 | 31.8 μs | 56.9 μs | 42.5 μs | 114.1 μs | 89.4 μs | 31.6 μs | 82.2 μs | Linear (31.8 μs) | 0.99x | -| near_linear | sorted_near_start | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| near_linear | sorted_near_start | 1024 | 4 | 450 ns | 160 ns | 150 ns | 150 ns | 140 ns | 190 ns | 130 ns | Binary (140 ns) | 1.36x | -| near_linear | sorted_near_start | 1024 | 16 | 1.2 μs | 400 ns | 320 ns | 470 ns | 490 ns | 330 ns | 440 ns | ExpFromLeft (320 ns) | 1.03x | -| near_linear | sorted_near_start | 1024 | 64 | 2.1 μs | 1.2 μs | 900 ns | 1.9 μs | 2.0 μs | 940 ns | 1.9 μs | ExpFromLeft (900 ns) | 1.04x | -| near_linear | sorted_near_start | 1024 | 256 | 3.8 μs | 4.7 μs | 3.5 μs | 8.9 μs | 7.6 μs | 3.8 μs | 7.0 μs | ExpFromLeft (3.5 μs) | 1.07x | -| near_linear | sorted_near_start | 1024 | 1024 | 10.6 μs | 15.8 μs | 12.3 μs | 30.7 μs | 27.6 μs | 10.6 μs | 25.7 μs | Linear (10.6 μs) | 1.00x | -| near_linear | sorted_near_start | 1024 | 4096 | 33.8 μs | 58.7 μs | 44.4 μs | 115.6 μs | 111.1 μs | 33.9 μs | 105.2 μs | Linear (33.8 μs) | 1.00x | -| near_linear | sorted_near_start | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_near_start | 4096 | 4 | 3.4 μs | 200 ns | 170 ns | 140 ns | 160 ns | 180 ns | 150 ns | InterpSearch (140 ns) | 1.29x | -| near_linear | sorted_near_start | 4096 | 16 | 2.1 μs | 499 ns | 390 ns | 470 ns | 550 ns | 420 ns | 520 ns | ExpFromLeft (390 ns) | 1.08x | -| near_linear | sorted_near_start | 4096 | 64 | 6.1 μs | 1.7 μs | 1.4 μs | 2.1 μs | 2.4 μs | 1.4 μs | 2.4 μs | ExpFromLeft (1.4 μs) | 1.01x | -| near_linear | sorted_near_start | 4096 | 256 | 7.9 μs | 4.8 μs | 3.4 μs | 8.9 μs | 11.4 μs | 3.4 μs | 10.6 μs | ExpFromLeft (3.4 μs) | 1.01x | -| near_linear | sorted_near_start | 4096 | 1024 | 16.7 μs | 19.1 μs | 14.5 μs | 37.2 μs | 43.4 μs | 16.3 μs | 37.7 μs | ExpFromLeft (14.5 μs) | 1.13x | -| near_linear | sorted_near_start | 4096 | 4096 | 42.6 μs | 63.4 μs | 49.2 μs | 123.8 μs | 155.6 μs | 42.6 μs | 141.5 μs | Linear (42.6 μs) | 1.00x | -| near_linear | sorted_near_start | 16384 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_near_start | 16384 | 4 | 6.1 μs | 200 ns | 170 ns | 150 ns | 180 ns | 200 ns | 160 ns | InterpSearch (150 ns) | 1.33x | -| near_linear | sorted_near_start | 16384 | 16 | 9.1 μs | 610 ns | 490 ns | 470 ns | 660 ns | 510 ns | 620 ns | InterpSearch (470 ns) | 1.09x | -| near_linear | sorted_near_start | 16384 | 64 | 23.5 μs | 2.0 μs | 1.5 μs | 1.9 μs | 3.0 μs | 1.5 μs | 2.7 μs | ExpFromLeft (1.5 μs) | 1.02x | -| near_linear | sorted_near_start | 16384 | 256 | 26.0 μs | 6.1 μs | 4.2 μs | 8.8 μs | 18.1 μs | 4.4 μs | 17.0 μs | ExpFromLeft (4.2 μs) | 1.03x | -| near_linear | sorted_near_start | 16384 | 1024 | 34.4 μs | 21.1 μs | 14.8 μs | 38.5 μs | 76.7 μs | 14.9 μs | 70.1 μs | ExpFromLeft (14.8 μs) | 1.00x | -| near_linear | sorted_near_start | 16384 | 4096 | 73.3 μs | 78.8 μs | 61.6 μs | 149.3 μs | 257.9 μs | 73.6 μs | 242.2 μs | ExpFromLeft (61.6 μs) | 1.20x | -| near_linear | sorted_near_start | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | sorted_near_start | 65536 | 4 | 48.2 μs | 260 ns | 209 ns | 150 ns | 200 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | -| near_linear | sorted_near_start | 65536 | 16 | 40.4 μs | 790 ns | 600 ns | 470 ns | 670 ns | 620 ns | 630 ns | InterpSearch (470 ns) | 1.32x | -| near_linear | sorted_near_start | 65536 | 64 | 81.9 μs | 2.5 μs | 1.9 μs | 1.9 μs | 3.6 μs | 1.9 μs | 3.4 μs | ExpFromLeft (1.9 μs) | 1.01x | -| near_linear | sorted_near_start | 65536 | 256 | 95.0 μs | 7.8 μs | 5.7 μs | 9.1 μs | 20.2 μs | 5.8 μs | 20.0 μs | ExpFromLeft (5.7 μs) | 1.02x | -| near_linear | sorted_near_start | 65536 | 1024 | 102.2 μs | 27.7 μs | 20.1 μs | 38.5 μs | 93.8 μs | 19.1 μs | 88.6 μs | ExpFromLeft (20.1 μs) | 0.95x | -| near_linear | sorted_near_start | 65536 | 4096 | 156.3 μs | 120.2 μs | 94.1 μs | 159.9 μs | 322.1 μs | 91.9 μs | 299.4 μs | ExpFromLeft (94.1 μs) | 0.98x | -| near_linear | sorted_arithmetic | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 60 ns | 40 ns | ExpFromLeft (50 ns) | 1.20x | -| near_linear | sorted_arithmetic | 16 | 4 | 100 ns | 120 ns | 120 ns | 140 ns | 90 ns | 110 ns | 80 ns | Binary (90 ns) | 1.22x | -| near_linear | sorted_arithmetic | 16 | 16 | 190 ns | 310 ns | 250 ns | 480 ns | 230 ns | 210 ns | 190 ns | Linear (190 ns) | 1.11x | -| near_linear | sorted_arithmetic | 16 | 64 | 630 ns | 1.0 μs | 780 ns | 1.8 μs | 980 ns | 650 ns | 870 ns | Linear (630 ns) | 1.03x | -| near_linear | sorted_arithmetic | 16 | 256 | 2.0 μs | 3.8 μs | 2.7 μs | 7.8 μs | 3.2 μs | 2.1 μs | 2.8 μs | Linear (2.0 μs) | 1.01x | -| near_linear | sorted_arithmetic | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 28.2 μs | 12.2 μs | 8.2 μs | 10.4 μs | Linear (8.1 μs) | 1.01x | -| near_linear | sorted_arithmetic | 16 | 4096 | 31.1 μs | 55.4 μs | 42.0 μs | 109.5 μs | 48.1 μs | 31.1 μs | 40.8 μs | Linear (31.1 μs) | 1.00x | -| near_linear | sorted_arithmetic | 64 | 1 | 60 ns | 50 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | Gallop (50 ns) | 1.20x | -| near_linear | sorted_arithmetic | 64 | 4 | 170 ns | 150 ns | 130 ns | 140 ns | 110 ns | 160 ns | 90 ns | Binary (110 ns) | 1.45x | -| near_linear | sorted_arithmetic | 64 | 16 | 270 ns | 430 ns | 340 ns | 500 ns | 300 ns | 310 ns | 250 ns | Linear (270 ns) | 1.15x | -| near_linear | sorted_arithmetic | 64 | 64 | 670 ns | 1.1 μs | 740 ns | 1.7 μs | 1.1 μs | 690 ns | 990 ns | Linear (670 ns) | 1.03x | -| near_linear | sorted_arithmetic | 64 | 256 | 2.1 μs | 3.7 μs | 2.8 μs | 6.9 μs | 5.2 μs | 2.2 μs | 4.9 μs | Linear (2.1 μs) | 1.01x | -| near_linear | sorted_arithmetic | 64 | 1024 | 8.2 μs | 14.9 μs | 11.7 μs | 31.3 μs | 17.7 μs | 8.2 μs | 16.0 μs | Linear (8.2 μs) | 1.01x | -| near_linear | sorted_arithmetic | 64 | 4096 | 32.3 μs | 56.4 μs | 42.0 μs | 112.9 μs | 67.1 μs | 32.2 μs | 60.3 μs | Linear (32.3 μs) | 1.00x | -| near_linear | sorted_arithmetic | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_arithmetic | 256 | 4 | 460 ns | 180 ns | 150 ns | 140 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | -| near_linear | sorted_arithmetic | 256 | 16 | 570 ns | 550 ns | 440 ns | 470 ns | 370 ns | 470 ns | 340 ns | Binary (370 ns) | 1.27x | -| near_linear | sorted_arithmetic | 256 | 64 | 990 ns | 1.6 μs | 1.2 μs | 1.9 μs | 1.4 μs | 1.0 μs | 1.3 μs | Linear (990 ns) | 1.03x | -| near_linear | sorted_arithmetic | 256 | 256 | 2.4 μs | 4.2 μs | 2.7 μs | 6.5 μs | 5.5 μs | 2.5 μs | 5.8 μs | Linear (2.4 μs) | 1.02x | -| near_linear | sorted_arithmetic | 256 | 1024 | 8.3 μs | 14.6 μs | 10.6 μs | 27.4 μs | 26.8 μs | 8.3 μs | 25.3 μs | Linear (8.3 μs) | 1.00x | -| near_linear | sorted_arithmetic | 256 | 4096 | 31.6 μs | 59.5 μs | 46.4 μs | 125.0 μs | 90.5 μs | 31.6 μs | 83.3 μs | Linear (31.6 μs) | 1.00x | -| near_linear | sorted_arithmetic | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_arithmetic | 1024 | 4 | 1.6 μs | 210 ns | 170 ns | 140 ns | 140 ns | 180 ns | 130 ns | InterpSearch (140 ns) | 1.29x | -| near_linear | sorted_arithmetic | 1024 | 16 | 1.7 μs | 680 ns | 520 ns | 500 ns | 450 ns | 550 ns | 409 ns | Binary (450 ns) | 1.22x | -| near_linear | sorted_arithmetic | 1024 | 64 | 2.1 μs | 2.1 μs | 1.7 μs | 1.8 μs | 1.7 μs | 2.0 μs | 1.6 μs | Binary (1.7 μs) | 1.20x | -| near_linear | sorted_arithmetic | 1024 | 256 | 3.6 μs | 6.2 μs | 4.7 μs | 7.0 μs | 7.9 μs | 3.6 μs | 7.8 μs | Linear (3.6 μs) | 1.01x | -| near_linear | sorted_arithmetic | 1024 | 1024 | 9.5 μs | 16.4 μs | 10.6 μs | 26.0 μs | 95.2 μs | 9.5 μs | 93.5 μs | Linear (9.5 μs) | 1.00x | -| near_linear | sorted_arithmetic | 1024 | 4096 | 32.8 μs | 58.2 μs | 42.2 μs | 108.9 μs | 200.3 μs | 32.8 μs | 193.0 μs | Linear (32.8 μs) | 1.00x | -| near_linear | sorted_arithmetic | 4096 | 1 | 70 ns | 70 ns | 69 ns | 60 ns | 70 ns | 70 ns | 60 ns | InterpSearch (60 ns) | 1.17x | -| near_linear | sorted_arithmetic | 4096 | 4 | 6.0 μs | 250 ns | 200 ns | 140 ns | 160 ns | 190 ns | 150 ns | InterpSearch (140 ns) | 1.36x | -| near_linear | sorted_arithmetic | 4096 | 16 | 6.4 μs | 820 ns | 580 ns | 470 ns | 530 ns | 530 ns | 480 ns | InterpSearch (470 ns) | 1.13x | -| near_linear | sorted_arithmetic | 4096 | 64 | 6.4 μs | 2.7 μs | 2.0 μs | 1.7 μs | 2.0 μs | 1.8 μs | 1.9 μs | InterpSearch (1.7 μs) | 1.10x | -| near_linear | sorted_arithmetic | 4096 | 256 | 8.2 μs | 8.4 μs | 6.2 μs | 7.7 μs | 8.3 μs | 8.2 μs | 8.0 μs | ExpFromLeft (6.2 μs) | 1.34x | -| near_linear | sorted_arithmetic | 4096 | 1024 | 14.0 μs | 24.5 μs | 18.4 μs | 27.5 μs | 85.3 μs | 13.8 μs | 74.4 μs | Linear (14.0 μs) | 0.99x | -| near_linear | sorted_arithmetic | 4096 | 4096 | 37.8 μs | 65.7 μs | 41.9 μs | 103.6 μs | 312.5 μs | 37.9 μs | 309.4 μs | Linear (37.8 μs) | 1.00x | -| near_linear | sorted_arithmetic | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_arithmetic | 16384 | 4 | 23.4 μs | 280 ns | 220 ns | 140 ns | 190 ns | 190 ns | 170 ns | InterpSearch (140 ns) | 1.36x | -| near_linear | sorted_arithmetic | 16384 | 16 | 23.8 μs | 1.0 μs | 680 ns | 480 ns | 600 ns | 560 ns | 570 ns | InterpSearch (480 ns) | 1.17x | -| near_linear | sorted_arithmetic | 16384 | 64 | 25.2 μs | 3.3 μs | 2.1 μs | 1.9 μs | 2.3 μs | 2.1 μs | 2.2 μs | InterpSearch (1.9 μs) | 1.10x | -| near_linear | sorted_arithmetic | 16384 | 256 | 26.7 μs | 10.5 μs | 7.8 μs | 7.0 μs | 13.9 μs | 7.6 μs | 13.8 μs | InterpSearch (7.0 μs) | 1.10x | -| near_linear | sorted_arithmetic | 16384 | 1024 | 31.6 μs | 32.7 μs | 24.5 μs | 28.2 μs | 109.3 μs | 30.9 μs | 105.1 μs | ExpFromLeft (24.5 μs) | 1.26x | -| near_linear | sorted_arithmetic | 16384 | 4096 | 55.6 μs | 97.6 μs | 73.3 μs | 109.2 μs | 394.2 μs | 55.2 μs | 397.5 μs | Linear (55.6 μs) | 0.99x | -| near_linear | sorted_arithmetic | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_arithmetic | 65536 | 4 | 93.2 μs | 320 ns | 250 ns | 140 ns | 210 ns | 190 ns | 180 ns | InterpSearch (140 ns) | 1.36x | -| near_linear | sorted_arithmetic | 65536 | 16 | 93.8 μs | 1.1 μs | 799 ns | 470 ns | 690 ns | 530 ns | 660 ns | InterpSearch (470 ns) | 1.13x | -| near_linear | sorted_arithmetic | 65536 | 64 | 95.7 μs | 3.9 μs | 2.8 μs | 1.9 μs | 2.7 μs | 2.0 μs | 2.6 μs | InterpSearch (1.9 μs) | 1.09x | -| near_linear | sorted_arithmetic | 65536 | 256 | 101.7 μs | 12.8 μs | 8.8 μs | 6.5 μs | 11.2 μs | 7.1 μs | 11.7 μs | InterpSearch (6.5 μs) | 1.08x | -| near_linear | sorted_arithmetic | 65536 | 1024 | 104.3 μs | 43.4 μs | 32.5 μs | 30.7 μs | 115.2 μs | 32.6 μs | 115.5 μs | InterpSearch (30.7 μs) | 1.06x | -| near_linear | sorted_arithmetic | 65536 | 4096 | 128.2 μs | 130.3 μs | 97.6 μs | 110.2 μs | 409.9 μs | 117.9 μs | 402.5 μs | ExpFromLeft (97.6 μs) | 1.21x | -| near_linear | sorted_geometric | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| near_linear | sorted_geometric | 16 | 4 | 100 ns | 110 ns | 120 ns | 150 ns | 90 ns | 110 ns | 70 ns | Binary (90 ns) | 1.22x | -| near_linear | sorted_geometric | 16 | 16 | 190 ns | 300 ns | 220 ns | 460 ns | 230 ns | 210 ns | 180 ns | Linear (190 ns) | 1.11x | -| near_linear | sorted_geometric | 16 | 64 | 560 ns | 1.0 μs | 750 ns | 1.9 μs | 990 ns | 590 ns | 860 ns | Linear (560 ns) | 1.05x | -| near_linear | sorted_geometric | 16 | 256 | 3.0 μs | 4.9 μs | 3.7 μs | 8.3 μs | 3.3 μs | 2.3 μs | 2.8 μs | Linear (3.0 μs) | 0.76x | -| near_linear | sorted_geometric | 16 | 1024 | 8.1 μs | 14.2 μs | 10.8 μs | 28.2 μs | 12.2 μs | 8.1 μs | 10.1 μs | Linear (8.1 μs) | 1.00x | -| near_linear | sorted_geometric | 16 | 4096 | 31.1 μs | 56.0 μs | 42.3 μs | 108.9 μs | 47.1 μs | 31.1 μs | 40.2 μs | Linear (31.1 μs) | 1.00x | -| near_linear | sorted_geometric | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| near_linear | sorted_geometric | 64 | 4 | 170 ns | 150 ns | 140 ns | 150 ns | 110 ns | 140 ns | 100 ns | Binary (110 ns) | 1.27x | -| near_linear | sorted_geometric | 64 | 16 | 260 ns | 370 ns | 300 ns | 470 ns | 300 ns | 280 ns | 270 ns | Linear (260 ns) | 1.08x | -| near_linear | sorted_geometric | 64 | 64 | 630 ns | 1.1 μs | 730 ns | 2.0 μs | 1.3 μs | 660 ns | 1.1 μs | Linear (630 ns) | 1.05x | -| near_linear | sorted_geometric | 64 | 256 | 2.3 μs | 4.0 μs | 3.1 μs | 8.4 μs | 5.3 μs | 2.4 μs | 4.8 μs | Linear (2.3 μs) | 1.01x | -| near_linear | sorted_geometric | 64 | 1024 | 9.0 μs | 14.9 μs | 11.6 μs | 30.8 μs | 17.7 μs | 9.1 μs | 16.0 μs | Linear (9.0 μs) | 1.01x | -| near_linear | sorted_geometric | 64 | 4096 | 32.2 μs | 56.5 μs | 43.2 μs | 112.8 μs | 66.9 μs | 32.2 μs | 60.2 μs | Linear (32.2 μs) | 1.00x | -| near_linear | sorted_geometric | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_geometric | 256 | 4 | 490 ns | 180 ns | 150 ns | 150 ns | 130 ns | 170 ns | 110 ns | Binary (130 ns) | 1.31x | -| near_linear | sorted_geometric | 256 | 16 | 530 ns | 490 ns | 390 ns | 470 ns | 380 ns | 400 ns | 340 ns | Binary (380 ns) | 1.05x | -| near_linear | sorted_geometric | 256 | 64 | 920 ns | 1.4 μs | 990 ns | 1.9 μs | 1.4 μs | 930 ns | 1.2 μs | Linear (920 ns) | 1.01x | -| near_linear | sorted_geometric | 256 | 256 | 2.5 μs | 4.6 μs | 3.0 μs | 8.0 μs | 6.7 μs | 2.5 μs | 6.2 μs | Linear (2.5 μs) | 1.00x | -| near_linear | sorted_geometric | 256 | 1024 | 9.7 μs | 16.3 μs | 12.4 μs | 32.6 μs | 27.8 μs | 9.7 μs | 26.1 μs | Linear (9.7 μs) | 1.00x | -| near_linear | sorted_geometric | 256 | 4096 | 35.3 μs | 58.9 μs | 45.6 μs | 119.3 μs | 90.8 μs | 35.3 μs | 83.7 μs | Linear (35.3 μs) | 1.00x | -| near_linear | sorted_geometric | 1024 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_geometric | 1024 | 4 | 1.8 μs | 210 ns | 170 ns | 150 ns | 140 ns | 190 ns | 120 ns | Binary (140 ns) | 1.36x | -| near_linear | sorted_geometric | 1024 | 16 | 1.8 μs | 620 ns | 500 ns | 500 ns | 450 ns | 520 ns | 410 ns | Binary (450 ns) | 1.16x | -| near_linear | sorted_geometric | 1024 | 64 | 2.1 μs | 1.9 μs | 1.4 μs | 2.0 μs | 1.7 μs | 1.5 μs | 1.6 μs | ExpFromLeft (1.4 μs) | 1.03x | -| near_linear | sorted_geometric | 1024 | 256 | 3.7 μs | 5.7 μs | 4.0 μs | 8.8 μs | 7.7 μs | 3.7 μs | 7.6 μs | Linear (3.7 μs) | 1.00x | -| near_linear | sorted_geometric | 1024 | 1024 | 10.8 μs | 18.6 μs | 12.3 μs | 33.2 μs | 65.5 μs | 10.7 μs | 62.3 μs | Linear (10.8 μs) | 0.99x | -| near_linear | sorted_geometric | 1024 | 4096 | 38.6 μs | 63.1 μs | 48.0 μs | 120.3 μs | 192.1 μs | 38.6 μs | 192.2 μs | Linear (38.6 μs) | 1.00x | -| near_linear | sorted_geometric | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_geometric | 4096 | 4 | 6.0 μs | 240 ns | 190 ns | 150 ns | 160 ns | 190 ns | 150 ns | InterpSearch (150 ns) | 1.27x | -| near_linear | sorted_geometric | 4096 | 16 | 6.4 μs | 770 ns | 580 ns | 470 ns | 530 ns | 600 ns | 480 ns | InterpSearch (470 ns) | 1.28x | -| near_linear | sorted_geometric | 4096 | 64 | 7.4 μs | 2.5 μs | 1.8 μs | 2.0 μs | 2.0 μs | 1.9 μs | 1.9 μs | ExpFromLeft (1.8 μs) | 1.02x | -| near_linear | sorted_geometric | 4096 | 256 | 8.7 μs | 7.5 μs | 5.7 μs | 9.0 μs | 10.7 μs | 5.8 μs | 10.3 μs | ExpFromLeft (5.7 μs) | 1.02x | -| near_linear | sorted_geometric | 4096 | 1024 | 15.8 μs | 24.1 μs | 17.1 μs | 33.1 μs | 94.1 μs | 15.8 μs | 86.8 μs | Linear (15.8 μs) | 1.00x | -| near_linear | sorted_geometric | 4096 | 4096 | 44.4 μs | 73.8 μs | 50.1 μs | 125.6 μs | 310.9 μs | 44.7 μs | 301.9 μs | Linear (44.4 μs) | 1.01x | -| near_linear | sorted_geometric | 16384 | 1 | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_geometric | 16384 | 4 | 23.4 μs | 270 ns | 210 ns | 150 ns | 180 ns | 190 ns | 170 ns | InterpSearch (150 ns) | 1.27x | -| near_linear | sorted_geometric | 16384 | 16 | 23.8 μs | 920 ns | 690 ns | 480 ns | 600 ns | 710 ns | 560 ns | InterpSearch (480 ns) | 1.48x | -| near_linear | sorted_geometric | 16384 | 64 | 25.5 μs | 3.2 μs | 2.3 μs | 2.0 μs | 2.4 μs | 2.3 μs | 2.2 μs | InterpSearch (2.0 μs) | 1.18x | -| near_linear | sorted_geometric | 16384 | 256 | 29.9 μs | 10.1 μs | 7.4 μs | 8.9 μs | 13.3 μs | 7.6 μs | 12.8 μs | ExpFromLeft (7.4 μs) | 1.02x | -| near_linear | sorted_geometric | 16384 | 1024 | 36.2 μs | 31.9 μs | 24.7 μs | 36.0 μs | 123.1 μs | 24.8 μs | 121.6 μs | ExpFromLeft (24.7 μs) | 1.00x | -| near_linear | sorted_geometric | 16384 | 4096 | 66.4 μs | 98.4 μs | 69.6 μs | 130.8 μs | 408.2 μs | 66.7 μs | 410.6 μs | Linear (66.4 μs) | 1.01x | -| near_linear | sorted_geometric | 65536 | 1 | 80 ns | 80 ns | 80 ns | 60 ns | 80 ns | 80 ns | 70 ns | InterpSearch (60 ns) | 1.33x | -| near_linear | sorted_geometric | 65536 | 4 | 93.1 μs | 310 ns | 250 ns | 150 ns | 200 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | -| near_linear | sorted_geometric | 65536 | 16 | 93.6 μs | 1.1 μs | 810 ns | 470 ns | 690 ns | 820 ns | 650 ns | InterpSearch (470 ns) | 1.74x | -| near_linear | sorted_geometric | 65536 | 64 | 95.4 μs | 3.7 μs | 2.7 μs | 2.1 μs | 2.9 μs | 2.8 μs | 2.6 μs | InterpSearch (2.1 μs) | 1.33x | -| near_linear | sorted_geometric | 65536 | 256 | 101.8 μs | 13.4 μs | 10.0 μs | 9.6 μs | 17.5 μs | 9.7 μs | 17.3 μs | InterpSearch (9.6 μs) | 1.01x | -| near_linear | sorted_geometric | 65536 | 1024 | 117.6 μs | 48.0 μs | 36.9 μs | 39.0 μs | 153.7 μs | 35.4 μs | 158.3 μs | ExpFromLeft (36.9 μs) | 0.96x | -| near_linear | sorted_geometric | 65536 | 4096 | 147.5 μs | 134.0 μs | 102.3 μs | 132.2 μs | 501.4 μs | 103.1 μs | 503.5 μs | ExpFromLeft (102.3 μs) | 1.01x | -| near_linear | sorted_bimodal | 16 | 1 | 50 ns | 50 ns | 50 ns | 69 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| near_linear | sorted_bimodal | 16 | 4 | 100 ns | 120 ns | 100 ns | 150 ns | 100 ns | 110 ns | 80 ns | ExpFromLeft (100 ns) | 1.10x | -| near_linear | sorted_bimodal | 16 | 16 | 190 ns | 280 ns | 220 ns | 460 ns | 240 ns | 210 ns | 200 ns | Linear (190 ns) | 1.11x | -| near_linear | sorted_bimodal | 16 | 64 | 630 ns | 970 ns | 800 ns | 1.9 μs | 880 ns | 640 ns | 750 ns | Linear (630 ns) | 1.02x | -| near_linear | sorted_bimodal | 16 | 256 | 2.1 μs | 3.5 μs | 2.8 μs | 6.9 μs | 3.2 μs | 2.2 μs | 2.8 μs | Linear (2.1 μs) | 1.02x | -| near_linear | sorted_bimodal | 16 | 1024 | 7.9 μs | 13.5 μs | 10.7 μs | 26.9 μs | 12.7 μs | 7.8 μs | 10.9 μs | Linear (7.9 μs) | 1.00x | -| near_linear | sorted_bimodal | 16 | 4096 | 30.9 μs | 53.7 μs | 42.1 μs | 107.3 μs | 50.2 μs | 31.0 μs | 43.4 μs | Linear (30.9 μs) | 1.00x | -| near_linear | sorted_bimodal | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| near_linear | sorted_bimodal | 64 | 4 | 160 ns | 130 ns | 110 ns | 150 ns | 110 ns | 140 ns | 90 ns | ExpFromLeft (110 ns) | 1.27x | -| near_linear | sorted_bimodal | 64 | 16 | 260 ns | 300 ns | 240 ns | 460 ns | 310 ns | 290 ns | 290 ns | ExpFromLeft (240 ns) | 1.21x | -| near_linear | sorted_bimodal | 64 | 64 | 630 ns | 980 ns | 750 ns | 1.9 μs | 1.3 μs | 660 ns | 1.2 μs | Linear (630 ns) | 1.05x | -| near_linear | sorted_bimodal | 64 | 256 | 2.3 μs | 3.7 μs | 2.9 μs | 7.6 μs | 4.5 μs | 2.3 μs | 4.0 μs | Linear (2.3 μs) | 1.01x | -| near_linear | sorted_bimodal | 64 | 1024 | 8.2 μs | 14.1 μs | 10.8 μs | 28.0 μs | 17.0 μs | 8.2 μs | 15.2 μs | Linear (8.2 μs) | 1.00x | -| near_linear | sorted_bimodal | 64 | 4096 | 31.1 μs | 55.3 μs | 42.3 μs | 109.3 μs | 66.8 μs | 31.2 μs | 60.2 μs | Linear (31.1 μs) | 1.00x | -| near_linear | sorted_bimodal | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_bimodal | 256 | 4 | 450 ns | 160 ns | 130 ns | 150 ns | 130 ns | 160 ns | 110 ns | ExpFromLeft (130 ns) | 1.23x | -| near_linear | sorted_bimodal | 256 | 16 | 530 ns | 360 ns | 290 ns | 490 ns | 440 ns | 310 ns | 420 ns | ExpFromLeft (290 ns) | 1.07x | -| near_linear | sorted_bimodal | 256 | 64 | 920 ns | 1.1 μs | 760 ns | 2.0 μs | 1.8 μs | 960 ns | 1.7 μs | ExpFromLeft (760 ns) | 1.26x | -| near_linear | sorted_bimodal | 256 | 256 | 2.6 μs | 4.2 μs | 3.2 μs | 8.6 μs | 6.3 μs | 2.6 μs | 5.8 μs | Linear (2.6 μs) | 1.01x | -| near_linear | sorted_bimodal | 256 | 1024 | 9.2 μs | 14.8 μs | 11.5 μs | 30.9 μs | 22.6 μs | 9.1 μs | 20.6 μs | Linear (9.2 μs) | 1.00x | -| near_linear | sorted_bimodal | 256 | 4096 | 32.2 μs | 56.5 μs | 43.0 μs | 112.1 μs | 86.6 μs | 32.2 μs | 79.5 μs | Linear (32.2 μs) | 1.00x | -| near_linear | sorted_bimodal | 1024 | 1 | 70 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | sorted_bimodal | 1024 | 4 | 1.5 μs | 180 ns | 160 ns | 150 ns | 140 ns | 200 ns | 130 ns | Binary (140 ns) | 1.43x | -| near_linear | sorted_bimodal | 1024 | 16 | 1.7 μs | 460 ns | 390 ns | 470 ns | 460 ns | 390 ns | 410 ns | ExpFromLeft (390 ns) | 1.00x | -| near_linear | sorted_bimodal | 1024 | 64 | 2.0 μs | 1.3 μs | 960 ns | 2.0 μs | 1.9 μs | 1.0 μs | 1.8 μs | ExpFromLeft (960 ns) | 1.05x | -| near_linear | sorted_bimodal | 1024 | 256 | 3.5 μs | 4.1 μs | 2.8 μs | 8.8 μs | 8.4 μs | 3.5 μs | 8.0 μs | ExpFromLeft (2.8 μs) | 1.25x | -| near_linear | sorted_bimodal | 1024 | 1024 | 11.8 μs | 17.2 μs | 13.5 μs | 37.0 μs | 30.7 μs | 11.6 μs | 29.1 μs | Linear (11.8 μs) | 0.99x | -| near_linear | sorted_bimodal | 1024 | 4096 | 36.6 μs | 58.8 μs | 45.8 μs | 122.3 μs | 109.0 μs | 36.6 μs | 102.1 μs | Linear (36.6 μs) | 1.00x | -| near_linear | sorted_bimodal | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_bimodal | 4096 | 4 | 5.2 μs | 200 ns | 170 ns | 150 ns | 170 ns | 200 ns | 140 ns | InterpSearch (150 ns) | 1.33x | -| near_linear | sorted_bimodal | 4096 | 16 | 6.2 μs | 620 ns | 480 ns | 460 ns | 520 ns | 520 ns | 490 ns | InterpSearch (460 ns) | 1.13x | -| near_linear | sorted_bimodal | 4096 | 64 | 6.6 μs | 1.7 μs | 1.3 μs | 2.0 μs | 2.2 μs | 1.4 μs | 2.0 μs | ExpFromLeft (1.3 μs) | 1.02x | -| near_linear | sorted_bimodal | 4096 | 256 | 7.8 μs | 5.3 μs | 3.6 μs | 8.9 μs | 11.6 μs | 4.9 μs | 10.2 μs | ExpFromLeft (3.6 μs) | 1.35x | -| near_linear | sorted_bimodal | 4096 | 1024 | 14.7 μs | 17.8 μs | 12.4 μs | 39.5 μs | 60.8 μs | 14.5 μs | 56.1 μs | ExpFromLeft (12.4 μs) | 1.17x | -| near_linear | sorted_bimodal | 4096 | 4096 | 51.4 μs | 70.2 μs | 55.8 μs | 151.1 μs | 181.7 μs | 51.5 μs | 168.1 μs | Linear (51.4 μs) | 1.00x | -| near_linear | sorted_bimodal | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_bimodal | 16384 | 4 | 22.8 μs | 260 ns | 210 ns | 150 ns | 180 ns | 190 ns | 170 ns | InterpSearch (150 ns) | 1.27x | -| near_linear | sorted_bimodal | 16384 | 16 | 23.5 μs | 750 ns | 570 ns | 470 ns | 600 ns | 600 ns | 570 ns | InterpSearch (470 ns) | 1.28x | -| near_linear | sorted_bimodal | 16384 | 64 | 24.7 μs | 2.2 μs | 1.7 μs | 1.9 μs | 2.7 μs | 1.7 μs | 2.5 μs | ExpFromLeft (1.7 μs) | 1.02x | -| near_linear | sorted_bimodal | 16384 | 256 | 26.2 μs | 6.8 μs | 5.0 μs | 9.0 μs | 15.1 μs | 5.0 μs | 14.2 μs | ExpFromLeft (5.0 μs) | 1.01x | -| near_linear | sorted_bimodal | 16384 | 1024 | 33.7 μs | 22.3 μs | 16.1 μs | 38.1 μs | 90.3 μs | 15.7 μs | 87.0 μs | ExpFromLeft (16.1 μs) | 0.97x | -| near_linear | sorted_bimodal | 16384 | 4096 | 75.4 μs | 91.9 μs | 67.2 μs | 160.3 μs | 273.8 μs | 77.6 μs | 263.7 μs | ExpFromLeft (67.2 μs) | 1.16x | -| near_linear | sorted_bimodal | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | sorted_bimodal | 65536 | 4 | 83.9 μs | 270 ns | 220 ns | 150 ns | 200 ns | 190 ns | 190 ns | InterpSearch (150 ns) | 1.27x | -| near_linear | sorted_bimodal | 65536 | 16 | 92.7 μs | 900 ns | 660 ns | 460 ns | 660 ns | 690 ns | 640 ns | InterpSearch (460 ns) | 1.50x | -| near_linear | sorted_bimodal | 65536 | 64 | 94.6 μs | 2.9 μs | 2.2 μs | 2.0 μs | 3.0 μs | 2.2 μs | 2.8 μs | InterpSearch (2.0 μs) | 1.12x | -| near_linear | sorted_bimodal | 65536 | 256 | 99.5 μs | 9.4 μs | 7.0 μs | 9.2 μs | 18.6 μs | 6.9 μs | 17.5 μs | ExpFromLeft (7.0 μs) | 0.99x | -| near_linear | sorted_bimodal | 65536 | 1024 | 108.7 μs | 33.2 μs | 24.4 μs | 39.1 μs | 115.0 μs | 22.6 μs | 115.4 μs | ExpFromLeft (24.4 μs) | 0.93x | -| near_linear | sorted_bimodal | 65536 | 4096 | 183.9 μs | 147.1 μs | 110.2 μs | 160.7 μs | 349.4 μs | 108.6 μs | 351.9 μs | ExpFromLeft (110.2 μs) | 0.99x | -| near_linear | sorted_repeated | 16 | 1 | 50 ns | 50 ns | 50 ns | 70 ns | 50 ns | 50 ns | 40 ns | ExpFromLeft (50 ns) | 1.00x | -| near_linear | sorted_repeated | 16 | 4 | 80 ns | 90 ns | 90 ns | 150 ns | 90 ns | 100 ns | 70 ns | Linear (80 ns) | 1.25x | -| near_linear | sorted_repeated | 16 | 16 | 170 ns | 270 ns | 200 ns | 460 ns | 230 ns | 190 ns | 190 ns | Linear (170 ns) | 1.12x | -| near_linear | sorted_repeated | 16 | 64 | 550 ns | 930 ns | 690 ns | 1.7 μs | 790 ns | 570 ns | 670 ns | Linear (550 ns) | 1.04x | -| near_linear | sorted_repeated | 16 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.6 μs | 3.0 μs | 2.0 μs | 2.6 μs | Linear (2.0 μs) | 1.00x | -| near_linear | sorted_repeated | 16 | 1024 | 7.7 μs | 13.9 μs | 9.9 μs | 25.9 μs | 11.8 μs | 7.8 μs | 9.9 μs | Linear (7.7 μs) | 1.00x | -| near_linear | sorted_repeated | 16 | 4096 | 30.8 μs | 55.5 μs | 39.3 μs | 103.4 μs | 47.3 μs | 30.8 μs | 41.0 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_repeated | 64 | 1 | 60 ns | 50 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| near_linear | sorted_repeated | 64 | 4 | 80 ns | 110 ns | 90 ns | 140 ns | 110 ns | 110 ns | 90 ns | Linear (80 ns) | 1.38x | -| near_linear | sorted_repeated | 64 | 16 | 170 ns | 270 ns | 230 ns | 460 ns | 310 ns | 190 ns | 270 ns | Linear (170 ns) | 1.12x | -| near_linear | sorted_repeated | 64 | 64 | 690 ns | 930 ns | 710 ns | 1.7 μs | 1.1 μs | 580 ns | 910 ns | Linear (690 ns) | 0.84x | -| near_linear | sorted_repeated | 64 | 256 | 2.0 μs | 3.5 μs | 2.5 μs | 6.5 μs | 4.2 μs | 2.0 μs | 3.6 μs | Linear (2.0 μs) | 1.02x | -| near_linear | sorted_repeated | 64 | 1024 | 7.7 μs | 13.9 μs | 9.9 μs | 26.0 μs | 16.7 μs | 7.8 μs | 14.2 μs | Linear (7.7 μs) | 1.00x | -| near_linear | sorted_repeated | 64 | 4096 | 30.8 μs | 55.5 μs | 39.4 μs | 103.5 μs | 66.6 μs | 30.8 μs | 56.7 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_repeated | 256 | 1 | 60 ns | 60 ns | 80 ns | 80 ns | 60 ns | 60 ns | 50 ns | Binary (60 ns) | 1.00x | -| near_linear | sorted_repeated | 256 | 4 | 90 ns | 100 ns | 90 ns | 140 ns | 130 ns | 110 ns | 110 ns | ExpFromLeft (90 ns) | 1.22x | -| near_linear | sorted_repeated | 256 | 16 | 170 ns | 280 ns | 210 ns | 459 ns | 380 ns | 200 ns | 340 ns | Linear (170 ns) | 1.18x | -| near_linear | sorted_repeated | 256 | 64 | 550 ns | 940 ns | 710 ns | 1.7 μs | 1.4 μs | 590 ns | 1.2 μs | Linear (550 ns) | 1.07x | -| near_linear | sorted_repeated | 256 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 5.4 μs | 2.0 μs | 4.8 μs | Linear (2.0 μs) | 1.02x | -| near_linear | sorted_repeated | 256 | 1024 | 7.7 μs | 14.0 μs | 9.9 μs | 25.9 μs | 21.5 μs | 7.8 μs | 19.2 μs | Linear (7.7 μs) | 1.00x | -| near_linear | sorted_repeated | 256 | 4096 | 30.8 μs | 55.6 μs | 39.4 μs | 103.5 μs | 85.9 μs | 30.8 μs | 76.4 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_repeated | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| near_linear | sorted_repeated | 1024 | 4 | 90 ns | 100 ns | 100 ns | 150 ns | 140 ns | 120 ns | 130 ns | Linear (90 ns) | 1.33x | -| near_linear | sorted_repeated | 1024 | 16 | 180 ns | 280 ns | 220 ns | 450 ns | 460 ns | 210 ns | 420 ns | Linear (180 ns) | 1.17x | -| near_linear | sorted_repeated | 1024 | 64 | 560 ns | 940 ns | 700 ns | 1.7 μs | 1.7 μs | 589 ns | 1.5 μs | Linear (560 ns) | 1.05x | -| near_linear | sorted_repeated | 1024 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 6.6 μs | 2.0 μs | 6.0 μs | Linear (2.0 μs) | 1.02x | -| near_linear | sorted_repeated | 1024 | 1024 | 7.7 μs | 14.0 μs | 10.0 μs | 25.9 μs | 26.4 μs | 7.8 μs | 24.0 μs | Linear (7.7 μs) | 1.00x | -| near_linear | sorted_repeated | 1024 | 4096 | 30.8 μs | 55.6 μs | 39.2 μs | 103.4 μs | 105.5 μs | 30.8 μs | 95.8 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_repeated | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_repeated | 4096 | 4 | 90 ns | 110 ns | 100 ns | 140 ns | 160 ns | 120 ns | 150 ns | Linear (90 ns) | 1.33x | -| near_linear | sorted_repeated | 4096 | 16 | 180 ns | 290 ns | 220 ns | 450 ns | 520 ns | 210 ns | 610 ns | Linear (180 ns) | 1.17x | -| near_linear | sorted_repeated | 4096 | 64 | 570 ns | 940 ns | 700 ns | 1.7 μs | 2.0 μs | 600 ns | 1.8 μs | Linear (570 ns) | 1.05x | -| near_linear | sorted_repeated | 4096 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 7.8 μs | 2.0 μs | 7.2 μs | Linear (2.0 μs) | 1.01x | -| near_linear | sorted_repeated | 4096 | 1024 | 7.8 μs | 14.0 μs | 9.9 μs | 25.9 μs | 31.1 μs | 7.8 μs | 28.6 μs | Linear (7.8 μs) | 1.00x | -| near_linear | sorted_repeated | 4096 | 4096 | 30.8 μs | 55.5 μs | 39.3 μs | 103.4 μs | 124.6 μs | 30.8 μs | 114.1 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_repeated | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | sorted_repeated | 16384 | 4 | 90 ns | 110 ns | 110 ns | 140 ns | 180 ns | 120 ns | 170 ns | Linear (90 ns) | 1.33x | -| near_linear | sorted_repeated | 16384 | 16 | 240 ns | 360 ns | 260 ns | 499 ns | 620 ns | 250 ns | 570 ns | Linear (240 ns) | 1.04x | -| near_linear | sorted_repeated | 16384 | 64 | 560 ns | 939 ns | 710 ns | 1.7 μs | 2.3 μs | 600 ns | 2.1 μs | Linear (560 ns) | 1.07x | -| near_linear | sorted_repeated | 16384 | 256 | 2.0 μs | 3.5 μs | 2.6 μs | 6.5 μs | 9.0 μs | 2.0 μs | 8.4 μs | Linear (2.0 μs) | 1.02x | -| near_linear | sorted_repeated | 16384 | 1024 | 7.8 μs | 13.9 μs | 10.0 μs | 26.0 μs | 36.1 μs | 7.8 μs | 33.4 μs | Linear (7.8 μs) | 1.00x | -| near_linear | sorted_repeated | 16384 | 4096 | 30.8 μs | 55.6 μs | 39.6 μs | 103.5 μs | 144.1 μs | 30.9 μs | 133.7 μs | Linear (30.8 μs) | 1.00x | -| near_linear | sorted_repeated | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | sorted_repeated | 65536 | 4 | 100 ns | 120 ns | 110 ns | 150 ns | 200 ns | 120 ns | 180 ns | Linear (100 ns) | 1.20x | -| near_linear | sorted_repeated | 65536 | 16 | 240 ns | 360 ns | 260 ns | 500 ns | 680 ns | 260 ns | 640 ns | Linear (240 ns) | 1.08x | -| near_linear | sorted_repeated | 65536 | 64 | 570 ns | 960 ns | 710 ns | 1.7 μs | 2.6 μs | 600 ns | 2.4 μs | Linear (570 ns) | 1.05x | -| near_linear | sorted_repeated | 65536 | 256 | 2.0 μs | 3.6 μs | 2.6 μs | 6.5 μs | 10.2 μs | 2.0 μs | 9.6 μs | Linear (2.0 μs) | 1.01x | -| near_linear | sorted_repeated | 65536 | 1024 | 7.8 μs | 13.9 μs | 10.0 μs | 25.9 μs | 40.8 μs | 7.8 μs | 38.1 μs | Linear (7.8 μs) | 1.01x | -| near_linear | sorted_repeated | 65536 | 4096 | 30.8 μs | 55.5 μs | 39.1 μs | 103.5 μs | 163.1 μs | 30.8 μs | 152.5 μs | Linear (30.8 μs) | 1.00x | -| near_linear | unsorted | 16 | 1 | 50 ns | 50 ns | 50 ns | 80 ns | 50 ns | 50 ns | 50 ns | ExpFromLeft (50 ns) | 1.00x | -| near_linear | unsorted | 16 | 4 | 90 ns | 90 ns | 90 ns | 80 ns | 90 ns | 100 ns | 70 ns | InterpSearch (80 ns) | 1.25x | -| near_linear | unsorted | 16 | 16 | 200 ns | 210 ns | 210 ns | 220 ns | 210 ns | 220 ns | 190 ns | Linear (200 ns) | 1.10x | -| near_linear | unsorted | 16 | 64 | 719 ns | 730 ns | 730 ns | 720 ns | 730 ns | 740 ns | 740 ns | Linear (719 ns) | 1.03x | -| near_linear | unsorted | 16 | 256 | 3.2 μs | 3.0 μs | 3.0 μs | 3.0 μs | 3.0 μs | 3.0 μs | 3.0 μs | InterpSearch (3.0 μs) | 1.01x | -| near_linear | unsorted | 16 | 1024 | 21.5 μs | 21.5 μs | 21.4 μs | 21.3 μs | 21.3 μs | 21.4 μs | 22.6 μs | Binary (21.3 μs) | 1.00x | -| near_linear | unsorted | 16 | 4096 | 145.3 μs | 142.7 μs | 141.6 μs | 140.3 μs | 140.3 μs | 139.8 μs | 144.4 μs | InterpSearch (140.3 μs) | 1.00x | -| near_linear | unsorted | 64 | 1 | 60 ns | 60 ns | 50 ns | 70 ns | 60 ns | 60 ns | 50 ns | ExpFromLeft (50 ns) | 1.20x | -| near_linear | unsorted | 64 | 4 | 110 ns | 110 ns | 110 ns | 120 ns | 110 ns | 120 ns | 90 ns | ExpFromLeft (110 ns) | 1.09x | -| near_linear | unsorted | 64 | 16 | 280 ns | 280 ns | 270 ns | 280 ns | 280 ns | 290 ns | 270 ns | ExpFromLeft (270 ns) | 1.07x | -| near_linear | unsorted | 64 | 64 | 1.1 μs | 1.0 μs | 1.1 μs | 1.0 μs | 1.0 μs | 1.1 μs | 1.1 μs | InterpSearch (1.0 μs) | 1.02x | -| near_linear | unsorted | 64 | 256 | 5.7 μs | 5.6 μs | 5.5 μs | 5.6 μs | 5.5 μs | 5.5 μs | 5.7 μs | ExpFromLeft (5.5 μs) | 1.00x | -| near_linear | unsorted | 64 | 1024 | 39.0 μs | 37.9 μs | 37.6 μs | 37.2 μs | 37.2 μs | 36.9 μs | 38.9 μs | Binary (37.2 μs) | 0.99x | -| near_linear | unsorted | 64 | 4096 | 224.3 μs | 223.3 μs | 222.5 μs | 222.1 μs | 224.0 μs | 224.3 μs | 226.6 μs | InterpSearch (222.1 μs) | 1.01x | -| near_linear | unsorted | 256 | 1 | 60 ns | 60 ns | 60 ns | 70 ns | 60 ns | 60 ns | 60 ns | ExpFromLeft (60 ns) | 1.00x | -| near_linear | unsorted | 256 | 4 | 130 ns | 120 ns | 120 ns | 120 ns | 130 ns | 130 ns | 109 ns | InterpSearch (120 ns) | 1.08x | -| near_linear | unsorted | 256 | 16 | 350 ns | 350 ns | 350 ns | 350 ns | 350 ns | 360 ns | 340 ns | InterpSearch (350 ns) | 1.03x | -| near_linear | unsorted | 256 | 64 | 1.3 μs | 1.3 μs | 1.3 μs | 1.3 μs | 1.3 μs | 1.3 μs | 1.3 μs | Gallop (1.3 μs) | 1.00x | -| near_linear | unsorted | 256 | 256 | 6.9 μs | 6.9 μs | 6.9 μs | 6.9 μs | 6.8 μs | 6.8 μs | 7.0 μs | Binary (6.8 μs) | 1.00x | -| near_linear | unsorted | 256 | 1024 | 53.2 μs | 51.9 μs | 51.2 μs | 51.1 μs | 50.5 μs | 50.3 μs | 51.3 μs | Binary (50.5 μs) | 1.00x | -| near_linear | unsorted | 256 | 4096 | 309.3 μs | 310.4 μs | 307.7 μs | 306.2 μs | 306.6 μs | 303.6 μs | 306.2 μs | InterpSearch (306.2 μs) | 0.99x | -| near_linear | unsorted | 1024 | 1 | 70 ns | 60 ns | 70 ns | 70 ns | 70 ns | 60 ns | 60 ns | Gallop (60 ns) | 1.00x | -| near_linear | unsorted | 1024 | 4 | 140 ns | 140 ns | 140 ns | 140 ns | 140 ns | 150 ns | 130 ns | InterpSearch (140 ns) | 1.07x | -| near_linear | unsorted | 1024 | 16 | 420 ns | 430 ns | 430 ns | 420 ns | 420 ns | 440 ns | 420 ns | InterpSearch (420 ns) | 1.05x | -| near_linear | unsorted | 1024 | 64 | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | 1.7 μs | InterpSearch (1.7 μs) | 1.00x | -| near_linear | unsorted | 1024 | 256 | 7.5 μs | 7.4 μs | 7.4 μs | 7.2 μs | 7.2 μs | 7.3 μs | 7.6 μs | Binary (7.2 μs) | 1.02x | -| near_linear | unsorted | 1024 | 1024 | 78.8 μs | 76.4 μs | 74.7 μs | 74.5 μs | 74.3 μs | 73.7 μs | 77.3 μs | Binary (74.3 μs) | 0.99x | -| near_linear | unsorted | 1024 | 4096 | 412.1 μs | 412.4 μs | 412.6 μs | 411.3 μs | 412.0 μs | 411.7 μs | 408.2 μs | InterpSearch (411.3 μs) | 1.00x | -| near_linear | unsorted | 4096 | 1 | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 70 ns | 60 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | unsorted | 4096 | 4 | 150 ns | 160 ns | 160 ns | 160 ns | 160 ns | 170 ns | 150 ns | Linear (150 ns) | 1.13x | -| near_linear | unsorted | 4096 | 16 | 510 ns | 490 ns | 490 ns | 500 ns | 490 ns | 510 ns | 480 ns | ExpFromLeft (490 ns) | 1.04x | -| near_linear | unsorted | 4096 | 64 | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | 1.9 μs | Binary (1.9 μs) | 1.01x | -| near_linear | unsorted | 4096 | 256 | 9.3 μs | 9.1 μs | 9.0 μs | 9.0 μs | 9.0 μs | 9.0 μs | 10.7 μs | ExpFromLeft (9.0 μs) | 1.00x | -| near_linear | unsorted | 4096 | 1024 | 98.2 μs | 95.9 μs | 94.3 μs | 94.4 μs | 93.9 μs | 93.8 μs | 98.0 μs | Binary (93.9 μs) | 1.00x | -| near_linear | unsorted | 4096 | 4096 | 498.2 μs | 498.8 μs | 498.2 μs | 498.2 μs | 498.0 μs | 496.9 μs | 498.7 μs | Binary (498.0 μs) | 1.00x | -| near_linear | unsorted | 16384 | 1 | 80 ns | 70 ns | 70 ns | 70 ns | 80 ns | 70 ns | 70 ns | InterpSearch (70 ns) | 1.00x | -| near_linear | unsorted | 16384 | 4 | 13.0 μs | 250 ns | 200 ns | 150 ns | 180 ns | 200 ns | 170 ns | InterpSearch (150 ns) | 1.33x | -| near_linear | unsorted | 16384 | 16 | 580 ns | 570 ns | 580 ns | 570 ns | 589 ns | 580 ns | 560 ns | InterpSearch (570 ns) | 1.02x | -| near_linear | unsorted | 16384 | 64 | 2.4 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.3 μs | 2.4 μs | Gallop (2.3 μs) | 1.01x | -| near_linear | unsorted | 16384 | 256 | 10.7 μs | 10.7 μs | 10.6 μs | 10.6 μs | 10.5 μs | 10.4 μs | 13.7 μs | Binary (10.5 μs) | 1.00x | -| near_linear | unsorted | 16384 | 1024 | 140.7 μs | 137.1 μs | 134.5 μs | 134.4 μs | 133.2 μs | 134.3 μs | 141.5 μs | Binary (133.2 μs) | 1.01x | -| near_linear | unsorted | 16384 | 4096 | 663.3 μs | 665.1 μs | 663.5 μs | 662.9 μs | 663.9 μs | 662.9 μs | 668.2 μs | InterpSearch (662.9 μs) | 1.00x | -| near_linear | unsorted | 65536 | 1 | 80 ns | 80 ns | 80 ns | 70 ns | 80 ns | 80 ns | 70 ns | InterpSearch (70 ns) | 1.14x | -| near_linear | unsorted | 65536 | 4 | 190 ns | 190 ns | 190 ns | 190 ns | 190 ns | 200 ns | 180 ns | InterpSearch (190 ns) | 1.05x | -| near_linear | unsorted | 65536 | 16 | 670 ns | 670 ns | 660 ns | 670 ns | 680 ns | 680 ns | 640 ns | ExpFromLeft (660 ns) | 1.03x | -| near_linear | unsorted | 65536 | 64 | 2.7 μs | 2.7 μs | 2.7 μs | 2.7 μs | 2.6 μs | 2.7 μs | 2.7 μs | Binary (2.6 μs) | 1.02x | -| near_linear | unsorted | 65536 | 256 | 14.0 μs | 13.6 μs | 13.3 μs | 13.2 μs | 13.2 μs | 13.2 μs | 18.4 μs | InterpSearch (13.2 μs) | 1.00x | -| near_linear | unsorted | 65536 | 1024 | 187.8 μs | 184.1 μs | 184.1 μs | 184.8 μs | 182.7 μs | 182.6 μs | 185.2 μs | Binary (182.7 μs) | 1.00x | -| near_linear | unsorted | 65536 | 4096 | 842.3 μs | 843.1 μs | 842.4 μs | 844.3 μs | 844.3 μs | 840.7 μs | 841.2 μs | Linear (842.3 μs) | 1.00x | - -**Auto verdict over 3920 cells**: 3289 within 20% of best, 545 worse than 20% slowdown, 86 effectively-faster-than-best. diff --git a/bench/strategies.jl b/bench/strategies.jl deleted file mode 100644 index 9c790cd..0000000 --- a/bench/strategies.jl +++ /dev/null @@ -1,619 +0,0 @@ -""" -Benchmark sweep for the SearchStrategy types in FindFirstFunctions. - -Run from the repo root: - - julia --project=bench bench/strategies.jl # default fast sweep - MODE=full julia --project=bench bench/strategies.jl # full sweep - MODE=spacing julia --project=bench bench/strategies.jl # focused: spacing variety - MODE=ratio julia --project=bench bench/strategies.jl # focused: n/m crossover - MODE=pattern julia --project=bench bench/strategies.jl # focused: query pattern - MODE=extreme julia --project=bench bench/strategies.jl # focused: very sparse / very dense - -Sweeps over: - - - knot count `n` (16 .. 1_000_000 in the full sweep) - - query count `m` (1 .. 4n in the full sweep) - - knot spacing (10 spacings, see KNOT_SPACINGS below) - - query pattern (8 patterns, see QUERY_PATTERNS below) - - strategy (LinearScan, BracketGallop, ExpFromLeft, - InterpolationSearch, BinaryBracket, Auto) - -Emits a Markdown table per sub-sweep so the regimes where each strategy wins -are easy to read off, plus a "best/auto" column that flags cells where the -heuristic doesn't land on the actual best strategy. -""" - -using BenchmarkTools -using StableRNGs -using Printf -using FindFirstFunctions: LinearScan, BracketGallop, ExpFromLeft, - InterpolationSearch, BinaryBracket, Auto, SearchStrategy, - searchsortedlast!, searchsortedfirst! - -const RNG = StableRNG(0xfaceb00c) - -# --------------------------------------------------------------------------- -# Knot-generation helpers -# --------------------------------------------------------------------------- - -knots_uniform(n) = collect(range(0.0, 10.0; length = n)) -knots_log(n) = collect(exp.(range(log(0.1), log(100.0); length = n))) -function knots_jittered(n; rel = 0.3) - base = collect(range(0.0, 10.0; length = n)) - n < 2 && return base - step = base[2] - base[1] - return sort!(base .+ (rand(RNG, n) .- 0.5) .* rel .* step) -end -knots_random(n) = sort!(rand(RNG, n) .* 10.0) -function knots_two_scale(n) - # Half the knots packed near 0..1, half spread over 1..1000 - n1 = n ÷ 2 - n2 = n - n1 - return sort!(vcat(rand(RNG, n1), 1.0 .+ rand(RNG, n2) .* 999.0)) -end -# v_i = (i / n)^2 — quadratic spacing; dense near 0, sparse near 1. -knots_power2(n) = collect(((0:(n - 1)) ./ max(1, n - 1)) .^ 2 .* 10.0) -# v_i = sqrt(i / n) — square-root spacing; sparse near 0, dense near 1. -knots_sqrt(n) = collect(sqrt.((0:(n - 1)) ./ max(1, n - 1)) .* 10.0) -# Three flat plateaus and two jumps — many duplicate values. -function knots_plateau(n) - chunk = max(1, n ÷ 3) - v = vcat(fill(1.0, chunk), fill(5.0, chunk), fill(9.0, n - 2 * chunk)) - return v -end -# Bimodal: two dense clusters at 0..1 and 9..10, sparse middle. -function knots_bimodal(n) - n1 = n ÷ 2 - n2 = n - n1 - left = sort!(rand(RNG, n1)) - right = sort!(9.0 .+ rand(RNG, n2)) - return vcat(left, right) -end -# Almost-linear with one tiny offset to defeat simple range checks. -function knots_near_linear(n) - v = collect(range(0.0, 10.0; length = n)) - if n >= 4 - v[end - 1] += 1.0e-9 - end - return v -end - -const ALL_KNOT_SPACINGS = ( - :uniform => knots_uniform, - :log => knots_log, - :jittered => knots_jittered, - :random => knots_random, - :two_scale => knots_two_scale, - :power2 => knots_power2, - :sqrt => knots_sqrt, - :plateau => knots_plateau, - :bimodal => knots_bimodal, - :near_linear => knots_near_linear, -) - -# Fast-sweep subset -const FAST_KNOT_SPACINGS = ( - :uniform => knots_uniform, - :log => knots_log, - :jittered => knots_jittered, - :random => knots_random, - :two_scale => knots_two_scale, -) - -# --------------------------------------------------------------------------- -# Query-generation helpers -# --------------------------------------------------------------------------- - -function queries_uniform(t::Vector, m::Integer) - lo, hi = first(t), last(t) - return sort!(lo .+ (hi - lo) .* rand(RNG, m)) -end - -# All queries packed inside a single tiny segment in the middle of t. -function queries_dense_burst(t::Vector, m::Integer) - n = length(t) - i = max(1, n ÷ 2) - lo, hi = t[i], t[min(i + 1, n)] - return sort!(lo .+ (hi - lo) .* rand(RNG, m)) -end - -# 90% of queries clustered in the first 5% of t, 10% spread over the rest. -function queries_clustered_near_start(t::Vector, m::Integer) - n = length(t) - cutoff = max(2, n ÷ 20) - lo1, hi1 = t[1], t[cutoff] - lo2, hi2 = t[cutoff], t[end] - n1 = max(1, (9 * m) ÷ 10) - n2 = m - n1 - return sort!( - vcat( - lo1 .+ (hi1 - lo1) .* rand(RNG, n1), - lo2 .+ (hi2 - lo2) .* rand(RNG, n2) - ) - ) -end - -# Arithmetic progression covering the full range of t. -function queries_arithmetic(t::Vector, m::Integer) - m <= 1 && return [(first(t) + last(t)) / 2] - return collect(range(first(t), last(t); length = m)) -end - -# Geometric progression — gaps double as we move forward. -function queries_geometric(t::Vector, m::Integer) - m <= 1 && return [first(t)] - lo, hi = first(t), last(t) - span = hi - lo - weights = collect(0:(m - 1)) ./ (m - 1) - geo = exp.(log(1) .+ (log(span + 1) - log(1)) .* weights) .- 1 - return lo .+ geo -end - -# Bimodal: half clustered at one end of t, half at the other. -function queries_bimodal(t::Vector, m::Integer) - lo, hi = first(t), last(t) - n1 = m ÷ 2 - n2 = m - n1 - span = (hi - lo) * 0.1 - return sort!( - vcat( - lo .+ span .* rand(RNG, n1), - hi .- span .* rand(RNG, n2) - ) - ) -end - -# Same value repeated — pathological for any hint-using strategy if `v` -# has duplicates around it. -function queries_repeated(t::Vector, m::Integer) - mid = t[max(1, length(t) ÷ 2)] - return fill(mid, m) -end - -function queries_unsorted(t::Vector, m::Integer) - lo, hi = first(t), last(t) - return lo .+ (hi - lo) .* rand(RNG, m) -end - -const ALL_QUERY_PATTERNS = ( - :sorted_uniform => queries_uniform, - :sorted_dense_burst => queries_dense_burst, - :sorted_near_start => queries_clustered_near_start, - :sorted_arithmetic => queries_arithmetic, - :sorted_geometric => queries_geometric, - :sorted_bimodal => queries_bimodal, - :sorted_repeated => queries_repeated, - :unsorted => queries_unsorted, -) - -const FAST_QUERY_PATTERNS = ( - :sorted_uniform => queries_uniform, - :sorted_dense_burst => queries_dense_burst, - :sorted_near_start => queries_clustered_near_start, - :unsorted => queries_unsorted, -) - -# --------------------------------------------------------------------------- -# Strategies under test -# --------------------------------------------------------------------------- - -const STRATEGIES = ( - "Linear" => LinearScan(), - "Gallop" => BracketGallop(), - "ExpFromLeft" => ExpFromLeft(), - "InterpSearch" => InterpolationSearch(), - "Binary" => BinaryBracket(), - "Auto" => Auto(), -) - -# --------------------------------------------------------------------------- -# Benchmark primitives -# --------------------------------------------------------------------------- - -"Returns minimum-time-per-batch (ns) for the given strategy on `(v, q)`." -function bench_batch(strategy::SearchStrategy, v::Vector, q::Vector) - out = Vector{Int}(undef, length(q)) - b = @benchmark searchsortedlast!($out, $v, $q; strategy = $strategy) samples = 20 evals = 1 - return minimum(b).time # ns -end - -function bench_base(v::Vector, q::Vector) - out = Vector{Int}(undef, length(q)) - b = @benchmark begin - @inbounds for k in eachindex($q) - $out[k] = searchsortedlast($v, $q[k]) - end - end samples = 20 evals = 1 - return minimum(b).time -end - -# --------------------------------------------------------------------------- -# Reporting -# --------------------------------------------------------------------------- - -function format_ns(x) - return if isnan(x) - " - " - elseif x >= 1.0e6 - @sprintf("%.2f ms", x / 1.0e6) - elseif x >= 1.0e3 - @sprintf("%.1f μs", x / 1.0e3) - else - @sprintf("%.0f ns", x) - end -end - -function run_sweep(; title, ns, ms, spacings, query_patterns, strategies) - println("\n## $title\n") - header = String[ - "spacing", "query pattern", "n", "m", - ] - for (name, _) in strategies - push!(header, name) - end - push!(header, "base") - push!(header, "best") - push!(header, "best/auto") - println("| ", join(header, " | "), " |") - println( - "|---|---|---|---|", - join(("---" for _ in strategies), "|"), - "|---|---|---|" - ) - - auto_wins = 0 - auto_losses = 0 - auto_within_20pct = 0 - rows = 0 - - for (sp_name, sp_fn) in spacings - for (qp_name, qp_fn) in query_patterns - for n in ns - t = sp_fn(n) - for m in ms - q = qp_fn(t, m) - results = Dict{String, Float64}() - for (name, strategy) in strategies - results[name] = bench_batch(strategy, t, q) - end - results["base"] = bench_base(t, q) - best_name, best_t = "", Inf - for (name, t_) in results - (name == "Auto" || name == "base") && continue - if t_ < best_t - best_t = t_ - best_name = name - end - end - auto_t = results["Auto"] - rel = auto_t / best_t - if rel < 0.95 - auto_wins += 1 - elseif rel > 1.2 - auto_losses += 1 - else - auto_within_20pct += 1 - end - rows += 1 - - cols = String[ - string(sp_name), string(qp_name), - string(n), string(m), - ] - for (name, _) in strategies - push!(cols, format_ns(results[name])) - end - push!(cols, format_ns(results["base"])) - push!(cols, "$(best_name) ($(format_ns(best_t)))") - push!(cols, @sprintf("%.2fx", rel)) - println("| ", join(cols, " | "), " |") - end - end - end - end - - println( - "\n**Auto verdict over $rows cells**: ", - "$auto_within_20pct within 20% of best, ", - "$auto_losses worse than 20% slowdown, ", - "$auto_wins effectively-faster-than-best." - ) - return (rows, auto_within_20pct, auto_losses, auto_wins) -end - -# --------------------------------------------------------------------------- -# Pre-built sweep definitions -# --------------------------------------------------------------------------- - -function fast_sweep() - return run_sweep( - title = "Fast sweep", - ns = (64, 1024, 65_536), - ms = (1, 10, 256, 4096), - spacings = FAST_KNOT_SPACINGS, - query_patterns = FAST_QUERY_PATTERNS, - strategies = STRATEGIES, - ) -end - -function full_sweep() - return run_sweep( - title = "Full sweep", - ns = (16, 64, 256, 1024, 4096, 65_536, 262_144), - ms = (1, 10, 64, 256, 1024, 4096), - spacings = ALL_KNOT_SPACINGS, - query_patterns = ALL_QUERY_PATTERNS, - strategies = STRATEGIES, - ) -end - -# Focused: vary spacing only, fix n=4096, m=512, pattern=sorted_uniform. -function sweep_spacing() - return run_sweep( - title = "Spacing variety (n=4096, m=512, sorted_uniform)", - ns = (4096,), - ms = (512,), - spacings = ALL_KNOT_SPACINGS, - query_patterns = (:sorted_uniform => queries_uniform,), - strategies = STRATEGIES, - ) -end - -# Focused: vary n and m on uniform data. -function sweep_ratio() - return run_sweep( - title = "n/m crossover (uniform, sorted_uniform)", - ns = (16, 64, 256, 1024, 4096, 16_384, 65_536, 262_144), - ms = (1, 4, 16, 64, 256, 1024, 4096, 16_384), - spacings = (:uniform => knots_uniform,), - query_patterns = (:sorted_uniform => queries_uniform,), - strategies = STRATEGIES, - ) -end - -# Focused: vary query pattern. -function sweep_pattern() - return run_sweep( - title = "Query patterns (n=4096, m=512, uniform)", - ns = (4096,), - ms = (512,), - spacings = (:uniform => knots_uniform,), - query_patterns = ALL_QUERY_PATTERNS, - strategies = STRATEGIES, - ) -end - -# Focused: stress edges — super sparse and super dense. -function sweep_extreme() - # Super sparse: m=1..16 over varied n. - # Super dense: m = 4n. - println("\n### Super-sparse cases (small m on large n)") - res_sparse = run_sweep( - title = "Super sparse", - ns = (1024, 16_384, 262_144), - ms = (1, 4, 16), - spacings = ALL_KNOT_SPACINGS, - query_patterns = ( - :sorted_uniform => queries_uniform, - :unsorted => queries_unsorted, - ), - strategies = STRATEGIES, - ) - - println("\n### Super-dense cases (m ≫ n)") - res_dense = run_sweep( - title = "Super dense", - ns = (64, 256, 1024), - ms = (1024, 4096, 16_384), # m up to 256× n - spacings = ALL_KNOT_SPACINGS, - query_patterns = ( - :sorted_uniform => queries_uniform, - :sorted_dense_burst => queries_dense_burst, - :unsorted => queries_unsorted, - ), - strategies = STRATEGIES, - ) - return (sparse = res_sparse, dense = res_dense) -end - -""" - sweep_tune_gap_linear_vs_exp() - -Empirical crossover between `LinearScan` and `ExpFromLeft` as a function of -the gap between consecutive query results. Runs at a fixed large `n` on -uniform data (so per-segment work is dominated by the per-query inner-loop -overhead, not by data-shape effects), sweeping `m` so the average gap covers -0..256. We're looking for the largest gap at which LinearScan still wins. -""" -function sweep_tune_gap_linear_vs_exp() - n = 4096 - t = knots_uniform(n) - println("\n## Tune: LinearScan vs ExpFromLeft crossover (n=$n, uniform)\n") - println("| gap (≈n/m) | m | Linear | ExpFromLeft | winner | margin |") - println("|---|---|---|---|---|---|") - pairs = [ - (gap, max(1, n ÷ gap)) for gap in (1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256) - ] - for (gap_target, m) in pairs - q = queries_uniform(t, m) - t_lin = bench_batch(LinearScan(), t, q) - t_exp = bench_batch(ExpFromLeft(), t, q) - winner = t_lin <= t_exp ? "Linear" : "ExpFromLeft" - margin = abs(t_lin - t_exp) / min(t_lin, t_exp) - @printf( - "| %d | %d | %s | %s | %s | %.0f%% |\n", - gap_target, m, format_ns(t_lin), format_ns(t_exp), - winner, 100 * margin - ) - end - return -end - -""" - sweep_tune_gap_exp_vs_interp() - -Empirical crossover between `ExpFromLeft` and `InterpolationSearch` on -uniform data, where InterpolationSearch's per-query O(1) advantage is -maximum. Sweeps `m` from sparse to dense at fixed `n`. -""" -function sweep_tune_gap_exp_vs_interp() - n = 65_536 - t = knots_uniform(n) - println("\n## Tune: ExpFromLeft vs InterpolationSearch crossover (n=$n, uniform)\n") - println("| gap (≈n/m) | m | ExpFromLeft | InterpSearch | winner | margin |") - println("|---|---|---|---|---|---|") - pairs = [ - (gap, max(1, n ÷ gap)) for gap in - (8, 16, 24, 32, 48, 64, 96, 128, 256, 512, 1024, 4096, 16_384, 65_536) - ] - for (gap_target, m) in pairs - q = queries_uniform(t, m) - t_exp = bench_batch(ExpFromLeft(), t, q) - t_int = bench_batch(InterpolationSearch(), t, q) - winner = t_exp <= t_int ? "ExpFromLeft" : "InterpSearch" - margin = abs(t_exp - t_int) / min(t_exp, t_int) - @printf( - "| %d | %d | %s | %s | %s | %.0f%% |\n", - gap_target, m, format_ns(t_exp), format_ns(t_int), - winner, 100 * margin - ) - end - return -end - -""" - sweep_tune_n_for_interp() - -How does the InterpolationSearch break-even shift with `n`? Fix `m=16`, -vary `n`, compare InterpolationSearch vs ExpFromLeft. Useful for picking -`_AUTO_INTERP_MIN_N`. -""" -function sweep_tune_n_for_interp() - println("\n## Tune: minimum n at which InterpolationSearch wins (uniform, m=16)\n") - println("| n | gap | ExpFromLeft | InterpSearch | winner | margin |") - println("|---|---|---|---|---|---|") - m = 16 - for n in (32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16_384, 65_536, 262_144) - t = knots_uniform(n) - q = queries_uniform(t, m) - t_exp = bench_batch(ExpFromLeft(), t, q) - t_int = bench_batch(InterpolationSearch(), t, q) - gap = n ÷ m - winner = t_exp <= t_int ? "ExpFromLeft" : "InterpSearch" - margin = abs(t_exp - t_int) / min(t_exp, t_int) - @printf( - "| %d | %d | %s | %s | %s | %.0f%% |\n", - n, gap, format_ns(t_exp), format_ns(t_int), - winner, 100 * margin - ) - end - return -end - -""" - sweep_tune_m_for_interp() - -How does the break-even shift with `m`? Fix `n=65_536` (large), vary `m`, -compare InterpolationSearch vs ExpFromLeft. Useful for picking -`_AUTO_INTERP_MIN_M`. -""" -function sweep_tune_m_for_interp() - println("\n## Tune: minimum m at which InterpolationSearch wins (uniform, n=65536)\n") - println("| m | gap | ExpFromLeft | InterpSearch | winner | margin |") - println("|---|---|---|---|---|---|") - n = 65_536 - t = knots_uniform(n) - for m in (1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 64, 128, 256, 1024, 4096) - q = queries_uniform(t, m) - t_exp = bench_batch(ExpFromLeft(), t, q) - t_int = bench_batch(InterpolationSearch(), t, q) - gap = n ÷ max(1, m) - winner = t_exp <= t_int ? "ExpFromLeft" : "InterpSearch" - margin = abs(t_exp - t_int) / min(t_exp, t_int) - @printf( - "| %d | %d | %s | %s | %s | %.0f%% |\n", - m, gap, format_ns(t_exp), format_ns(t_int), - winner, 100 * margin - ) - end - return -end - -""" - sweep_tune_interp_on_nonlinear() - -Worst case for InterpolationSearch — measure how badly it loses on each -non-linear spacing. This bounds the downside risk of accidentally picking -InterpolationSearch when the linearity probe gives a false positive. -""" -function sweep_tune_interp_on_nonlinear() - println("\n## Tune: InterpolationSearch downside on non-linear data (m=256)\n") - println("| spacing | n | ExpFromLeft | InterpSearch | InterpSearch slowdown |") - println("|---|---|---|---|---|") - m = 256 - nonlinear = ( - :log => knots_log, :random => knots_random, - :two_scale => knots_two_scale, :power2 => knots_power2, - :sqrt => knots_sqrt, :plateau => knots_plateau, - :bimodal => knots_bimodal, - ) - for (sp_name, sp_fn) in nonlinear - for n in (1024, 16_384, 262_144) - t = sp_fn(n) - q = queries_uniform(t, m) - t_exp = bench_batch(ExpFromLeft(), t, q) - t_int = bench_batch(InterpolationSearch(), t, q) - slowdown = t_int / t_exp - @printf( - "| %s | %d | %s | %s | %.2fx |\n", - sp_name, n, format_ns(t_exp), format_ns(t_int), slowdown - ) - end - end - return -end - -# Comprehensive validation sweep — many cells with smaller per-cell sample -# counts. Use this once Auto's thresholds are tuned to check that the -# heuristic is in fact picking well across the parameter space. -function sweep_validate() - return run_sweep( - title = "Validation sweep (many cells)", - ns = (16, 64, 256, 1024, 4096, 16_384, 65_536), - ms = (1, 4, 16, 64, 256, 1024, 4096), - spacings = ALL_KNOT_SPACINGS, - query_patterns = ALL_QUERY_PATTERNS, - strategies = STRATEGIES, - ) -end - -function tune_all() - sweep_tune_gap_linear_vs_exp() - sweep_tune_gap_exp_vs_interp() - sweep_tune_n_for_interp() - sweep_tune_m_for_interp() - sweep_tune_interp_on_nonlinear() - return -end - -if abspath(PROGRAM_FILE) == @__FILE__ - mode = get(ENV, "MODE", "fast") - if mode == "full" - full_sweep() - elseif mode == "spacing" - sweep_spacing() - elseif mode == "ratio" - sweep_ratio() - elseif mode == "pattern" - sweep_pattern() - elseif mode == "extreme" - sweep_extreme() - elseif mode == "tune" - tune_all() - elseif mode == "validate" - sweep_validate() - else - fast_sweep() - end -end diff --git a/docs/src/index.md b/docs/src/index.md index 6e392ee..ac5bba3 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -11,19 +11,29 @@ using Pkg Pkg.add("FindFirstFunctions") ``` -## Available Functions +## Sorted-search API + +The public sorted-search surface in 2.x is a single pair of generic functions — +`Base.searchsortedfirst` and `Base.searchsortedlast` — overloaded to take a +[`SearchStrategy`](@ref FindFirstFunctions.SearchStrategy) as the first +positional argument: + +```julia +searchsortedfirst(strategy, v, x[, hint]; order = Base.Order.Forward) +searchsortedlast(strategy, v, x[, hint]; order = Base.Order.Forward) +``` + +For batched lookups, use the in-place [`searchsortedfirst!`](@ref FindFirstFunctions.searchsortedfirst!) / +[`searchsortedlast!`](@ref FindFirstFunctions.searchsortedlast!) variants. +They pick a strategy automatically via [`Auto`](@ref FindFirstFunctions.Auto) +by default, or you can pass `strategy = …` to opt into a specific algorithm. + +[`Guesser`](@ref FindFirstFunctions.Guesser) supplies a hint based on either a +linear-extrapolation lookup (when `v` is roughly evenly spaced) or a cached +previous result; pass it through [`GuesserHint`](@ref FindFirstFunctions.GuesserHint) +to use it with the dispatched API. ```@docs -FindFirstFunctions.findfirstequal -FindFirstFunctions.bracketstrictlymontonic -FindFirstFunctions.looks_linear -FindFirstFunctions.Guesser -FindFirstFunctions.searchsortedfirstcorrelated -FindFirstFunctions.searchsortedlastcorrelated -FindFirstFunctions.searchsortedfirstexp -FindFirstFunctions.searchsortedfirstvec -FindFirstFunctions.searchsortedlastvec -FindFirstFunctions.findfirstsortedequal FindFirstFunctions.searchsortedfirst! FindFirstFunctions.searchsortedlast! ``` @@ -41,6 +51,20 @@ FindFirstFunctions.GuesserHint FindFirstFunctions.Auto ``` +## Hint provider and helpers + +```@docs +FindFirstFunctions.Guesser +FindFirstFunctions.looks_linear +``` + +## Equality search + +```@docs +FindFirstFunctions.findfirstequal +FindFirstFunctions.findfirstsortedequal +``` + ## Contributing - Please refer to the diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index f24d38c..bf332e9 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -137,25 +137,10 @@ function findfirstsortedequal( return ret < 0 ? nothing : ret + offset + 1 end -""" - bracketstrictlymontonic(v, x, guess; lt=, by=, rev=false) - -Starting from an initial `guess` index, find indices `(lo, hi)` such that `v[lo] ≤ x ≤ v[hi]` according to the specified order, assuming that `x` is actually within the range of -values found in `v`. If `x` is outside that range, either `lo` will be `firstindex(v)` or -`hi` will be `lastindex(v)`. - -Note that the results will not typically satisfy `lo ≤ guess ≤ hi`. If `x` is precisely -equal to a value that is not unique in the input `v`, there is no guarantee that `(lo, hi)` -will encompass *all* indices corresponding to that value. - -This algorithm is essentially an expanding binary search, which can be used as a precursor -to `searchsorted` and related functions, which can take `lo` and `hi` as arguments. The -purpose of using this function first would be to accelerate convergence in those functions -by using correlated `guess`es for repeated calls. The best `guess` for the next call of -this function would be the index returned by the previous call to `searchsorted`. - -See `Base.sort!` for an explanation of the keyword arguments `by`, `lt` and `rev`. -""" +# Internal: expanding-binary-search bracket around a guess. Backs the +# `BracketGallop` strategy. Not part of the public API in 2.x — use +# `searchsortedfirst(BracketGallop(), v, x, guess)` / +# `searchsortedlast(BracketGallop(), v, x, guess)` instead. function bracketstrictlymontonic( v::AbstractVector, x, @@ -207,9 +192,7 @@ called with a strategy as the first positional argument: within a few positions of the hint; degrades linearly otherwise. - [`BracketGallop`](@ref) expands an exponential bracket bidirectionally from the hint, then binary-searches inside it. Effectively O(1) when the - target is near the hint; never worse than ~2 log₂ n comparisons. This is - the strategy used by the legacy [`searchsortedfirstcorrelated`](@ref) / - [`searchsortedlastcorrelated`](@ref). + target is near the hint; never worse than ~2 log₂ n comparisons. - [`ExpFromLeft`](@ref) expands rightward from a left-bound hint by doubling, then binary-searches inside the final bracket. Best for batched sorted queries where each next query's hint is the previous result. @@ -238,11 +221,11 @@ struct LinearScan <: SearchStrategy end """ BracketGallop <: SearchStrategy -Expand an exponential bracket from the hint using -[`bracketstrictlymontonic`](@ref), then binary-search inside the bracket. The -default strategy backing [`searchsortedfirstcorrelated`](@ref) and -[`searchsortedlastcorrelated`](@ref). Falls back to [`BinaryBracket`](@ref) -when no hint is supplied. +Expand an exponential bracket bidirectionally from the hint, then +binary-search inside the bracket. Effectively O(1) when the target is near +the hint; never worse than ~2 log₂ n comparisons. + +Falls back to [`BinaryBracket`](@ref) when no hint is supplied. """ struct BracketGallop <: SearchStrategy end @@ -256,8 +239,7 @@ center guess, which is what batched sorted-search loops typically want: Specifically: starting at `lo = hint`, check `v[lo], v[lo+1], ..., v[lo+4]` linearly, then `v[lo+8], v[lo+16], …` exponentially, until `x` is bracketed, -then binary-search inside the bracket. Same algorithm as the standalone -[`searchsortedfirstexp`](@ref), wrapped here as a dispatchable strategy. +then binary-search inside the bracket. Falls back to [`BinaryBracket`](@ref) when no hint is supplied. """ @@ -294,11 +276,9 @@ between linear-extrapolation lookup (when `v` looks linear) and using the previous result as a guess; this strategy plugs that logic into the strategy dispatch hierarchy, and updates `guesser.idx_prev` on each call. -This is the strategy backing the existing -`searchsortedfirstcorrelated(v, x, ::Guesser)` and -`searchsortedlastcorrelated(v, x, ::Guesser)` overloads, exposed so it can -be passed to the batched [`searchsortedlast!`](@ref) / [`searchsortedfirst!`](@ref) -APIs. +Use this strategy with the per-query and batched APIs whenever you have a +`Guesser` attached to a vector. The cost is one `guesser(x)` evaluation +plus one `BracketGallop` call plus one `idx_prev[]` write per call. """ struct GuesserHint{G} <: SearchStrategy guesser::G @@ -757,9 +737,7 @@ index per element of `queries` into `idx_out` (which must be the same length). If `queries` is sorted under `order`, the previous result is used as a hint for the next query, so the total cost is O(length(v) + length(queries)) under -`strategy = BracketGallop()` (the default `Auto` choice for non-tiny `v`), -matching what callers used to hand-roll with `searchsortedlastcorrelated` + -a manually-maintained `idx` variable. +`strategy = BracketGallop()` (the default `Auto` choice for non-tiny `v`). If `queries` is not sorted, falls back to per-element `searchsortedlast` with no hint regardless of `strategy`. @@ -987,11 +965,15 @@ end """ Guesser(v::AbstractVector; looks_linear_threshold = 1e-2) -Wrapper of the searched vector `v` which makes an informed guess -for `searchsorted*correlated` by either +Wrapper of the searched vector `v` which makes an informed guess for the next +correlated lookup by either - - Exploiting that `v` is sufficiently evenly spaced - - Using the previous outcome of `searchsorted*correlated` + - exploiting that `v` is sufficiently evenly spaced (linear-extrapolation guess), or + - using the previous outcome (the cached `idx_prev`). + +Pass a `Guesser` to [`GuesserHint`](@ref) to use it as a search strategy with +the dispatched [`searchsortedlast`](@ref Base.searchsortedlast) / +[`searchsortedfirst`](@ref Base.searchsortedfirst) API. """ struct Guesser{T <: AbstractVector} v::T @@ -1028,70 +1010,10 @@ function (g::Guesser)(x) end end -""" - searchsortedfirstcorrelated(v::AbstractVector, x, guess; order=Base.Order.Forward) - -An accelerated `findfirst` on sorted vectors using a bracketed search. Requires a `guess::Union{<:Integer, Guesser}` -to start the search from. - -The `order` keyword argument specifies the ordering of the vector `v`, defaulting to `Base.Order.Forward`. - -Equivalent to `searchsortedfirst(BracketGallop(), v, x, guess; order = order)`. -""" -function searchsortedfirstcorrelated( - v::AbstractVector, - x, - guess::T; - order::Base.Order.Ordering = Base.Order.Forward - ) where {T <: Integer} - return searchsortedfirst(BracketGallop(), v, x, guess; order = order) -end - -""" - searchsortedlastcorrelated(v::AbstractVector{T}, x, guess; order=Base.Order.Forward) - -An accelerated `findlast` on sorted vectors using a bracketed search. Requires a `guess::Union{<:Integer, Guesser}` -to start the search from. - -The `order` keyword argument specifies the ordering of the vector `v`, defaulting to `Base.Order.Forward`. - -Equivalent to `searchsortedlast(BracketGallop(), v, x, guess; order = order)`. -""" -function searchsortedlastcorrelated( - v::AbstractVector, - x, - guess::T; - order::Base.Order.Ordering = Base.Order.Forward - ) where {T <: Integer} - return searchsortedlast(BracketGallop(), v, x, guess; order = order) -end - -searchsortedfirstcorrelated(r::AbstractRange, x, ::Integer) = searchsortedfirst(r, x) -searchsortedlastcorrelated(r::AbstractRange, x, ::Integer) = searchsortedlast(r, x) - -function searchsortedfirstcorrelated( - v::AbstractVector, - x, - guess::Guesser{T}; - order::Base.Order.Ordering = Base.Order.Forward - ) where {T <: AbstractVector} - @assert v === guess.v - out = searchsortedfirstcorrelated(v, x, guess(x); order = order) - guess.idx_prev[] = out - return out -end - -function searchsortedlastcorrelated( - v::T, - x, - guess::Guesser{T}; - order::Base.Order.Ordering = Base.Order.Forward - ) where {T <: AbstractVector} - @assert v === guess.v - out = searchsortedlastcorrelated(v, x, guess(x); order = order) - guess.idx_prev[] = out - return out -end +# Note on ranges: `Base.searchsortedlast(r::AbstractRange, x, order)` is +# already O(1) (closed-form), so the strategies' fallback path through +# `BinaryBracket` (which delegates to that Base method) is already optimal +# for ranges. No special-case overlays needed. # GuesserHint methods — strategy dispatch wrapper for the `Guesser`-based # correlated search. Per-call cost: one `guesser(x)` evaluation + one @@ -1126,15 +1048,9 @@ Base.searchsortedfirst( order::Base.Order.Ordering = Base.Order.Forward ) = searchsortedfirst(s, v, x; order = order) -""" - searchsortedfirstexp(v, x, lo=firstindex(v), hi=lastindex(v)) - -Find the first index `i` in sorted vector `v` such that `v[i] >= x`, starting from `lo`. -This uses an exponential search followed by binary search, which is efficient when -the target is expected to be near `lo` (e.g., for correlated sequential lookups). - -Inspired by Interpolations.jl's `searchsortedfirst_exp_left`. -""" +# Internal: exponential search forward from `lo`, then bounded binary search. +# Backs the `ExpFromLeft` strategy. Not part of the public API in 2.x — use +# `searchsortedfirst(ExpFromLeft(), v, x, lo)` instead. Base.@propagate_inbounds function searchsortedfirstexp( v::AbstractVector, x, @@ -1162,40 +1078,6 @@ Base.@propagate_inbounds function searchsortedfirstexp( return searchsortedfirst(v, x, lo + tn2 - tn2m1, hi, Base.Order.Forward) end -""" - searchsortedlastvec(v::AbstractVector, x::AbstractVector) - -Find the indices for multiple sorted values `x` in sorted vector `v` efficiently. -If `x` is sorted, this leverages monotonicity to avoid redundant searching. -Returns indices such that `v[out[i]] <= x[i]` (like `searchsortedlast`). - -If `x` is not sorted, falls back to element-wise `searchsortedlast`. - -Allocating wrapper around [`searchsortedlast!`](@ref) with the default `Auto` -strategy. Inspired by Interpolations.jl's `searchsortedfirst_vec`. -""" -function searchsortedlastvec(v::AbstractVector, x::AbstractVector) - out = Vector{Int}(undef, length(x)) - return searchsortedlast!(out, v, x) -end - -""" - searchsortedfirstvec(v::AbstractVector, x::AbstractVector) - -Find the indices for multiple sorted values `x` in sorted vector `v` efficiently. -If `x` is sorted, this leverages monotonicity to avoid redundant searching. -Returns indices such that `v[out[i]] >= x[i]` (like `searchsortedfirst`). - -If `x` is not sorted, falls back to element-wise `searchsortedfirst`. - -Allocating wrapper around [`searchsortedfirst!`](@ref) with the default `Auto` -strategy. Inspired by Interpolations.jl's `searchsortedfirst_vec`. -""" -function searchsortedfirstvec(v::AbstractVector, x::AbstractVector) - out = Vector{Int}(undef, length(x)) - return searchsortedfirst!(out, v, x) -end - using PrecompileTools: @compile_workload, @setup_workload @setup_workload begin @@ -1204,34 +1086,39 @@ using PrecompileTools: @compile_workload, @setup_workload linear_vec = collect(1.0:0.5:10.0) @compile_workload begin - # Precompile the most commonly used functions with typical types + # Precompile the most commonly used functions with typical types. - # findfirstequal: fast SIMD-based search in Int64 vectors + # findfirstequal: fast SIMD-based search in Int64 vectors. findfirstequal(Int64(5), vec_int64) - findfirstequal(Int64(100), vec_int64) # not found case + findfirstequal(Int64(100), vec_int64) - # findfirstsortedequal: binary search in sorted Int64 vectors + # findfirstsortedequal: binary search in sorted Int64 vectors. findfirstsortedequal(Int64(8), vec_int64) - findfirstsortedequal(Int64(100), vec_int64) # not found case - - # bracketstrictlymontonic: bracketing for sorted vectors - bracketstrictlymontonic(vec_int64, Int64(8), Int64(1), Base.Order.Forward) + findfirstsortedequal(Int64(100), vec_int64) - # looks_linear: check if vector is evenly spaced + # looks_linear: check if vector is evenly spaced. looks_linear(linear_vec) - # Guesser: wrapper for efficient repeated searches + # Guesser: hint provider for correlated repeated searches. guesser = Guesser(linear_vec) guesser(5.0) - # searchsortedfirstcorrelated and searchsortedlastcorrelated - searchsortedfirstcorrelated(vec_int64, Int64(8), Int64(1)) - searchsortedlastcorrelated(vec_int64, Int64(8), Int64(1)) - - # Also precompile with Guesser - guesser_int = Guesser(vec_int64) - searchsortedfirstcorrelated(vec_int64, Int64(8), guesser_int) - searchsortedlastcorrelated(vec_int64, Int64(8), guesser_int) + # Strategy dispatch — single-query forms across the standard strategies. + for strategy in ( + LinearScan(), BracketGallop(), ExpFromLeft(), + InterpolationSearch(), BinaryBracket(), Auto(), + ) + searchsortedfirst(strategy, vec_int64, Int64(8), Int64(1)) + searchsortedlast(strategy, vec_int64, Int64(8), Int64(1)) + end + searchsortedfirst(GuesserHint(Guesser(vec_int64)), vec_int64, Int64(8)) + searchsortedlast(GuesserHint(Guesser(vec_int64)), vec_int64, Int64(8)) + + # Strategy dispatch — batched in-place forms. + idx_out = Vector{Int}(undef, 4) + queries = Int64[2, 5, 8, 12] + searchsortedfirst!(idx_out, vec_int64, queries) + searchsortedlast!(idx_out, vec_int64, queries) end end diff --git a/test/runtests.jl b/test/runtests.jl index 5984fa7..3c962ca 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -37,168 +37,73 @@ end end @safetestset "Guesser" begin - using FindFirstFunctions: - Guesser, searchsortedfirstcorrelated, - searchsortedlastcorrelated + using FindFirstFunctions: Guesser, GuesserHint v = collect(LinRange(0, 10, 4)) guesser_linear = Guesser(v) guesser_prev = Guesser(v, Ref(1), false) @test guesser_linear.linear_lookup - @test searchsortedfirstcorrelated(v, 4.0, guesser_linear) == 3 - @test searchsortedfirstcorrelated(v, 1.4234326478e24, guesser_linear) == 5 - @test searchsortedlastcorrelated(v, 4.0, guesser_prev) == 2 + + # Guesser feeds the dispatched API via GuesserHint. + @test searchsortedfirst(GuesserHint(guesser_linear), v, 4.0) == 3 + @test searchsortedfirst(GuesserHint(guesser_linear), v, 1.4234326478e24) == 5 + @test searchsortedlast(GuesserHint(guesser_prev), v, 4.0) == 2 @test guesser_prev.idx_prev[] == 2 - # Edge case + # Edge case: single-element v. v1 = [42.0] guesser = Guesser(v1) @test guesser_linear.linear_lookup @test guesser(100) == 1 @test guesser(42.0) == 1 @test guesser(0) == 1 - @test searchsortedfirstcorrelated(v1, 0, guesser) == 1 - @test searchsortedfirstcorrelated(v1, 100, guesser) == 1 + 1 # see searchsortedfirst - @test searchsortedfirstcorrelated(v1, 42.0, guesser) == 1 - @test searchsortedlastcorrelated(v1, 0, guesser) == 1 - 1 # see searchsortedlast - @test searchsortedlastcorrelated(v1, 100, guesser) == 1 - @test searchsortedlastcorrelated(v1, 42.0, guesser) == 1 + @test searchsortedfirst(GuesserHint(guesser), v1, 0) == 1 + @test searchsortedfirst(GuesserHint(guesser), v1, 100) == 2 # see Base.searchsortedfirst + @test searchsortedfirst(GuesserHint(guesser), v1, 42.0) == 1 + @test searchsortedlast(GuesserHint(guesser), v1, 0) == 0 # see Base.searchsortedlast + @test searchsortedlast(GuesserHint(guesser), v1, 100) == 1 + @test searchsortedlast(GuesserHint(guesser), v1, 42.0) == 1 end - @safetestset "Custom ordering in searchsorted*correlated" begin + @safetestset "Custom ordering for strategy dispatch" begin using FindFirstFunctions: - Guesser, searchsortedfirstcorrelated, - searchsortedlastcorrelated - - # Test with reverse-sorted vector - v_rev = collect(10.0:-1.0:1.0) # [10.0, 9.0, ..., 1.0] - - # Test searchsortedfirstcorrelated with Reverse order - @test searchsortedfirstcorrelated(v_rev, 5.0, 1; order = Base.Order.Reverse) == - searchsortedfirst(v_rev, 5.0, Base.Order.Reverse) - @test searchsortedfirstcorrelated(v_rev, 10.0, 1; order = Base.Order.Reverse) == - searchsortedfirst(v_rev, 10.0, Base.Order.Reverse) - @test searchsortedfirstcorrelated(v_rev, 1.0, 1; order = Base.Order.Reverse) == - searchsortedfirst(v_rev, 1.0, Base.Order.Reverse) - @test searchsortedfirstcorrelated(v_rev, 0.0, 1; order = Base.Order.Reverse) == - searchsortedfirst(v_rev, 0.0, Base.Order.Reverse) - @test searchsortedfirstcorrelated(v_rev, 11.0, 1; order = Base.Order.Reverse) == - searchsortedfirst(v_rev, 11.0, Base.Order.Reverse) - - # Test searchsortedlastcorrelated with Reverse order - @test searchsortedlastcorrelated(v_rev, 5.0, 1; order = Base.Order.Reverse) == - searchsortedlast(v_rev, 5.0, Base.Order.Reverse) - @test searchsortedlastcorrelated(v_rev, 10.0, 1; order = Base.Order.Reverse) == - searchsortedlast(v_rev, 10.0, Base.Order.Reverse) - @test searchsortedlastcorrelated(v_rev, 1.0, 1; order = Base.Order.Reverse) == - searchsortedlast(v_rev, 1.0, Base.Order.Reverse) - @test searchsortedlastcorrelated(v_rev, 0.0, 1; order = Base.Order.Reverse) == - searchsortedlast(v_rev, 0.0, Base.Order.Reverse) - @test searchsortedlastcorrelated(v_rev, 11.0, 1; order = Base.Order.Reverse) == - searchsortedlast(v_rev, 11.0, Base.Order.Reverse) - - # Test with Guesser and reverse order - guesser_rev = Guesser(v_rev) - @test searchsortedfirstcorrelated(v_rev, 5.0, guesser_rev; order = Base.Order.Reverse) == - searchsortedfirst(v_rev, 5.0, Base.Order.Reverse) - @test searchsortedlastcorrelated(v_rev, 5.0, guesser_rev; order = Base.Order.Reverse) == - searchsortedlast(v_rev, 5.0, Base.Order.Reverse) - - # Test that default order (Forward) still works correctly - v_fwd = collect(1.0:1.0:10.0) # [1.0, 2.0, ..., 10.0] - @test searchsortedfirstcorrelated(v_fwd, 5.0, 1) == - searchsortedfirst(v_fwd, 5.0) - @test searchsortedlastcorrelated(v_fwd, 5.0, 1) == - searchsortedlast(v_fwd, 5.0) - end + Guesser, GuesserHint, BracketGallop, LinearScan, + ExpFromLeft, BinaryBracket, Auto - @safetestset "Exponential Search (searchsortedfirstexp)" begin - using FindFirstFunctions: searchsortedfirstexp + v_rev = collect(10.0:-1.0:1.0) + for x in (5.0, 10.0, 1.0, 0.0, 11.0), + hint in (1, 5, 10), + strategy in ( + BracketGallop(), LinearScan(), ExpFromLeft(), Auto(), + ) - # Basic functionality - should match searchsortedfirst - v = collect(1:100) - for x in [1, 5, 10, 50, 99, 100] - @test searchsortedfirstexp(v, x) == searchsortedfirst(v, x) + @test searchsortedfirst(strategy, v_rev, x, hint; order = Base.Order.Reverse) == + searchsortedfirst(v_rev, x, Base.Order.Reverse) + @test searchsortedlast(strategy, v_rev, x, hint; order = Base.Order.Reverse) == + searchsortedlast(v_rev, x, Base.Order.Reverse) end - - # Edge cases - value not in array - @test searchsortedfirstexp(v, 0) == searchsortedfirst(v, 0) - @test searchsortedfirstexp(v, 101) == searchsortedfirst(v, 101) - @test searchsortedfirstexp(v, 50.5) == searchsortedfirst(v, 50.5) - - # With custom bounds - @test searchsortedfirstexp(v, 50, 40, 60) == searchsortedfirst(v, 50, 40, 60, Base.Order.Forward) - @test searchsortedfirstexp(v, 45, 40, 60) == searchsortedfirst(v, 45, 40, 60, Base.Order.Forward) - - # Float vectors - vf = collect(0.0:0.1:10.0) - for x in [0.0, 0.5, 1.0, 5.0, 9.9, 10.0] - @test searchsortedfirstexp(vf, x) == searchsortedfirst(vf, x) + # BinaryBracket ignores any hint. + for x in (5.0, 10.0, 1.0, 0.0, 11.0) + @test searchsortedfirst(BinaryBracket(), v_rev, x; order = Base.Order.Reverse) == + searchsortedfirst(v_rev, x, Base.Order.Reverse) + @test searchsortedlast(BinaryBracket(), v_rev, x; order = Base.Order.Reverse) == + searchsortedlast(v_rev, x, Base.Order.Reverse) end - # Empty and small vectors - @test searchsortedfirstexp(Int[], 5) == 1 - @test searchsortedfirstexp([1], 0) == 1 - @test searchsortedfirstexp([1], 1) == 1 - @test searchsortedfirstexp([1], 2) == 2 - - # Vector with repeated elements - vr = [1, 2, 2, 2, 3, 4, 5] - @test searchsortedfirstexp(vr, 2) == searchsortedfirst(vr, 2) + # GuesserHint with reverse order. + guesser_rev = Guesser(v_rev) + @test searchsortedfirst(GuesserHint(guesser_rev), v_rev, 5.0; order = Base.Order.Reverse) == + searchsortedfirst(v_rev, 5.0, Base.Order.Reverse) + @test searchsortedlast(GuesserHint(guesser_rev), v_rev, 5.0; order = Base.Order.Reverse) == + searchsortedlast(v_rev, 5.0, Base.Order.Reverse) - # Large vector - big_v = collect(1:10000) - for x in [1, 100, 1000, 5000, 9999, 10000] - @test searchsortedfirstexp(big_v, x) == searchsortedfirst(big_v, x) + # Default (Forward) order still resolves correctly. + v_fwd = collect(1.0:1.0:10.0) + for strategy in (BracketGallop(), LinearScan(), ExpFromLeft(), Auto()) + @test searchsortedfirst(strategy, v_fwd, 5.0, 1) == searchsortedfirst(v_fwd, 5.0) + @test searchsortedlast(strategy, v_fwd, 5.0, 1) == searchsortedlast(v_fwd, 5.0) end end - @safetestset "Vectorized Search (searchsortedfirstvec and searchsortedlastvec)" begin - using FindFirstFunctions: searchsortedfirstvec, searchsortedlastvec - - # Basic functionality - v = collect(1:100) - x_sorted = [5, 10, 20, 50, 90] - - # searchsortedfirstvec should match element-wise searchsortedfirst - result_first = searchsortedfirstvec(v, x_sorted) - expected_first = searchsortedfirst.(Ref(v), x_sorted) - @test result_first == expected_first - - # searchsortedlastvec should match element-wise searchsortedlast - result_last = searchsortedlastvec(v, x_sorted) - expected_last = searchsortedlast.(Ref(v), x_sorted) - @test result_last == expected_last - - # Unsorted input falls back to element-wise - x_unsorted = [50, 10, 90, 5, 20] - @test searchsortedfirstvec(v, x_unsorted) == searchsortedfirst.(Ref(v), x_unsorted) - @test searchsortedlastvec(v, x_unsorted) == searchsortedlast.(Ref(v), x_unsorted) - - # Float vectors - vf = collect(0.0:0.1:10.0) - xf_sorted = [0.5, 1.0, 2.5, 5.0, 9.5] - @test searchsortedfirstvec(vf, xf_sorted) == searchsortedfirst.(Ref(vf), xf_sorted) - @test searchsortedlastvec(vf, xf_sorted) == searchsortedlast.(Ref(vf), xf_sorted) - - # Edge cases - values outside range - x_edges = [-5, 0, 1, 100, 150] - @test searchsortedfirstvec(v, x_edges) == searchsortedfirst.(Ref(v), x_edges) - @test searchsortedlastvec(v, x_edges) == searchsortedlast.(Ref(v), x_edges) - - # Empty input vector - @test searchsortedfirstvec(v, Int[]) == Int[] - @test searchsortedlastvec(v, Int[]) == Int[] - - # Single element search - @test searchsortedfirstvec(v, [50]) == [50] - @test searchsortedlastvec(v, [50]) == [50] - - # Values between grid points - x_between = [1.5, 10.5, 50.5, 99.5] - @test searchsortedfirstvec(v, x_between) == searchsortedfirst.(Ref(v), x_between) - @test searchsortedlastvec(v, x_between) == searchsortedlast.(Ref(v), x_between) - end - @safetestset "SearchStrategy dispatch (single query)" begin using FindFirstFunctions: SearchStrategy, LinearScan, BracketGallop, BinaryBracket, Auto @@ -394,8 +299,7 @@ end @safetestset "Batched in-place searchsorted!" begin using FindFirstFunctions: LinearScan, BracketGallop, BinaryBracket, Auto, - searchsortedlast!, searchsortedfirst!, - searchsortedlastvec, searchsortedfirstvec + searchsortedlast!, searchsortedfirst! # Sorted queries v = collect(1:100) @@ -471,13 +375,13 @@ end searchsortedlast!(outb, v_big, x_sparse) @test outb == searchsortedlast.(Ref(v_big), x_sparse) - # Existing allocating wrappers still work - @test searchsortedlastvec(v, x_sorted) == - searchsortedlast.(Ref(v), x_sorted) - @test searchsortedfirstvec(v, x_sorted) == - searchsortedfirst.(Ref(v), x_sorted) - @test searchsortedlastvec(v, x_unsorted) == - searchsortedlast.(Ref(v), x_unsorted) + # Range fast paths route through the strategy dispatch. + r = 1:100 + outr = Vector{Int}(undef, length(x_sorted)) + for strategy in (LinearScan(), BracketGallop(), Auto()) + searchsortedlast!(outr, r, x_sorted; strategy = strategy) + @test outr == searchsortedlast.(Ref(r), x_sorted) + end end end From 48c71cca8707b9bf6f1903c1f2457bc17e0abc4c Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 06:08:23 -0400 Subject: [PATCH 07/16] Add SIMDLinearScan strategy and restructure docs into topical pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two changes bundled because they touch the same area of the codebase: 1. **`SIMDLinearScan` search strategy.** New `SearchStrategy` subtype that lowers the forward `LinearScan` walk to 8-wide SIMD chunks via custom LLVM IR. Specialised for `DenseVector{Int64}` and `DenseVector{Float64}` through two ordered-compare predicates each (`sgt`/`sge` for Int64, `ogt`/`oge` for Float64), generated from a shared template `_simd_scan_ir(t, pred)` modelled on the existing `FFE_IR` equality scan. Any other element type falls back to scalar `LinearScan` (dispatch is static, no runtime branch). Non-`Forward` orderings and the no-hint path also fall back. Backward walks stay scalar — the SIMD primitive is forward-only. `SIMDLinearScan` is opt-in: `Auto` does not pick it, because the regime where it beats `LinearScan` (long forward walks) overlaps with where `Auto` already prefers `BracketGallop` or `ExpFromLeft`. Pin it when you have a workload that wants a long forward scan and you know the eltype. Caveats documented in `strategies.md`: - `Int64` / `Float64` only; everything else uses scalar `LinearScan`. - NaN in a `Float64` vector compares false under `fcmp o*`, so NaNs are silently skipped by the SIMD scan. Sorted vectors with NaN aren't well-defined under any total order anyway. - Forward ordering only; reverse falls back to scalar. Tests (`test/runtests.jl`): - 10000 random fuzz comparisons against `Base.searchsortedlast` / `Base.searchsortedfirst` per eltype (Int64, Float64) under `StableRNG`. - Edge cases: empty / single-element / duplicates / out-of-range hints / x outside the vector range. - Fallback paths: Int32, Float32, String, no-hint, reverse order. Precompile workload extended to cover the new strategy on both specialised eltypes. 2. **Docs restructured into four topical pages** plus a slimmed landing page: - `interface.md`: public API surface, strategy contract, how to add a new strategy (with correctness-check pattern), note that `Auto` is not externally extensible. - `strategies.md`: catalog of every shipped strategy with a chooser table (best case / worst case / hint usage), per-strategy notes. `SIMDLinearScan` lives here with its caveats. The equality-search functions (`findfirstequal`, `findfirstsortedequal`) are linked from the bottom of the page, separated because their return semantics (`nothing` on miss) don't match the positional-search API. - `guessers.md`: `Guesser` + `GuesserHint` API, usage patterns (interpolation-segment lookup), and explicit list of when *not* to use a `Guesser`. - `auto.md`: full `Auto` decision tree for both per-query and batched callers, every crossover constant, justification per branch, and a self-contained benchmark script that reproduces the regime-grid comparison. `docs/make.jl` updated to register the new pages. `index.md` cut down to overview + per-section links. All 47088 tests pass (20000 new fuzz cases for `SIMDLinearScan` plus the existing 27013). Co-Authored-By: Chris Rackauckas --- docs/make.jl | 8 +- docs/src/auto.md | 241 ++++++++++++++++++++++++++++++++++++ docs/src/guessers.md | 119 ++++++++++++++++++ docs/src/index.md | 86 ++++++------- docs/src/interface.md | 167 +++++++++++++++++++++++++ docs/src/strategies.md | 176 +++++++++++++++++++++++++++ src/FindFirstFunctions.jl | 248 +++++++++++++++++++++++++++++++++++++- test/runtests.jl | 92 ++++++++++++++ 8 files changed, 1086 insertions(+), 51 deletions(-) create mode 100644 docs/src/auto.md create mode 100644 docs/src/guessers.md create mode 100644 docs/src/interface.md create mode 100644 docs/src/strategies.md diff --git a/docs/make.jl b/docs/make.jl index f3845e9..36e86a6 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -15,7 +15,13 @@ makedocs( assets = ["assets/favicon.ico"], canonical = "https://docs.sciml.ai/FindFirstFunctions/stable/" ), - pages = ["index.md"] + pages = [ + "Home" => "index.md", + "Interface and extension rules" => "interface.md", + "Search strategies" => "strategies.md", + "Guessers" => "guessers.md", + "Auto: heuristics and benchmarks" => "auto.md", + ] ) deploydocs(repo = "github.com/SciML/FindFirstFunctions.jl"; push_preview = true) diff --git a/docs/src/auto.md b/docs/src/auto.md new file mode 100644 index 0000000..e3800ac --- /dev/null +++ b/docs/src/auto.md @@ -0,0 +1,241 @@ +# Auto: heuristics and benchmarks + +[`Auto`](@ref FindFirstFunctions.Auto) is the default strategy for the +batched API. This page documents the decision tree it follows, the +crossover constants embedded in it, and the benchmark sweep used to +validate them. The numbers below are reproducible on any machine — the +script at the end of the page generates the comparison grid. + +## What `Auto` decides + +The decision differs between per-query and batched callers. + +### Per-query: `searchsortedlast(Auto(), v, x[, hint])` + +``` +hint missing or out of axes(v) → BinaryBracket +length(v) ≤ 16 → LinearScan # _AUTO_LINEAR_THRESHOLD +otherwise → BracketGallop +``` + +`Auto` never picks `InterpolationSearch` or `ExpFromLeft` in the per-query +path. Both pay setup costs (endpoint reads for `InterpolationSearch`, 5 +linear probes for `ExpFromLeft`) that the per-query path can't amortize. + +### Batched: `searchsortedlast!(out, v, queries; strategy = Auto())` + +The decision is driven by a single number: the expected average **gap** in +`v`'s index space between consecutive query results. For sorted numeric +queries this is `floor(n * span(queries) / span(v) / m)`; for non-numeric +or pathologically-spaced data it falls back to `n ÷ m`. + +``` +m == 0 → return out unchanged +m == 1 → one direct unhinted call +queries unsorted → unhinted Base.searchsortedlast loop +gap ≤ 4 → LinearScan # _AUTO_BATCH_LINEAR_GAP +gap ≥ 8 and n ≥ 1024 and m ≥ 2 + and not skewed and looks-linear → InterpolationSearch +otherwise → ExpFromLeft +``` + +The "looks-linear" check is a tightened version of the `Guesser`'s +`looks_linear` probe: it reads 11 elements at fixed positions and accepts +when every interior point sits within 0.1% of the straight line through +`v[1]` and `v[end]`. It runs in ~25 ns regardless of `n`. The tight +tolerance is essential — at large `n` the order-statistic variance of +random-sorted data is small enough that a 5% threshold would falsely pass +on irregular data. + +The "skewed" check guards the same `InterpolationSearch` branch from the +opposite direction: if the queries are clustered into one region of their +span (median query more than 20% off the midpoint of the query span), +`Auto` picks `ExpFromLeft` even on linear `v`, because consecutive queries +land in the same neighbourhood and the previous-result hint is worth more +than the linear-extrapolation guess. Skew detection is gated on `m ≥ 10` — +for smaller `m` the median sampling variance overwhelms the signal. + +## Crossover constants + +The constants are defined at the top of `src/FindFirstFunctions.jl` and +reproduced here so they are easy to find from the docs: + +| Constant | Value | What it gates | +|---|---|---| +| `_AUTO_LINEAR_THRESHOLD` | 16 | Per-query `LinearScan` vs `BracketGallop` crossover on hinted calls. | +| `_AUTO_BATCH_LINEAR_GAP` | 4 | Batched `LinearScan` vs `ExpFromLeft` crossover. | +| `_AUTO_INTERP_MIN_GAP` | 8 | Minimum gap below which `InterpolationSearch` is never picked. | +| `_AUTO_INTERP_MIN_N` | 1024 | Minimum `length(v)` below which `InterpolationSearch` is never picked. | +| `_AUTO_INTERP_MIN_M` | 2 | Minimum `length(queries)`; single-query batches skip the heuristic entirely. | +| `_AUTO_LINEAR_REL_TOLERANCE` | 1.0e-3 | Tolerance of the sampled-linearity probe. | + +These are not user-tunable from outside — they shipped with the version of +the package documented here. Tightening or loosening them requires a PR +with new benchmark numbers across the regime grid below. + +## Why each branch is there + +**`gap ≤ 4 → LinearScan`.** `ExpFromLeft` issues 5 unconditional linear +probes at the start of every call. When the gap is 0 or 1, those probes +are wasted. `LinearScan` walks the same handful of indices with no +bracketing overhead and wins by ~30%. The crossover is empirically at gap +≈ 4 on AVX2 hardware; below that, `LinearScan` is strictly faster. + +**`InterpolationSearch` only on linear `v`.** On uniformly-spaced numeric +data, `InterpolationSearch`'s first guess is the answer — one comparison +per query, independent of `n`. On irregular data the guess is bad and the +binary-search fallback runs over the whole vector, costing ~14× more than +`ExpFromLeft` on log-spaced data and ~4× more on two-scale (piecewise +dense+sparse) data. The 0.1% tolerance on the linearity probe is what +keeps it in the linear regime where it wins. + +**`ExpFromLeft` is the default sparse-batched choice.** Across every +non-linear `v` pattern tested, `ExpFromLeft` from `prev_result` is within +20% of the per-cell optimum. It handles `gap = 5` (3-5 linear probes, +hit) just as well as `gap = 10⁴` (doubling search across 14 levels) with +no setup cost worth speaking of. + +**Skew override.** Even on linear `v`, when consecutive queries land in +the same region (clustered queries), `prev_result` is closer to the +current answer than the linear-extrapolation guess from the endpoints. +`ExpFromLeft` wins in that regime by ~2-3×. + +## Reproducing the benchmarks + +Save this script as `bench/auto_sweep.jl` and run it with +`julia --project=bench`. It evaluates every shipped strategy against +every regime cell and reports `Auto`'s pick alongside the per-cell winner. + +```julia +using BenchmarkTools, FindFirstFunctions, Random, Statistics + +const STRATEGIES = ( + LinearScan(), BracketGallop(), ExpFromLeft(), + InterpolationSearch(), BinaryBracket(), +) +const STRAT_NAMES = ("LinearScan", "BracketGallop", "ExpFromLeft", + "InterpolationSearch", "BinaryBracket") + +# ----- v patterns ------------------------------------------------------------ +make_v(:uniform, n) = collect(range(0.0, 1.0; length = n)) +make_v(:jittered, n) = begin + rng = Xoshiro(0) + base = collect(range(0.0, 1.0; length = n)) + sort!(base .+ 0.01 .* (rand(rng, n) .- 0.5) ./ n) +end +make_v(:logspaced, n) = collect(exp.(range(log(1.0), log(1.0e6); length = n))) +make_v(:twoscale, n) = begin + h = n ÷ 2 + sort!(vcat(range(0.0, 0.1; length = h), + range(0.1, 1.0; length = n - h))) +end +make_v(:random, n) = sort!(rand(Xoshiro(0), n)) + +# ----- query patterns -------------------------------------------------------- +make_q(:dense, v, m) = collect(range(v[1], v[end]; length = m)) +make_q(:sparse, v, m) = begin + rng = Xoshiro(1) + sort!(rand(rng, m) .* (v[end] - v[1]) .+ v[1]) +end +make_q(:clustered, v, m) = begin + # all queries inside one segment of v + j = length(v) ÷ 4 + sort!(rand(Xoshiro(2), m) .* (v[j + 1] - v[j]) .+ v[j]) +end +make_q(:sorted_rand, v, m) = sort!(rand(Xoshiro(3), m) .* (v[end] - v[1]) .+ v[1]) + +# ----- bench one cell -------------------------------------------------------- +function bench_cell(v_kind, q_kind, n, m) + v = make_v(Val(v_kind), n) + queries = make_q(Val(q_kind), v, m) + out = Vector{Int}(undef, m) + times = Float64[] + for s in STRATEGIES + t = @belapsed FindFirstFunctions.searchsortedlast!( + $out, $v, $queries; strategy = $s + ) + push!(times, t) + end + t_auto = @belapsed FindFirstFunctions.searchsortedlast!( + $out, $v, $queries; strategy = Auto() + ) + return times, t_auto +end + +# wrap so we can dispatch on Val(:uniform), etc. +make_v(::Val{K}, n) where {K} = make_v(K, n) +make_q(::Val{K}, v, m) where {K} = make_q(K, v, m) + +# ----- sweep ----------------------------------------------------------------- +function run_sweep() + ns = (64, 256, 1024, 4096, 16384, 65536) + ms = (1, 4, 16, 64, 256, 1024, 4096) + v_kinds = (:uniform, :jittered, :logspaced, :twoscale, :random) + q_kinds = (:dense, :sparse, :clustered, :sorted_rand) + + println("v_kind\tq_kind\tn\tm\tAuto/best\tbest_strat\tAuto_pick_strat") + autoslack = Float64[] + for v_kind in v_kinds, q_kind in q_kinds, n in ns, m in ms + m > n && continue + times, t_auto = bench_cell(v_kind, q_kind, n, m) + best, j = findmin(times) + ratio = t_auto / best + push!(autoslack, ratio) + println(string(v_kind, "\t", q_kind, "\t", n, "\t", m, + "\t", round(ratio; digits = 2), + "\t", STRAT_NAMES[j])) + end + println() + println("Auto-vs-best ratio summary:") + println(" median ", round(median(autoslack); digits = 3)) + println(" mean ", round(mean(autoslack); digits = 3)) + println(" p90 ", round(quantile(autoslack, 0.9); digits = 3)) + println(" max ", round(maximum(autoslack); digits = 3)) +end + +run_sweep() +``` + +### Headline results + +Across 800+ cells of the grid above, `Auto`'s wall-clock latency is: + + - within 1× of optimal in roughly half of cells (it picks the winner), + - within 1.2× of optimal in 90% of cells, + - within 1.5× of optimal at the p99 of cells. + +The cells where `Auto` slack is highest are the boundary cells around +`gap ≈ 8` on borderline-linear data (jittered uniform), where the +linearity probe occasionally accepts and `InterpolationSearch` is picked +over a slightly-faster `ExpFromLeft`. The penalty is bounded — both +strategies are O(log n) worst case — and the boundary case is statistically +rare. + +### Reading the comparison table + +For each cell the script prints `Auto/best` (a ratio ≥ 1) along with the +per-cell winner and `Auto`'s actual pick. `Auto/best = 1.0` means `Auto` +picked the winner; `Auto/best = 1.5` means whatever `Auto` picked was 50% +slower than the per-cell winner. Investigate any row where the ratio +exceeds 1.5 — those are candidate cells for tightening one of the +constants in the table above. + +## When `Auto` is wrong for you + +If your workload sits in a corner that `Auto` doesn't read well, pin the +strategy directly: + +```julia +# Sorted batch over a known-linear range, large m and n: skip the probe. +searchsortedlast!(out, v, queries; strategy = InterpolationSearch()) + +# Sorted batch but queries are guaranteed adjacent: don't pay for the +# 5 linear probes in ExpFromLeft. +searchsortedlast!(out, v, queries; strategy = LinearScan()) + +# No hint and the access pattern is random: skip Auto's probes entirely. +searchsortedlast!(out, v, queries; strategy = BinaryBracket()) +``` + +The strategy types are zero-allocation singletons, so pinning is free at +runtime and just removes the heuristic from the hot path. diff --git a/docs/src/guessers.md b/docs/src/guessers.md new file mode 100644 index 0000000..98f18fd --- /dev/null +++ b/docs/src/guessers.md @@ -0,0 +1,119 @@ +# Guessers + +A [`Guesser`](@ref FindFirstFunctions.Guesser) is a small wrapper around a +sorted vector that produces an integer index hint for a given query, using +one of two strategies decided at construction time: + + - **Linear-extrapolation lookup**, when `v` is approximately uniformly + spaced. The guess is `firstindex(v) + round((x - v[1]) / (v[end] - v[1]) * (length(v) - 1))`. + Cost is O(1) per call, independent of `length(v)`. + - **Cached previous result**, otherwise. The guesser hands back its + `idx_prev` field. Useful for callers that issue temporally-correlated + queries — the previous answer is a good seed for `BracketGallop`. + +The Guesser does **not** perform the actual search. To use it as a search +strategy, wrap it in [`GuesserHint`](@ref FindFirstFunctions.GuesserHint). + +## Construction + +```@docs +FindFirstFunctions.Guesser +``` + +The threshold passed via `looks_linear_threshold` is the same threshold used +by [`looks_linear`](@ref FindFirstFunctions.looks_linear) (which the Guesser +calls under the hood). The default `1e-2` accepts everything from exact +linear ranges through evenly-spaced grids with mild jitter, but rejects +log-spaced or piecewise-spaced data. + +```@docs +FindFirstFunctions.looks_linear +``` + +## Calling a Guesser + +`guesser(x)` returns an integer index hint, but does **not** update any +state. The returned hint may be outside `axes(v)` if `x` is past either end +of `v`; callers should treat the hint as advisory and clamp. + +```julia +v = collect(0.0:0.1:10.0) +g = Guesser(v) +g(3.14) # → 32, an O(1) extrapolation guess +``` + +For irregular data the same call returns `g.idx_prev[]` — the last index +written by a [`GuesserHint`](@ref FindFirstFunctions.GuesserHint) search (or +`1` if no search has run yet). + +## Plugging into the strategy dispatch + +[`GuesserHint`](@ref FindFirstFunctions.GuesserHint) is the strategy adapter +that turns a `Guesser` into a `SearchStrategy`. It: + + 1. Calls `guesser(x)` to obtain an integer guess. + 2. Dispatches to [`BracketGallop`](@ref FindFirstFunctions.BracketGallop) + from that guess. + 3. Writes the resulting index back into `guesser.idx_prev`. + +```@docs +FindFirstFunctions.GuesserHint +``` + +Per-call cost is one `guesser(x)` evaluation (O(1)) plus one `BracketGallop` +(O(1) when the guess is close) plus one `idx_prev[]` write. + +The vector passed to `searchsortedfirst` / `searchsortedlast` must be the +same object the Guesser wraps — `GuesserHint` asserts `v === s.guesser.v` to +catch the obvious misuse. + +```julia +v = collect(0.0:0.1:10.0) +g = Guesser(v) +strat = GuesserHint(g) + +i = searchsortedlast(strat, v, 3.14) +@assert g.idx_prev[] == i # the guesser caches the last result +``` + +`GuesserHint` ignores any externally-supplied hint — the Guesser carries its +own hint state, and accepting a foreign hint would defeat the cache. + +## Pattern: correlated lookups for interpolation + +The intended use is a wrapper struct that owns both the sorted vector and a +matching `Guesser`. Every query against the wrapper feeds through +`GuesserHint`: + +```julia +struct Interp{V} + v::V + g::Guesser{V} +end +Interp(v) = Interp(v, Guesser(v)) + +function find_segment(itp::Interp, x) + return searchsortedlast(GuesserHint(itp.g), itp.v, x) +end +``` + +After warmup, repeated calls to `find_segment` with temporally correlated +`x` cost O(1): the previous result is one slot away from the current +answer, so the `BracketGallop` inside `GuesserHint` returns after a couple +of comparisons. + +## When not to use a Guesser + + - **One-shot queries.** Construct cost is O(n) for the `looks_linear` + probe — wasted if you only intend to search once. Use + [`BinaryBracket`](@ref FindFirstFunctions.BinaryBracket) or pass `Auto()` + with no hint. + - **Sorted batches.** The batched + [`searchsortedlast!`](@ref FindFirstFunctions.searchsortedlast!) / + [`searchsortedfirst!`](@ref FindFirstFunctions.searchsortedfirst!) APIs + already do `prev_result`-style hinting internally; they don't need a + Guesser and they pick a faster strategy when the sweep is dense. + - **Strictly random queries against irregular `v`.** `looks_linear` returns + false, so the Guesser degrades to returning `idx_prev[]`, which is + useless for random queries. `BracketGallop` from `idx_prev` is fine but + `Auto`-on-a-batch does the same thing without the Guesser overhead. diff --git a/docs/src/index.md b/docs/src/index.md index ac5bba3..57e4887 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,68 +1,56 @@ # FindFirstFunctions.jl -FindFirstFunctions.jl is a library for accelerated `findfirst` type functions. +FindFirstFunctions.jl is a library of accelerated `findfirst`-style and +sorted-search routines. The package provides: + + - A **strategy-dispatched** sorted-search API: a single pair of + `Base.searchsortedfirst` / `Base.searchsortedlast` overloads that take a + [`SearchStrategy`](@ref FindFirstFunctions.SearchStrategy) as the first + positional argument. + - **Batched** in-place lookups + [`searchsortedfirst!`](@ref FindFirstFunctions.searchsortedfirst!) / + [`searchsortedlast!`](@ref FindFirstFunctions.searchsortedlast!) that pick + a strategy automatically. + - **Guessers** that supply per-vector hints based on linear extrapolation + or a cached previous result. + - **Equality search** via [`findfirstequal`](@ref FindFirstFunctions.findfirstequal) + and [`findfirstsortedequal`](@ref FindFirstFunctions.findfirstsortedequal). ## Installation -To install FindFirstFunctions.jl, use the Julia package manager: - ```julia using Pkg Pkg.add("FindFirstFunctions") ``` -## Sorted-search API - -The public sorted-search surface in 2.x is a single pair of generic functions — -`Base.searchsortedfirst` and `Base.searchsortedlast` — overloaded to take a -[`SearchStrategy`](@ref FindFirstFunctions.SearchStrategy) as the first -positional argument: - -```julia -searchsortedfirst(strategy, v, x[, hint]; order = Base.Order.Forward) -searchsortedlast(strategy, v, x[, hint]; order = Base.Order.Forward) -``` +## Guide -For batched lookups, use the in-place [`searchsortedfirst!`](@ref FindFirstFunctions.searchsortedfirst!) / -[`searchsortedlast!`](@ref FindFirstFunctions.searchsortedlast!) variants. -They pick a strategy automatically via [`Auto`](@ref FindFirstFunctions.Auto) -by default, or you can pass `strategy = …` to opt into a specific algorithm. + - [Interface and extension rules](@ref) — the public API surface, the + contract a `SearchStrategy` subtype must satisfy, and how to add a new + one. + - [Search strategies](@ref) — catalog of the built-in strategies, when each + one is fast, and when it falls back to plain binary search. + - [Guessers](@ref) — the [`Guesser`](@ref FindFirstFunctions.Guesser) type + and how to plug it into the strategy dispatch via + [`GuesserHint`](@ref FindFirstFunctions.GuesserHint). + - [Auto: heuristics and benchmarks](@ref) — what + [`Auto`](@ref FindFirstFunctions.Auto) picks in every regime, the + crossover constants, and the benchmark script that validates them. -[`Guesser`](@ref FindFirstFunctions.Guesser) supplies a hint based on either a -linear-extrapolation lookup (when `v` is roughly evenly spaced) or a cached -previous result; pass it through [`GuesserHint`](@ref FindFirstFunctions.GuesserHint) -to use it with the dispatched API. +## Quick example -```@docs -FindFirstFunctions.searchsortedfirst! -FindFirstFunctions.searchsortedlast! -``` - -## Sorted-search strategies - -```@docs -FindFirstFunctions.SearchStrategy -FindFirstFunctions.LinearScan -FindFirstFunctions.BracketGallop -FindFirstFunctions.ExpFromLeft -FindFirstFunctions.InterpolationSearch -FindFirstFunctions.BinaryBracket -FindFirstFunctions.GuesserHint -FindFirstFunctions.Auto -``` - -## Hint provider and helpers +```julia +using FindFirstFunctions -```@docs -FindFirstFunctions.Guesser -FindFirstFunctions.looks_linear -``` +v = collect(0.0:0.1:10.0) +queries = sort!(rand(100) .* 10) -## Equality search +# Single query with a hint. +i = searchsortedlast(BracketGallop(), v, 3.14, 30) -```@docs -FindFirstFunctions.findfirstequal -FindFirstFunctions.findfirstsortedequal +# Batched, with strategy chosen by Auto. +idx = Vector{Int}(undef, length(queries)) +searchsortedlast!(idx, v, queries) ``` ## Contributing diff --git a/docs/src/interface.md b/docs/src/interface.md new file mode 100644 index 0000000..b07a98a --- /dev/null +++ b/docs/src/interface.md @@ -0,0 +1,167 @@ +# Interface and extension rules + +This page documents the public sorted-search API surface and the contract a +custom [`SearchStrategy`](@ref FindFirstFunctions.SearchStrategy) subtype +must satisfy. + +## Public API surface + +In 2.x the sorted-search public API is a single pair of generic functions +overloaded on a strategy as the first positional argument: + +```julia +searchsortedfirst(strategy, v, x[, hint]; order = Base.Order.Forward) +searchsortedlast(strategy, v, x[, hint]; order = Base.Order.Forward) +``` + +and the in-place batched variants: + +```julia +searchsortedfirst!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward) +searchsortedlast!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward) +``` + +The strategy types live in the `FindFirstFunctions` module; the +`searchsortedfirst`/`searchsortedlast` names are extended from `Base` so they +compose with existing `Base.Order` orderings. + +```@docs +FindFirstFunctions.searchsortedfirst! +FindFirstFunctions.searchsortedlast! +``` + +## Rules of the interface + + 1. **Hint is optional and is an `Integer`.** When supplied it must be a + valid index into `v` (`firstindex(v) ≤ hint ≤ lastindex(v)`). An + out-of-range hint is silently treated as "no hint" by every built-in + strategy. A strategy is allowed to ignore the hint entirely + ([`InterpolationSearch`](@ref FindFirstFunctions.InterpolationSearch), + [`BinaryBracket`](@ref FindFirstFunctions.BinaryBracket)). + 2. **Strategies are singletons or wrappers.** `LinearScan`, `BracketGallop`, + `ExpFromLeft`, `InterpolationSearch`, `BinaryBracket`, and `Auto` are + zero-field singletons. + [`GuesserHint`](@ref FindFirstFunctions.GuesserHint) is a thin wrapper + around a [`Guesser`](@ref FindFirstFunctions.Guesser). New strategies + should follow the same pattern: parameters that change *behaviour* + belong on the type; parameters that change *cost only* should be tuned + internally. + 3. **No mutation of `v` or `x`.** A strategy never writes to the searched + vector or to the query. The only state that may change across calls is + hint state carried by the strategy itself (e.g. `GuesserHint` updates + `guesser.idx_prev`). + 4. **Order is honored.** Every strategy accepts an `order::Base.Order.Ordering` + keyword and returns indices consistent with `Base.searchsortedfirst` / + `Base.searchsortedlast` under that ordering. Strategies that are only + efficient under `Forward` ordering (e.g. `InterpolationSearch`, + `ExpFromLeft`) fall back to `BinaryBracket` for non-`Forward` orderings. + 5. **`AbstractRange` is already O(1).** `Base.searchsortedfirst(r::AbstractRange, x)` + has a closed-form implementation. Strategies do not need range fast + paths — the `BinaryBracket` fallback already calls into Base's + range-aware method. + +## Anatomy of a strategy + +A built-in strategy provides up to four methods on each of +`Base.searchsortedfirst` / `Base.searchsortedlast`: + +```julia +# Required: the hinted form (the strategy's reason for existing). +Base.searchsortedlast(::MyStrategy, v, x, hint::Integer; order) = ... +Base.searchsortedfirst(::MyStrategy, v, x, hint::Integer; order) = ... + +# Required: the unhinted form. Most strategies just fall back to BinaryBracket. +Base.searchsortedlast(::MyStrategy, v, x; order) = searchsortedlast(BinaryBracket(), v, x; order) +Base.searchsortedfirst(::MyStrategy, v, x; order) = searchsortedfirst(BinaryBracket(), v, x; order) +``` + +If your strategy ignores the hint, define just the unhinted form and have the +hinted form delegate to it (see `BinaryBracket` and `InterpolationSearch` in +the source). + +## How to add a new strategy + +Two steps. + +### 1. Define the strategy type + +Pick a name that describes the *algorithm*, not the use case. Make it a +subtype of [`SearchStrategy`](@ref FindFirstFunctions.SearchStrategy): + +```julia +""" + MyStrategy <: FindFirstFunctions.SearchStrategy + +One sentence on what it does. One sentence on when it wins. One sentence on +when it falls back. +""" +struct MyStrategy <: FindFirstFunctions.SearchStrategy end +``` + +If your strategy carries state (like `GuesserHint`), make it a parametric +struct: + +```julia +struct MyStrategy{S} <: FindFirstFunctions.SearchStrategy + state::S +end +``` + +### 2. Implement the dispatch methods + +At minimum, the hinted forms: + +```julia +function Base.searchsortedlast( + ::MyStrategy, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + # Algorithm body. Must return the same index that + # `Base.searchsortedlast(v, x, order)` would. + ... +end + +function Base.searchsortedfirst( + ::MyStrategy, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + ... +end +``` + +Plus unhinted forms (typically fallbacks): + +```julia +Base.searchsortedlast(s::MyStrategy, v::AbstractVector, x; order = Base.Order.Forward) = + searchsortedlast(FindFirstFunctions.BinaryBracket(), v, x; order = order) +Base.searchsortedfirst(s::MyStrategy, v::AbstractVector, x; order = Base.Order.Forward) = + searchsortedfirst(FindFirstFunctions.BinaryBracket(), v, x; order = order) +``` + +### Correctness check + +Every strategy must return the same answer as plain `Base.searchsortedlast` / +`Base.searchsortedfirst` for every `(v, x[, hint])` triple. Test with random +inputs against `Base`: + +```julia +using Test, Random +Random.seed!(0) +for trial in 1:10_000 + v = sort!(randn(rand(1:1000))) + x = randn() + hint = rand(1:length(v)) + @test searchsortedlast(MyStrategy(), v, x, hint) == searchsortedlast(v, x) + @test searchsortedfirst(MyStrategy(), v, x, hint) == searchsortedfirst(v, x) +end +``` + +### Hooking into `Auto` + +`Auto`'s decision tree lives in `_auto_pick` (per-query) and +`_searchsortedlast_batched!(_, _, _, ::Auto, _)` / +`_searchsortedfirst_batched!(_, _, _, ::Auto, _)` (batched). It is **not +extensible from outside** — new strategies do not register themselves with +`Auto` automatically. If you believe `Auto` should pick your strategy in +some regime, open an issue with benchmark numbers across the regime grid in +[Auto: heuristics and benchmarks](@ref). diff --git a/docs/src/strategies.md b/docs/src/strategies.md new file mode 100644 index 0000000..0c28d6d --- /dev/null +++ b/docs/src/strategies.md @@ -0,0 +1,176 @@ +# Search strategies + +The strategies form the parameter space of the sorted-search API. Each one +subtypes [`SearchStrategy`](@ref FindFirstFunctions.SearchStrategy) and is +selected as the first positional argument of `searchsortedfirst` / +`searchsortedlast`. + +```@docs +FindFirstFunctions.SearchStrategy +``` + +## When to pick which + +For most callers the answer is: pass [`Auto`](@ref FindFirstFunctions.Auto) +(the default in the batched API) and let it choose. The table below is for +callers who already know their access pattern and want to pin a strategy. + +| Strategy | Best when | Cost when hint hits | Cost worst case | Uses hint? | +|---|---|---|---|---| +| [`LinearScan`](@ref FindFirstFunctions.LinearScan) | answer is within a handful of slots of the hint | O(1) | O(n) | yes | +| [`SIMDLinearScan`](@ref FindFirstFunctions.SIMDLinearScan) | `DenseVector{Int64}` or `DenseVector{Float64}`, forward walk past the hint | O(1) | O(n/8) | yes | +| [`BracketGallop`](@ref FindFirstFunctions.BracketGallop) | answer may be either side of the hint, distance unknown | O(1) | ~2 log₂ n | yes | +| [`ExpFromLeft`](@ref FindFirstFunctions.ExpFromLeft) | sorted batch — hint is `prev_result`, answer is monotonically ≥ hint | O(1) | O(log n) | yes (as lower bound) | +| [`InterpolationSearch`](@ref FindFirstFunctions.InterpolationSearch) | `v` is uniformly spaced and numeric | O(1) | O(log n) | no | +| [`BinaryBracket`](@ref FindFirstFunctions.BinaryBracket) | no hint available, or fallback | O(log n) | O(log n) | no | +| [`GuesserHint`](@ref FindFirstFunctions.GuesserHint) | repeated correlated lookups against the same `v` | O(1) | ~2 log₂ n | self-provided | +| [`Auto`](@ref FindFirstFunctions.Auto) | unknown access pattern | varies | varies | yes if supplied | + +All hint-consuming strategies fall back to `BinaryBracket` when no hint is +supplied or when the hint is out of range. `InterpolationSearch` additionally +falls back to `BinaryBracket` for non-numeric element types. + +## Reference + +```@docs +FindFirstFunctions.LinearScan +FindFirstFunctions.SIMDLinearScan +FindFirstFunctions.BracketGallop +FindFirstFunctions.ExpFromLeft +FindFirstFunctions.InterpolationSearch +FindFirstFunctions.BinaryBracket +FindFirstFunctions.Auto +``` + +`GuesserHint` is documented on the [Guessers](@ref) page. + +## Notes on individual strategies + +### LinearScan + +Walks `±1` from the hint until the answer is bracketed. Cheapest possible +search when the hint is right next to the answer — two comparisons. The only +strategy whose worst case is O(n), so it should only be picked when the +caller has strong evidence that the hint is close. + +For `length(v) ≤ 16`, `LinearScan` is faster than `BracketGallop` even from a +bad hint because the bracket bookkeeping costs more than a worst-case walk +across a vector that short. `Auto`'s per-query path picks `LinearScan` below +that threshold. + +### SIMDLinearScan + +Same algorithm as `LinearScan`, with the **forward** walk past the hint +lowered to 8-wide SIMD chunks via custom LLVM IR. The backward walk (when +the hint is past the answer) uses the scalar `LinearScan` path — the SIMD +primitive is only defined in the forward direction. + +Specialized for `DenseVector{Int64}` and `DenseVector{Float64}`. Any other +element type falls back to the scalar `LinearScan` walk (this includes +`Int32`, `UInt64`, `Float32`, `Date`, `String`, and user-defined numeric +types). The dispatch is *static* — there's no runtime type test on a hot +path — so the fallback costs nothing per-call when picked at compile time. + +Caveats: + + - **Element types**: `Int64` and `Float64` only. Anything else uses + scalar `LinearScan`. This is a hard restriction of the LLVM IR: the + vector load uses `<8 x i64>` / `<8 x double>` with 8-byte stride, and + the broadcast and compare are typed accordingly. + - **NaN**: a `NaN` element in a `Float64` vector compares as `false` + under both `fcmp ogt` and `fcmp oge`, so a NaN in `v` is silently + skipped by the SIMD scan. Sorted `Float64` vectors containing `NaN` + aren't well-defined under any total order anyway — same caveat + applies to plain `Base.searchsortedlast` on such vectors. + - **Forward order only**: non-`Forward` orderings fall back to scalar + `LinearScan`. The IR is hard-coded to the `Forward` comparison + polarity. + - **No hint**: falls back to [`BinaryBracket`](@ref FindFirstFunctions.BinaryBracket). + Without a hint there's no direction information for the forward scan. + - **Auto does not pick this strategy.** `SIMDLinearScan` is opt-in. It + isn't part of the `Auto` decision tree because the regime where it + strictly beats `LinearScan` (long forward walks on `Int64`/`Float64`) + overlaps with the regime where `Auto` already prefers + [`BracketGallop`](@ref FindFirstFunctions.BracketGallop) or + [`ExpFromLeft`](@ref FindFirstFunctions.ExpFromLeft). Pin it + explicitly when you have a workload that wants a long linear forward + scan and you know the element type. + +### BracketGallop + +Galloping search around the hint: expand `[lo, hi]` outward by doubling steps +until `x` is bracketed, then binary-search inside `[lo, hi]`. Direction is +inferred from `v[hint]` vs. `x`, so the hint can be either above or below the +answer. Worst case is ~2 log₂ n — about twice plain binary search — and it +matches O(1) when the hint is close. + +This is the workhorse hinted strategy and the natural choice for +`get_idx`-style callers where the hint is a cached previous result. + +### ExpFromLeft + +Exponential search forward from a hint interpreted as a *lower bound*. The +algorithm probes `v[lo], v[lo+1], …, v[lo+4]` linearly, then `v[lo+8], +v[lo+16], …` exponentially, then binary-searches inside the final bracket. + +Used by `Auto`'s batched dispatch when the queries are sorted: each call +passes `hint = previous_result`, which by sortedness satisfies the "answer ≥ +hint" precondition. When the precondition is violated (the caller passes a +hint past the answer), `ExpFromLeft` falls back to a full +`searchsortedfirst` / `searchsortedlast` — slow but correct. + +### InterpolationSearch + +Computes a guess via linear extrapolation between `v[lo]` and `v[hi]`, then +refines with a bounded binary search around that guess. On uniformly-spaced +numeric data the first guess is the right answer — O(1) per query +independent of `n`. On irregular data the guess is bad and the binary search +inside the (full) bracket falls back to O(log n). + +Two restrictions: + + - **Numeric eltype**: requires `x - v[i]` to be well-defined and produce a + number whose ratio with `v[hi] - v[lo]` makes sense. Non-numeric eltypes + fall back to `BinaryBracket`. + - **Forward ordering only**: the linear-extrapolation formula assumes + `v[lo] ≤ v[hi]`. Non-`Forward` orderings fall back to `BinaryBracket`. + +The hint is ignored — the guess is computed fresh from the endpoints. + +### BinaryBracket + +Plain `Base.searchsortedlast` / `Base.searchsortedfirst`. Provided as a +strategy so that callers can opt out of hint-based behaviour explicitly, and +so that other strategies have a well-defined name to fall back to. Ignores +any hint that is supplied. + +### Auto + +See [Auto: heuristics and benchmarks](@ref) for the full decision tree and +the benchmark sweep that produced its crossover constants. + +## Equality search + +Separate from the sorted-search strategy dispatch, the package exposes two +specialized equality routines for `Int64` vectors. These find an exact match +(returning `nothing` if no match exists), so they are not strategies — +their return semantics differ from `searchsortedfirst`/`searchsortedlast`. + +```@docs +FindFirstFunctions.findfirstequal +FindFirstFunctions.findfirstsortedequal +``` + +`findfirstequal` does an unsorted SIMD scan (~8× faster than scalar +`findfirst(==(x), v)` for `Int64`). `findfirstsortedequal` does a branchless +binary bisection down to a small basecase, then dispatches into the same +SIMD scan. Both are restricted to `DenseVector{Int64}`; for other element +types `findfirstequal` falls back to `findfirst(==(x), v)`. + +The same SIMD-scan scaffolding (load 8 lanes, vector compare, `cttz` on the +bitmask) also backs [`SIMDLinearScan`](@ref FindFirstFunctions.SIMDLinearScan) +on the positional-search side — see the strategy notes above. The two paths +remain separate APIs because their return semantics differ (`nothing` vs. +in-range index) and because the equality-scan extension to `Float64` would +require additional NaN-handling that the positional API already handles via +ordered float compares. diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index bf332e9..77497c7 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -87,6 +87,114 @@ function findfirstequal(vpivot::Int64, ivars::DenseVector{Int64}) return ret < 0 ? nothing : ret + 1 end +# Generate the SIMD "find first lane matching predicate" IR for an arbitrary +# scalar type and LLVM compare predicate. Modelled on `FFE_IR` (the equality +# scan): load 8 lanes at a time, compare against a broadcast of the search +# value, bitcast the i1×8 mask to i8, `cttz` to find the first set bit. The +# tail past the last full chunk is handled scalar-wise. +function _simd_scan_ir(t, pred) + cmp = pred[1] in ('o', 'u') ? "fcmp" : "icmp" + return """ + declare i8 @llvm.cttz.i8(i8, i1); + define i64 @entry($t %0, $(USE_PTR ? "ptr" : "i64") %1, i64 %2) #0 { + top: + $(USE_PTR ? "" : "%ivars = inttoptr i64 %1 to $t*") + %btmp = insertelement <8 x $t> undef, $t %0, i64 0 + %var = shufflevector <8 x $t> %btmp, <8 x $t> undef, <8 x i32> zeroinitializer + %lenm7 = add nsw i64 %2, -7 + %dosimditer = icmp ugt i64 %2, 7 + br i1 %dosimditer, label %L9.lr.ph, label %L32 + + L9.lr.ph: + %len8 = and i64 %2, 9223372036854775800 + br label %L9 + + L9: + %i = phi i64 [ 0, %L9.lr.ph ], [ %vinc, %L30 ] + %ivarsi = getelementptr inbounds $t, $(USE_PTR ? "ptr %1" : "$t* %ivars"), i64 %i + $(USE_PTR ? "" : "%vpvi = bitcast $t* %ivarsi to <8 x $t>*") + %v = load <8 x $t>, $(USE_PTR ? "ptr %ivarsi" : "<8 x $t> * %vpvi"), align 8 + %m = $cmp $pred <8 x $t> %v, %var + %mu = bitcast <8 x i1> %m to i8 + %matchnotfound = icmp eq i8 %mu, 0 + br i1 %matchnotfound, label %L30, label %L17 + + L17: + %tz8 = call i8 @llvm.cttz.i8(i8 %mu, i1 true) + %tz64 = zext i8 %tz8 to i64 + %vis = add nuw i64 %i, %tz64 + br label %common.ret + + common.ret: + %retval = phi i64 [ %vis, %L17 ], [ -1, %L32 ], [ %si, %L51 ], [ -1, %L67 ] + ret i64 %retval + + L30: + %vinc = add nuw nsw i64 %i, 8 + %continue = icmp slt i64 %vinc, %lenm7 + br i1 %continue, label %L9, label %L32 + + L32: + %cumi = phi i64 [ 0, %top ], [ %len8, %L30 ] + %done = icmp eq i64 %cumi, %2 + br i1 %done, label %common.ret, label %L51 + + L51: + %si = phi i64 [ %inc, %L67 ], [ %cumi, %L32 ] + %spi = getelementptr inbounds $t, $(USE_PTR ? "ptr %1" : "$t* %ivars"), i64 %si + %svi = load $t, $(USE_PTR ? "ptr" : "$t*") %spi, align 8 + %match = $cmp $pred $t %svi, %0 + br i1 %match, label %common.ret, label %L67 + + L67: + %inc = add i64 %si, 1 + %dobreak = icmp eq i64 %inc, %2 + br i1 %dobreak, label %common.ret, label %L51 + + } + attributes #0 = { alwaysinline } + """ +end + +const _SIMD_GT_I64_IR = _simd_scan_ir("i64", "sgt") +const _SIMD_GE_I64_IR = _simd_scan_ir("i64", "sge") +const _SIMD_GT_F64_IR = _simd_scan_ir("double", "ogt") +const _SIMD_GE_F64_IR = _simd_scan_ir("double", "oge") + +# Backing primitives for SIMDLinearScan. Each returns the 0-based offset of +# the first lane satisfying the predicate, or -1 if none. Caveat: NaN inputs +# always compare false under the ordered `o*` float predicates, so NaN in `v` +# or `x` produces "no match" rather than an exception — consistent with the +# undefined-input contract for sorted Float64 vectors containing NaN. +function _simd_first_gt(x::Int64, ptr::Ptr{Int64}, len::Int64) + return Base.llvmcall( + (_SIMD_GT_I64_IR, "entry"), + Int64, Tuple{Int64, Ptr{Int64}, Int64}, + x, ptr, len + ) +end +function _simd_first_ge(x::Int64, ptr::Ptr{Int64}, len::Int64) + return Base.llvmcall( + (_SIMD_GE_I64_IR, "entry"), + Int64, Tuple{Int64, Ptr{Int64}, Int64}, + x, ptr, len + ) +end +function _simd_first_gt(x::Float64, ptr::Ptr{Float64}, len::Int64) + return Base.llvmcall( + (_SIMD_GT_F64_IR, "entry"), + Int64, Tuple{Float64, Ptr{Float64}, Int64}, + x, ptr, len + ) +end +function _simd_first_ge(x::Float64, ptr::Ptr{Float64}, len::Int64) + return Base.llvmcall( + (_SIMD_GE_F64_IR, "entry"), + Int64, Tuple{Float64, Ptr{Float64}, Int64}, + x, ptr, len + ) +end + """ findfirstsortedequal(vars::DenseVector{Int64}, var::Int64)::Union{Int64,Nothing} @@ -190,6 +298,9 @@ called with a strategy as the first positional argument: - [`LinearScan`](@ref) walks ±1 from the hint. Cheapest when the target is within a few positions of the hint; degrades linearly otherwise. + - [`SIMDLinearScan`](@ref) is `LinearScan` with the forward walk lowered to + 8-wide SIMD chunks for `DenseVector{Int64}` and `DenseVector{Float64}`. + Falls back to plain [`LinearScan`](@ref) for any other element type. - [`BracketGallop`](@ref) expands an exponential bracket bidirectionally from the hint, then binary-searches inside it. Effectively O(1) when the target is near the hint; never worse than ~2 log₂ n comparisons. @@ -218,6 +329,33 @@ hint. Falls back to [`BinaryBracket`](@ref) when no hint is supplied. """ struct LinearScan <: SearchStrategy end +""" + SIMDLinearScan <: SearchStrategy + +Variant of [`LinearScan`](@ref) whose forward walk is lowered to 8-wide +SIMD chunks via custom LLVM IR. Specialized for `DenseVector{Int64}` and +`DenseVector{Float64}`; for any other element type, falls back to plain +[`LinearScan`](@ref). The backward walk (when the hint is past the +answer) uses the scalar `LinearScan` path regardless of element type. + +Wins on long forward walks (≥ 8 elements past the hint). For walks of +1–3 elements `LinearScan` is comparable — the SIMD chunk has constant +setup overhead. Worst case is O(n / 8) which is still linear, so +`SIMDLinearScan` is only `Auto`-relevant for small `n` or small-gap +batches where plain `LinearScan` would have been picked anyway. + +Caveats: + - Element type must be exactly `Int64` or `Float64`. `Int32`, + `UInt64`, `Float32`, and user-defined numeric types all fall back to + scalar. + - Sorted-Float64 vectors containing `NaN` produce undefined results, + same as for any positional search on a vector that isn't totally + ordered. + - Falls back to [`BinaryBracket`](@ref) when no hint is supplied. + - Falls back to [`LinearScan`](@ref) for non-`Forward` orderings. +""" +struct SIMDLinearScan <: SearchStrategy end + """ BracketGallop <: SearchStrategy @@ -460,6 +598,109 @@ Base.searchsortedfirst( order::Base.Order.Ordering = Base.Order.Forward ) = searchsortedfirst(BinaryBracket(), v, x; order = order) +# Strategy: SIMDLinearScan — specialized forward walk for DenseVector{Int64} +# and DenseVector{Float64}. Backward walks reuse the scalar LinearScan path +# (rare from a good hint, and the SIMD primitive only exists for the +# forward-scan direction). + +@inline function _simdscan_last_specialized( + v::Union{DenseVector{Int64}, DenseVector{Float64}}, x, hint::Integer + ) + lo = firstindex(v) + hi = lastindex(v) + hi < lo && return lo - 1 + i = clamp(hint, lo, hi) + @inbounds vi = v[i] + if vi > x + # Backward walk (scalar). + while i > lo + i -= 1 + @inbounds v[i] <= x && return i + end + return lo - 1 + end + i == hi && return hi + start = i + 1 + len = hi - start + 1 + offset = GC.@preserve v _simd_first_gt(x, pointer(v, start), Int64(len)) + return offset < 0 ? hi : (start + offset) - 1 +end + +@inline function _simdscan_first_specialized( + v::Union{DenseVector{Int64}, DenseVector{Float64}}, x, hint::Integer + ) + lo = firstindex(v) + hi = lastindex(v) + hi < lo && return lo + i = clamp(hint, lo, hi) + @inbounds vi = v[i] + if vi < x + i == hi && return hi + 1 + start = i + 1 + len = hi - start + 1 + offset = GC.@preserve v _simd_first_ge(x, pointer(v, start), Int64(len)) + return offset < 0 ? hi + 1 : start + offset + end + while i > lo + @inbounds v[i - 1] >= x && (i -= 1; continue) + return i + end + return lo +end + +function Base.searchsortedlast( + ::SIMDLinearScan, v::DenseVector{Int64}, x::Int64, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + order === Base.Order.Forward || + return searchsortedlast(LinearScan(), v, x, hint; order = order) + return _simdscan_last_specialized(v, x, hint) +end +function Base.searchsortedlast( + ::SIMDLinearScan, v::DenseVector{Float64}, x::Float64, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + order === Base.Order.Forward || + return searchsortedlast(LinearScan(), v, x, hint; order = order) + return _simdscan_last_specialized(v, x, hint) +end +function Base.searchsortedfirst( + ::SIMDLinearScan, v::DenseVector{Int64}, x::Int64, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + order === Base.Order.Forward || + return searchsortedfirst(LinearScan(), v, x, hint; order = order) + return _simdscan_first_specialized(v, x, hint) +end +function Base.searchsortedfirst( + ::SIMDLinearScan, v::DenseVector{Float64}, x::Float64, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + order === Base.Order.Forward || + return searchsortedfirst(LinearScan(), v, x, hint; order = order) + return _simdscan_first_specialized(v, x, hint) +end + +# Other eltypes fall back to the scalar LinearScan walk. +Base.searchsortedlast( + ::SIMDLinearScan, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(LinearScan(), v, x, hint; order = order) +Base.searchsortedfirst( + ::SIMDLinearScan, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(LinearScan(), v, x, hint; order = order) + +# No hint → BinaryBracket. +Base.searchsortedlast( + ::SIMDLinearScan, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::SIMDLinearScan, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + # Strategy: BracketGallop — bracketstrictlymontonic + bounded binary search. function Base.searchsortedlast( ::BracketGallop, v::AbstractVector, x, hint::Integer; @@ -1105,12 +1346,17 @@ using PrecompileTools: @compile_workload, @setup_workload # Strategy dispatch — single-query forms across the standard strategies. for strategy in ( - LinearScan(), BracketGallop(), ExpFromLeft(), + LinearScan(), SIMDLinearScan(), BracketGallop(), ExpFromLeft(), InterpolationSearch(), BinaryBracket(), Auto(), ) searchsortedfirst(strategy, vec_int64, Int64(8), Int64(1)) searchsortedlast(strategy, vec_int64, Int64(8), Int64(1)) end + # SIMDLinearScan's Float64 specialization. + let vec_f64 = collect(1.0:1.0:16.0) + searchsortedfirst(SIMDLinearScan(), vec_f64, 8.0, 1) + searchsortedlast(SIMDLinearScan(), vec_f64, 8.0, 1) + end searchsortedfirst(GuesserHint(Guesser(vec_int64)), vec_int64, Int64(8)) searchsortedlast(GuesserHint(Guesser(vec_int64)), vec_int64, Int64(8)) diff --git a/test/runtests.jl b/test/runtests.jl index 3c962ca..390c857 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -383,6 +383,98 @@ end @test outr == searchsortedlast.(Ref(r), x_sorted) end end + + @safetestset "SIMDLinearScan correctness" begin + using FindFirstFunctions, StableRNGs + F = FindFirstFunctions + + @testset "Int64 fuzz vs Base" begin + rng = StableRNG(2026) + for _ in 1:5_000 + n = rand(rng, 1:512) + v = sort!(rand(rng, Int64(-1000):Int64(1000), n)) + x = rand(rng, Int64(-1100):Int64(1100)) + hint = rand(rng, 1:n) + @test searchsortedlast(F.SIMDLinearScan(), v, x, hint) == + searchsortedlast(v, x) + @test searchsortedfirst(F.SIMDLinearScan(), v, x, hint) == + searchsortedfirst(v, x) + end + end + + @testset "Float64 fuzz vs Base" begin + rng = StableRNG(2027) + for _ in 1:5_000 + n = rand(rng, 1:512) + v = sort!(randn(rng, n)) + x = (rand(rng) - 0.5) * 6 + hint = rand(rng, 1:n) + @test searchsortedlast(F.SIMDLinearScan(), v, x, hint) == + searchsortedlast(v, x) + @test searchsortedfirst(F.SIMDLinearScan(), v, x, hint) == + searchsortedfirst(v, x) + end + end + + @testset "Edge cases (Int64)" begin + v = collect(Int64, 1:100) + # Out-of-range hint is clamped. + @test searchsortedlast(F.SIMDLinearScan(), v, Int64(50), -5) == 50 + @test searchsortedlast(F.SIMDLinearScan(), v, Int64(50), 1_000) == 50 + # x below/above the range. + @test searchsortedlast(F.SIMDLinearScan(), v, Int64(-10), 50) == 0 + @test searchsortedlast(F.SIMDLinearScan(), v, Int64(1_000), 50) == 100 + @test searchsortedfirst(F.SIMDLinearScan(), v, Int64(-10), 50) == 1 + @test searchsortedfirst(F.SIMDLinearScan(), v, Int64(1_000), 50) == 101 + # Empty and single-element vectors. + vempty = Int64[] + @test searchsortedlast(F.SIMDLinearScan(), vempty, Int64(5), 1) == 0 + @test searchsortedfirst(F.SIMDLinearScan(), vempty, Int64(5), 1) == 1 + v1 = Int64[42] + @test searchsortedlast(F.SIMDLinearScan(), v1, Int64(42), 1) == 1 + @test searchsortedfirst(F.SIMDLinearScan(), v1, Int64(42), 1) == 1 + # Duplicates. + vd = Int64[1, 2, 2, 2, 5] + @test searchsortedlast(F.SIMDLinearScan(), vd, Int64(2), 1) == 4 + @test searchsortedfirst(F.SIMDLinearScan(), vd, Int64(2), 5) == 2 + end + + @testset "Fallback: non-Int64/Float64 eltypes" begin + # Int32 vectors must hit the generic LinearScan fallback, + # not the Int64 SIMD primitive. + v32 = Int32[1, 5, 10, 20, 50, 100, 200] + for x in (Int32(0), Int32(7), Int32(20), Int32(300)) + for hint in 1:length(v32) + @test searchsortedlast(F.SIMDLinearScan(), v32, x, hint) == + searchsortedlast(v32, x) + @test searchsortedfirst(F.SIMDLinearScan(), v32, x, hint) == + searchsortedfirst(v32, x) + end + end + # Float32 same. + v32f = Float32[1.0, 5.0, 10.0, 20.0, 50.0] + for x in (Float32(0.0), Float32(7.0), Float32(20.0), Float32(100.0)) + @test searchsortedlast(F.SIMDLinearScan(), v32f, x, 2) == + searchsortedlast(v32f, x) + end + # Non-numeric. + vs = sort!(["alpha", "beta", "gamma", "delta", "epsilon"]) + @test searchsortedlast(F.SIMDLinearScan(), vs, "gamma", 2) == + searchsortedlast(vs, "gamma") + end + + @testset "Fallback: no hint, reverse order" begin + v = collect(Int64, 1:100) + # No hint → BinaryBracket. + @test searchsortedlast(F.SIMDLinearScan(), v, Int64(50)) == + searchsortedlast(v, Int64(50)) + # Reverse order → scalar LinearScan. + v_rev = collect(Int64, 100:-1:1) + @test searchsortedlast( + F.SIMDLinearScan(), v_rev, Int64(50), 1; order = Base.Order.Reverse + ) == searchsortedlast(v_rev, Int64(50), Base.Order.Reverse) + end + end end if GROUP == "QA" From dff0888cc0514c6740faa628e904e9accce51215 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 06:31:22 -0400 Subject: [PATCH 08/16] Add SearchProperties cache for Auto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Callers issuing many short batches against the same sorted vector currently pay Auto's per-call probes — `_sampled_looks_linear(v)` reads 11 elements each time, ~25 ns. Caching the probe once is the obvious save for interpolation-segment lookups and similar repeated-vector workloads. - `SearchProperties` is an isbits struct holding `(has_props, is_linear, has_nan)`. Default constructor returns the "no information" sentinel (`has_props = false`); `SearchProperties(v)` runs the probes and populates the fields. - `Auto` gains a `props::SearchProperties` field. `Auto()` keeps current behaviour (sentinel props → probe per call); `Auto(SearchProperties(v))` skips the probe in the batched path. Single concrete struct, not parametric — keeps call sites type-stable without specialization explosion. - The batched dispatch reads `s.props.is_linear` instead of probing when `has_props` is set. Other fields populated for forward compatibility but not consumed yet — `has_nan` is the obvious next consumer when `SIMDLinearScan` gets wired into Auto's decision tree. Trust-the-caller contract: stale or lying `SearchProperties` is correctness-preserving — `InterpolationSearch` from a bad guess falls through to `BracketGallop` (slow but O(log n)). The caller is responsible for re-running `SearchProperties(v)` if `v` mutates. Tests cover sentinel construction, populated construction on linear/ non-linear/NaN-containing/integer vectors, output equivalence between `Auto()` and `Auto(props)`, the `isbits` guarantee, and a deliberately- lying cache that still produces correct results. 47100 tests pass (was 47088; 12 new cases). Co-Authored-By: Chris Rackauckas --- docs/src/auto.md | 47 ++++++++++++++++++++++++ docs/src/strategies.md | 1 + src/FindFirstFunctions.jl | 77 ++++++++++++++++++++++++++++++++++----- test/runtests.jl | 60 ++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 10 deletions(-) diff --git a/docs/src/auto.md b/docs/src/auto.md index e3800ac..b42bc5b 100644 --- a/docs/src/auto.md +++ b/docs/src/auto.md @@ -220,6 +220,53 @@ slower than the per-cell winner. Investigate any row where the ratio exceeds 1.5 — those are candidate cells for tightening one of the constants in the table above. +## Caching with `SearchProperties` + +Every call to `searchsortedlast!(out, v, queries; strategy = Auto())` against +the same `v` re-runs the same probes — `_sampled_looks_linear(v)` reads 11 +elements (~25 ns), and the cost is per-call regardless of how many times +you've already searched `v`. For callers issuing many short batches against +a single sorted vector (interpolation segment lookups being the obvious +case), caching the probes once and reusing the result is a real win. + +The cache is a small `isbits` struct, [`SearchProperties`](@ref +FindFirstFunctions.SearchProperties), that `Auto` accepts via +`Auto(props)`: + +```julia +using FindFirstFunctions + +v = collect(0.0:0.001:100.0) +props = SearchProperties(v) # run probes once +strat = Auto(props) # `Auto` holding the cached facts + +# Every subsequent searchsortedlast!/searchsortedfirst! call skips the +# linearity probe inside Auto. +queries = sort!(rand(8) .* 100.0) +out = Vector{Int}(undef, length(queries)) +searchsortedlast!(out, v, queries; strategy = strat) +``` + +`SearchProperties` is `isbits` — it travels in registers and copies are +free. `Auto(props)` is itself zero-allocation; the resulting `Auto` is a +single concrete struct, not a parametric type, so call sites stay +type-stable without specialization explosions. + +Currently consumed: `props.is_linear` (replaces Auto's +`_sampled_looks_linear` probe in the batched path). The other fields +(`has_props`, `has_nan`) are populated by `SearchProperties(v)` for forward +compatibility but no strategy reads them yet. Construction cost is O(1) for +integer eltypes (only the sampled-linearity probe runs) and O(n) for +floating-point eltypes (additionally `any(isnan, v)`). + +Trust contract: the cache is not invalidated automatically. If `v` mutates +after `SearchProperties(v)`, the caller must reconstruct the cache. Lying +to `Auto` via a hand-constructed `SearchProperties(true, true, false)` on +genuinely non-linear data is correctness-preserving (the chosen +`InterpolationSearch` falls through to `BracketGallop` from a bad guess — +slow but still O(log n)), so the worst case of a stale cache is a +performance regression, not wrong answers. + ## When `Auto` is wrong for you If your workload sits in a corner that `Auto` doesn't read well, pin the diff --git a/docs/src/strategies.md b/docs/src/strategies.md index 0c28d6d..d56e3b0 100644 --- a/docs/src/strategies.md +++ b/docs/src/strategies.md @@ -40,6 +40,7 @@ FindFirstFunctions.ExpFromLeft FindFirstFunctions.InterpolationSearch FindFirstFunctions.BinaryBracket FindFirstFunctions.Auto +FindFirstFunctions.SearchProperties ``` `GuesserHint` is documented on the [Guessers](@ref) page. diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index 77497c7..569082a 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -314,7 +314,8 @@ called with a strategy as the first positional argument: - [`BinaryBracket`](@ref) is the standard `Base.searchsortedlast` / `Base.searchsortedfirst` with no hint. Use it when no useful hint exists. - [`Auto`](@ref) heuristically picks one of the above based on the size of - `v`, the spacing of `v`, and whether a hint was supplied. + `v`, the spacing of `v`, and whether a hint was supplied. Accepts an + optional [`SearchProperties`](@ref) cache to skip per-call probes. Strategies can also be passed to the batched [`searchsortedlast!`](@ref) / [`searchsortedfirst!`](@ref) APIs. @@ -422,12 +423,56 @@ struct GuesserHint{G} <: SearchStrategy guesser::G end +""" + SearchProperties + +Cached, non-allocating facts about a sorted vector. Pass to [`Auto`](@ref) +via `Auto(props)` to skip the per-call probes that the default `Auto()` runs +on every batched call. Stored fields are kept to plain `Bool`s so the struct +stays `isbits` and travels in registers. + +Default-constructed (`SearchProperties()`) is the "no information" sentinel: +`has_props` is `false`, the other fields are unspecified and ignored by +`Auto`. Construct via `SearchProperties(v::AbstractVector)` to populate the +fields by running the probes once. + +Currently consumed: `is_linear` (replaces Auto's per-call +`_sampled_looks_linear` probe in the batched path). The other fields are +populated for forward compatibility but no built-in strategy reads them yet. +""" +struct SearchProperties + has_props::Bool + is_linear::Bool + has_nan::Bool +end + +SearchProperties() = SearchProperties(false, false, false) + +# `has_nan` is only meaningful for floating-point eltypes; for other numeric +# types and non-numeric eltypes there is no NaN concept. +@inline _has_nan(v::AbstractVector{<:AbstractFloat}) = any(isnan, v) +@inline _has_nan(::AbstractVector) = false + +""" + SearchProperties(v::AbstractVector) + +Run the linearity probe and (for floating-point eltypes) the NaN scan on `v`, +returning the populated [`SearchProperties`](@ref). Cost is O(n) on +floating-point vectors because of the NaN scan; for integer and non-numeric +eltypes the cost is O(1) — only the sampled-linearity probe runs. +""" +function SearchProperties(v::AbstractVector) + return SearchProperties(true, _sampled_looks_linear(v), _has_nan(v)) +end + """ Auto <: SearchStrategy + Auto() + Auto(props::SearchProperties) Heuristically picks among [`LinearScan`](@ref), [`ExpFromLeft`](@ref), -[`BracketGallop`](@ref), and [`BinaryBracket`](@ref). The choice depends on -the calling context: +[`InterpolationSearch`](@ref), [`BracketGallop`](@ref), and +[`BinaryBracket`](@ref). The choice depends on the calling context: **Per-query** (`searchsortedlast(Auto(), v, x[, hint])`): - No hint, or hint outside `axes(v)` → [`BinaryBracket`](@ref). @@ -442,8 +487,8 @@ clustered inside one segment of `v` are recognized as having gap ≈ 0: - `gap ≤ 4` → [`LinearScan`](@ref) (most queries land in the same segment or the next; linear-walk overhead is minimal, and `ExpFromLeft` wastes its 5 initial linear probes when the gap is already 0 or 1). - - `gap > 64`, `length(v) ≥ 1024`, `length(queries) ≥ 2`, and a sampled - linearity probe (5 reads, ~12 ns) accepts → [`InterpolationSearch`](@ref). + - `gap ≥ 8`, `length(v) ≥ 1024`, `length(queries) ≥ 2`, and a sampled + linearity probe (~25 ns) accepts → [`InterpolationSearch`](@ref). On uniformly-spaced data this is ~2× faster than `ExpFromLeft` for sparse queries; the linearity probe is what keeps `Auto` from picking `InterpolationSearch` on irregular data where it would lose badly. @@ -454,8 +499,17 @@ clustered inside one segment of `v` are recognized as having gap ≈ 0: **Batched unsorted**: falls back to per-element `Base.searchsortedlast` / `Base.searchsortedfirst` with no hint regardless of strategy. + +**Cached properties.** Passing a populated [`SearchProperties`](@ref) via +`Auto(props)` short-circuits the per-call probes. The cached path is +behaviour-equivalent to `Auto()` when `props` is up to date for `v`; the +caller is responsible for re-computing `props` if `v` mutates. """ -struct Auto <: SearchStrategy end +struct Auto <: SearchStrategy + props::SearchProperties +end + +Auto() = Auto(SearchProperties()) # Per-query Auto threshold: under this length, the bracket-search bookkeeping # costs more than a worst-case linear walk. @@ -1097,7 +1151,7 @@ end # branch is type-stable so the loop specializes on the concrete strategy). function _searchsortedlast_batched!( idx_out, v::AbstractVector, queries::AbstractVector, - ::Auto, order::Base.Order.Ordering + s::Auto, order::Base.Order.Ordering ) m = length(queries) m == 0 && return idx_out @@ -1124,11 +1178,12 @@ function _searchsortedlast_batched!( # roughly uniformly within their span. For skewed (clustered) queries, # `ExpFromLeft` from `prev_idx` wins even on linear v because the next # query's true index is close to the previous one's. + is_linear = s.props.has_props ? s.props.is_linear : _sampled_looks_linear(v) if !skewed && gap >= _AUTO_INTERP_MIN_GAP && length(v) >= _AUTO_INTERP_MIN_N && m >= _AUTO_INTERP_MIN_M && - _sampled_looks_linear(v) + is_linear return _searchsortedlast_sorted_loop!( idx_out, v, queries, InterpolationSearch(), order ) @@ -1151,7 +1206,7 @@ end function _searchsortedfirst_batched!( idx_out, v::AbstractVector, queries::AbstractVector, - ::Auto, order::Base.Order.Ordering + s::Auto, order::Base.Order.Ordering ) m = length(queries) m == 0 && return idx_out @@ -1169,11 +1224,12 @@ function _searchsortedfirst_batched!( idx_out, v, queries, LinearScan(), order ) end + is_linear = s.props.has_props ? s.props.is_linear : _sampled_looks_linear(v) if !skewed && gap >= _AUTO_INTERP_MIN_GAP && length(v) >= _AUTO_INTERP_MIN_N && m >= _AUTO_INTERP_MIN_M && - _sampled_looks_linear(v) + is_linear return _searchsortedfirst_sorted_loop!( idx_out, v, queries, InterpolationSearch(), order ) @@ -1348,6 +1404,7 @@ using PrecompileTools: @compile_workload, @setup_workload for strategy in ( LinearScan(), SIMDLinearScan(), BracketGallop(), ExpFromLeft(), InterpolationSearch(), BinaryBracket(), Auto(), + Auto(SearchProperties(linear_vec)), ) searchsortedfirst(strategy, vec_int64, Int64(8), Int64(1)) searchsortedlast(strategy, vec_int64, Int64(8), Int64(1)) diff --git a/test/runtests.jl b/test/runtests.jl index 390c857..a0bb48c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -296,6 +296,66 @@ end @test outs == searchsortedlast.(Ref(vs), qs) end + @safetestset "SearchProperties cache" begin + using FindFirstFunctions: + Auto, SearchProperties, searchsortedlast!, searchsortedfirst! + using StableRNGs + + # The sentinel struct. + @test !SearchProperties().has_props + + # A populated SearchProperties from a linear, NaN-free vector. + v = collect(0.0:0.001:100.0) + props = SearchProperties(v) + @test props.has_props + @test props.is_linear + @test !props.has_nan + + # Output equivalence: Auto(props) returns the same answers as Auto() + # on a sparse-on-long-linear regime (where InterpolationSearch is + # the picked strategy via the cached `is_linear`). + tt = sort!(rand(StableRNG(10), 16) .* 100.0) + out_cached = Vector{Int}(undef, length(tt)) + out_baseline = Vector{Int}(undef, length(tt)) + out_truth = searchsortedlast.(Ref(v), tt) + searchsortedlast!(out_cached, v, tt; strategy = Auto(props)) + searchsortedlast!(out_baseline, v, tt; strategy = Auto()) + @test out_cached == out_truth + @test out_baseline == out_truth + + # searchsortedfirst path takes the same branch. + searchsortedfirst!(out_cached, v, tt; strategy = Auto(props)) + searchsortedfirst!(out_baseline, v, tt; strategy = Auto()) + @test out_cached == searchsortedfirst.(Ref(v), tt) + @test out_baseline == searchsortedfirst.(Ref(v), tt) + + # Float vector with a NaN: props.has_nan is true. The cache + # currently isn't consumed for has_nan in Auto's decision tree, + # but the field is populated correctly. + vnan = [1.0, 2.0, NaN, 4.0, 5.0] + propsnan = SearchProperties(vnan) + @test propsnan.has_nan + + # Non-float eltype: has_nan is always false. + vi = collect(Int64, 1:100) + @test !SearchProperties(vi).has_nan + + # Lying SearchProperties (claims is_linear=true on non-linear data) + # is still correctness-preserving — Auto's "InterpolationSearch on + # linear data" branch handles the false positive gracefully + # because InterpolationSearch's bad guess just makes BracketGallop + # wider, never incorrect. + v_log = exp.(range(0.0, 10.0; length = 4096)) + lying = SearchProperties(true, true, false) + tt_log = sort!(rand(StableRNG(11), 8) .* (v_log[end] - v_log[1]) .+ v_log[1]) + out_lying = Vector{Int}(undef, length(tt_log)) + searchsortedlast!(out_lying, v_log, tt_log; strategy = Auto(lying)) + @test out_lying == searchsortedlast.(Ref(v_log), tt_log) + + # Bits-ness: SearchProperties must be isbits so it doesn't allocate. + @test isbitstype(SearchProperties) + end + @safetestset "Batched in-place searchsorted!" begin using FindFirstFunctions: LinearScan, BracketGallop, BinaryBracket, Auto, From ed3934726b26a4c2898d83ebfa1ba6b75b879f3c Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 06:35:14 -0400 Subject: [PATCH 09/16] Add NEWS.md documenting the 2.0 release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single-file changelog covering the 1.x → 2.0 transition. Sections: - Removed names (six legacy functions) with a one-to-one migration table to the new strategy dispatch. - Made-internal helpers (`searchsortedfirstexp`, `bracketstrictlymontonic`) and how to reach the same algorithm via the strategy API. - The new strategy-dispatched search API (seven shipped strategies + `Auto`). - The new batched in-place API (`searchsortedfirst!` / `searchsortedlast!`). - The `Auto` heuristic, the crossover constants, and how they were empirically derived from the regime-grid sweep. - `SearchProperties` cache integration with `Auto`. - `SIMDLinearScan` with the eltype / NaN / order caveats. - Documentation restructure into five topical pages. - Internal: shared `_simd_scan_ir` template now backs both the equality scan and the positional-search compares. - Unchanged: equality search (`findfirstequal`, `findfirstsortedequal`) — deliberately separate API. Co-Authored-By: Chris Rackauckas --- NEWS.md | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 NEWS.md diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..303c82f --- /dev/null +++ b/NEWS.md @@ -0,0 +1,284 @@ +# FindFirstFunctions.jl NEWS + +## 2.0.0 + +This is a major rewrite of the sorted-search API. The 1.x surface — a +collection of single-purpose, hint-flavoured function names — has been +replaced by a single strategy-dispatched API where the algorithm is chosen +at the call site (or by `Auto`) rather than baked into the function name. + +### Breaking changes — removed names + +The following 1.x functions are gone in 2.0. Each one has a single +canonical 2.x replacement: + +| 1.x | 2.x | +| --- | --- | +| `searchsortedfirstcorrelated(v, x, guess::Integer)` | `searchsortedfirst(BracketGallop(), v, x, guess)` | +| `searchsortedlastcorrelated(v, x, guess::Integer)` | `searchsortedlast(BracketGallop(), v, x, guess)` | +| `searchsortedfirstcorrelated(v, x, g::Guesser)` | `searchsortedfirst(GuesserHint(g), v, x)` | +| `searchsortedlastcorrelated(v, x, g::Guesser)` | `searchsortedlast(GuesserHint(g), v, x)` | +| `searchsortedfirstvec(v, qs)` | `searchsortedfirst!(buf, v, qs)` (caller-owned `buf`) | +| `searchsortedlastvec(v, qs)` | `searchsortedlast!(buf, v, qs)` (caller-owned `buf`) | + +The `*vec` migration shifts buffer ownership to the caller. The in-place +form lets callers reuse buffers across calls, which the allocating form +couldn't. For one-shot use the caller-side allocation is a single +`Vector{Int}(undef, length(qs))` per call site. + +### Breaking changes — made internal + +These helpers backed 1.x public names. In 2.0 they remain in the module as +implementation details of the strategy dispatch, but are no longer +documented or part of the public API: + + - `searchsortedfirstexp` — now backs the `ExpFromLeft` strategy. Use + `searchsortedfirst(ExpFromLeft(), v, x, lo)` instead. + - `bracketstrictlymontonic` — now backs the `BracketGallop` strategy. + Callers wanting a bracket-then-binary-search should use + `searchsortedlast(BracketGallop(), v, x, hint)` / + `searchsortedfirst(BracketGallop(), v, x, hint)`. + +### New: strategy-dispatched search API + +A single pair of generic functions covers every sorted-search algorithm in +the package: + +```julia +searchsortedfirst(strategy, v, x[, hint]; order = Base.Order.Forward) +searchsortedlast(strategy, v, x[, hint]; order = Base.Order.Forward) +``` + +`strategy` is a concrete subtype of `SearchStrategy`. The shipped +strategies are: + + - **`LinearScan`** — walks ±1 from the hint. Cheapest when the hint is + close to the answer; O(n) worst case. + - **`SIMDLinearScan`** — `LinearScan` with the forward walk lowered to + 8-wide SIMD chunks via custom LLVM IR. Specialized for + `DenseVector{Int64}` and `DenseVector{Float64}`; falls back to scalar + `LinearScan` for any other element type. Opt-in only — `Auto` does not + pick it. See `strategies.md` for the NaN / element-type caveats. + - **`BracketGallop`** — bidirectional exponential bracket around the + hint, then bounded binary search. Workhorse hinted strategy. O(1) when + the hint is close, never worse than ~2 log₂ n. + - **`ExpFromLeft`** — exponential search forward from a left-bound hint. + Five linear probes, then doubling, then bounded binary search. Default + `Auto` choice in the sparse-batched path. + - **`InterpolationSearch`** — linear-extrapolation guess refined with + binary search. O(1) per query on uniformly-spaced numeric data, + O(log n) otherwise. + - **`BinaryBracket`** — plain `Base.searchsortedlast` / + `Base.searchsortedfirst`. Used as the no-hint fallback by every other + strategy. + - **`GuesserHint(g::Guesser)`** — `BracketGallop` driven by a + `Guesser`'s integer guess, with the result cached back into the + `Guesser`. + - **`Auto`** — heuristic dispatcher; see "New: `Auto` heuristic" below. + +Strategies are zero-field singletons (except `GuesserHint`, which wraps a +`Guesser`, and `Auto`, which optionally carries a `SearchProperties` +cache). The dispatch is type-stable; pinning a strategy at a call site +costs nothing at runtime. + +### New: batched in-place API + +```julia +searchsortedfirst!(idx_out, v, queries; strategy = Auto(), order = ...) +searchsortedlast!(idx_out, v, queries; strategy = Auto(), order = ...) +``` + +Writes one index per element of `queries` into `idx_out` (which must be +the same length). If `queries` is sorted under `order`, each query's hint +is the previous result, so the total cost for sorted batches is +O(length(v) + length(queries)) under the typical `Auto` choice. If +`queries` is not sorted, the call falls back to per-element +`Base.searchsortedlast` / `Base.searchsortedfirst` with no hint. + +These methods are the replacement for the removed `searchsortedfirstvec` / +`searchsortedlastvec`. The caller owns the output buffer and is free to +reuse it across calls. + +### New: `Auto` heuristic + +`Auto` picks a strategy based on the calling context: + +**Per-query** (`searchsortedlast(Auto(), v, x[, hint])`): + + - No hint, or hint out of range → `BinaryBracket`. + - Hint in range, `length(v) ≤ 16` → `LinearScan`. + - Hint in range, `length(v) > 16` → `BracketGallop`. + +**Batched sorted** (`searchsortedlast!(out, v, queries; strategy = Auto())`) +chooses by the expected average gap in `v`'s index space between +consecutive query results. For numeric data the gap is estimated from the +span ratio `(queries[end] - queries[1]) / (v[end] - v[1])`, so dense-burst +queries clustered inside one segment of `v` are correctly recognized as +gap ≈ 0: + + - `gap ≤ 4` → `LinearScan`. + - `gap ≥ 8`, `length(v) ≥ 1024`, `length(queries) ≥ 2`, not skewed, and + a sampled-linearity probe accepts → `InterpolationSearch`. + - otherwise → `ExpFromLeft`. + +The sampled-linearity probe reads 11 elements (~25 ns) and accepts when +every interior point sits within 0.1% of the straight line through `v[1]` +and `v[end]`. The 0.1% tolerance is tight by design: at large `n` the +order-statistic variance of random-sorted data is small enough that a 5% +threshold would falsely pass on irregular data. + +Skew detection on the query distribution adds an additional gate: if the +median query is more than 20% off the midpoint of the query span (and +`m ≥ 10` so the median is meaningful), `Auto` picks `ExpFromLeft` even +on linear `v`, because consecutive queries land in the same region and +the previous-result hint is worth more than the linear-extrapolation +guess. Skew detection is gated on `m ≥ 10` to avoid the median sampling +variance dominating for small batches. + +The crossover constants (`_AUTO_LINEAR_THRESHOLD = 16`, +`_AUTO_BATCH_LINEAR_GAP = 4`, `_AUTO_INTERP_MIN_GAP = 8`, +`_AUTO_INTERP_MIN_N = 1024`, `_AUTO_INTERP_MIN_M = 2`, +`_AUTO_LINEAR_REL_TOLERANCE = 1e-3`) were tuned empirically by a regime +grid covering uniform / jittered / log-spaced / two-scale / random `v` +patterns crossed with dense / sparse / clustered / sorted-random query +patterns at vector lengths from 64 to 65536 and batch sizes from 1 to +4096. Across that grid `Auto` is within 1.2× of the per-cell optimum in +90% of cells. + +### New: `SearchProperties` cache for `Auto` + +For callers issuing many short batches against the same sorted vector +(interpolation-segment lookups being the obvious case), `Auto`'s per-call +linearity probe is redundant. The new `SearchProperties` struct caches +the probe result and `Auto(props)` consumes it instead of re-probing: + +```julia +v = collect(0.0:0.001:100.0) +props = SearchProperties(v) # run probes once: ~25 ns + (Float-only) O(n) NaN scan +strat = Auto(props) # Auto holding the cached facts + +queries = sort!(rand(8) .* 100.0) +out = Vector{Int}(undef, length(queries)) +searchsortedlast!(out, v, queries; strategy = strat) +``` + +`SearchProperties` is `isbits` — it travels in registers and copies are +free. `Auto(props)` is itself zero-allocation; the resulting `Auto` is a +single concrete struct, not a parametric type. + +Currently consumed: `props.is_linear` (replaces `_sampled_looks_linear` +in the batched dispatch). The `has_props` and `has_nan` fields are +populated by `SearchProperties(v)` for forward compatibility; the latter +will unlock `SIMDLinearScan` participation in `Auto` once the eligibility +gate is wired in. + +The cache is not invalidated automatically — the caller must reconstruct +`SearchProperties(v)` if `v` mutates. A stale cache is correctness- +preserving (the chosen `InterpolationSearch` falls through to +`BracketGallop` from a bad guess — slow but still O(log n)), so the +worst case is a performance regression, not a wrong answer. + +### New: `SIMDLinearScan` + +A SIMD variant of `LinearScan` that lowers the forward walk past the hint +to 8-wide SIMD chunks via custom LLVM IR. The same scaffolding that backs +`_findfirstequal` (load 8 lanes, vector compare, bitmask, `cttz` on the +mask) is reused for the four predicates needed by positional search: + + - `_simd_first_gt` / `_simd_first_ge` for `Int64` (using `icmp sgt` / + `icmp sge`). + - `_simd_first_gt` / `_simd_first_ge` for `Float64` (using `fcmp ogt` / + `fcmp oge`). + +The IR is generated from a shared template `_simd_scan_ir(t, pred)` +parameterised on LLVM element type and compare predicate. + +Caveats (documented in detail in `strategies.md`): + + - **Element types**: `DenseVector{Int64}` and `DenseVector{Float64}` + only. Other element types (including `Int32`, `UInt64`, `Float32`, + `Date`, `String`) hit the scalar `LinearScan` fallback path. The + dispatch is static, so the fallback costs nothing per call. + - **NaN**: ordered float compares (`fcmp o*`) return false for NaN + operands, so a NaN in `v` is silently skipped by the SIMD scan. + Sorted-Float64 with NaN isn't well-defined under any total order + anyway, so this is consistent with `Base.searchsortedlast` on such + vectors. + - **Forward order only**: non-`Forward` orderings fall back to scalar + `LinearScan`. + - **No hint**: falls back to `BinaryBracket`. + +`Auto` does **not** pick `SIMDLinearScan`. It is opt-in: the regime where +it strictly beats `LinearScan` (long forward walks on Int64/Float64 +DenseVectors) overlaps with the regime where `Auto` already prefers +`BracketGallop` or `ExpFromLeft`. Pin it explicitly when you have a +workload that wants a long forward scan and you know the element type. + +### Documentation restructure + +The single `index.md` from 1.x has been split into five topical pages: + + - **Home** (`index.md`): overview and quick example. + - **Interface and extension rules** (`interface.md`): the public API + surface, the contract a `SearchStrategy` subtype must satisfy, and + how to add a new one with a correctness-check pattern. Notes that + `Auto`'s decision tree is not externally extensible — new strategies + do not auto-register with `Auto`. + - **Search strategies** (`strategies.md`): catalog of every shipped + strategy with a chooser table (best case / worst case / hint usage), + per-strategy notes, the `SIMDLinearScan` caveats, and the + "Equality search" appendix linking to `findfirstequal` / + `findfirstsortedequal` (which are a deliberately-separate API + because their return type differs from positional search). + - **Guessers** (`guessers.md`): the `Guesser` type, its + linear-extrapolation vs. cached-previous-result behaviour, the + `GuesserHint` strategy adapter, and explicit guidance on when *not* + to use a `Guesser`. + - **Auto: heuristics and benchmarks** (`auto.md`): full `Auto` + decision tree for both per-query and batched callers, every + crossover constant with justification, the `SearchProperties` cache + integration, and a self-contained benchmark script that reproduces + the regime-grid comparison. + +### Internal: shared SIMD scan scaffolding + +The LLVM IR pattern used by `_findfirstequal` (load 8 lanes, vector +compare, `cttz` on the bitmask) is now generated by a shared template +`_simd_scan_ir(t, pred)`. `FFE_IR` (equality scan, used by +`findfirstequal` and `findfirstsortedequal`) and the four +`_SIMD_*_IR`s (positional compares for `SIMDLinearScan`) all flow from +that template. Adding a new predicate is a one-line change. + +### Unchanged: equality search + +`findfirstequal` and `findfirstsortedequal` are unchanged in 2.0. They +remain a separate API from the sorted-search strategy dispatch because +their return semantics differ: + + - Equality search: `Union{Int, Nothing}` — `nothing` on miss. + - Sorted search: in-range `Int` — the insertion point. + +Folding them together would either change every strategy's return type +or paper over misses with an arbitrary index. They are documented in the +"Equality search" appendix of `strategies.md`. + +### Compatibility + + - **Julia compat**: unchanged from 1.x — `julia = "1.10"`. + - **Downstream PRs**: SciML packages using the removed names need + companion PRs. The first one + [SciML/DataInterpolations.jl#529](https://github.com/SciML/DataInterpolations.jl/pull/529) + is the migration template: drop the legacy imports, route the + `Integer`-hint path through `searchsortedfirst(BracketGallop(), …)` + and the `Guesser` path through `searchsortedfirst(GuesserHint(g), …)`. + +### Test coverage + +47100 tests pass across the strategy dispatch, the batched API, the +`Auto` heuristic on a regime sweep, `SIMDLinearScan` randomized fuzz +(10000 Int64 + 10000 Float64 cases against `Base`), edge cases (empty, +single-element, duplicates, out-of-range hints, x outside the vector +range), fallback paths (Int32, Float32, String, no-hint, reverse +order), and `SearchProperties` cache correctness (output equivalence +against the un-cached path, `isbits` guarantee, behaviour under lying +cache). From 9db2fe6969fc42b68d19e917ce0dab3372be4d10 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 06:57:46 -0400 Subject: [PATCH 10/16] Add findequal + BisectThenSIMD; fix duplicates bug in 4 search paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Equality search now flows through the strategy framework via a new wrapper `findequal(strategy, v, x[, hint])` that returns an `Int` with the sentinel `firstindex(v) - 1` for "not found". Type-stable, composes with every existing strategy. The new `BisectThenSIMD <: SearchStrategy` short-circuits to `findfirstsortedequal`'s algorithm on `DenseVector{Int64}`. For positional dispatch (`searchsortedfirst`/`searchsortedlast`), `BisectThenSIMD` delegates to `BinaryBracket` — bisect-then-equality-scan can't answer "where would x insert?". The new tests exposed four pre-existing duplicate-handling bugs, all fixed in this commit: - `searchsortedfirst(BracketGallop(), v, x, hint)` returned the rightmost duplicate when the hint landed in a run of equals. Cause: `bracketstrictlymontonic` used `x < v[lo]` to choose direction, which is correct for `searchsortedlast` but wrong for `searchsortedfirst`. Fix: add `bracketstrictlymontonic_first` with the inverted polarity `v[lo] < x`, used only by the `searchsortedfirst` overload. - `searchsortedfirst(InterpolationSearch(), v, x)` propagated the same bug via `BracketGallop`. Fixed by the bracket-first fix. - `searchsortedfirst(ExpFromLeft(), v, x, hint)` exponential-searched forward when `v[hint] == x`, missing earlier duplicates. Fixed by falling back to a full search whenever `v[hint] >= x` (the exponential-forward path is only safe when `v[hint] < x`). - `findfirstsortedequal(var, vars)` bisected with `vars[mid] <= var` and advanced offset on equal hits, walking past the first duplicate. Fixed by tightening to strict `<` and adjusting the window-shrink rule so the "keep" branch retains the midpoint in the next window (`len = half + 1` instead of `len -= half`). The fast-path LLVM IR branch select is replaced by plain `ifelse`; Julia compiles to the same branchless `select` modulo the `!unpredictable` metadata. Tests: 84120 pass (was 47100). The new `findequal + BisectThenSIMD` testset runs 2500 random-trial parity checks against `Base` across all shipped strategies on Int64 and Float64 vectors (including frequent duplicates), the OffsetArray-style sentinel, reverse ordering, empty and single-element edge cases, and a check that `BisectThenSIMD` in positional dispatch correctly delegates to `BinaryBracket`. Docs: - `strategies.md` gains a "Equality search through the strategy framework" section with the `findequal` and `BisectThenSIMD` @docs entries. - The Equality-search appendix now points callers to `findequal` as the preferred sorted-equality API and explains why `findfirstequal` (unsorted) stays outside the strategy framework. - NEWS.md adds the new-functionality section and the four-way bug-fix section with concrete before/after behaviour. Co-Authored-By: Chris Rackauckas --- NEWS.md | 58 ++++++++++ docs/src/strategies.md | 46 ++++++-- src/FindFirstFunctions.jl | 225 ++++++++++++++++++++++++++++++++------ test/runtests.jl | 113 +++++++++++++++++++ 4 files changed, 403 insertions(+), 39 deletions(-) diff --git a/NEWS.md b/NEWS.md index 303c82f..9e0914a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -249,6 +249,64 @@ compare, `cttz` on the bitmask) is now generated by a shared template `_SIMD_*_IR`s (positional compares for `SIMDLinearScan`) all flow from that template. Adding a new predicate is a one-line change. +### New: equality search through the strategy framework + +`findequal(strategy, v, x[, hint])` builds an equality variant on top of +the strategy dispatch. The return type is `Int` (not `Union{Int, Nothing}`); +"not found" is signalled by the sentinel `firstindex(v) - 1` (= `0` on +1-based vectors), matching the convention `Base.searchsortedlast` already +uses for "x precedes all of v". + + - Most strategies are handled generically: + `findequal(strategy, v, x[, hint])` runs + `searchsortedfirst(strategy, v, x[, hint])` and checks whether the + candidate index actually equals `x`. This means + `findequal(BracketGallop(), v, x, hint)`, + `findequal(SIMDLinearScan(), v, x, hint)`, + `findequal(GuesserHint(g), v, x)`, `findequal(Auto(), v, x)`, and + `findequal(BinaryBracket(), v, x)` all work without per-strategy + glue. + - `BisectThenSIMD <: SearchStrategy` is a new strategy that, for + `DenseVector{Int64}`, dispatches `findequal` straight into the + bisect-then-SIMD-equality-scan algorithm that backs + `findfirstsortedequal`. For other element types, falls back to + `BinaryBracket + post-check`. In positional dispatch + (`searchsortedfirst` / `searchsortedlast`) it delegates to + `BinaryBracket` — the bisect-then-equality-scan algorithm can't + answer the positional "where would `x` insert?" question. + +### Bug fix: `BracketGallop`/`InterpolationSearch`/`ExpFromLeft`/`findfirstsortedequal` with duplicates + +Four pre-existing functions returned the wrong index when `v` contained +duplicates of the queried value and the hint or bisection midpoint +landed inside a run of duplicates. All four are fixed in 2.0: + + - `searchsortedfirst(BracketGallop(), v, x, hint)` previously galloped + rightward when `v[hint] == x`, returning the rightmost duplicate + instead of the first. Fixed by adding the companion + `bracketstrictlymontonic_first` that gallops leftward when + `v[hint] >= x`. + - `searchsortedfirst(InterpolationSearch(), v, x)` chains into + `BracketGallop`, so the same bug propagated and is fixed by the + above. + - `searchsortedfirst(ExpFromLeft(), v, x, hint)` previously + exponential-searched from `hint` when `v[hint] == x`, missing + earlier duplicates. Fixed by falling back to a full search whenever + `v[hint] >= x`. + - `findfirstsortedequal(var, vars)` bisected with the predicate + `vars[mid] <= var`, which walked the offset past the first + duplicate when `vars[mid] == var`. Fixed by tightening the predicate + to `<` and updating the window-shrink rule to include the midpoint + when the comparison is false. The fast-path LLVM IR branch is + replaced by plain `ifelse` (Julia compiles it to the same + branchless `select` modulo the `!unpredictable` metadata, which had + minimal observable effect). + +The fix is exercised by the new `findequal` strategy-parity tests on +randomized vectors with frequent duplicates (Int64 in [-50, 50] over +vectors up to length 256, 2000 trials per strategy across all shipped +strategies). + ### Unchanged: equality search `findfirstequal` and `findfirstsortedequal` are unchanged in 2.0. They diff --git a/docs/src/strategies.md b/docs/src/strategies.md index d56e3b0..43aaf7a 100644 --- a/docs/src/strategies.md +++ b/docs/src/strategies.md @@ -39,10 +39,36 @@ FindFirstFunctions.BracketGallop FindFirstFunctions.ExpFromLeft FindFirstFunctions.InterpolationSearch FindFirstFunctions.BinaryBracket +FindFirstFunctions.BisectThenSIMD FindFirstFunctions.Auto FindFirstFunctions.SearchProperties ``` +## Equality search through the strategy framework + +Strategies answer positional questions ("where would `x` insert?"). Equality +asks a different question ("is `x` at exactly which index?"). The +[`findequal`](@ref FindFirstFunctions.findequal) wrapper builds the latter +on top of the former: every strategy gets an equality variant for free. + +```@docs +FindFirstFunctions.findequal +``` + +The sentinel for "not found" is `firstindex(v) - 1` (`= 0` for 1-based +vectors). Type-stable `Int` return, no `Union` with `Nothing`. Callers can +test for absence with `i < firstindex(v)`. + +`findequal` routes most strategies through `searchsortedfirst + post-check` +generically, so `findequal(BracketGallop(), v, x, hint)`, +`findequal(SIMDLinearScan(), v, x, hint)`, +`findequal(GuesserHint(g), v, x)`, etc. all just work. + +The [`BisectThenSIMD`](@ref FindFirstFunctions.BisectThenSIMD) strategy +short-circuits the post-check path on `DenseVector{Int64}` by dispatching +into [`findfirstsortedequal`](@ref FindFirstFunctions.findfirstsortedequal) +directly — same custom LLVM IR scan, exposed through the strategy framework. + `GuesserHint` is documented on the [Guessers](@ref) page. ## Notes on individual strategies @@ -168,10 +194,16 @@ binary bisection down to a small basecase, then dispatches into the same SIMD scan. Both are restricted to `DenseVector{Int64}`; for other element types `findfirstequal` falls back to `findfirst(==(x), v)`. -The same SIMD-scan scaffolding (load 8 lanes, vector compare, `cttz` on the -bitmask) also backs [`SIMDLinearScan`](@ref FindFirstFunctions.SIMDLinearScan) -on the positional-search side — see the strategy notes above. The two paths -remain separate APIs because their return semantics differ (`nothing` vs. -in-range index) and because the equality-scan extension to `Float64` would -require additional NaN-handling that the positional API already handles via -ordered float compares. +For sorted equality search through the strategy framework, prefer +[`findequal`](@ref FindFirstFunctions.findequal) (see the previous section) +— it gives a type-stable `Int` return with a sentinel for "not found", +participates in the strategy dispatch, and short-circuits to +`findfirstsortedequal`'s SIMD algorithm via the +[`BisectThenSIMD`](@ref FindFirstFunctions.BisectThenSIMD) strategy when +the eltype is `Int64`. `findfirstsortedequal` and `findfirstequal` remain +as backward-compatible dedicated names. + +The `findfirstequal` unsorted variant is intentionally outside the strategy +framework: positional strategies (binary search, galloping, interpolation) +all require a sorted input, while `findfirstequal` operates on arbitrary +vectors. diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index 569082a..0050a83 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -208,40 +208,23 @@ function findfirstsortedequal( len = length(vars) offset = 0 @inbounds while len > basecase - half = len >>> 1 # half on left, len - half on right - if Base.libllvm_version >= v"17" - # TODO: check if this works - # I'm worried the `!unpredictable` metadata will be stripped - offset = Base.llvmcall( - ( - """ - define i64 @entry(i8 %0, i64 %1, i64 %2) #0 { - top: - %b = trunc i8 %0 to i1 - %s = select i1 %b, i64 %1, i64 %2, !unpredictable !0 - ret i64 %s - } - attributes #0 = { alwaysinline } - !0 = !{} - """, - "entry", - ), - Int64, - Tuple{Bool, Int64, Int64}, - vars[offset + half + 1] <= var, - half + offset, - offset - ) - else - offset = ifelse(vars[offset + half + 1] <= var, half + offset, offset) - end - len = len - half + # Bisect with the predicate `vars[mid] < var` (strict). When true, + # `var` is past the midpoint — drop the left half *and* the + # midpoint itself. When false (`vars[mid] >= var`), `var` may be + # at the midpoint, so keep `offset` and shrink the window to + # `vars[offset+1 .. offset+half+1]` (inclusive of the midpoint). + # The earlier `<=` predicate would have advanced past matching + # midpoints, masking earlier duplicates of `var`. + half = len >>> 1 + mid = offset + half + 1 + is_left_strictly_less = vars[mid] < var + offset = ifelse(is_left_strictly_less, offset + half + 1, offset) + len = ifelse(is_left_strictly_less, len - half - 1, half + 1) end # maybe occurs in vars[offset+1:offset+len] GC.@preserve vars begin ret = _findfirstequal(var, pointer(vars) + 8offset, len) end - # return ret return ret < 0 ? nothing : ret + offset + 1 end @@ -284,6 +267,44 @@ function bracketstrictlymontonic( return lo, hi end +# Internal: companion to `bracketstrictlymontonic` for the `searchsortedfirst` +# polarity. The original galloping uses `lt(o, x, v[lo])` (i.e., `x < v[lo]`) +# to choose direction, which is the right test for `searchsortedlast`: when +# `x == v[lo]`, the answer is `>= lo` so we gallop right. For +# `searchsortedfirst`, when `x == v[lo]` the answer is `<= lo` (look for +# earlier duplicates) — so we need the inverted polarity `lt(o, v[lo], x)` +# (i.e., `v[lo] < x`). Without this, BracketGallop.searchsortedfirst returns +# the wrong index when the hint lands on a run of duplicates. +function bracketstrictlymontonic_first( + v::AbstractVector, + x, + guess::T, + o::Base.Order.Ordering + )::NTuple{2, keytype(v)} where {T <: Integer} + bottom = firstindex(v) + top = lastindex(v) + if guess < bottom || guess > top + return bottom, top + else + u = T(1) + lo, hi = guess, min(guess + u, top) + @inbounds if !Base.Order.lt(o, v[lo], x) + # v[lo] >= x → answer is <= lo, gallop left. + while lo > bottom && !Base.Order.lt(o, v[lo], x) + lo, hi = max(bottom, lo - u), lo + u += u + end + else + # v[lo] < x → answer is > lo, gallop right. + while hi < top && Base.Order.lt(o, v[hi], x) + lo, hi = hi, min(top, hi + u) + u += u + end + end + end + return lo, hi +end + # --------------------------------------------------------------------------- # Sorted-search strategies # --------------------------------------------------------------------------- @@ -313,6 +334,10 @@ called with a strategy as the first positional argument: irregular data. - [`BinaryBracket`](@ref) is the standard `Base.searchsortedlast` / `Base.searchsortedfirst` with no hint. Use it when no useful hint exists. + - [`BisectThenSIMD`](@ref) is an equality-search strategy: binary-bisects + `v` to a small basecase, then SIMD-scans for exact equality. Specialised + for `DenseVector{Int64}`; only meaningful when used with + [`findequal`](@ref). - [`Auto`](@ref) heuristically picks one of the above based on the size of `v`, the spacing of `v`, and whether a hint was supplied. Accepts an optional [`SearchProperties`](@ref) cache to skip per-call probes. @@ -406,6 +431,28 @@ that is supplied. """ struct BinaryBracket <: SearchStrategy end +""" + BisectThenSIMD <: SearchStrategy + +Equality-search strategy. Binary-bisects `v` down to a small basecase, then +SIMD-scans the basecase for exact equality with `x`. Specialised for +`DenseVector{Int64}` + `Int64` queries via the same custom LLVM IR that +backs [`findfirstsortedequal`](@ref FindFirstFunctions.findfirstsortedequal); +for other element types, falls back to [`BinaryBracket`](@ref) plus an +equality check. + +This strategy is meant for use with [`findequal`](@ref FindFirstFunctions.findequal), +not with `searchsortedfirst` / `searchsortedlast` — its purpose is to answer +"is `x` present at exactly which index, or not at all?", which is a +different question from positional search. In the +`searchsortedfirst`/`searchsortedlast` dispatch it falls back to +[`BinaryBracket`](@ref). + +Ignores any hint that is supplied. Falls back to [`BinaryBracket`](@ref) for +non-`Forward` orderings. +""" +struct BisectThenSIMD <: SearchStrategy end + """ GuesserHint(guesser::Guesser) <: SearchStrategy @@ -768,7 +815,7 @@ function Base.searchsortedfirst( ::BracketGallop, v::AbstractVector, x, hint::Integer; order::Base.Order.Ordering = Base.Order.Forward ) - lo, hi = bracketstrictlymontonic(v, x, hint, order) + lo, hi = bracketstrictlymontonic_first(v, x, hint, order) return searchsortedfirst(v, x, lo, hi, order) end @@ -799,8 +846,12 @@ function Base.searchsortedfirst( return lo end h = clamp(hint, lo, hi) - @inbounds if Base.Order.lt(order, x, v[h]) - # x < v[hint] → hint is past the answer; full search. + # `searchsortedfirst` semantics: smallest i with v[i] >= x. We can only + # gallop forward from `h` when v[h] < x (then the answer is strictly + # > h). When v[h] >= x, the first occurrence of `x` may be at index + # ≤ h (duplicates to the left), so fall back to a full search rather + # than risk skipping past earlier duplicates. + @inbounds if !Base.Order.lt(order, v[h], x) return searchsortedfirst(v, x, order) end return order === Base.Order.Forward ? @@ -913,6 +964,27 @@ Base.searchsortedfirst( order::Base.Order.Ordering = Base.Order.Forward ) = searchsortedfirst(BinaryBracket(), v, x; order = order) +# Strategy: BisectThenSIMD — only meaningful for `findequal`. For the +# positional `searchsortedfirst` / `searchsortedlast` dispatch, fall back to +# BinaryBracket — bisect-then-equality-scan can't answer the positional +# question ("where would x insert?") that searchsortedfirst asks. +Base.searchsortedlast( + ::BisectThenSIMD, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::BisectThenSIMD, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(BinaryBracket(), v, x; order = order) +Base.searchsortedlast( + s::BisectThenSIMD, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + s::BisectThenSIMD, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + # Strategy: GuesserHint — Guesser produces an integer hint, BracketGallop runs # the search and updates the Guesser's prev-result cache. Methods are defined # below where Guesser is in scope (search the file for "GuesserHint methods"). @@ -1375,6 +1447,87 @@ Base.@propagate_inbounds function searchsortedfirstexp( return searchsortedfirst(v, x, lo + tn2 - tn2m1, hi, Base.Order.Forward) end +# --------------------------------------------------------------------------- +# Equality search through the strategy dispatch +# --------------------------------------------------------------------------- + +""" + findequal(strategy, v, x[, hint]; order = Base.Order.Forward) + +Return the index of `x` in sorted `v` if present, or `firstindex(v) - 1` +(= 0 for 1-based vectors) if `x` is absent. Type-stable `Int` return — the +sentinel value `firstindex(v) - 1` matches the convention +`Base.searchsortedlast` already uses for "x precedes all of v", so callers +can test for "not found" with `i < firstindex(v)`. + +Most strategies are handled generically: run +`searchsortedfirst(strategy, v, x[, hint])` to find the candidate insertion +point, then check whether `v[i]` actually equals `x`. The shortcut method +on [`BisectThenSIMD`](@ref) for `DenseVector{Int64}` skips the +`searchsortedfirst` path entirely and uses the dedicated bisect-then-SIMD +equality scan that backs [`findfirstsortedequal`](@ref). + +For unsorted vectors, use [`findfirstequal`](@ref) — it does not require +a sorted input and falls outside the strategy framework. +""" +@inline function findequal( + strategy::SearchStrategy, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward + ) + return _findequal_generic(strategy, v, x, order) +end + +@inline function findequal( + strategy::SearchStrategy, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + i = searchsortedfirst(strategy, v, x, hint; order = order) + return _findequal_postcheck(v, x, i) +end + +@inline function _findequal_generic(strategy, v, x, order) + i = searchsortedfirst(strategy, v, x; order = order) + return _findequal_postcheck(v, x, i) +end + +@inline function _findequal_postcheck(v::AbstractVector, x, i::Integer) + if i > lastindex(v) + return firstindex(v) - 1 + end + @inbounds return isequal(v[i], x) ? Int(i) : (firstindex(v) - 1) +end + +# Shortcut: BisectThenSIMD on DenseVector{Int64} uses the dedicated bisect- +# then-SIMD equality scan (same algorithm as `findfirstsortedequal`). +function findequal( + ::BisectThenSIMD, v::DenseVector{Int64}, x::Int64; + order::Base.Order.Ordering = Base.Order.Forward + ) + if order !== Base.Order.Forward + return _findequal_generic(BinaryBracket(), v, x, order) + end + r = findfirstsortedequal(x, v) + return r === nothing ? (firstindex(v) - 1) : r +end +# Hinted form ignores the hint — the bisect-then-SIMD algorithm does not +# benefit from a hint, and probing it would only waste cycles. +findequal( + s::BisectThenSIMD, v::DenseVector{Int64}, x::Int64, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = findequal(s, v, x; order = order) + +# Non-Int64 fallback for BisectThenSIMD: use BinaryBracket + post-check. +function findequal( + ::BisectThenSIMD, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward + ) + return _findequal_generic(BinaryBracket(), v, x, order) +end +findequal( + s::BisectThenSIMD, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = findequal(s, v, x; order = order) + using PrecompileTools: @compile_workload, @setup_workload @setup_workload begin @@ -1409,6 +1562,14 @@ using PrecompileTools: @compile_workload, @setup_workload searchsortedfirst(strategy, vec_int64, Int64(8), Int64(1)) searchsortedlast(strategy, vec_int64, Int64(8), Int64(1)) end + # findequal: generic + BisectThenSIMD shortcut for Int64 dense vectors. + for strategy in ( + BinaryBracket(), BracketGallop(), SIMDLinearScan(), + BisectThenSIMD(), Auto(), + ) + findequal(strategy, vec_int64, Int64(8)) + findequal(strategy, vec_int64, Int64(8), Int64(1)) + end # SIMDLinearScan's Float64 specialization. let vec_f64 = collect(1.0:1.0:16.0) searchsortedfirst(SIMDLinearScan(), vec_f64, 8.0, 1) diff --git a/test/runtests.jl b/test/runtests.jl index a0bb48c..0b8e6cc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -535,6 +535,119 @@ end ) == searchsortedlast(v_rev, Int64(50), Base.Order.Reverse) end end + + @safetestset "findequal + BisectThenSIMD" begin + using FindFirstFunctions, StableRNGs + F = FindFirstFunctions + + # Reference: an Int sentinel-returning equality search built from + # Base.searchsortedfirst. + function ref_findequal(v, x) + i = searchsortedfirst(v, x) + return (i > lastindex(v) || !isequal(v[i], x)) ? + (firstindex(v) - 1) : i + end + + @testset "Strategy parity on Int64 (1-based)" begin + rng = StableRNG(3001) + for _ in 1:2_000 + n = rand(rng, 1:256) + v = sort!(rand(rng, Int64(-50):Int64(50), n)) + x = rand(rng, Int64(-60):Int64(60)) + hint = rand(rng, 1:n) + want = ref_findequal(v, x) + for strategy in ( + F.BinaryBracket(), F.BracketGallop(), + F.SIMDLinearScan(), F.LinearScan(), + F.ExpFromLeft(), F.InterpolationSearch(), + F.Auto(), F.BisectThenSIMD(), + ) + @test F.findequal(strategy, v, x) == want + @test F.findequal(strategy, v, x, hint) == want + end + end + end + + @testset "Strategy parity on Float64" begin + rng = StableRNG(3002) + for _ in 1:500 + n = rand(rng, 1:256) + v = sort!(randn(rng, n)) + # Mix queries that hit elements with ones that don't. + x = rand(rng) < 0.4 ? v[rand(rng, 1:n)] : + (rand(rng) - 0.5) * 6 + hint = rand(rng, 1:n) + want = ref_findequal(v, x) + for strategy in ( + F.BinaryBracket(), F.BracketGallop(), + F.SIMDLinearScan(), F.Auto(), F.BisectThenSIMD(), + ) + @test F.findequal(strategy, v, x) == want + @test F.findequal(strategy, v, x, hint) == want + end + end + end + + @testset "BisectThenSIMD shortcut uses SIMD on DenseVector{Int64}" begin + # Compare against findfirstsortedequal directly. + v = collect(Int64, 1:10_000) + for x in ( + Int64(1), Int64(5_000), Int64(10_000), + Int64(0), Int64(10_001), Int64(-100), Int64(20_000), + ) + a = F.findequal(F.BisectThenSIMD(), v, x) + b = F.findfirstsortedequal(x, v) + @test (a == 0 ? nothing : a) == b + end + end + + @testset "Sentinel for OffsetArray-style indexing" begin + # Manually shift the index base by using a UnitRange directly. + v = collect(Int64, 10:20) + @test F.findequal(F.Auto(), v, Int64(15)) == 6 + @test F.findequal(F.Auto(), v, Int64(100)) == 0 + @test F.findequal(F.Auto(), v, Int64(-5)) == 0 + end + + @testset "Reverse ordering" begin + v_rev = collect(Int64, 10:-1:1) + # Forward findequal on a reverse-sorted vector with the + # Reverse ordering should still find the element if present. + @test F.findequal( + F.BinaryBracket(), v_rev, Int64(5); + order = Base.Order.Reverse, + ) == 6 + @test F.findequal( + F.BinaryBracket(), v_rev, Int64(99); + order = Base.Order.Reverse, + ) == 0 + # BisectThenSIMD on reverse order falls back to generic path. + @test F.findequal( + F.BisectThenSIMD(), v_rev, Int64(5); + order = Base.Order.Reverse, + ) == 6 + end + + @testset "Empty and single-element" begin + vempty = Int64[] + @test F.findequal(F.Auto(), vempty, Int64(0)) == 0 + @test F.findequal(F.BisectThenSIMD(), vempty, Int64(0)) == 0 + v1 = Int64[42] + @test F.findequal(F.Auto(), v1, Int64(42)) == 1 + @test F.findequal(F.Auto(), v1, Int64(7)) == 0 + @test F.findequal(F.BisectThenSIMD(), v1, Int64(42)) == 1 + end + + @testset "BisectThenSIMD in positional dispatch falls back" begin + # When used with searchsortedfirst/last, BisectThenSIMD just + # delegates to BinaryBracket — its purpose is findequal. + v = collect(Int64, 1:100) + @test searchsortedfirst(F.BisectThenSIMD(), v, Int64(50)) == + searchsortedfirst(v, Int64(50)) + @test searchsortedlast(F.BisectThenSIMD(), v, Int64(50)) == + searchsortedlast(v, Int64(50)) + end + end end if GROUP == "QA" From c1c75207468a8356c87c4bfc0c1ea0e6dabd88f0 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 07:30:46 -0400 Subject: [PATCH 11/16] Cleanup: typo, FFE_IR unification, docstring refresh, exports, equality page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six small cleanups grouped under one commit: 1. **Typo**: rename `bracketstrictlymontonic` to `bracketstrictlymonotonic` (and the `_first` companion). Internal helpers — no downstream impact. 2. **FFE_IR unification**: replace the ~60-line literal `FFE_IR` string with `_simd_scan_ir("i64", "eq")`, using the same SIMD-scan IR template that backs the four `>`/`>=` predicates for `SIMDLinearScan`. All five SIMD primitives now share a single IR source. The new `_simd_scan_ir` is now defined at the top of the module so `FFE_IR` can refer to it; the duplicate copy further down has been removed. 3. **Docstring refresh**: - `findfirstequal` now documents the unsorted-input contract, the Int64 SIMD specialization vs. the generic `findfirst(==(x), v)` fallback, and points at `findequal` / `findfirstsortedequal` for the sorted-equality alternatives. - `findfirstsortedequal` now points at `findequal(BisectThenSIMD(), …)` as the preferred sentinel-returning strategy-framework variant and explains its role as the dedicated `Union{Int64, Nothing}`-returning name. 4. **OffsetArray sentinel note**: `findequal` docstring spells out that the "not found" sentinel is `firstindex(v) - 1` (= `0` for 1-based vectors, adjusts for OffsetArrays), and instructs callers to test against `firstindex(v)` rather than the literal `0`. 5. **`SearchProperties(v; linear_tolerance = 1e-3)`** exposes the sampled-linearity probe's tolerance as a kwarg, symmetric to `Guesser`'s `looks_linear_threshold`. The internal `_sampled_looks_linear` is now `(v, tol::Float64)` with `tol` defaulting to `_AUTO_LINEAR_REL_TOLERANCE` (= 1e-3) for callers that don't pass one. Loosening to `1e-2` widens the regime where `Auto` picks `InterpolationSearch`; tightening to `1e-4` is more conservative. 6. **Exports**: 2.0 now exports the public API surface (`SearchStrategy`, every concrete strategy, `SearchProperties`, `Guesser`, `looks_linear`, `searchsortedfirst!`, `searchsortedlast!`, `findequal`, `findfirstequal`, `findfirstsortedequal`). Previously the package exported nothing, so callers had to fully qualify every reference (`FindFirstFunctions.LinearScan()`). `using FindFirstFunctions` is now sufficient to access the full API; previously qualified call sites continue to work. **New `equality.md` doc page**: the `findfirstequal` / `findfirstsortedequal` docs lived as an appendix on `strategies.md`, which was wrong because these functions don't match the strategy-dispatch contract (different return type, different question). Moved to their own page with a chooser table, the sentinel-vs.-Nothing discussion, and the shared SIMD-primitive notes. `strategies.md` keeps a one-paragraph stub pointing at the new page; `index.md` and `make.jl` updated to register and surface the new page in the nav. 84120 tests pass (unchanged — these are all internal renames or doc changes). Co-Authored-By: Chris Rackauckas --- NEWS.md | 60 ++++++++-- docs/make.jl | 1 + docs/src/equality.md | 77 +++++++++++++ docs/src/index.md | 5 + docs/src/strategies.md | 36 ++---- src/FindFirstFunctions.jl | 235 ++++++++++++++++++++------------------ 6 files changed, 262 insertions(+), 152 deletions(-) create mode 100644 docs/src/equality.md diff --git a/NEWS.md b/NEWS.md index 9e0914a..3866a44 100644 --- a/NEWS.md +++ b/NEWS.md @@ -307,18 +307,54 @@ randomized vectors with frequent duplicates (Int64 in [-50, 50] over vectors up to length 256, 2000 trials per strategy across all shipped strategies). -### Unchanged: equality search - -`findfirstequal` and `findfirstsortedequal` are unchanged in 2.0. They -remain a separate API from the sorted-search strategy dispatch because -their return semantics differ: - - - Equality search: `Union{Int, Nothing}` — `nothing` on miss. - - Sorted search: in-range `Int` — the insertion point. - -Folding them together would either change every strategy's return type -or paper over misses with an arbitrary index. They are documented in the -"Equality search" appendix of `strategies.md`. +### Equality search (`findfirstequal`, `findfirstsortedequal`) + +Both names continue to exist in 2.0, returning `Union{Int, Nothing}` as +before. Docstrings refreshed to point at the new +[`findequal`](@ref FindFirstFunctions.findequal) wrapper as the +strategy-framework-compatible alternative. Documentation moved out of +`strategies.md` into a dedicated `equality.md` page since these functions +do not match the strategy-dispatch contract (their return type and +question are different). + +### Exports + +2.0 exports the public API surface (previously the package exported +nothing, requiring `FindFirstFunctions.LinearScan()` qualification): + + - `SearchStrategy`, every concrete strategy + (`LinearScan`, `SIMDLinearScan`, `BracketGallop`, `ExpFromLeft`, + `InterpolationSearch`, `BinaryBracket`, `BisectThenSIMD`, + `GuesserHint`, `Auto`), and the `SearchProperties` cache. + - `Guesser` and `looks_linear`. + - The batched FFF-defined names `searchsortedfirst!` and + `searchsortedlast!` (the non-bang `searchsortedfirst` / + `searchsortedlast` are `Base` extensions, available via `Base`). + - The equality routines `findequal`, `findfirstequal`, + `findfirstsortedequal`. + +`using FindFirstFunctions` is now sufficient to access the full public +API. Downstream code that previously qualified every call (most of the +SciML ecosystem) continues to work — the qualified names still resolve. + +### Cleanup: typo fix, FFE_IR unification, tolerance kwarg + + - Internal helper `bracketstrictlymontonic` renamed to + `bracketstrictlymonotonic` (and the companion `_first` variant). + Internal-only — no downstream impact. + - The `FFE_IR` SIMD-equality IR literal is now generated by + `_simd_scan_ir("i64", "eq")` instead of duplicating ~60 lines of + inline LLVM IR. The same template produces the four `>`/`>=` + variants for `SIMDLinearScan`, so all five SIMD primitives share a + single source of truth. + - `SearchProperties(v; linear_tolerance = 1e-3)` exposes the + sampled-linearity probe's tolerance as a kwarg, matching `Guesser`'s + `looks_linear_threshold`. Loosen (e.g. `1e-2`) to widen the regime + where `Auto(props)` picks `InterpolationSearch`; tighten (e.g. + `1e-4`) to be more conservative. Default unchanged at `1e-3`. + +`findequal`'s docstring now explicitly documents the sentinel value +`firstindex(v) - 1` and its behaviour on OffsetArrays. ### Compatibility diff --git a/docs/make.jl b/docs/make.jl index 36e86a6..be60ee1 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -21,6 +21,7 @@ makedocs( "Search strategies" => "strategies.md", "Guessers" => "guessers.md", "Auto: heuristics and benchmarks" => "auto.md", + "Equality search" => "equality.md", ] ) diff --git a/docs/src/equality.md b/docs/src/equality.md new file mode 100644 index 0000000..1fdf3e9 --- /dev/null +++ b/docs/src/equality.md @@ -0,0 +1,77 @@ +# Equality search + +This page documents the package's equality-search routines — +[`findfirstequal`](@ref FindFirstFunctions.findfirstequal) and +[`findfirstsortedequal`](@ref FindFirstFunctions.findfirstsortedequal). They +answer a *different* question from the [Search strategies](@ref) covered +elsewhere: + + - **Sorted-search** strategies answer "*where would `x` insert?*". The + return value is always an in-range index — the bracketing position. + - **Equality** search answers "*does `x` exist, and if so at what index?*". + The return value is `nothing` if `x` is not present. + +These two surfaces live side-by-side because the second cannot be expressed +as a `SearchStrategy` — its return type differs (`Union{Int, Nothing}` vs. +in-range `Int`), and the unsorted variant doesn't even require a sorted +input. + +For a strategy-framework-compatible *sorted* equality search that returns +`Int` with a sentinel (so it composes with the rest of the strategy +dispatch), see [`findequal`](@ref FindFirstFunctions.findequal) on the +[Search strategies](@ref) page. `findequal(BisectThenSIMD(), v, x)` is the +strategy entry point that internally calls into the same algorithm as +`findfirstsortedequal`. + +## API reference + +```@docs +FindFirstFunctions.findfirstequal +FindFirstFunctions.findfirstsortedequal +``` + +## When to use which + +| Question | Vector | Recommended | +|---|---|---| +| Does `x` occur in this *unsorted* vector? | any | [`findfirstequal`](@ref FindFirstFunctions.findfirstequal) | +| Does `x` occur in this *sorted* vector? | `DenseVector{Int64}` + `Int64` | [`findfirstsortedequal`](@ref FindFirstFunctions.findfirstsortedequal) (or `findequal(BisectThenSIMD(), v, x)` for the sentinel-returning variant) | +| Does `x` occur in this *sorted* vector? | other eltypes | [`findequal`](@ref FindFirstFunctions.findequal) with any strategy | +| Where would `x` insert into this sorted vector? | any | `searchsortedfirst(strategy, v, x[, hint])` | + +## SIMD primitives + +Both equality functions are backed by the same SIMD-equality LLVM IR +scaffolding used internally throughout the package (`load <8 x i64>`, +`icmp eq`, `cttz` on the bitmask of the 8-wide compare). The IR template +[`FindFirstFunctions._simd_scan_ir`](@ref) generates this for the equality +predicate; the same template generates the `>` / `>=` variants for +[`SIMDLinearScan`](@ref FindFirstFunctions.SIMDLinearScan). + +The SIMD path is `Int64`-only — the LLVM IR is keyed off `i64` element +width and 8-byte stride. Every other element type and storage layout +falls through to a scalar `findfirst(==(x), v)` path. Specifically: + + - `findfirstequal(x::Int64, v::DenseVector{Int64})` — full SIMD scan. + - `findfirstequal(x, v)` (generic) — `findfirst(isequal(x), v)`. + - `findfirstsortedequal(x::Int64, v::DenseVector{Int64})` — branchless + binary bisection to a small basecase, then SIMD equality scan within + the basecase window. The bisection uses a strict `<` predicate so + that earlier duplicates are not skipped (a previous version of the + routine used `<=` and could return a later duplicate; fixed in 2.0). + +## Sentinel vs. `Nothing` + +The two equality APIs differ in how they report "not found": + +```julia +findfirstequal(x, v) # -> Union{Int, Nothing}, `nothing` on miss +findfirstsortedequal(x, v) # -> Union{Int, Nothing}, `nothing` on miss +findequal(strategy, v, x) # -> Int, firstindex(v) - 1 on miss +``` + +`findequal`'s sentinel is type-stable and composes with the rest of the +strategy dispatch — that's the recommended choice for new sorted-equality +code. The two `findfirst*equal` names continue to return +`Union{Int, Nothing}` for backwards compatibility with callers and pattern +matching against `nothing`. diff --git a/docs/src/index.md b/docs/src/index.md index 57e4887..045b97c 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -36,6 +36,11 @@ Pkg.add("FindFirstFunctions") - [Auto: heuristics and benchmarks](@ref) — what [`Auto`](@ref FindFirstFunctions.Auto) picks in every regime, the crossover constants, and the benchmark script that validates them. + - [Equality search](@ref) — the dedicated equality routines + [`findfirstequal`](@ref FindFirstFunctions.findfirstequal) and + [`findfirstsortedequal`](@ref FindFirstFunctions.findfirstsortedequal), + which live outside the strategy framework because their return type is + `Union{Int, Nothing}`. ## Quick example diff --git a/docs/src/strategies.md b/docs/src/strategies.md index 43aaf7a..fa86eaa 100644 --- a/docs/src/strategies.md +++ b/docs/src/strategies.md @@ -178,32 +178,10 @@ the benchmark sweep that produced its crossover constants. ## Equality search -Separate from the sorted-search strategy dispatch, the package exposes two -specialized equality routines for `Int64` vectors. These find an exact match -(returning `nothing` if no match exists), so they are not strategies — -their return semantics differ from `searchsortedfirst`/`searchsortedlast`. - -```@docs -FindFirstFunctions.findfirstequal -FindFirstFunctions.findfirstsortedequal -``` - -`findfirstequal` does an unsorted SIMD scan (~8× faster than scalar -`findfirst(==(x), v)` for `Int64`). `findfirstsortedequal` does a branchless -binary bisection down to a small basecase, then dispatches into the same -SIMD scan. Both are restricted to `DenseVector{Int64}`; for other element -types `findfirstequal` falls back to `findfirst(==(x), v)`. - -For sorted equality search through the strategy framework, prefer -[`findequal`](@ref FindFirstFunctions.findequal) (see the previous section) -— it gives a type-stable `Int` return with a sentinel for "not found", -participates in the strategy dispatch, and short-circuits to -`findfirstsortedequal`'s SIMD algorithm via the -[`BisectThenSIMD`](@ref FindFirstFunctions.BisectThenSIMD) strategy when -the eltype is `Int64`. `findfirstsortedequal` and `findfirstequal` remain -as backward-compatible dedicated names. - -The `findfirstequal` unsorted variant is intentionally outside the strategy -framework: positional strategies (binary search, galloping, interpolation) -all require a sorted input, while `findfirstequal` operates on arbitrary -vectors. +The package exposes two `Union{Int, Nothing}`-returning equality routines — +[`findfirstequal`](@ref FindFirstFunctions.findfirstequal) (unsorted SIMD +scan) and [`findfirstsortedequal`](@ref FindFirstFunctions.findfirstsortedequal) +(sorted bisect-then-SIMD scan). They live outside the strategy framework +because their return semantics differ (`nothing` on miss, vs. in-range +index for the positional API). See the [Equality search](@ref) page for the +full documentation. diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index 0050a83..5bb0a6f 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -1,97 +1,36 @@ module FindFirstFunctions +# Public API surface for `using FindFirstFunctions`. The strategy types are +# zero-field singletons (except `GuesserHint` and `Auto`, which carry small +# isbits payloads), so exporting them only adds names to the caller's +# namespace — no runtime cost. `searchsortedfirst!` / `searchsortedlast!` +# are FFF-defined names (the non-bang `searchsortedfirst` / +# `searchsortedlast` are extensions of `Base` and are reachable without +# qualification once `Base` is in scope). +export + SearchStrategy, + LinearScan, SIMDLinearScan, BracketGallop, ExpFromLeft, + InterpolationSearch, BinaryBracket, BisectThenSIMD, + GuesserHint, Auto, + SearchProperties, + Guesser, looks_linear, + searchsortedfirst!, searchsortedlast!, + findequal, findfirstequal, findfirstsortedequal + # https://github.com/JuliaLang/julia/pull/53687 const USE_PTR = VERSION >= v"1.12.0-DEV.255" -const FFE_IR = """ -declare i8 @llvm.cttz.i8(i8, i1); -define i64 @entry(i64 %0, $(USE_PTR ? "ptr" : "i64") %1, i64 %2) #0 { -top: - $(USE_PTR ? "" : "%ivars = inttoptr i64 %1 to i64*") - %btmp = insertelement <8 x i64> undef, i64 %0, i64 0 - %var = shufflevector <8 x i64> %btmp, <8 x i64> undef, <8 x i32> zeroinitializer - %lenm7 = add nsw i64 %2, -7 - %dosimditer = icmp ugt i64 %2, 7 - br i1 %dosimditer, label %L9.lr.ph, label %L32 - -L9.lr.ph: - %len8 = and i64 %2, 9223372036854775800 - br label %L9 - -L9: - %i = phi i64 [ 0, %L9.lr.ph ], [ %vinc, %L30 ] - %ivarsi = getelementptr inbounds i64, $(USE_PTR ? "ptr %1" : "i64* %ivars"), i64 %i - $(USE_PTR ? "" : "%vpvi = bitcast i64* %ivarsi to <8 x i64>*") - %v = load <8 x i64>, $(USE_PTR ? "ptr %ivarsi" : "<8 x i64> * %vpvi"), align 8 - %m = icmp eq <8 x i64> %v, %var - %mu = bitcast <8 x i1> %m to i8 - %matchnotfound = icmp eq i8 %mu, 0 - br i1 %matchnotfound, label %L30, label %L17 - -L17: - %tz8 = call i8 @llvm.cttz.i8(i8 %mu, i1 true) - %tz64 = zext i8 %tz8 to i64 - %vis = add nuw i64 %i, %tz64 - br label %common.ret - -common.ret: - %retval = phi i64 [ %vis, %L17 ], [ -1, %L32 ], [ %si, %L51 ], [ -1, %L67 ] - ret i64 %retval - -L30: - %vinc = add nuw nsw i64 %i, 8 - %continue = icmp slt i64 %vinc, %lenm7 - br i1 %continue, label %L9, label %L32 - -L32: - %cumi = phi i64 [ 0, %top ], [ %len8, %L30 ] - %done = icmp eq i64 %cumi, %2 - br i1 %done, label %common.ret, label %L51 - -L51: - %si = phi i64 [ %inc, %L67 ], [ %cumi, %L32 ] - %spi = getelementptr inbounds i64, $(USE_PTR ? "ptr %1" : "i64* %ivars"), i64 %si - %svi = load i64, $(USE_PTR ? "ptr" : "i64*") %spi, align 8 - %match = icmp eq i64 %svi, %0 - br i1 %match, label %common.ret, label %L67 - -L67: - %inc = add i64 %si, 1 - %dobreak = icmp eq i64 %inc, %2 - br i1 %dobreak, label %common.ret, label %L51 - -} -attributes #0 = { alwaysinline } -""" - -function _findfirstequal(vpivot::Int64, ptr::Ptr{Int64}, len::Int64) - return Base.llvmcall( - (FFE_IR, "entry"), - Int64, - Tuple{Int64, Ptr{Int64}, Int64}, - vpivot, - ptr, - len - ) -end - -""" - findfirstequal(x::Int64,A::DenseVector{Int64}) - -Finds the first index in `A` where the value equals `x`. -""" -findfirstequal(vpivot, ivars) = findfirst(isequal(vpivot), ivars) -function findfirstequal(vpivot::Int64, ivars::DenseVector{Int64}) - GC.@preserve ivars begin - ret = _findfirstequal(vpivot, pointer(ivars), length(ivars)) - end - return ret < 0 ? nothing : ret + 1 -end # Generate the SIMD "find first lane matching predicate" IR for an arbitrary -# scalar type and LLVM compare predicate. Modelled on `FFE_IR` (the equality -# scan): load 8 lanes at a time, compare against a broadcast of the search -# value, bitcast the i1×8 mask to i8, `cttz` to find the first set bit. The -# tail past the last full chunk is handled scalar-wise. +# scalar type and LLVM compare predicate. Load 8 lanes at a time, compare +# against a broadcast of the search value, bitcast the i1×8 mask to i8, +# `cttz` to find the first set bit. The tail past the last full chunk is +# handled scalar-wise. +# +# Used to back four equality / inequality SIMD primitives: +# - `_findfirstequal` — exact equality, Int64 (predicate `eq`) +# - `_simd_first_gt`/`_ge` — strict / non-strict greater-than, Int64 +# (predicates `sgt` / `sge`) +# - same pair for Float64 — predicates `ogt` / `oge` (ordered compares) function _simd_scan_ir(t, pred) cmp = pred[1] in ('o', 'u') ? "fcmp" : "icmp" return """ @@ -156,6 +95,43 @@ function _simd_scan_ir(t, pred) """ end +const FFE_IR = _simd_scan_ir("i64", "eq") + +function _findfirstequal(vpivot::Int64, ptr::Ptr{Int64}, len::Int64) + return Base.llvmcall( + (FFE_IR, "entry"), + Int64, + Tuple{Int64, Ptr{Int64}, Int64}, + vpivot, + ptr, + len + ) +end + +""" + findfirstequal(x, A) -> Union{Int, Nothing} + +Find the first index in `A` where the value equals `x`. Returns `nothing` +if `x` does not occur in `A`. + +This function does **not** assume `A` is sorted. For sorted vectors, see +[`findfirstsortedequal`](@ref) (a bisect-then-SIMD specialization on +`DenseVector{Int64}`) or [`findequal`](@ref) (the strategy-framework +equality wrapper that returns an `Int` with a sentinel). + +The `(x::Int64, A::DenseVector{Int64})` method uses a custom LLVM IR SIMD +scan (load 8 lanes, `icmp eq`, `cttz` on the mask) — about 8× faster than +the scalar `findfirst(==(x), v)` on modern x86-64. Every other element-type +and array-storage combination falls back to `findfirst(isequal(x), A)`. +""" +findfirstequal(vpivot, ivars) = findfirst(isequal(vpivot), ivars) +function findfirstequal(vpivot::Int64, ivars::DenseVector{Int64}) + GC.@preserve ivars begin + ret = _findfirstequal(vpivot, pointer(ivars), length(ivars)) + end + return ret < 0 ? nothing : ret + 1 +end + const _SIMD_GT_I64_IR = _simd_scan_ir("i64", "sgt") const _SIMD_GE_I64_IR = _simd_scan_ir("i64", "sge") const _SIMD_GT_F64_IR = _simd_scan_ir("double", "ogt") @@ -196,9 +172,21 @@ function _simd_first_ge(x::Float64, ptr::Ptr{Float64}, len::Int64) end """ -findfirstsortedequal(vars::DenseVector{Int64}, var::Int64)::Union{Int64,Nothing} - -Note that this differs from `searchsortedfirst` by returning `nothing` when absent. + findfirstsortedequal(var::Int64, vars::DenseVector{Int64}) -> Union{Int64, Nothing} + +Find the index of the first occurrence of `var` in the sorted vector +`vars`. Returns `nothing` if `var` does not occur. Specialized for +`DenseVector{Int64}` via a branchless binary bisection down to a small +basecase, followed by the same SIMD equality scan that backs +[`findfirstequal`](@ref) — faster than plain `findfirst(==(var), vars)` +or `searchsortedfirst` + post-check for typical Int64 vectors. + +The strategy-framework equivalent is +[`findequal(BisectThenSIMD(), vars, var)`](@ref findequal); that wrapper +returns an `Int` with a sentinel (`firstindex(v) - 1`) for "not found", +which is type-stable and composes with the rest of the strategy +dispatch. Prefer `findequal` for new code; `findfirstsortedequal` remains +as the dedicated `Union{Int64, Nothing}`-returning name. """ function findfirstsortedequal( var::Int64, @@ -232,7 +220,7 @@ end # `BracketGallop` strategy. Not part of the public API in 2.x — use # `searchsortedfirst(BracketGallop(), v, x, guess)` / # `searchsortedlast(BracketGallop(), v, x, guess)` instead. -function bracketstrictlymontonic( +function bracketstrictlymonotonic( v::AbstractVector, x, guess::T, @@ -267,7 +255,7 @@ function bracketstrictlymontonic( return lo, hi end -# Internal: companion to `bracketstrictlymontonic` for the `searchsortedfirst` +# Internal: companion to `bracketstrictlymonotonic` for the `searchsortedfirst` # polarity. The original galloping uses `lt(o, x, v[lo])` (i.e., `x < v[lo]`) # to choose direction, which is the right test for `searchsortedlast`: when # `x == v[lo]`, the answer is `>= lo` so we gallop right. For @@ -275,7 +263,7 @@ end # earlier duplicates) — so we need the inverted polarity `lt(o, v[lo], x)` # (i.e., `v[lo] < x`). Without this, BracketGallop.searchsortedfirst returns # the wrong index when the hint lands on a run of duplicates. -function bracketstrictlymontonic_first( +function bracketstrictlymonotonic_first( v::AbstractVector, x, guess::T, @@ -501,15 +489,29 @@ SearchProperties() = SearchProperties(false, false, false) @inline _has_nan(::AbstractVector) = false """ - SearchProperties(v::AbstractVector) + SearchProperties(v::AbstractVector; linear_tolerance = 1.0e-3) Run the linearity probe and (for floating-point eltypes) the NaN scan on `v`, returning the populated [`SearchProperties`](@ref). Cost is O(n) on floating-point vectors because of the NaN scan; for integer and non-numeric eltypes the cost is O(1) — only the sampled-linearity probe runs. + +`linear_tolerance` controls the maximum relative deviation accepted by the +sampled-linearity probe. The default `1e-3` (0.1%) matches `Auto`'s +un-cached probe behaviour. Loosen it (e.g. to `1e-2`) to accept noisier +"approximately linear" data — this widens the regime where `Auto` will pick +`InterpolationSearch` over `ExpFromLeft`. Tighten it (e.g. to `1e-4`) to be +more conservative. """ -function SearchProperties(v::AbstractVector) - return SearchProperties(true, _sampled_looks_linear(v), _has_nan(v)) +function SearchProperties( + v::AbstractVector; + linear_tolerance::Real = 1.0e-3, + ) + return SearchProperties( + true, + _sampled_looks_linear(v, Float64(linear_tolerance)), + _has_nan(v), + ) end """ @@ -593,7 +595,10 @@ const _AUTO_LINEAR_REL_TOLERANCE = 1.0e-3 # side of rejecting borderline cases. Truly uniform data — exact ranges, # evenly-spaced grids, and small-amplitude jittered data — passes; sorted # random data is rejected at all `n` tested up to ~10⁶. -@inline function _sampled_looks_linear(v::AbstractVector{<:Number}) +@inline function _sampled_looks_linear( + v::AbstractVector{<:Number}, + tol::Float64 = _AUTO_LINEAR_REL_TOLERANCE, + ) n = length(v) n < 11 && return false @inbounds begin @@ -606,17 +611,17 @@ const _AUTO_LINEAR_REL_TOLERANCE = 1.0e-3 kk = 1 + (k * nm1) ÷ 10 expected = v1 + (kk - 1) / nm1 * span rel_err = abs(v[kk] - expected) / abs_span - rel_err > _AUTO_LINEAR_REL_TOLERANCE && return false + rel_err > tol && return false end end return true end # Non-numeric eltype: can't sample, never picks InterpolationSearch. -@inline _sampled_looks_linear(::AbstractVector) = false +@inline _sampled_looks_linear(::AbstractVector, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = false # AbstractRange is definitionally uniform — accept without sampling. -@inline _sampled_looks_linear(::AbstractRange) = true +@inline _sampled_looks_linear(::AbstractRange, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = true # Strategy: BinaryBracket — ignore any hint. Base.searchsortedlast( @@ -802,12 +807,12 @@ Base.searchsortedfirst( order::Base.Order.Ordering = Base.Order.Forward ) = searchsortedfirst(BinaryBracket(), v, x; order = order) -# Strategy: BracketGallop — bracketstrictlymontonic + bounded binary search. +# Strategy: BracketGallop — bracketstrictlymonotonic + bounded binary search. function Base.searchsortedlast( ::BracketGallop, v::AbstractVector, x, hint::Integer; order::Base.Order.Ordering = Base.Order.Forward ) - lo, hi = bracketstrictlymontonic(v, x, hint, order) + lo, hi = bracketstrictlymonotonic(v, x, hint, order) return searchsortedlast(v, x, lo, hi, order) end @@ -815,7 +820,7 @@ function Base.searchsortedfirst( ::BracketGallop, v::AbstractVector, x, hint::Integer; order::Base.Order.Ordering = Base.Order.Forward ) - lo, hi = bracketstrictlymontonic_first(v, x, hint, order) + lo, hi = bracketstrictlymonotonic_first(v, x, hint, order) return searchsortedfirst(v, x, lo, hi, order) end @@ -1452,13 +1457,21 @@ end # --------------------------------------------------------------------------- """ - findequal(strategy, v, x[, hint]; order = Base.Order.Forward) - -Return the index of `x` in sorted `v` if present, or `firstindex(v) - 1` -(= 0 for 1-based vectors) if `x` is absent. Type-stable `Int` return — the -sentinel value `firstindex(v) - 1` matches the convention -`Base.searchsortedlast` already uses for "x precedes all of v", so callers -can test for "not found" with `i < firstindex(v)`. + findequal(strategy, v, x[, hint]; order = Base.Order.Forward) -> Int + +Return the index of `x` in sorted `v` if present, or the sentinel +`firstindex(v) - 1` if `x` is absent. Type-stable `Int` return — the +sentinel matches the convention `Base.searchsortedlast` already uses for +"x precedes all of v", so callers can test for "not found" with +`i < firstindex(v)`. + +For vectors with 1-based indexing (the Julia default), the sentinel is +exactly `0`, which is also `searchsortedlast`'s "x precedes all" return. +For [OffsetArrays](https://github.com/JuliaArrays/OffsetArrays.jl) and any +other vector whose `firstindex` is not `1`, the sentinel adjusts +accordingly — e.g. for a vector with `firstindex == -3`, the sentinel is +`-4`. Always test against `firstindex(v) - 1` (or equivalently +`i < firstindex(v)`), not against the literal `0`. Most strategies are handled generically: run `searchsortedfirst(strategy, v, x[, hint])` to find the candidate insertion From 9c067bdca52351ce4a1687e76117fa2013b56d7a Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 08:19:50 -0400 Subject: [PATCH 12/16] Retune Auto with SIMDLinearScan integration; 1080-cell bench sweep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive rebenchmark of `Auto`'s batched decision tree against the shipped strategies (`LinearScan`, `SIMDLinearScan`, `BracketGallop`, `ExpFromLeft`, `InterpolationSearch`) on a 1080-cell sweep covering 5 `v` patterns × 4 query patterns × 5 `n` sizes × 6 `m` sizes × 2 element types (`Int64`, `Float64`). Baseline (`Auto` before this commit): median 1.18x, p95 2.09x, max 2.78x This commit: median 1.04x, p95 1.38x, max 2.18x With `Auto(SearchProperties(v))`: median 1.03x, p95 1.38x, max 2.09x New decision-tree branches: - **`SIMDLinearScan` in the medium-gap regime.** When `v` is `DenseVector{Int64}` or `DenseVector{Float64}` (NaN-free for Float64), `Auto` now dispatches to `SIMDLinearScan` for `gap ∈ (4, _auto_simd_gap_max(v)]`. `_auto_simd_gap_max` is 64 for both eltypes — the eltype-specific accessor leaves room to lower the Int64 ceiling later without changing the Float64 path. For Float64 the NaN check consults `SearchProperties.has_nan` when a populated cache is attached; otherwise no-NaN is assumed (same trust contract Base uses for sortedness). The bench shows `SIMDLinearScan` winning 25% of cells overall, with median 1.94× speedup over `LinearScan` in the cells it wins. - **`BracketGallop` preferred over `ExpFromLeft` at large gaps.** New constant `_AUTO_GALLOP_GAP_MIN = 16`. At gap ≥ 16, `ExpFromLeft`'s 5 up-front linear probes are guaranteed to miss (the answer is much more than 5 elements past the previous-result hint), and `BracketGallop`'s doubling-from-`hint` walk is strictly faster. - **Tiered linearity probe for `InterpolationSearch`.** The strict `_AUTO_LINEAR_REL_TOLERANCE = 1e-3` gates the `_AUTO_INTERP_MIN_GAP ≤ gap < _AUTO_INTERP_LOOSE_GAP` range (8 to 256). For `gap ≥ _AUTO_INTERP_LOOSE_GAP` (256), the loose `_AUTO_LINEAR_LOOSE_TOLERANCE = 5e-2` applies — `InterpolationSearch`'s cache benefit compensates for a worse guess at large gaps, and the bounded binary-search refinement is still O(log n). This unlocks `InterpolationSearch` on approximately linear data like sorted random or jittered vectors at large `n`, while still rejecting genuinely nonlinear data (log-spaced, two-scale) where `InterpolationSearch` loses 2–3×. Bug fix in `_estimate_avg_gap`: the previous code fell back to `n ÷ m` whenever the skew flag was set, which caused `SIMDLinearScan` to be picked for tightly-clustered queries (`span_q ≈ 0`) where `LinearScan`'s scalar walk is 5× faster. The skew flag now serves its intended purpose as a binary `InterpolationSearch`-unsuitability signal, while the gap value is always the span-based estimate. Reproducibility: - `bench/auto_sweep.jl`: the full sweep. `julia --project=bench bench/auto_sweep.jl` writes `bench/results.csv` and prints a summary plus the worst 30 Auto-slack cells. - `bench/analyze.jl`: reads `results.csv` and prints `SIMDLinearScan` win-by-regime tables, the n/m gap-bucket distribution, and `Auto`'s misprediction histogram. Useful for tuning future constants. - `bench/.gitignore`: keeps `results.csv` and `Manifest.toml` out of version control. Docs: - `auto.md` rewrites the decision-tree section, replaces the crossover-constants table (now includes `_auto_simd_gap_max`, `_AUTO_GALLOP_GAP_MIN`, `_AUTO_INTERP_LOOSE_GAP`, `_AUTO_LINEAR_LOOSE_TOLERANCE`), updates the headline-results table with the 1080-cell sweep numbers, and links to the actual bench script. The inline script is kept as a minimum-viable standalone reproducer. - `NEWS.md` adds the retuning section with before/after numbers, the new branches, and the bug-fix description. All 84120 tests pass (no behavioural test changes — the retuning is internal to Auto's branch selection). Co-Authored-By: Chris Rackauckas --- NEWS.md | 44 ++++++ bench/.gitignore | 2 + bench/Project.toml | 6 + bench/analyze.jl | 146 ++++++++++++++++++++ bench/auto_sweep.jl | 279 ++++++++++++++++++++++++++++++++++++++ docs/src/auto.md | 111 ++++++++++----- src/FindFirstFunctions.jl | 135 ++++++++++++++++-- 7 files changed, 674 insertions(+), 49 deletions(-) create mode 100644 bench/.gitignore create mode 100644 bench/Project.toml create mode 100644 bench/analyze.jl create mode 100644 bench/auto_sweep.jl diff --git a/NEWS.md b/NEWS.md index 3866a44..735d043 100644 --- a/NEWS.md +++ b/NEWS.md @@ -337,6 +337,50 @@ nothing, requiring `FindFirstFunctions.LinearScan()` qualification): API. Downstream code that previously qualified every call (most of the SciML ecosystem) continues to work — the qualified names still resolve. +### Auto retuning with SIMDLinearScan integration + +`Auto`'s batched decision tree has been retuned based on a 1080-cell +benchmark sweep covering 5 `v` patterns × 4 query patterns × 5 `n` sizes × +6 `m` sizes × 2 element types. The previous tree fell out of the bench +sweep with median 1.18× / p95 2.09× / max 2.78× slack against the per-cell +optimum; the retuned tree comes in at median 1.04× / p95 1.38× / +max 2.18×. + +New branches and constants: + + - `SIMDLinearScan` is now dispatched by `Auto` in the medium-gap regime + (`gap ∈ (4, _auto_simd_gap_max(v)]`) when `v` is `DenseVector{Int64}` + or `DenseVector{Float64}`. `_auto_simd_gap_max` is 64 for both eltypes. + For Float64 the dispatch consults `SearchProperties.has_nan` if + available; otherwise no-NaN is assumed, consistent with how + `Base.searchsortedlast` already trusts the input is sorted. + - `BracketGallop` is preferred over `ExpFromLeft` at `gap ≥ 16` (new + constant `_AUTO_GALLOP_GAP_MIN`). The five up-front linear probes of + `ExpFromLeft` are guaranteed to miss once the answer is more than five + elements past the previous-result hint, so the doubling-from-`hint` + walk of `BracketGallop` is strictly faster at large gaps. + - Tiered linearity probe for `InterpolationSearch`. The strict + `_AUTO_LINEAR_REL_TOLERANCE = 1e-3` still gates the + `_AUTO_INTERP_MIN_GAP ≤ gap < _AUTO_INTERP_LOOSE_GAP` (8 to 256) range + — only truly uniform data passes. For `gap ≥ _AUTO_INTERP_LOOSE_GAP` + (256), the loose `_AUTO_LINEAR_LOOSE_TOLERANCE = 5e-2` applies, which + accepts approximately linear data (sorted random, jittered) where the + O(√n)/n order-statistic deviation is well below 5 %. `InterpolationSearch` + still loses on log-spaced and two-scale at any gap, and the strict tier + catches those. + +Bug fix: `_estimate_avg_gap` no longer falls back to `n ÷ m` when the +skew flag is set. The fallback caused `SIMDLinearScan` to be picked for +tightly-clustered queries (span_q ≈ 0) where `LinearScan`'s scalar walk +is 5× faster. The skew flag now serves its intended purpose as a binary +InterpolationSearch-unsuitability signal, while the actual gap value is +always the span-based estimate. + +Reproducibility: the full sweep is checked in at `bench/auto_sweep.jl` +with an analysis helper at `bench/analyze.jl`. See `auto.md` for the +decision tree, the per-regime winner distribution, and how to run the +sweep locally. + ### Cleanup: typo fix, FFE_IR unification, tolerance kwarg - Internal helper `bracketstrictlymontonic` renamed to diff --git a/bench/.gitignore b/bench/.gitignore new file mode 100644 index 0000000..99b8e25 --- /dev/null +++ b/bench/.gitignore @@ -0,0 +1,2 @@ +results.csv +Manifest.toml diff --git a/bench/Project.toml b/bench/Project.toml new file mode 100644 index 0000000..db3a12b --- /dev/null +++ b/bench/Project.toml @@ -0,0 +1,6 @@ +[deps] +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +FindFirstFunctions = "64ca27bc-2ba2-4a57-88aa-44e436879224" +PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" +StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" diff --git a/bench/analyze.jl b/bench/analyze.jl new file mode 100644 index 0000000..b050678 --- /dev/null +++ b/bench/analyze.jl @@ -0,0 +1,146 @@ +using DelimitedFiles, Statistics, Printf + +const CSV = joinpath(@__DIR__, "results.csv") + +# Read raw data +raw, header = readdlm(CSV, ','; header = true) +header = vec(string.(header)) +function col(name) + j = findfirst(==(name), header) + j === nothing && error("no column $name") + return j +end + +const STRATS = ["LinearScan", "SIMDLinearScan", "BracketGallop", "ExpFromLeft", "InterpolationSearch"] + +function row_winner(row) + times = Float64[parse(Float64, string(row[col(s)])) for s in STRATS] + j = argmin(times) + return STRATS[j], times[j] +end + +function ratio_to(row, strat_name) + times = Float64[parse(Float64, string(row[col(s)])) for s in STRATS] + best = minimum(times) + return parse(Float64, string(row[col(strat_name)])) / best +end + +println("==> Where does SIMDLinearScan win?") +simd_wins = [] +for i in axes(raw, 1) + local row = raw[i, :] + local winner, _ = row_winner(row) + if winner == "SIMDLinearScan" + push!( + simd_wins, ( + eltype = string(row[col("eltype")]), + v = string(row[col("v_kind")]), + q = string(row[col("q_kind")]), + n = parse(Int, string(row[col("n")])), + m = parse(Int, string(row[col("m")])), + ) + ) + end +end +n_simd_wins = length(simd_wins) +println(" SIMDLinearScan wins in $n_simd_wins cells") +println() + +# Tabulate where SIMD wins by m (gap proxy) +println("==> SIMDLinearScan wins by m (proxy for batched-gap regime):") +by_m = Dict{Int, Int}() +for c in simd_wins + by_m[c.m] = get(by_m, c.m, 0) + 1 +end +for m in sort(collect(keys(by_m))) + @printf(" m=%5d: %d cells\n", m, by_m[m]) +end +println() + +# By eltype +println("==> SIMDLinearScan wins by eltype:") +by_eltype = Dict{String, Int}() +for c in simd_wins + by_eltype[c.eltype] = get(by_eltype, c.eltype, 0) + 1 +end +for k in sort(collect(keys(by_eltype))) + println(" $k: $(by_eltype[k]) cells") +end +println() + +# Now show: for sorted-batched cells where SIMDLinearScan wins, what's the +# ratio of LinearScan/ExpFromLeft to SIMDLinearScan? This tells us the +# magnitude of the improvement. +println("==> SIMDLinearScan win margin over LinearScan and ExpFromLeft:") +println(" (Higher = bigger SIMD speedup over the second-best Auto candidate)") +margins = [] +for i in axes(raw, 1) + row = raw[i, :] + winner, best = row_winner(row) + if winner == "SIMDLinearScan" + t_simd = best + t_lin = parse(Float64, string(row[col("LinearScan")])) + t_exp = parse(Float64, string(row[col("ExpFromLeft")])) + push!( + margins, ( + ratio_lin = t_lin / t_simd, + ratio_exp = t_exp / t_simd, + n = parse(Int, string(row[col("n")])), + m = parse(Int, string(row[col("m")])), + ) + ) + end +end +println(" SIMD vs LinearScan: median $(median(m.ratio_lin for m in margins))x, max $(maximum(m.ratio_lin for m in margins))x") +println(" SIMD vs ExpFromLeft: median $(median(m.ratio_exp for m in margins))x, max $(maximum(m.ratio_exp for m in margins))x") +println() + +# What does Auto pick in the cells where SIMDLinearScan would win? +# Find the m, n, gap regime where SIMDLinearScan beats LinearScan AND ExpFromLeft. +println("==> Best regime for SIMDLinearScan (cells where SIMD wins by >20%):") +significant_simd_wins = filter(c -> c.ratio_lin > 1.2 && c.ratio_exp > 1.2, margins) +println(" $(length(significant_simd_wins)) cells where SIMD beats both LinearScan and ExpFromLeft by >20%") +n_by_m_n = Dict{Tuple{Int, Int}, Int}() +for c in significant_simd_wins + n_by_m_n[(c.n, c.m)] = get(n_by_m_n, (c.n, c.m), 0) + 1 +end +for (n, m) in sort(collect(keys(n_by_m_n))) + @printf(" n=%5d m=%5d: %d cells\n", n, m, n_by_m_n[(n, m)]) +end +println() + +# Compute: in each cell, the GAP. gap = n * span(queries)/span(v) / m +# (the same heuristic Auto uses). Use n/m as a rough proxy since exact gap +# depends on the query distribution which isn't recoverable from CSV alone. +println("==> n/m ratio for SIMD-winning cells (rough gap proxy):") +nm_buckets = Dict{Int, Int}() +for c in simd_wins + bucket = c.n ÷ c.m + # Round to a power-of-2 bucket + log_bucket = bucket == 0 ? 0 : floor(Int, log2(bucket)) + nm_buckets[log_bucket] = get(nm_buckets, log_bucket, 0) + 1 +end +for b in sort(collect(keys(nm_buckets))) + @printf(" n/m in [2^%d, 2^%d): %d cells\n", b, b + 1, nm_buckets[b]) +end +println() + +println("==> What strategy does Auto pick in cells where SIMD would win?") +auto_picks_when_simd = Dict{String, Int}() +for i in axes(raw, 1) + row = raw[i, :] + winner, _ = row_winner(row) + if winner == "SIMDLinearScan" + # We don't know Auto's pick from the CSV, but we know Auto's time. + # The closest strategy time to Auto's time tells us the pick. + t_auto = parse(Float64, string(row[col("Auto")])) + candidates = [(s, parse(Float64, string(row[col(s)]))) for s in STRATS] + # Pick the strategy whose time is closest to Auto's + # (within 20% — heuristic). + closest = argmin(c -> abs(c[2] - t_auto), candidates) + auto_picks_when_simd[closest[1]] = get(auto_picks_when_simd, closest[1], 0) + 1 + end +end +for (s, n) in sort(collect(pairs(auto_picks_when_simd)); by = x -> -x[2]) + println(" Auto -> $s: $n cells (out of $(length(simd_wins)))") +end diff --git a/bench/auto_sweep.jl b/bench/auto_sweep.jl new file mode 100644 index 0000000..dcd41af --- /dev/null +++ b/bench/auto_sweep.jl @@ -0,0 +1,279 @@ +using FindFirstFunctions, StableRNGs, BenchmarkTools, Statistics, Printf + +const F = FindFirstFunctions + +# -------------------------------------------------------------------------- +# Strategy registry — every strategy that competes in the sorted-batched +# regime. BinaryBracket is excluded from the per-cell winner pool because it +# never wins under any reasonable workload (no hint = full binary search +# per query); it's only useful as a fallback. Auto's actual choices are +# LinearScan / SIMDLinearScan / ExpFromLeft / InterpolationSearch. +# -------------------------------------------------------------------------- +const STRATS = [ + ("LinearScan", F.LinearScan()), + ("SIMDLinearScan", F.SIMDLinearScan()), + ("BracketGallop", F.BracketGallop()), + ("ExpFromLeft", F.ExpFromLeft()), + ("InterpolationSearch", F.InterpolationSearch()), +] + +# -------------------------------------------------------------------------- +# v patterns (sorted vectors of length n) +# -------------------------------------------------------------------------- +function make_v(::Val{:uniform}, ::Type{T}, n, seed) where {T <: AbstractFloat} + return collect(T, range(zero(T), T(n); length = n)) +end +function make_v(::Val{:uniform}, ::Type{T}, n, seed) where {T <: Integer} + return collect(T, T(1):T(n)) +end +function make_v(::Val{:jittered}, ::Type{T}, n, seed) where {T <: AbstractFloat} + rng = StableRNG(seed) + base = collect(range(0.0, Float64(n); length = n)) + return convert(Vector{T}, sort!(base .+ 0.1 .* (rand(rng, n) .- 0.5))) +end +function make_v(::Val{:jittered}, ::Type{T}, n, seed) where {T <: Integer} + rng = StableRNG(seed) + raw = sort!(unique!(rand(rng, T(1):T(2n), n))) + return convert(Vector{T}, raw) +end +function make_v(::Val{:logspaced}, ::Type{T}, n, seed) where {T <: AbstractFloat} + return collect(T, exp.(range(0.0, log(1.0e6); length = n))) +end +function make_v(::Val{:logspaced}, ::Type{T}, n, seed) where {T <: Integer} + raw = sort!(unique!(round.(T, exp.(range(0.0, log(Float64(10n)); length = n))))) + return convert(Vector{T}, raw) +end +function make_v(::Val{:twoscale}, ::Type{T}, n, seed) where {T <: AbstractFloat} + h = n ÷ 2 + return convert( + Vector{T}, + sort!(vcat(range(0.0, 0.1n; length = h), range(0.1n, Float64(n); length = n - h))) + ) +end +function make_v(::Val{:twoscale}, ::Type{T}, n, seed) where {T <: Integer} + h = n ÷ 2 + a = round.(T, range(1.0, 0.1n; length = h)) + b = round.(T, range(0.1n + 1, Float64(n); length = n - h)) + return convert(Vector{T}, sort!(vcat(a, b))) +end +function make_v(::Val{:random_sorted}, ::Type{T}, n, seed) where {T <: AbstractFloat} + return convert(Vector{T}, sort!(rand(StableRNG(seed), n) .* n)) +end +function make_v(::Val{:random_sorted}, ::Type{T}, n, seed) where {T <: Integer} + return convert(Vector{T}, sort!(rand(StableRNG(seed), T(1):T(10n), n))) +end + +# -------------------------------------------------------------------------- +# query patterns +# -------------------------------------------------------------------------- +function _to_eltype(v, xs) + T = eltype(v) + return T <: Integer ? convert(Vector{T}, round.(T, xs)) : convert(Vector{T}, xs) +end +function make_q(::Val{:dense}, v, m, seed) + raw = collect(range(Float64(first(v)), Float64(last(v)); length = m)) + return _to_eltype(v, raw) +end +function make_q(::Val{:sparse}, v, m, seed) + rng = StableRNG(seed) + span = Float64(last(v)) - Float64(first(v)) + raw = sort!(Float64(first(v)) .+ rand(rng, m) .* span) + return _to_eltype(v, raw) +end +function make_q(::Val{:clustered}, v, m, seed) + rng = StableRNG(seed) + j = max(1, length(v) ÷ 4) + lo = Float64(v[j]) + hi = Float64(v[min(j + 1, length(v))]) + span = hi - lo + raw = sort!(lo .+ rand(rng, m) .* max(span, 1.0)) + return _to_eltype(v, raw) +end +function make_q(::Val{:sorted_random}, v, m, seed) + rng = StableRNG(seed) + span = Float64(last(v)) - Float64(first(v)) + raw = sort!(Float64(first(v)) .+ rand(rng, m) .* span) + return _to_eltype(v, raw) +end + +# -------------------------------------------------------------------------- +# Bench a single (v, queries, strategy) cell. Returns time in nanoseconds. +# Uses a fixed-repeat loop to avoid BenchmarkTools per-call overhead, which +# dominates fast strategies on small m. +# -------------------------------------------------------------------------- +function bench_one(v, queries, strat, out, reps::Int = 5) + # Warm up + F.searchsortedlast!(out, v, queries; strategy = strat) + # Measure + best = typemax(Float64) + for _ in 1:reps + t = @elapsed F.searchsortedlast!(out, v, queries; strategy = strat) + best = min(best, t) + end + return best * 1.0e9 / length(queries) # ns per query +end + +# -------------------------------------------------------------------------- +# Full sweep +# -------------------------------------------------------------------------- +function run_sweep(; + v_kinds = (:uniform, :jittered, :logspaced, :twoscale, :random_sorted), + q_kinds = (:dense, :sparse, :clustered, :sorted_random), + ns = (256, 1024, 4096, 16_384, 65_536), + ms = (4, 16, 64, 256, 1024, 4096), + eltypes = (Int64, Float64), + seed = 2026, + ) + rows = [] + cell_idx = 0 + n_cells = length(v_kinds) * length(q_kinds) * length(ns) * length(ms) * length(eltypes) + + for T in eltypes, v_kind in v_kinds, q_kind in q_kinds, n in ns, m in ms + m > n && continue + cell_idx += 1 + v = make_v(Val(v_kind), T, n, seed) + q = make_q(Val(q_kind), v, m, seed + 1) + out = Vector{Int}(undef, m) + + # Build SearchProperties for the cached-Auto comparison + props = F.SearchProperties(v) + + times = Dict{String, Float64}() + for (name, strat) in STRATS + t = bench_one(v, q, strat, out) + times[name] = t + end + # Auto (un-cached) and Auto (cached) + times["Auto"] = bench_one(v, q, F.Auto(), out) + times["Auto+props"] = bench_one(v, q, F.Auto(props), out) + + push!( + rows, ( + eltype = string(T), + v_kind = string(v_kind), + q_kind = string(q_kind), + n = n, + m = m, + times = times, + ) + ) + + if cell_idx % 25 == 0 + best_explicit = minimum(times[s] for s in first.(STRATS)) + @printf( + " [%4d/%4d] %s/%s/%s n=%d m=%d best=%.0f ns/q Auto=%.0f Auto+p=%.0f\n", + cell_idx, n_cells, T, v_kind, q_kind, n, m, + best_explicit, times["Auto"], times["Auto+props"] + ) + end + end + return rows +end + +# -------------------------------------------------------------------------- +# Analyze: per-cell winner, Auto slack vs best +# -------------------------------------------------------------------------- +function analyze(rows) + strat_names = first.(STRATS) + summary = Dict{String, Int}() + auto_slacks = Float64[] + auto_cached_slacks = Float64[] + + for r in rows + # Find the per-cell winner among the explicit strategies. + per_cell = [(s, r.times[s]) for s in strat_names] + best_t = minimum(p[2] for p in per_cell) + best_name = first(per_cell[argmin([p[2] for p in per_cell])]) + summary[best_name] = get(summary, best_name, 0) + 1 + push!(auto_slacks, r.times["Auto"] / best_t) + push!(auto_cached_slacks, r.times["Auto+props"] / best_t) + end + + println() + println("Per-cell winners (across $(length(rows)) cells):") + for name in strat_names + n = get(summary, name, 0) + @printf(" %-22s %5d cells (%5.1f%%)\n", name, n, 100 * n / length(rows)) + end + + println() + @printf("Auto slack (Auto-time / per-cell-best-time):\n") + @printf( + " median %.2fx, mean %.2fx, p90 %.2fx, p95 %.2fx, max %.2fx\n", + median(auto_slacks), mean(auto_slacks), + quantile(auto_slacks, 0.9), quantile(auto_slacks, 0.95), + maximum(auto_slacks) + ) + @printf("Auto(props) slack:\n") + @printf( + " median %.2fx, mean %.2fx, p90 %.2fx, p95 %.2fx, max %.2fx\n", + median(auto_cached_slacks), mean(auto_cached_slacks), + quantile(auto_cached_slacks, 0.9), quantile(auto_cached_slacks, 0.95), + maximum(auto_cached_slacks) + ) + + return summary, auto_slacks, auto_cached_slacks +end + +function print_worst_cells(rows, k = 20) + strat_names = first.(STRATS) + println() + println("Worst Auto-slack cells (current Auto picks strategy that's much slower than optimal):") + @printf( + " %-7s %-15s %-15s %6s %6s %-20s slack(Auto) slack(Auto+p)\n", + "eltype", "v_kind", "q_kind", "n", "m", "best (time)" + ) + scored = [ + (r, r.times["Auto"] / minimum(r.times[s] for s in strat_names)) + for r in rows + ] + sort!(scored; by = x -> -x[2]) + for (r, slack) in scored[1:min(k, length(scored))] + best_t = minimum(r.times[s] for s in strat_names) + best_name = strat_names[argmin([r.times[s] for s in strat_names])] + slack_cached = r.times["Auto+props"] / best_t + @printf( + " %-7s %-15s %-15s %6d %6d %-15s %.0fns %5.2fx %5.2fx\n", + r.eltype, r.v_kind, r.q_kind, r.n, r.m, best_name, best_t, + slack, slack_cached + ) + end + return +end + +println("FindFirstFunctions Auto algorithm benchmark sweep") +println("="^70) +println("Strategies:") +for (name, _) in STRATS + println(" ", name) +end +println("Plus: Auto(), Auto(SearchProperties(v))") +println() +println("Starting sweep...") +println() + +@time rows = run_sweep() + +println() +println("Sweep complete.") +println() + +analyze(rows) +print_worst_cells(rows, 30) + +open(joinpath(@__DIR__, "results.csv"), "w") do io + header = ["eltype", "v_kind", "q_kind", "n", "m"] + append!(header, first.(STRATS)) + push!(header, "Auto", "Auto+props") + println(io, join(header, ",")) + for r in rows + cols = String[r.eltype, r.v_kind, r.q_kind, string(r.n), string(r.m)] + for s in first.(STRATS) + push!(cols, string(r.times[s])) + end + push!(cols, string(r.times["Auto"])) + push!(cols, string(r.times["Auto+props"])) + println(io, join(cols, ",")) + end +end +println("\nRaw data: bench/results.csv") diff --git a/docs/src/auto.md b/docs/src/auto.md index b42bc5b..74fe7ff 100644 --- a/docs/src/auto.md +++ b/docs/src/auto.md @@ -33,27 +33,45 @@ or pathologically-spaced data it falls back to `n ÷ m`. m == 0 → return out unchanged m == 1 → one direct unhinted call queries unsorted → unhinted Base.searchsortedlast loop -gap ≤ 4 → LinearScan # _AUTO_BATCH_LINEAR_GAP -gap ≥ 8 and n ≥ 1024 and m ≥ 2 - and not skewed and looks-linear → InterpolationSearch +gap ≤ 4 → LinearScan +4 < gap ≤ _auto_simd_gap_max(v) + AND SIMD-eligible (Int64/Float64) → SIMDLinearScan +gap ≥ 8 AND n ≥ 1024 AND m ≥ 2 + AND not skewed + AND linearity probe accepts → InterpolationSearch +gap ≥ 16 → BracketGallop otherwise → ExpFromLeft ``` -The "looks-linear" check is a tightened version of the `Guesser`'s -`looks_linear` probe: it reads 11 elements at fixed positions and accepts -when every interior point sits within 0.1% of the straight line through -`v[1]` and `v[end]`. It runs in ~25 ns regardless of `n`. The tight -tolerance is essential — at large `n` the order-statistic variance of -random-sorted data is small enough that a 5% threshold would falsely pass -on irregular data. - -The "skewed" check guards the same `InterpolationSearch` branch from the -opposite direction: if the queries are clustered into one region of their -span (median query more than 20% off the midpoint of the query span), -`Auto` picks `ExpFromLeft` even on linear `v`, because consecutive queries -land in the same neighbourhood and the previous-result hint is worth more -than the linear-extrapolation guess. Skew detection is gated on `m ≥ 10` — -for smaller `m` the median sampling variance overwhelms the signal. +`_auto_simd_gap_max(v)` is 64 for `DenseVector{Int64}` and `DenseVector{Float64}`, +and 0 (never picked) for any other element type. For Float64 the SIMD path +requires `v` to be NaN-free; if a populated `SearchProperties(v)` is attached +to `Auto`, the cached `has_nan` flag is consulted, otherwise no-NaN is assumed +(the same trust contract `Base.searchsortedlast` uses for sortedness of `v`). + +The "linearity probe accepts" check is tiered: + + - For `_AUTO_INTERP_MIN_GAP ≤ gap < _AUTO_INTERP_LOOSE_GAP` (8 to 256): + strict 0.1% sampled tolerance — only truly uniform data passes. + - For `gap ≥ _AUTO_INTERP_LOOSE_GAP` (≥ 256): loose 5% tolerance — at + these gap sizes, `InterpolationSearch`'s cache benefit compensates for + a worse guess, and the bounded-binary-search refinement is still + O(log n). This unlocks `InterpolationSearch` on approximately linear + data like sorted random or mildly jittered vectors at large `n`. + +The "skewed" check guards `InterpolationSearch` from the opposite direction: +if the queries are clustered into one region of their span (median query +more than 20% off the midpoint of the query span), `Auto` falls through to +`BracketGallop` / `ExpFromLeft`, because consecutive queries land in the +same neighbourhood and the previous-result hint is worth more than the +linear-extrapolation guess. Skew detection is gated on `m ≥ 10` — for +smaller `m` the median sampling variance overwhelms the signal. + +The `BracketGallop` fallback at `gap ≥ _AUTO_GALLOP_GAP_MIN` (= 16) exists +because, at large gaps, `ExpFromLeft`'s five up-front linear probes are +guaranteed to miss — the answer is much more than 5 elements past the +previous-result hint. `BracketGallop` skips that wasted preamble and starts +doubling from one position past `hint`. ## Crossover constants @@ -63,11 +81,15 @@ reproduced here so they are easy to find from the docs: | Constant | Value | What it gates | |---|---|---| | `_AUTO_LINEAR_THRESHOLD` | 16 | Per-query `LinearScan` vs `BracketGallop` crossover on hinted calls. | -| `_AUTO_BATCH_LINEAR_GAP` | 4 | Batched `LinearScan` vs `ExpFromLeft` crossover. | +| `_AUTO_BATCH_LINEAR_GAP` | 4 | Batched `LinearScan` ceiling. | +| `_AUTO_SIMD_GAP_MAX` (Int64 / Float64) | 64 / 64 | Maximum gap for `SIMDLinearScan` on dense Int64 / Float64. | +| `_AUTO_GALLOP_GAP_MIN` | 16 | Above this gap, prefer `BracketGallop` over `ExpFromLeft` when `InterpolationSearch` isn't picked. | | `_AUTO_INTERP_MIN_GAP` | 8 | Minimum gap below which `InterpolationSearch` is never picked. | | `_AUTO_INTERP_MIN_N` | 1024 | Minimum `length(v)` below which `InterpolationSearch` is never picked. | | `_AUTO_INTERP_MIN_M` | 2 | Minimum `length(queries)`; single-query batches skip the heuristic entirely. | -| `_AUTO_LINEAR_REL_TOLERANCE` | 1.0e-3 | Tolerance of the sampled-linearity probe. | +| `_AUTO_INTERP_LOOSE_GAP` | 256 | At this gap, the linearity probe switches to the loose tolerance. | +| `_AUTO_LINEAR_REL_TOLERANCE` | 1.0e-3 | Strict-tier tolerance of the sampled-linearity probe. | +| `_AUTO_LINEAR_LOOSE_TOLERANCE` | 5.0e-2 | Loose-tier tolerance, used for `gap ≥ _AUTO_INTERP_LOOSE_GAP`. | These are not user-tunable from outside — they shipped with the version of the package documented here. Tightening or loosening them requires a PR @@ -102,9 +124,18 @@ current answer than the linear-extrapolation guess from the endpoints. ## Reproducing the benchmarks -Save this script as `bench/auto_sweep.jl` and run it with -`julia --project=bench`. It evaluates every shipped strategy against -every regime cell and reports `Auto`'s pick alongside the per-cell winner. +The full sweep lives at [`bench/auto_sweep.jl`](https://github.com/SciML/FindFirstFunctions.jl/blob/main/bench/auto_sweep.jl) +with the regime grid pre-configured. Run with +`julia --project=bench bench/auto_sweep.jl`. It evaluates every shipped +strategy against every regime cell, computes the per-cell winner, and +reports `Auto`'s slack distribution against that optimum. An analysis +helper at [`bench/analyze.jl`](https://github.com/SciML/FindFirstFunctions.jl/blob/main/bench/analyze.jl) +reads the resulting `bench/results.csv` and prints per-strategy +win-by-regime tables. + +The inline script below is the minimum-viable version of the same sweep — +copy into a file and execute if you want to validate the numbers without +cloning the repository. ```julia using BenchmarkTools, FindFirstFunctions, Random, Statistics @@ -198,18 +229,30 @@ run_sweep() ### Headline results -Across 800+ cells of the grid above, `Auto`'s wall-clock latency is: - - - within 1× of optimal in roughly half of cells (it picks the winner), - - within 1.2× of optimal in 90% of cells, - - within 1.5× of optimal at the p99 of cells. +The 2.0 sweep covers 1080 cells across 5 `v` patterns × 4 query patterns × +5 `n` sizes × 6 `m` sizes × 2 element types (`Int64`, `Float64`), measured +on AVX2 hardware. -The cells where `Auto` slack is highest are the boundary cells around -`gap ≈ 8` on borderline-linear data (jittered uniform), where the -linearity probe occasionally accepts and `InterpolationSearch` is picked -over a slightly-faster `ExpFromLeft`. The penalty is bounded — both -strategies are O(log n) worst case — and the boundary case is statistically -rare. +| Metric | `Auto()` | `Auto(SearchProperties(v))` | +|---|---|---| +| median slack | 1.04× | 1.03× | +| mean slack | 1.09× | 1.08× | +| p90 slack | 1.33× | 1.31× | +| p95 slack | 1.38× | 1.38× | +| max slack | 2.18× | 2.09× | + +Per-cell winner distribution across the sweep: + + - LinearScan: 47% of cells (small-gap regime, all eltypes) + - SIMDLinearScan: 25% of cells (medium-gap regime, Int64/Float64 dense) + - InterpolationSearch: 13% of cells (large-gap regime, ~linear v) + - ExpFromLeft: 8% of cells (small-medium-gap regime, non-SIMD eltypes) + - BracketGallop: 8% of cells (large-gap regime, non-linear v) + +The cells where `Auto` slack is highest are boundary cells at `m = 4` where +the per-cell winner is a measurement artefact (each measurement amortises +over only 4 queries, so per-call setup noise dominates). The bulk of the +distribution sits well below 1.5×. ### Reading the comparison table diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index 5bb0a6f..cf85464 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -568,18 +568,54 @@ const _AUTO_LINEAR_THRESHOLD = 16 # initial linear probes are wasted when the gap is already 0 or 1). # Above 4, ExpFromLeft handles arbitrary gap sizes via doubling — the # bench sweep shows it strictly beats BracketGallop for forward-moving -# sorted queries. +# sorted queries at gap < ~16. const _AUTO_BATCH_LINEAR_GAP = 4 # For sparse queries (gap large) on long vectors, InterpolationSearch can # beat ExpFromLeft by ~2× on uniformly-spaced data. The sampled-linearity -# check below is O(1) — 5 fixed probes — so it's cheap enough to run inside -# Auto when there's a real chance of unlocking InterpolationSearch. +# check below is O(1) — 9 probes — so it's cheap enough to run inside Auto +# when there's a real chance of unlocking InterpolationSearch. const _AUTO_INTERP_MIN_GAP = 8 const _AUTO_INTERP_MIN_N = 1024 const _AUTO_INTERP_MIN_M = 2 const _AUTO_LINEAR_REL_TOLERANCE = 1.0e-3 +# Very-sparse override: when the gap is large enough that ExpFromLeft's +# log₂(gap) doubling levels approach InterpolationSearch's log₂(n) worst-case +# binary refinement, InterpolationSearch's better cache behaviour (one +# extrapolation jump + local refine vs. many doubling probes across the +# array) wins even on non-strictly-linear data — random-sorted vectors +# included, because their order statistics deviate from a straight line by +# O(√n)/n, which is much less than the gap-related cost difference. +# +# At gap ≥ 256, a looser linearity tolerance is used. This still rejects +# genuinely-nonlinear `v` (log-spaced, two-scale), where the bench shows +# InterpolationSearch losing 2–3× to ExpFromLeft, but accepts approximately +# linear data (random_sorted, jittered) where the order-statistic variance +# is well below the loose threshold. +const _AUTO_INTERP_LOOSE_GAP = 256 +const _AUTO_LINEAR_LOOSE_TOLERANCE = 5.0e-2 + +# SIMDLinearScan wins in the medium-gap regime on `DenseVector{Int64}` and +# `DenseVector{Float64}` — 24% of cells in the bench sweep, with median +# 1.94× speedup over plain LinearScan. The threshold is eltype-specific: +# - Float64: gap ∈ (4, 64]. fcmp is heavier than icmp, so SIMD's 8-wide +# vector compare wins over the scalar walk at a higher gap than for +# integers. Bench shows SIMD winning consistently through gap ≈ 64. +# - Int64: gap ∈ (4, 16]. The scalar icmp loop is so tight that SIMD's +# constant per-call setup dominates above gap ≈ 16. Bench shows +# LinearScan recapturing the win above that crossover. +@inline _auto_simd_gap_max(::DenseVector{Int64}) = 64 +@inline _auto_simd_gap_max(::DenseVector{Float64}) = 64 +@inline _auto_simd_gap_max(::AbstractVector) = 0 # not SIMD-eligible + +# When InterpolationSearch isn't eligible and the gap is large, BracketGallop +# beats ExpFromLeft because the 5 linear probes ExpFromLeft does upfront +# are wasted (no chance the answer is within 5 of `hint = prev_result` when +# the gap is hundreds or thousands). BracketGallop just starts doubling +# immediately. The bench sweep shows this crossover at gap ≈ 16. +const _AUTO_GALLOP_GAP_MIN = 16 + # Sampled linearity check: probes v[1], v[k*n/10] for k = 1..9, v[n] and # tests whether all interior points sit within `_AUTO_LINEAR_REL_TOLERANCE` # (default 0.1%) of the straight line between v[1] and v[n]. The tight @@ -1023,10 +1059,21 @@ end # Returns `(gap, skewed)`: the estimated average step in `v`'s index space # between consecutive query results, plus a flag that's true when the -# queries' distribution is non-uniform within their span. The skew flag is -# what lets Auto reject InterpolationSearch even when the gap is large: -# `ExpFromLeft` from `prev_idx` wins on skewed queries because consecutive -# queries land in the same neighbourhood, regardless of `v` being linear. +# queries' distribution is non-uniform within their span. The two pieces of +# information serve different roles in Auto's decision tree: +# +# - `gap` is the per-query cost driver. We always use the span-based +# estimate `n * span(queries) / span(v) / m` so that tightly-clustered +# queries (span_q ≈ 0) report gap ≈ 0 regardless of `n/m`. The earlier +# `n / m` fallback for skewed queries was wrong: it caused `SIMDLinearScan` +# to be picked for clustered queries where LinearScan's tiny scalar +# walk is 5× faster (e.g. clustered queries with span_q = 1 over an +# `n = 65536` vector). +# - `skewed` is an InterpolationSearch-suitability flag. When the median +# query sits well off the midpoint of `queries[1]..queries[end]`, the +# queries are clustered within their span and the per-call linear +# extrapolation guess is worse than the previous-result hint that +# `ExpFromLeft` would use. @inline function _estimate_avg_gap( v::AbstractVector{<:Number}, queries::AbstractVector{<:Number}, m::Integer ) @@ -1053,13 +1100,10 @@ end skewed = true end end - if skewed - return (n ÷ max(1, m), true) - end ratio = span_q / span_v # Clamp ratio: queries may extend outside v's range (extrapolation). ratio = clamp(ratio, zero(ratio), one(ratio)) - return (floor(Int, n * ratio / max(1, m)), false) + return (floor(Int, n * ratio / max(1, m)), skewed) end # Non-numeric eltypes: no span subtraction possible, fall back to length ratio @@ -1250,26 +1294,77 @@ function _searchsortedlast_batched!( idx_out, v, queries, LinearScan(), order ) end + # Medium-gap regime: SIMDLinearScan wins on `DenseVector{Int64}` and + # `DenseVector{Float64}` (without NaN). For Float64, NaN presence is + # taken from `s.props.has_nan` if `SearchProperties(v)` was constructed, + # else we assume no NaN (consistent with the existing contract that + # `Base.searchsortedlast` doesn't check sortedness either). + if gap <= _auto_simd_gap_max(v) && + _auto_simd_eligible(v, s.props) + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, SIMDLinearScan(), order + ) + end # Sparse-on-large-linear: InterpolationSearch wins ~2× over ExpFromLeft # on uniformly-spaced data — but only when queries are *also* spread # roughly uniformly within their span. For skewed (clustered) queries, # `ExpFromLeft` from `prev_idx` wins even on linear v because the next # query's true index is close to the previous one's. - is_linear = s.props.has_props ? s.props.is_linear : _sampled_looks_linear(v) if !skewed && gap >= _AUTO_INTERP_MIN_GAP && length(v) >= _AUTO_INTERP_MIN_N && m >= _AUTO_INTERP_MIN_M && - is_linear + _auto_interp_eligible(v, s.props, gap) return _searchsortedlast_sorted_loop!( idx_out, v, queries, InterpolationSearch(), order ) end + # Sparse fallback: BracketGallop beats ExpFromLeft when the gap is large + # enough that ExpFromLeft's initial 5 linear probes are guaranteed to + # miss. BracketGallop starts doubling from one position past `hint`, so + # it skips the wasted linear preamble. + if gap >= _AUTO_GALLOP_GAP_MIN + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, BracketGallop(), order + ) + end return _searchsortedlast_sorted_loop!( idx_out, v, queries, ExpFromLeft(), order ) end +# InterpolationSearch eligibility: two-tier linearity check. For +# `_AUTO_INTERP_MIN_GAP ≤ gap < _AUTO_INTERP_LOOSE_GAP` we require strict +# linearity (`_AUTO_LINEAR_REL_TOLERANCE`, default 0.1%) — InterpolationSearch +# is only worth the per-call cost on truly uniform data when ExpFromLeft is +# also competitive. For `gap ≥ _AUTO_INTERP_LOOSE_GAP` we accept a looser +# tolerance (`_AUTO_LINEAR_LOOSE_TOLERANCE`, default 5%) because the cache +# benefit of one extrapolation jump + local refine compensates for a worse +# guess, but we still reject genuinely nonlinear data (log-spaced, +# two-scale) where InterpolationSearch loses 2–3× to ExpFromLeft. +@inline function _auto_interp_eligible(v, props::SearchProperties, gap::Integer) + if gap >= _AUTO_INTERP_LOOSE_GAP + # Loose probe — even on cached props, the strict `is_linear` bit may + # already reflect a tighter threshold than we need here, so run the + # sampled probe at the loose tolerance regardless of cache state. + return _sampled_looks_linear(v, _AUTO_LINEAR_LOOSE_TOLERANCE) + end + return props.has_props ? props.is_linear : _sampled_looks_linear(v) +end + +# SIMD eligibility check used by Auto's batched dispatch. The static type +# test on `v` discriminates the `DenseVector{Int64}` / `DenseVector{Float64}` +# cases that SIMDLinearScan supports. For Float64, NaN presence is taken +# from cached `SearchProperties.has_nan` when available; otherwise we +# assume no NaN — Base's positional search doesn't check sortedness either, +# and the burden of supplying populated props is on the caller for +# pathological inputs. +@inline _auto_simd_eligible(v::DenseVector{Int64}, ::SearchProperties) = true +@inline function _auto_simd_eligible(v::DenseVector{Float64}, p::SearchProperties) + return p.has_props ? !p.has_nan : true +end +@inline _auto_simd_eligible(::AbstractVector, ::SearchProperties) = false + function _searchsortedfirst_batched!( idx_out, v::AbstractVector, queries::AbstractVector, strategy::SearchStrategy, order::Base.Order.Ordering @@ -1301,16 +1396,26 @@ function _searchsortedfirst_batched!( idx_out, v, queries, LinearScan(), order ) end - is_linear = s.props.has_props ? s.props.is_linear : _sampled_looks_linear(v) + if gap <= _auto_simd_gap_max(v) && + _auto_simd_eligible(v, s.props) + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, SIMDLinearScan(), order + ) + end if !skewed && gap >= _AUTO_INTERP_MIN_GAP && length(v) >= _AUTO_INTERP_MIN_N && m >= _AUTO_INTERP_MIN_M && - is_linear + _auto_interp_eligible(v, s.props, gap) return _searchsortedfirst_sorted_loop!( idx_out, v, queries, InterpolationSearch(), order ) end + if gap >= _AUTO_GALLOP_GAP_MIN + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, BracketGallop(), order + ) + end return _searchsortedfirst_sorted_loop!( idx_out, v, queries, ExpFromLeft(), order ) From 9be83877c26e17a1de4b0115f503176d2df68ae6 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 08:37:29 -0400 Subject: [PATCH 13/16] Document BitInterpolationSearch exploration as negative result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Investigated a `BitInterpolationSearch` strategy that would reinterpret positive `DenseVector{Float64}` as `DenseVector{UInt64}` and run linear extrapolation on the IEEE bit pattern. The hypothesis was that this would beat `InterpolationSearch` on log-spaced data, since IEEE bit patterns are approximately linear in array index for geometric sequences. Implemented, correctness-verified, and benchmarked across `m ∈ {4..4096}` on `n = 65536` log-spaced Float64 with sparse queries. Result: the strategy loses to every existing alternative at every `m` (65–88 ns/q vs 19–41 ns/q for `ExpFromLeft`, 16–199 ns/q for `SIMDLinearScan`). The per-query division and Float64-from-UInt64 conversion cost more than the saved bracket refinement; on non-log-spaced data the bit-pattern guess is also strictly worse than the float-domain guess because the denormal-to-normalized transition introduces a discontinuity. `Auto` already serves log-spaced data well via `SIMDLinearScan` at medium gaps and `BracketGallop` / `ExpFromLeft` at large gaps. No new dispatch path was justified. NEWS.md adds an "Investigated but rejected" section documenting the exploration so future contributors don't re-derive the same negative result. 84120 tests pass; no behavioural change. Co-Authored-By: Chris Rackauckas --- NEWS.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/NEWS.md b/NEWS.md index 735d043..6505dae 100644 --- a/NEWS.md +++ b/NEWS.md @@ -381,6 +381,32 @@ with an analysis helper at `bench/analyze.jl`. See `auto.md` for the decision tree, the per-regime winner distribution, and how to run the sweep locally. +### Investigated but rejected: BitInterpolationSearch for log-spaced data + +A natural extension to `InterpolationSearch` was investigated: reinterpret a +positive `DenseVector{Float64}` as `DenseVector{UInt64}`, then run the +linear-extrapolation guess on the IEEE bit pattern. The hypothesis was that +bit-pattern interpolation should beat `InterpolationSearch` on log-spaced +(geometric) data — bit patterns are approximately linear in array index for +log-spaced floats, since the IEEE binary exponent occupies the high bits. + +The strategy was implemented, correctness-verified against `Base`, and +benchmarked against `InterpolationSearch` / `BracketGallop` / `ExpFromLeft` +/ `SIMDLinearScan` / `Auto` across `m` ∈ {4, 16, 64, 256, 1024, 4096} on a +`n = 65536` log-spaced Float64 vector with sparse queries. The result was +that `BitInterpolationSearch` lost to every alternative at every `m`, +clocking 65–88 ns/q while `ExpFromLeft` ran at 19–41 ns/q and +`SIMDLinearScan` at 16–199 ns/q. The per-query division and floating-point +arithmetic in the bit-domain guess cost more than the saved bracket +refinement on log-spaced data, and the same overhead made the strategy +strictly worse than plain `InterpolationSearch` on uniform-spaced data +(where the bit pattern isn't linear in index in the first place — the +denormal-to-normalized transition introduces a huge non-linearity at zero). + +The strategy was not retained. `Auto` already serves log-spaced data well +via `SIMDLinearScan` (medium gap) and `BracketGallop` / `ExpFromLeft` +(large gap); no new dispatch path is needed. + ### Cleanup: typo fix, FFE_IR unification, tolerance kwarg - Internal helper `bracketstrictlymontonic` renamed to From 23fa0581743c5a96ad6eadf7bc983a5392a24f19 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 09:41:33 -0400 Subject: [PATCH 14/16] Restore BitInterpolationSearch as opt-in strategy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reinstating BitInterpolationSearch after a more comprehensive bench than my earlier sweep — that earlier conclusion ("never wins") was based on a too-narrow regime grid (single v pattern, single q pattern). The new sweep at `bench/bitinterp_sweep.jl` covers 1404 cells across 9 v patterns (uniform, logspaced, logspaced_wide spanning 10⁻³ to 10¹⁵, geometric_dense, geometric_sparse, power2, sqrt, two_decade, jittered_log) × 4 q patterns (linear_uniform, log_uniform, dense_grid, log_grid) × 6 n sizes up to 2²⁰ × 7 m sizes from 4 to 16384. Results: - BitInterp wins outright in 59/1404 cells (4.2%) - Within 10% of per-cell best in 75 cells (5.3%) - Within 20% of per-cell best in 105 cells (7.5%) Wins concentrate in the regime BitInterp is designed for: log-spaced/geometric Float64 data at small m (= 4) and large n (≥ 16384). Margins range from 1.0× tie to 1.43× on `logspaced_wide log_grid n=2²⁰ m=4`. Other wide-spread wins: logspaced_wide log_grid n=2¹² m=4: 35.0 vs ExpFromLeft 47.5 (1.36×) logspaced_wide log_grid n=2¹⁸ m=4: 47.5 vs ExpFromLeft 62.5 (1.32×) logspaced_wide dense_grid n=2²⁰ m=4: 50.0 vs ExpFromLeft 65.0 (1.30×) `Auto` does NOT pick BitInterp. The wins are narrow (4% of cells in a bench specifically designed to probe BitInterp's regime), and adding the eligibility check + sampled-log-linearity probe to Auto's hot path would penalize the much larger set of non-log-spaced workloads. Users with known log-spaced workloads can pin `searchsortedlast!(out, v, queries; strategy = BitInterpolationSearch())` once and get the win at zero heuristic cost. Implementation: - `_bit_interp_guess_f64(v, x, lo, hi)` does per-element bitcast rather than reinterpret(UInt64, v) on the whole vector, avoiding the ReinterpretArray wrapper overhead. - Strict guard on positive + finite v[lo] and x; non-positive or non-finite Float64 bit patterns are not monotonic with float value under raw reinterpret, so the strategy falls back to BinaryBracket. - Non-Float64 dense eltypes fall back to plain InterpolationSearch (where the bit pattern equals the value). Tests pass (84120). Docs updated: - `strategies.md` chooser table adds BitInterp with eltype/regime caveats. - `strategies.md` per-strategy section documents the win regime, the sample wins table, and why Auto doesn't pick it. - `NEWS.md` documents the bench findings and the "opt-in" decision. Co-Authored-By: Chris Rackauckas --- NEWS.md | 66 ++++++----- bench/bitinterp_sweep.jl | 226 ++++++++++++++++++++++++++++++++++++++ docs/src/strategies.md | 57 ++++++++++ src/FindFirstFunctions.jl | 125 ++++++++++++++++++++- 4 files changed, 448 insertions(+), 26 deletions(-) create mode 100644 bench/bitinterp_sweep.jl diff --git a/NEWS.md b/NEWS.md index 6505dae..53cef6a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -381,31 +381,47 @@ with an analysis helper at `bench/analyze.jl`. See `auto.md` for the decision tree, the per-regime winner distribution, and how to run the sweep locally. -### Investigated but rejected: BitInterpolationSearch for log-spaced data - -A natural extension to `InterpolationSearch` was investigated: reinterpret a -positive `DenseVector{Float64}` as `DenseVector{UInt64}`, then run the -linear-extrapolation guess on the IEEE bit pattern. The hypothesis was that -bit-pattern interpolation should beat `InterpolationSearch` on log-spaced -(geometric) data — bit patterns are approximately linear in array index for -log-spaced floats, since the IEEE binary exponent occupies the high bits. - -The strategy was implemented, correctness-verified against `Base`, and -benchmarked against `InterpolationSearch` / `BracketGallop` / `ExpFromLeft` -/ `SIMDLinearScan` / `Auto` across `m` ∈ {4, 16, 64, 256, 1024, 4096} on a -`n = 65536` log-spaced Float64 vector with sparse queries. The result was -that `BitInterpolationSearch` lost to every alternative at every `m`, -clocking 65–88 ns/q while `ExpFromLeft` ran at 19–41 ns/q and -`SIMDLinearScan` at 16–199 ns/q. The per-query division and floating-point -arithmetic in the bit-domain guess cost more than the saved bracket -refinement on log-spaced data, and the same overhead made the strategy -strictly worse than plain `InterpolationSearch` on uniform-spaced data -(where the bit pattern isn't linear in index in the first place — the -denormal-to-normalized transition introduces a huge non-linearity at zero). - -The strategy was not retained. `Auto` already serves log-spaced data well -via `SIMDLinearScan` (medium gap) and `BracketGallop` / `ExpFromLeft` -(large gap); no new dispatch path is needed. +### New (opt-in): BitInterpolationSearch for log-spaced Float64 data + +`BitInterpolationSearch` is a variant of `InterpolationSearch` that +reinterprets a positive `DenseVector{Float64}` as `DenseVector{UInt64}` +before computing the extrapolation guess. The IEEE bit pattern is +monotonically increasing with the float value (for positive Float64) and +approximately linear in array index when the underlying data is +log-spaced (geometric). On such data the bit-domain guess can be far +better than the float-domain guess that `InterpolationSearch` would +compute. + +A targeted bench sweep at `bench/bitinterp_sweep.jl` covers 9 v patterns +× 4 q patterns × 6 n sizes (up to 2²⁰) × 7 m sizes, with v patterns +specifically chosen to probe BitInterp's regime: `logspaced` (1 to 10⁶), +`logspaced_wide` (10⁻³ to 10¹⁵), `geometric_dense` (geometric spanning +10⁶), `geometric_sparse` (geometric spanning 10¹²), `power2`, `sqrt`, +`two_decade`, `jittered_log`, and `uniform` (as the negative control). + +Result over 1404 cells: BitInterp wins outright in 59 cells (4.2%) and +sits within 10% of the per-cell best in 75 cells (5.3%). The wins +concentrate in `logspaced_wide` / `logspaced` / `geometric_*` / +`jittered_log` at small m (= 4) and large n (≥ 16384). Margins range +from 1.0× (tie) to 1.43× (`logspaced_wide log_grid n=2²⁰ m=4`). On +non-log-spaced data (`uniform`, `power2`, `sqrt`, `two_decade`) +BitInterp loses — the bit-pattern guess is worse than the float-domain +guess when the data isn't geometric. + +**`Auto` does not pick BitInterp.** The wins are real but narrow +(small batches, very large n, true log-spacing), and adding the dispatch +overhead to Auto's hot path would penalize the much larger set of +non-log-spaced workloads. The strategy is exported as `BitInterpolationSearch` +for callers who know their data is log-spaced and want to pin it. + +Constraints: + - `DenseVector{Float64}` only; non-Float64 dense eltypes fall back to + plain `InterpolationSearch`. + - Requires `v[1] > 0`, `x > 0`, and both finite. Subnormal / + non-finite Float64 bit patterns are not monotonic with float value + under raw reinterpret, so the strategy falls back to `BinaryBracket` + in those cases. + - Forward ordering only. ### Cleanup: typo fix, FFE_IR unification, tolerance kwarg diff --git a/bench/bitinterp_sweep.jl b/bench/bitinterp_sweep.jl new file mode 100644 index 0000000..234bb0f --- /dev/null +++ b/bench/bitinterp_sweep.jl @@ -0,0 +1,226 @@ +using FindFirstFunctions, StableRNGs, BenchmarkTools, Statistics, Printf + +const F = FindFirstFunctions + +# Strategies under test. BitInterp is the one we're vetting; the others are +# the alternatives `Auto` might pick or that a user might pin. +const STRATS = [ + ("BitInterp", F.BitInterpolationSearch()), + ("Interp", F.InterpolationSearch()), + ("Bracket", F.BracketGallop()), + ("Exp", F.ExpFromLeft()), + ("SIMD", F.SIMDLinearScan()), + ("Auto", F.Auto()), +] + +# Data shapes covering the regimes BitInterp could conceivably win. +function build_v(::Val{:uniform}, n, seed) + return collect(range(1.0, Float64(n); length = n)) +end +function build_v(::Val{:logspaced}, n, seed) + return collect(exp.(range(0.0, log(1.0e6); length = n))) +end +function build_v(::Val{:logspaced_wide}, n, seed) + # 10⁻³ to 10¹⁵ — ~18 decades, like a particle-physics interpolation table + return collect(exp.(range(log(1.0e-3), log(1.0e15); length = n))) +end +function build_v(::Val{:geometric_dense}, n, seed) + # Geometric with ratio chosen so the series spans 10⁶ — keeps Float64 + # range usable up to n ≈ 10⁷ while keeping the spacing tight. + r = (1.0e6)^(1.0 / max(n - 1, 1)) + return collect(r .^ (0:(n - 1))) +end +function build_v(::Val{:geometric_sparse}, n, seed) + # Geometric spanning 10¹² with sparser spacing. + r = (1.0e12)^(1.0 / max(n - 1, 1)) + return collect(r .^ (0:(n - 1))) +end +function build_v(::Val{:power2}, n, seed) + return collect(Float64(i)^2 for i in 1:n) +end +function build_v(::Val{:sqrt}, n, seed) + return collect(sqrt(Float64(i)) for i in 1:n) +end +function build_v(::Val{:two_decade}, n, seed) + # 80% of values in [1, 2], 20% in [2, 1e6] — extreme density-then-sparse + h = (8n) ÷ 10 + a = collect(range(1.0, 2.0; length = h)) + b = collect(exp.(range(log(2.0), log(1.0e6); length = n - h))) + return sort!(vcat(a[1:(end - 1)], b)) +end +function build_v(::Val{:jittered_log}, n, seed) + base = collect(exp.(range(0.0, log(1.0e6); length = n))) + rng = StableRNG(seed) + return sort!(base .* (1.0 .+ 0.01 .* (rand(rng, n) .- 0.5))) +end + +function build_q(v, m, kind::Symbol, seed) + rng = StableRNG(seed) + if kind == :linear_uniform + # m queries uniformly random in v's full LINEAR range + return sort!(first(v) .+ rand(rng, m) .* (last(v) - first(v))) + elseif kind == :log_uniform + # m queries uniformly random in v's full LOG range — matches the + # distribution of log-spaced v itself + first(v) > 0 || error("log_uniform requires positive v") + return sort!( + exp.(log(first(v)) .+ rand(rng, m) .* (log(last(v)) - log(first(v)))) + ) + elseif kind == :dense_grid + # Evenly-spaced linear grid + return collect(range(first(v), last(v); length = m)) + elseif kind == :log_grid + first(v) > 0 || error("log_grid requires positive v") + return collect(exp.(range(log(first(v)), log(last(v)); length = m))) + else + error("unknown q kind: $kind") + end +end + +function bench_cell(v, q, strat, out, reps = 5) + F.searchsortedlast!(out, v, q; strategy = strat) + best = typemax(Float64) + for _ in 1:reps + t = @elapsed F.searchsortedlast!(out, v, q; strategy = strat) + best = min(best, t) + end + return best * 1.0e9 / length(q) +end + +function correctness_check(v, q, strat) + out = Vector{Int}(undef, length(q)) + expected = searchsortedlast.(Ref(v), q) + F.searchsortedlast!(out, v, q; strategy = strat) + return out == expected +end + +println("BitInterpolationSearch comprehensive sweep") +println("="^70) +println("Testing where BitInterp might win across spacing × density × n × m") +println() + +# Multiple seeds for noise reduction +function run_sweep() + v_kinds = ( + :uniform, :logspaced, :logspaced_wide, + :geometric_dense, :geometric_sparse, + :power2, :sqrt, :two_decade, :jittered_log, + ) + q_kinds = (:linear_uniform, :log_uniform, :dense_grid, :log_grid) + ns = (1024, 4096, 16_384, 65_536, 262_144, 1_048_576) + ms = (4, 16, 64, 256, 1024, 4096, 16_384) + + rows = [] + bit_wins = 0 + bit_within10 = 0 # within 10% of best + bit_within20 = 0 # within 20% of best + total = 0 + + for v_kind in v_kinds, q_kind in q_kinds, n in ns, m in ms + m > n && continue + v = build_v(Val(v_kind), n, 2026) + # Some q_kinds require positive v + if (q_kind == :log_uniform || q_kind == :log_grid) && first(v) <= 0 + continue + end + q = build_q(v, m, q_kind, 2027) + out = Vector{Int}(undef, m) + + # Correctness first — bail loudly if mismatch. + correctness_check(v, q, F.BitInterpolationSearch()) || + error("BitInterp correctness fail on $v_kind/$q_kind n=$n m=$m") + + times = Dict{String, Float64}() + for (name, strat) in STRATS + times[name] = bench_cell(v, q, strat, out) + end + push!(rows, (v_kind, q_kind, n, m, times)) + + # Score + explicit = [(n, t) for (n, t) in pairs(times) if n != "Auto"] + best_t = minimum(t for (_, t) in explicit) + bit_t = times["BitInterp"] + if bit_t <= best_t + bit_wins += 1 + end + if bit_t <= 1.1 * best_t + bit_within10 += 1 + end + if bit_t <= 1.2 * best_t + bit_within20 += 1 + end + total += 1 + end + + println("Cells tested: $total") + @printf( + "BitInterp wins outright: %d cells (%.1f%%)\n", + bit_wins, 100 * bit_wins / total + ) + @printf( + "BitInterp within 10%% of best: %d cells (%.1f%%)\n", + bit_within10, 100 * bit_within10 / total + ) + @printf( + "BitInterp within 20%% of best: %d cells (%.1f%%)\n", + bit_within20, 100 * bit_within20 / total + ) + println() + + # If BitInterp wins anywhere, show those cells. + win_rows = [ + r for r in rows if begin + explicit = [(n, t) for (n, t) in pairs(r[5]) if n != "Auto"] + best_t = minimum(t for (_, t) in explicit) + r[5]["BitInterp"] <= best_t + end + ] + if !isempty(win_rows) + println("Cells where BitInterp wins:") + @printf( + " %-16s %-14s %8s %6s %-10s vs second-best\n", + "v_kind", "q_kind", "n", "m", "BitInterp" + ) + for (v_kind, q_kind, n, m, times) in win_rows + explicit = sort( + [(name, t) for (name, t) in pairs(times) if name != "Auto"]; + by = x -> x[2] + ) + second = explicit[2] + @printf( + " %-16s %-14s %8d %6d %5.1f ns/q vs %s=%5.1f (%.2fx)\n", + v_kind, q_kind, n, m, times["BitInterp"], + second[1], second[2], second[2] / times["BitInterp"] + ) + end + println() + end + + # Show the cells where BitInterp is closest to winning (top 10). + closest = sort( + rows; by = r -> begin + explicit = [(n, t) for (n, t) in pairs(r[5]) if n != "Auto"] + best_t = minimum(t for (_, t) in explicit) + r[5]["BitInterp"] / best_t + end + ) + println("Closest 10 cells (BitInterp/best ratio):") + @printf( + " %-16s %-14s %8s %6s %-10s ratio winner\n", + "v_kind", "q_kind", "n", "m", "BitInterp" + ) + for (v_kind, q_kind, n, m, times) in closest[1:min(10, end)] + explicit = [(name, t) for (name, t) in pairs(times) if name != "Auto"] + best_t = minimum(t for (_, t) in explicit) + winner = first(sort(explicit; by = x -> x[2])) + @printf( + " %-16s %-14s %8d %6d %5.1f ns/q %.2fx %s\n", + v_kind, q_kind, n, m, times["BitInterp"], + times["BitInterp"] / best_t, winner[1] + ) + end + + return rows +end + +@time run_sweep() diff --git a/docs/src/strategies.md b/docs/src/strategies.md index fa86eaa..6836fb4 100644 --- a/docs/src/strategies.md +++ b/docs/src/strategies.md @@ -22,6 +22,7 @@ callers who already know their access pattern and want to pin a strategy. | [`BracketGallop`](@ref FindFirstFunctions.BracketGallop) | answer may be either side of the hint, distance unknown | O(1) | ~2 log₂ n | yes | | [`ExpFromLeft`](@ref FindFirstFunctions.ExpFromLeft) | sorted batch — hint is `prev_result`, answer is monotonically ≥ hint | O(1) | O(log n) | yes (as lower bound) | | [`InterpolationSearch`](@ref FindFirstFunctions.InterpolationSearch) | `v` is uniformly spaced and numeric | O(1) | O(log n) | no | +| [`BitInterpolationSearch`](@ref FindFirstFunctions.BitInterpolationSearch) | `DenseVector{Float64}` and log-spaced (geometric) — opt-in, `Auto` does not pick | O(1) | O(log n) | no | | [`BinaryBracket`](@ref FindFirstFunctions.BinaryBracket) | no hint available, or fallback | O(log n) | O(log n) | no | | [`GuesserHint`](@ref FindFirstFunctions.GuesserHint) | repeated correlated lookups against the same `v` | O(1) | ~2 log₂ n | self-provided | | [`Auto`](@ref FindFirstFunctions.Auto) | unknown access pattern | varies | varies | yes if supplied | @@ -38,6 +39,7 @@ FindFirstFunctions.SIMDLinearScan FindFirstFunctions.BracketGallop FindFirstFunctions.ExpFromLeft FindFirstFunctions.InterpolationSearch +FindFirstFunctions.BitInterpolationSearch FindFirstFunctions.BinaryBracket FindFirstFunctions.BisectThenSIMD FindFirstFunctions.Auto @@ -123,6 +125,61 @@ Caveats: explicitly when you have a workload that wants a long linear forward scan and you know the element type. +### BitInterpolationSearch + +`InterpolationSearch` with the extrapolation guess computed on the IEEE +bit pattern of `v` rather than the float values themselves. For positive +Float64 values, the IEEE bit pattern is monotonically increasing with the +float value and is approximately *linear* in array index for log-spaced +(geometric) data. That makes the bit-domain linear extrapolation a far +better guess than the float-domain linear extrapolation on geometric data +— sometimes O(1) versus O(log n) refinement cost. + +**Opt-in only.** `Auto` does not pick `BitInterpolationSearch`. The bench +sweep at `bench/bitinterp_sweep.jl` covers 1404 cells (9 v patterns × 4 q +patterns × 6 n sizes up to 2²⁰ × 7 m sizes, exercising pure-geometric, +log-spaced over 18 decades, power-of-2 spacing, two-decade clumps, and +jittered-log alongside uniform/sqrt as negative controls). BitInterp +wins outright in 59 cells (4.2%) and sits within 10% of the per-cell +best in 75 cells (5.3%). The wins concentrate in: + + - `logspaced` / `logspaced_wide` / `geometric_dense` / `geometric_sparse` + / `jittered_log` — i.e. genuinely geometric data. + - Small `m` (= 4, occasionally 16): the per-query bit-domain guess cost + amortizes poorly across larger batches. + - Large `n` (≥ 2¹⁴, peaking at 2²⁰): the saved bracket refinement scales + with `log₂ n`, while the per-query setup cost is constant. + +Sample wins (BitInterp vs second-best, ns/q): + +| Cell | BitInterp | Runner-up | Margin | +|---|---|---|---| +| `logspaced_wide log_grid n=2²⁰ m=4` | 52.5 | InterpolationSearch 75.0 | 1.43× | +| `logspaced_wide log_grid n=2¹² m=4` | 35.0 | ExpFromLeft 47.5 | 1.36× | +| `logspaced_wide log_grid n=2¹⁸ m=4` | 47.5 | ExpFromLeft 62.5 | 1.32× | +| `logspaced_wide dense_grid n=2²⁰ m=4` | 50.0 | ExpFromLeft 65.0 | 1.30× | + +`Auto` doesn't pick it because: + - The wins are narrow (4% of cells in a bench specifically designed to + probe BitInterp's regime). + - Adding the eligibility check to `Auto`'s hot path (Float64 + positive + + log-linear sampled probe) would burn a few ns on every call, paying + back only in cells with `m ≤ 16` where Auto's overhead already + dominates the per-query cost. + - Users with a known log-spaced workload can pin + `searchsortedlast!(out, v, queries; strategy = BitInterpolationSearch())` + once and get the win without any heuristic cost. + +The strategy is retained as an opt-in for callers whose workload sits +outside what `Auto` discovers cheaply: domain-specific tables (radiation +transport, log-frequency, gravitational potentials) or hardware where +Float64 division is unusually cheap. + +Falls back to plain `InterpolationSearch` on non-Float64 dense eltypes +(where the bit pattern equals the value, making the strategies +equivalent), and to `BinaryBracket` for non-positive or non-finite Float64 +data. + ### BracketGallop Galloping search around the hint: expand `[lo, hi]` outward by doubling steps diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index cf85464..ed5920d 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -10,7 +10,8 @@ module FindFirstFunctions export SearchStrategy, LinearScan, SIMDLinearScan, BracketGallop, ExpFromLeft, - InterpolationSearch, BinaryBracket, BisectThenSIMD, + InterpolationSearch, BitInterpolationSearch, + BinaryBracket, BisectThenSIMD, GuesserHint, Auto, SearchProperties, Guesser, looks_linear, @@ -411,6 +412,45 @@ types where subtraction isn't defined. """ struct InterpolationSearch <: SearchStrategy end +""" + BitInterpolationSearch <: SearchStrategy + +Variant of [`InterpolationSearch`](@ref) that reinterprets `DenseVector{Float64}` +as `DenseVector{UInt64}` before computing the extrapolation guess. For +positive IEEE Float64 values, the bit pattern is monotonically increasing +with the float value and is approximately linear in array index when the +underlying data is *log-spaced* (geometric). On such data the bit-domain +guess is far better than the float-domain guess that `InterpolationSearch` +would compute — sometimes O(1) versus O(log n) refinement. + +After computing the bit-domain guess, the bracket and binary refine step +uses the original float values for comparison, so the answer is identical +to `Base.searchsortedlast` / `Base.searchsortedfirst`. + +Constraints: + - `DenseVector{Float64}` only (the IEEE bit-pattern trick is Float64-specific). + - Requires `v[1] > 0` and the query `x > 0` (negative, zero, subnormal, + and non-finite Float64 bit patterns are not monotonic with float value + under raw reinterpret). + - Forward ordering only. + +**This strategy is opt-in only** — `Auto` does not pick it. The bench sweep +shows the per-query division and UInt64↔Float64 conversion overhead +(~60–90 ns/q) costs more than the bracket refinement that the guess +saves at every gap tested; pinning `BitInterpolationSearch` is slower than +letting `Auto` pick `SIMDLinearScan` / `BracketGallop` / `ExpFromLeft`. +The strategy is retained for users with workloads not covered by the +sweep — for instance, very-large `n` (≥ 2²⁰), pathologically log-spaced +data, or hardware where Float64 division is unusually cheap relative to +the scalar walk. + +Falls back to [`InterpolationSearch`](@ref) for non-Float64 dense eltypes +(where the bit pattern equals the value and the two strategies are +equivalent), and to [`BinaryBracket`](@ref) for non-positive or +non-finite Float64 data. +""" +struct BitInterpolationSearch <: SearchStrategy end + """ BinaryBracket <: SearchStrategy @@ -1005,6 +1045,89 @@ Base.searchsortedfirst( order::Base.Order.Ordering = Base.Order.Forward ) = searchsortedfirst(BinaryBracket(), v, x; order = order) +# Strategy: BitInterpolationSearch — InterpolationSearch on the IEEE bit +# pattern of positive Float64. Cheaper than reinterpret-as-array because we +# only need two endpoint reads and one query bitcast per call. +@inline function _bit_interp_guess_f64( + v::DenseVector{Float64}, x::Float64, lo::Integer, hi::Integer + ) + @inbounds vlo_bits = reinterpret(UInt64, v[lo]) + @inbounds vhi_bits = reinterpret(UInt64, v[hi]) + xu = reinterpret(UInt64, x) + span = vhi_bits - vlo_bits + iszero(span) && return lo + if xu <= vlo_bits + return lo + elseif xu >= vhi_bits + return hi + end + num = xu - vlo_bits + f = Float64(num) / Float64(span) + g = lo + round(Int, f * (hi - lo)) + return clamp(g, lo, hi) +end + +function Base.searchsortedlast( + ::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64; + order::Base.Order.Ordering = Base.Order.Forward + ) + if order !== Base.Order.Forward + return searchsortedlast(v, x, order) + end + lo, hi = firstindex(v), lastindex(v) + hi < lo && return lo - 1 + @inbounds if v[lo] <= 0.0 || !isfinite(v[lo]) || x <= 0.0 || !isfinite(x) + return searchsortedlast(BinaryBracket(), v, x; order = order) + end + g = _bit_interp_guess_f64(v, x, lo, hi) + return searchsortedlast(BracketGallop(), v, x, g; order = order) +end + +function Base.searchsortedfirst( + ::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64; + order::Base.Order.Ordering = Base.Order.Forward + ) + if order !== Base.Order.Forward + return searchsortedfirst(v, x, order) + end + lo, hi = firstindex(v), lastindex(v) + hi < lo && return lo + @inbounds if v[lo] <= 0.0 || !isfinite(v[lo]) || x <= 0.0 || !isfinite(x) + return searchsortedfirst(BinaryBracket(), v, x; order = order) + end + g = _bit_interp_guess_f64(v, x, lo, hi) + return searchsortedfirst(BracketGallop(), v, x, g; order = order) +end + +# Hint pass-through (bit-interp ignores externally-supplied hints). +Base.searchsortedlast( + s::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(s, v, x; order = order) +Base.searchsortedfirst( + s::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(s, v, x; order = order) + +# Non-Float64 / non-dense eltypes: fall back to plain InterpolationSearch +# (bit reinterpret only carries the log-linearity trick for Float64). +Base.searchsortedlast( + ::BitInterpolationSearch, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(InterpolationSearch(), v, x; order = order) +Base.searchsortedfirst( + ::BitInterpolationSearch, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(InterpolationSearch(), v, x; order = order) +Base.searchsortedlast( + ::BitInterpolationSearch, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedlast(InterpolationSearch(), v, x; order = order) +Base.searchsortedfirst( + ::BitInterpolationSearch, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward +) = searchsortedfirst(InterpolationSearch(), v, x; order = order) + # Strategy: BisectThenSIMD — only meaningful for `findequal`. For the # positional `searchsortedfirst` / `searchsortedlast` dispatch, fall back to # BinaryBracket — bisect-then-equality-scan can't answer the positional From aaaf5a5ffd17996cffde6560ddda517e58c13585 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 10:05:16 -0400 Subject: [PATCH 15/16] Add queries_sorted kwarg, searchsortedrange, is_log_linear, AirspeedVelocity CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four 2.0 followup additions: 1. **`queries_sorted` kwarg** on `searchsortedfirst!` / `searchsortedlast!`. Caller-supplied override for the runtime `issorted(queries)` check. `nothing` (default) keeps current behaviour; `true` skips the O(m) probe and takes the sorted-loop path unconditionally; `false` skips the probe and takes the unsorted-loop path. Measured savings: ~6.6 μs on m=4096 batched call on the bench machine (~1.6 ns/q, ~6% headroom on top of Auto's hot path). Wrong-answer risk for `queries_sorted = true` on unsorted input is documented in the docstring; the inner sorted loop uses previous-result as a hint, which becomes invalid when queries jump backward. Tests cover sorted-true on every shipped strategy plus unsorted-false on unsorted data. 2. **`searchsortedrange(strategy, v, lo, hi[, hint]; order)`** returning a `UnitRange{Int}` of all indices `i` with `lo ≤ v[i] ≤ hi`. Implemented as `searchsortedfirst(strategy, v, lo) : searchsortedlast(strategy, v, hi)`, with the hinted form passing the left-bound result as the hint for the right-bound search (shared bracket discovery). Exported. Tests cover all shipped strategies on several `(lo, hi)` pairs including out-of-range cases, plus 200-trial random fuzz on Int64 vectors vs the Base composition. 3. **`is_log_linear::Bool` field on `SearchProperties`** + backing `_sampled_looks_log_linear(v, tol)` probe. The probe is the same 9-point sampled check as `_sampled_looks_linear` but applied to `log.(v)` — accepts geometric / log-spaced data, rejects linear / two-scale. Requires strictly positive finite values throughout the sample. `Auto` does NOT consume `is_log_linear` (the wins from `BitInterpolationSearch` are narrow per the bitinterp_sweep bench). The field is populated for callers who want to manually pin `BitInterpolationSearch` based on data shape; the cost is a single sampled-log probe at `SearchProperties(v)` construction time (~30 ns). 4. **AirspeedVelocity benchmark CI**. Adds: - `.github/workflows/Benchmark.yml` — runs on PRs touching `src/`, `bench/`, `Project.toml`, or the workflow itself. Uses `benchpkg` / `benchpkgtable` from AirspeedVelocity 0.6 to time both base and PR commits, post a markdown diff as a PR comment, and upload raw results as an artifact. - `benchmark/benchmarks.jl` — `SUITE = BenchmarkGroup()` with 40 entries across four groups: per-query micro-benchmarks across every shipped strategy, batched in-place benchmarks on a (3 × 3 × 3) grid of `(v_kind, q_kind, n, m)` including the Auto / Auto+sorted / Auto+props variants, `SearchProperties` construction cost on three eltypes, and equality-search comparison (`findequal(BinaryBracket)` vs `findequal(BisectThenSIMD)` vs `findfirstsortedequal`). 84626 tests pass (+506 from the new test blocks). Co-Authored-By: Chris Rackauckas --- .github/workflows/Benchmark.yml | 69 +++++++++++++ benchmark/benchmarks.jl | 132 +++++++++++++++++++++++++ src/FindFirstFunctions.jl | 166 ++++++++++++++++++++++++++++---- test/runtests.jl | 99 ++++++++++++++++++- 4 files changed, 444 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/Benchmark.yml create mode 100644 benchmark/benchmarks.jl diff --git a/.github/workflows/Benchmark.yml b/.github/workflows/Benchmark.yml new file mode 100644 index 0000000..db5d163 --- /dev/null +++ b/.github/workflows/Benchmark.yml @@ -0,0 +1,69 @@ +name: Benchmarks + +on: + pull_request: + paths: + - "src/**" + - "bench/**" + - "Project.toml" + - ".github/workflows/Benchmark.yml" + workflow_dispatch: + +# Only one benchmark run per PR at a time; cancel stale ones. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write + +jobs: + benchmark: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 # we need both PR head and base branch + - uses: julia-actions/setup-julia@v3 + with: + version: "1.11" + - uses: julia-actions/cache@v2 + - name: Install AirspeedVelocity + run: | + julia -e 'using Pkg; Pkg.add(PackageSpec(name="AirspeedVelocity", version="0.6"))' + # Resolve commit shas explicitly so AirspeedVelocity sees stable refs. + - name: Resolve refs + id: resolve + run: | + PR_SHA=$(git rev-parse HEAD) + BASE_SHA=$(git rev-parse origin/${{ github.base_ref }}) + echo "pr_sha=$PR_SHA" >> "$GITHUB_OUTPUT" + echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT" + - name: Run benchmark comparison + run: | + export JULIA_NUM_THREADS=1 + ~/.julia/bin/benchpkg FindFirstFunctions \ + --rev=${{ steps.resolve.outputs.base_sha }},${{ steps.resolve.outputs.pr_sha }} \ + --bench-on=${{ steps.resolve.outputs.pr_sha }} \ + --output-dir=results/ \ + --tune + - name: Render comparison table + run: | + ~/.julia/bin/benchpkgtable FindFirstFunctions \ + --rev=${{ steps.resolve.outputs.base_sha }},${{ steps.resolve.outputs.pr_sha }} \ + --input-dir=results/ \ + > benchmark_table.md + cat benchmark_table.md + - name: Post benchmark comment + if: github.event_name == 'pull_request' + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + body-path: benchmark_table.md + edit-mode: replace + - name: Upload raw results + uses: actions/upload-artifact@v4 + with: + name: benchmark-results + path: results/ diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl new file mode 100644 index 0000000..8aba939 --- /dev/null +++ b/benchmark/benchmarks.jl @@ -0,0 +1,132 @@ +# AirspeedVelocity-driven benchmark suite. Each `SUITE[...]` entry is a +# `BenchmarkGroup` (or `@benchmarkable`) that AirspeedVelocity will time on +# both the PR branch and the base branch, then diff. Keep individual cells +# fast (< 200 ms target) so the CI run finishes in a few minutes. + +using BenchmarkTools +using FindFirstFunctions +using StableRNGs + +const SUITE = BenchmarkGroup() + +# Helper: build a sorted Float64 vector with the given pattern. +function _make_v(kind, n, seed = 2026) + rng = StableRNG(seed) + return if kind === :uniform + collect(range(0.0, Float64(n); length = n)) + elseif kind === :logspaced + collect(exp.(range(0.0, log(1.0e6); length = n))) + elseif kind === :random_sorted + sort!(rand(rng, n) .* n) + else + error("unknown v kind $kind") + end +end + +function _make_q(v, m, kind, seed = 2027) + rng = StableRNG(seed) + return if kind === :dense + collect(range(first(v), last(v); length = m)) + elseif kind === :sparse + sort!(first(v) .+ rand(rng, m) .* (last(v) - first(v))) + elseif kind === :clustered + j = max(1, length(v) ÷ 4) + lo = v[j] + hi = v[min(j + 1, length(v))] + span = hi - lo + sort!(lo .+ rand(rng, m) .* max(span, 1.0)) + else + error("unknown q kind $kind") + end +end + +# --------------------------------------------------------------------------- +# Per-strategy single-query micro-benchmarks (Int64, n=1024, hint near answer) +# --------------------------------------------------------------------------- +SUITE["per_query"] = BenchmarkGroup() +let v = collect(Int64, 1:1024), x = Int64(500), hint = 480 + for (name, strategy) in [ + ("LinearScan", LinearScan()), + ("SIMDLinearScan", SIMDLinearScan()), + ("BracketGallop", BracketGallop()), + ("ExpFromLeft", ExpFromLeft()), + ("InterpolationSearch", InterpolationSearch()), + ("BinaryBracket", BinaryBracket()), + ("Auto", Auto()), + ] + SUITE["per_query"][name] = @benchmarkable( + searchsortedlast($strategy, $v, $x, $hint), + evals = 1, samples = 200, + ) + end +end + +# --------------------------------------------------------------------------- +# Batched in-place benchmarks: a small grid of (v_kind, q_kind, n, m). +# Auto vs hand-picked strategies, plus the queries_sorted = true fast path. +# --------------------------------------------------------------------------- +SUITE["batched"] = BenchmarkGroup() +for v_kind in (:uniform, :logspaced, :random_sorted), + q_kind in (:dense, :sparse, :clustered), + (n, m) in ((1024, 64), (16_384, 256), (65_536, 4096)) + + v = _make_v(v_kind, n) + q = _make_q(v, m, q_kind) + out = Vector{Int}(undef, m) + + key = "$(v_kind)/$(q_kind)/n=$n/m=$m" + grp = BenchmarkGroup() + grp["Auto"] = @benchmarkable( + FindFirstFunctions.searchsortedlast!($out, $v, $q; strategy = Auto()), + evals = 1, samples = 50, + ) + grp["Auto+sorted"] = @benchmarkable( + FindFirstFunctions.searchsortedlast!( + $out, $v, $q; + strategy = Auto(), queries_sorted = true, + ), + evals = 1, samples = 50, + ) + grp["Auto+props"] = @benchmarkable( + FindFirstFunctions.searchsortedlast!( + $out, $v, $q; + strategy = Auto(SearchProperties($v)), + ), + evals = 1, samples = 50, + ) + SUITE["batched"][key] = grp +end + +# --------------------------------------------------------------------------- +# SearchProperties construction cost (probe + NaN scan on Float64) +# --------------------------------------------------------------------------- +SUITE["props_construct"] = BenchmarkGroup() +for (name, v) in [ + ("uniform_64k", collect(range(0.0, 100.0; length = 65_536))), + ("logspaced_64k", collect(exp.(range(0.0, log(1.0e6); length = 65_536)))), + ("int64_64k", collect(Int64, 1:65_536)), + ] + SUITE["props_construct"][name] = @benchmarkable( + SearchProperties($v), + evals = 1, samples = 50, + ) +end + +# --------------------------------------------------------------------------- +# Equality search comparison +# --------------------------------------------------------------------------- +SUITE["equality"] = BenchmarkGroup() +let v = collect(Int64, 1:65_536), x = Int64(50_000) + SUITE["equality"]["findequal_BinaryBracket"] = @benchmarkable( + findequal(BinaryBracket(), $v, $x), + evals = 1, samples = 200, + ) + SUITE["equality"]["findequal_BisectThenSIMD"] = @benchmarkable( + findequal(BisectThenSIMD(), $v, $x), + evals = 1, samples = 200, + ) + SUITE["equality"]["findfirstsortedequal"] = @benchmarkable( + findfirstsortedequal($x, $v), + evals = 1, samples = 200, + ) +end diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index ed5920d..d114843 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -15,7 +15,7 @@ export GuesserHint, Auto, SearchProperties, Guesser, looks_linear, - searchsortedfirst!, searchsortedlast!, + searchsortedfirst!, searchsortedlast!, searchsortedrange, findequal, findfirstequal, findfirstsortedequal # https://github.com/JuliaLang/julia/pull/53687 @@ -511,17 +511,20 @@ Default-constructed (`SearchProperties()`) is the "no information" sentinel: `Auto`. Construct via `SearchProperties(v::AbstractVector)` to populate the fields by running the probes once. -Currently consumed: `is_linear` (replaces Auto's per-call -`_sampled_looks_linear` probe in the batched path). The other fields are -populated for forward compatibility but no built-in strategy reads them yet. +Currently consumed: `is_linear` and `has_nan` (the latter only on Float64, +to gate `SIMDLinearScan` eligibility in `Auto`). `is_log_linear` is +populated for callers that want to manually pin +[`BitInterpolationSearch`](@ref) based on data shape; `Auto` does not +consume it. The fields are otherwise populated for forward compatibility. """ struct SearchProperties has_props::Bool is_linear::Bool has_nan::Bool + is_log_linear::Bool end -SearchProperties() = SearchProperties(false, false, false) +SearchProperties() = SearchProperties(false, false, false, false) # `has_nan` is only meaningful for floating-point eltypes; for other numeric # types and non-numeric eltypes there is no NaN concept. @@ -547,10 +550,12 @@ function SearchProperties( v::AbstractVector; linear_tolerance::Real = 1.0e-3, ) + tol = Float64(linear_tolerance) return SearchProperties( true, - _sampled_looks_linear(v, Float64(linear_tolerance)), + _sampled_looks_linear(v, tol), _has_nan(v), + _sampled_looks_log_linear(v, tol), ) end @@ -699,6 +704,41 @@ end # AbstractRange is definitionally uniform — accept without sampling. @inline _sampled_looks_linear(::AbstractRange, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = true +# Sampled "log-linear" probe: same 9-point probe as `_sampled_looks_linear` +# but tests whether `log(v)` is linear in array index. Used to detect +# geometric / log-spaced data where `BitInterpolationSearch` is a win. +# Requires all sampled points to be strictly positive and finite; otherwise +# returns false. The probe runs in ~30 ns (the `log` calls are not cheap +# but only 11 of them, all at fixed index positions). +@inline function _sampled_looks_log_linear( + v::AbstractVector{<:Real}, + tol::Float64 = _AUTO_LINEAR_REL_TOLERANCE, + ) + n = length(v) + n < 11 && return false + @inbounds begin + v1, vn = v[1], v[n] + (v1 <= 0 || vn <= 0 || !isfinite(v1) || !isfinite(vn)) && return false + log_v1 = log(Float64(v1)) + log_vn = log(Float64(vn)) + span = log_vn - log_v1 + (iszero(span) || !isfinite(span)) && return false + abs_span = abs(span) + nm1 = n - 1 + for k in 1:9 + kk = 1 + (k * nm1) ÷ 10 + vk = v[kk] + (vk <= 0 || !isfinite(vk)) && return false + expected = log_v1 + (kk - 1) / nm1 * span + rel_err = abs(log(Float64(vk)) - expected) / abs_span + rel_err > tol && return false + end + end + return true +end + +@inline _sampled_looks_log_linear(::AbstractVector, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = false + # Strategy: BinaryBracket — ignore any hint. Base.searchsortedlast( ::BinaryBracket, v::AbstractVector, x; @@ -1269,7 +1309,8 @@ Base.searchsortedfirst( # --------------------------------------------------------------------------- """ - searchsortedlast!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward) + searchsortedlast!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward, + queries_sorted = nothing) In-place batched [`searchsortedlast`](@ref Base.searchsortedlast). Writes one index per element of `queries` into `idx_out` (which must be the same length). @@ -1281,6 +1322,20 @@ the next query, so the total cost is O(length(v) + length(queries)) under If `queries` is not sorted, falls back to per-element `searchsortedlast` with no hint regardless of `strategy`. +The `queries_sorted` kwarg controls the runtime `issorted(queries)` check: + + - `nothing` (default): run `issorted(queries; order = order)` on every call. + O(m) bookkeeping, roughly 1 ns/q on long batches. + - `true`: trust the caller — skip the check and take the sorted-loop path + unconditionally. Use this when you already know your queries are sorted + (you computed them as a range, sorted them yourself, etc.). Wrong-answer + risk: a non-sorted `queries` passed with `queries_sorted = true` will + produce incorrect results, since the inner loop uses the previous result + as a hint and that hint becomes invalid when queries jump backward. + - `false`: skip the check and take the unsorted-loop path unconditionally + (per-query unhinted `Base.searchsortedlast`). Use when you know queries + are not sorted and want to avoid the O(m) probe. + Returns `idx_out`. """ function searchsortedlast!( @@ -1288,7 +1343,8 @@ function searchsortedlast!( v::AbstractVector, queries::AbstractVector; strategy::SearchStrategy = Auto(), - order::Base.Order.Ordering = Base.Order.Forward + order::Base.Order.Ordering = Base.Order.Forward, + queries_sorted::Union{Nothing, Bool} = nothing, ) if length(idx_out) != length(queries) throw( @@ -1297,21 +1353,25 @@ function searchsortedlast!( ) ) end - return _searchsortedlast_batched!(idx_out, v, queries, strategy, order) + return _searchsortedlast_batched!( + idx_out, v, queries, strategy, order, queries_sorted + ) end """ - searchsortedfirst!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward) + searchsortedfirst!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward, + queries_sorted = nothing) In-place batched [`searchsortedfirst`](@ref Base.searchsortedfirst). See -[`searchsortedlast!`](@ref) for behavior. +[`searchsortedlast!`](@ref) for behavior and for the `queries_sorted` kwarg. """ function searchsortedfirst!( idx_out::AbstractVector{<:Integer}, v::AbstractVector, queries::AbstractVector; strategy::SearchStrategy = Auto(), - order::Base.Order.Ordering = Base.Order.Forward + order::Base.Order.Ordering = Base.Order.Forward, + queries_sorted::Union{Nothing, Bool} = nothing, ) if length(idx_out) != length(queries) throw( @@ -1320,7 +1380,9 @@ function searchsortedfirst!( ) ) end - return _searchsortedfirst_batched!(idx_out, v, queries, strategy, order) + return _searchsortedfirst_batched!( + idx_out, v, queries, strategy, order, queries_sorted + ) end # Sorted inner loop, parameterized on strategy. Used by both the generic and @@ -1379,11 +1441,23 @@ function _searchsortedfirst_unsorted_loop!( return idx_out end +# Decide whether to take the sorted-queries fast path. `queries_sorted` is +# the caller-supplied override: `nothing` means "check at runtime", `true` +# means "trust the caller, skip the O(m) issorted probe", `false` means +# "force the unsorted path". +@inline function _take_sorted_path( + queries, order::Base.Order.Ordering, queries_sorted::Union{Nothing, Bool} + ) + return queries_sorted === nothing ? + issorted(queries; order = order) : queries_sorted +end + function _searchsortedlast_batched!( idx_out, v::AbstractVector, queries::AbstractVector, - strategy::SearchStrategy, order::Base.Order.Ordering + strategy::SearchStrategy, order::Base.Order.Ordering, + queries_sorted::Union{Nothing, Bool}, ) - return if issorted(queries; order = order) + return if _take_sorted_path(queries, order, queries_sorted) _searchsortedlast_sorted_loop!(idx_out, v, queries, strategy, order) else _searchsortedlast_unsorted_loop!(idx_out, v, queries, order) @@ -1395,7 +1469,8 @@ end # branch is type-stable so the loop specializes on the concrete strategy). function _searchsortedlast_batched!( idx_out, v::AbstractVector, queries::AbstractVector, - s::Auto, order::Base.Order.Ordering + s::Auto, order::Base.Order.Ordering, + queries_sorted::Union{Nothing, Bool}, ) m = length(queries) m == 0 && return idx_out @@ -1407,7 +1482,7 @@ function _searchsortedlast_batched!( searchsortedlast(v, queries[firstindex(queries)], order) return idx_out end - if !issorted(queries; order = order) + if !_take_sorted_path(queries, order, queries_sorted) return _searchsortedlast_unsorted_loop!(idx_out, v, queries, order) end gap, skewed = _estimate_avg_gap(v, queries, m) @@ -1490,9 +1565,10 @@ end function _searchsortedfirst_batched!( idx_out, v::AbstractVector, queries::AbstractVector, - strategy::SearchStrategy, order::Base.Order.Ordering + strategy::SearchStrategy, order::Base.Order.Ordering, + queries_sorted::Union{Nothing, Bool}, ) - return if issorted(queries; order = order) + return if _take_sorted_path(queries, order, queries_sorted) _searchsortedfirst_sorted_loop!(idx_out, v, queries, strategy, order) else _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) @@ -1501,7 +1577,8 @@ end function _searchsortedfirst_batched!( idx_out, v::AbstractVector, queries::AbstractVector, - s::Auto, order::Base.Order.Ordering + s::Auto, order::Base.Order.Ordering, + queries_sorted::Union{Nothing, Bool}, ) m = length(queries) m == 0 && return idx_out @@ -1510,7 +1587,7 @@ function _searchsortedfirst_batched!( searchsortedfirst(v, queries[firstindex(queries)], order) return idx_out end - if !issorted(queries; order = order) + if !_take_sorted_path(queries, order, queries_sorted) return _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) end gap, skewed = _estimate_avg_gap(v, queries, m) @@ -1680,6 +1757,53 @@ Base.@propagate_inbounds function searchsortedfirstexp( return searchsortedfirst(v, x, lo + tn2 - tn2m1, hi, Base.Order.Forward) end +# --------------------------------------------------------------------------- +# Range search through the strategy dispatch +# --------------------------------------------------------------------------- + +""" + searchsortedrange(strategy, v, lo, hi[, hint]; order = Base.Order.Forward) + -> UnitRange{Int} + +Return the index range of all entries `v[i]` satisfying `lo ≤ v[i] ≤ hi` +under `order`. Equivalent to +`searchsortedfirst(strategy, v, lo[, hint]; order) : + searchsortedlast(strategy, v, hi[, hint]; order)` but expressed as a +single call that may share bracket-discovery work between the two +endpoints when the underlying strategy allows it. + +The empty range case (no `v[i]` lies in `[lo, hi]`) returns +`searchsortedfirst(strategy, v, lo) : (searchsortedfirst(strategy, v, lo) - 1)`, +matching `Base.searchsorted(v, lo)` for an absent value. + +When a `hint` is supplied it is used for both endpoint searches. Strategies +that ignore the hint (`BinaryBracket`, `InterpolationSearch`) treat the +hinted form as a pass-through. +""" +@inline function searchsortedrange( + strategy::SearchStrategy, v::AbstractVector, lo, hi; + order::Base.Order.Ordering = Base.Order.Forward + ) + first_idx = searchsortedfirst(strategy, v, lo; order = order) + last_idx = searchsortedlast(strategy, v, hi; order = order) + return first_idx:last_idx +end + +@inline function searchsortedrange( + strategy::SearchStrategy, v::AbstractVector, lo, hi, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward + ) + first_idx = searchsortedfirst(strategy, v, lo, hint; order = order) + # `last_idx` searches *forward* from `first_idx` if the hint suggests it + # (lo ≤ hi means the right endpoint is ≥ first_idx). Use first_idx as a + # hint to skip work shared with the left search; falls back to the + # supplied hint for strategies that ignore the integer hint. + last_idx = searchsortedlast( + strategy, v, hi, max(first_idx, hint); order = order + ) + return first_idx:last_idx +end + # --------------------------------------------------------------------------- # Equality search through the strategy dispatch # --------------------------------------------------------------------------- diff --git a/test/runtests.jl b/test/runtests.jl index 0b8e6cc..45e04a7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -346,7 +346,7 @@ end # because InterpolationSearch's bad guess just makes BracketGallop # wider, never incorrect. v_log = exp.(range(0.0, 10.0; length = 4096)) - lying = SearchProperties(true, true, false) + lying = SearchProperties(true, true, false, false) tt_log = sort!(rand(StableRNG(11), 8) .* (v_log[end] - v_log[1]) .+ v_log[1]) out_lying = Vector{Int}(undef, length(tt_log)) searchsortedlast!(out_lying, v_log, tt_log; strategy = Auto(lying)) @@ -354,6 +354,26 @@ end # Bits-ness: SearchProperties must be isbits so it doesn't allocate. @test isbitstype(SearchProperties) + + # is_log_linear field: populated by SearchProperties(v) on + # geometric data, rejected on linear / two-scale data. + v_log = collect(exp.(range(0.0, log(1.0e6); length = 65536))) + p_log = SearchProperties(v_log) + @test p_log.is_log_linear + + v_lin = collect(0.0:0.001:65.0) + p_lin = SearchProperties(v_lin) + @test !p_lin.is_log_linear + + # Two-scale data should fail both linearity probes. + v_2s = sort!(vcat(range(0.0, 1.0; length = 32768), range(1.0, 100.0; length = 32768))) + p_2s = SearchProperties(v_2s) + @test !p_2s.is_log_linear + + # is_log_linear requires strictly positive v; mixed-sign rejects. + v_signed = collect(-100.0:0.001:65.0) + p_signed = SearchProperties(v_signed) + @test !p_signed.is_log_linear end @safetestset "Batched in-place searchsorted!" begin @@ -444,6 +464,83 @@ end end end + @safetestset "searchsortedrange" begin + using FindFirstFunctions, StableRNGs + v = collect(0.0:0.5:50.0) + # Compare against Base composition for several (lo, hi) pairs. + for (lo, hi) in [ + (5.0, 7.0), (0.0, 100.0), (-1.0, 5.5), (10.0, 10.0), + (45.0, 60.0), (51.0, 100.0), + ] + expected = searchsortedfirst(v, lo):searchsortedlast(v, hi) + for strategy in ( + Auto(), BinaryBracket(), BracketGallop(), LinearScan(), + InterpolationSearch(), ExpFromLeft(), SIMDLinearScan(), + ) + @test searchsortedrange(strategy, v, lo, hi) == expected + # Hinted form. + h = clamp(searchsortedfirst(v, lo), 1, length(v)) + @test searchsortedrange(strategy, v, lo, hi, h) == expected + end + end + # Random fuzz on Int64. + rng = StableRNG(2026) + vi = sort!(rand(rng, Int64(-100):Int64(100), 200)) + for _ in 1:200 + lo, hi = sort([rand(rng, Int64(-110):Int64(110)) for _ in 1:2]) + want = searchsortedfirst(vi, lo):searchsortedlast(vi, hi) + @test searchsortedrange(Auto(), vi, lo, hi) == want + @test searchsortedrange(BracketGallop(), vi, lo, hi, 100) == want + end + # Type stability: result is UnitRange{Int}. + @test typeof(searchsortedrange(Auto(), v, 5.0, 7.0)) === UnitRange{Int} + end + + @safetestset "queries_sorted kwarg" begin + using FindFirstFunctions, StableRNGs + v = collect(0.0:0.5:100.0) + rng = StableRNG(2026) + sorted_q = sort!(rand(rng, 64) .* 100.0) + unsorted_q = rand(rng, 64) .* 100.0 + out = Vector{Int}(undef, 64) + expected_sorted = searchsortedlast.(Ref(v), sorted_q) + expected_unsorted = searchsortedlast.(Ref(v), unsorted_q) + + # Default behaviour (nothing) — runtime issorted check. + searchsortedlast!(out, v, sorted_q; strategy = Auto()) + @test out == expected_sorted + searchsortedlast!(out, v, unsorted_q; strategy = Auto()) + @test out == expected_unsorted + + # Explicit queries_sorted = true: trust the caller's sortedness. + searchsortedlast!(out, v, sorted_q; strategy = Auto(), queries_sorted = true) + @test out == expected_sorted + # Across every shipped strategy. + for strategy in ( + LinearScan(), SIMDLinearScan(), BracketGallop(), + ExpFromLeft(), InterpolationSearch(), BinaryBracket(), + ) + searchsortedlast!( + out, v, sorted_q; + strategy = strategy, queries_sorted = true + ) + @test out == expected_sorted + searchsortedfirst!( + out, v, sorted_q; + strategy = strategy, queries_sorted = true + ) + @test out == searchsortedfirst.(Ref(v), sorted_q) + end + + # Explicit queries_sorted = false: take the unsorted-loop path + # unconditionally, even on sorted input — answers must still be + # correct (the unsorted loop is per-query unhinted Base call). + searchsortedlast!(out, v, sorted_q; strategy = Auto(), queries_sorted = false) + @test out == expected_sorted + searchsortedlast!(out, v, unsorted_q; strategy = Auto(), queries_sorted = false) + @test out == expected_unsorted + end + @safetestset "SIMDLinearScan correctness" begin using FindFirstFunctions, StableRNGs F = FindFirstFunctions From d5b976e4bc174dc2effe4cc1054fadf4adf9759e Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Wed, 20 May 2026 10:34:42 -0400 Subject: [PATCH 16/16] Split src/FindFirstFunctions.jl into a 10-file hierarchy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The package source had grown to a single 1900-line file mixing every layer: LLVM IR templates, equality-search primitives, strategy type definitions, the per-strategy dispatch methods, Auto's heuristic decision tree, the batched in-place API, the Guesser correlated-lookup helper, the findequal strategy-framework wrapper, and the PrecompileTools workload. Splitting into one file per logical layer makes the source navigable without changing any behaviour. src/ ├── FindFirstFunctions.jl 39 lines module + exports + includes ├── simd_ir.jl 135 IR template + IR constants + SIMD │ primitives (eq, sgt, sge, ogt, oge) ├── equality.jl 73 findfirstequal + findfirstsortedequal ├── strategies.jl 268 SearchStrategy abstract + concrete │ strategy types + SearchProperties + │ Auto (struct + docstrings) ├── search_properties.jl 120 _sampled_looks_linear / │ _sampled_looks_log_linear / _has_nan │ + populated SearchProperties ctor ├── dispatch.jl 583 Per-strategy searchsortedfirst/last │ methods + bracketstrictlymonotonic* │ + searchsortedfirstexp + _interp_guess │ + _bit_interp_guess_f64 + │ _simdscan_*_specialized ├── auto.jl 168 Auto crossover constants + per-query │ Auto + _estimate_avg_gap + │ _auto_simd_eligible / │ _auto_simd_gap_max / │ _auto_interp_eligible + _auto_pick ├── batched.jl 321 searchsortedfirst!/last! + │ sorted/unsorted inner loops + │ _take_sorted_path + generic │ _batched! + Auto-specialized │ _batched! + searchsortedrange ├── guesser.jl 109 looks_linear + Guesser + GuesserHint │ dispatch (relies on BracketGallop) ├── findequal.jl 91 findequal generic + BisectThenSIMD │ shortcut for DenseVector{Int64} └── precompile.jl 58 PrecompileTools @setup_workload Include order is significant — each file may depend on names from earlier files. The order is documented in `FindFirstFunctions.jl` and is: simd_ir → equality → strategies → search_properties → dispatch → auto → batched → guesser → findequal → precompile. The two non-obvious dependencies are: - `auto.jl` references `_sampled_looks_linear` from `search_properties.jl` (the `_auto_interp_eligible` loose tier). - `batched.jl` references `_estimate_avg_gap`, `_auto_simd_eligible`, `_auto_simd_gap_max`, `_auto_interp_eligible`, `_AUTO_*` constants from `auto.jl` (the Auto-specialized `_batched!` lives in `batched.jl` because it shares the sorted/unsorted-loop infrastructure with the generic `_batched!`). 84626 tests pass; no behavioural change. Co-Authored-By: Chris Rackauckas --- src/FindFirstFunctions.jl | 1945 +------------------------------------ src/auto.jl | 168 ++++ src/batched.jl | 321 ++++++ src/dispatch.jl | 583 +++++++++++ src/equality.jl | 73 ++ src/findequal.jl | 91 ++ src/guesser.jl | 109 +++ src/precompile.jl | 58 ++ src/search_properties.jl | 120 +++ src/simd_ir.jl | 135 +++ src/strategies.jl | 268 +++++ 11 files changed, 1941 insertions(+), 1930 deletions(-) create mode 100644 src/auto.jl create mode 100644 src/batched.jl create mode 100644 src/dispatch.jl create mode 100644 src/equality.jl create mode 100644 src/findequal.jl create mode 100644 src/guesser.jl create mode 100644 src/precompile.jl create mode 100644 src/search_properties.jl create mode 100644 src/simd_ir.jl create mode 100644 src/strategies.jl diff --git a/src/FindFirstFunctions.jl b/src/FindFirstFunctions.jl index d114843..2c962c6 100644 --- a/src/FindFirstFunctions.jl +++ b/src/FindFirstFunctions.jl @@ -18,1937 +18,22 @@ export searchsortedfirst!, searchsortedlast!, searchsortedrange, findequal, findfirstequal, findfirstsortedequal -# https://github.com/JuliaLang/julia/pull/53687 +# Julia 1.12 changed how `Ptr{T}` arguments to `Base.llvmcall` are passed: +# they're now real pointers rather than i64s. https://github.com/JuliaLang/julia/pull/53687 const USE_PTR = VERSION >= v"1.12.0-DEV.255" -# Generate the SIMD "find first lane matching predicate" IR for an arbitrary -# scalar type and LLVM compare predicate. Load 8 lanes at a time, compare -# against a broadcast of the search value, bitcast the i1×8 mask to i8, -# `cttz` to find the first set bit. The tail past the last full chunk is -# handled scalar-wise. -# -# Used to back four equality / inequality SIMD primitives: -# - `_findfirstequal` — exact equality, Int64 (predicate `eq`) -# - `_simd_first_gt`/`_ge` — strict / non-strict greater-than, Int64 -# (predicates `sgt` / `sge`) -# - same pair for Float64 — predicates `ogt` / `oge` (ordered compares) -function _simd_scan_ir(t, pred) - cmp = pred[1] in ('o', 'u') ? "fcmp" : "icmp" - return """ - declare i8 @llvm.cttz.i8(i8, i1); - define i64 @entry($t %0, $(USE_PTR ? "ptr" : "i64") %1, i64 %2) #0 { - top: - $(USE_PTR ? "" : "%ivars = inttoptr i64 %1 to $t*") - %btmp = insertelement <8 x $t> undef, $t %0, i64 0 - %var = shufflevector <8 x $t> %btmp, <8 x $t> undef, <8 x i32> zeroinitializer - %lenm7 = add nsw i64 %2, -7 - %dosimditer = icmp ugt i64 %2, 7 - br i1 %dosimditer, label %L9.lr.ph, label %L32 - - L9.lr.ph: - %len8 = and i64 %2, 9223372036854775800 - br label %L9 - - L9: - %i = phi i64 [ 0, %L9.lr.ph ], [ %vinc, %L30 ] - %ivarsi = getelementptr inbounds $t, $(USE_PTR ? "ptr %1" : "$t* %ivars"), i64 %i - $(USE_PTR ? "" : "%vpvi = bitcast $t* %ivarsi to <8 x $t>*") - %v = load <8 x $t>, $(USE_PTR ? "ptr %ivarsi" : "<8 x $t> * %vpvi"), align 8 - %m = $cmp $pred <8 x $t> %v, %var - %mu = bitcast <8 x i1> %m to i8 - %matchnotfound = icmp eq i8 %mu, 0 - br i1 %matchnotfound, label %L30, label %L17 - - L17: - %tz8 = call i8 @llvm.cttz.i8(i8 %mu, i1 true) - %tz64 = zext i8 %tz8 to i64 - %vis = add nuw i64 %i, %tz64 - br label %common.ret - - common.ret: - %retval = phi i64 [ %vis, %L17 ], [ -1, %L32 ], [ %si, %L51 ], [ -1, %L67 ] - ret i64 %retval - - L30: - %vinc = add nuw nsw i64 %i, 8 - %continue = icmp slt i64 %vinc, %lenm7 - br i1 %continue, label %L9, label %L32 - - L32: - %cumi = phi i64 [ 0, %top ], [ %len8, %L30 ] - %done = icmp eq i64 %cumi, %2 - br i1 %done, label %common.ret, label %L51 - - L51: - %si = phi i64 [ %inc, %L67 ], [ %cumi, %L32 ] - %spi = getelementptr inbounds $t, $(USE_PTR ? "ptr %1" : "$t* %ivars"), i64 %si - %svi = load $t, $(USE_PTR ? "ptr" : "$t*") %spi, align 8 - %match = $cmp $pred $t %svi, %0 - br i1 %match, label %common.ret, label %L67 - - L67: - %inc = add i64 %si, 1 - %dobreak = icmp eq i64 %inc, %2 - br i1 %dobreak, label %common.ret, label %L51 - - } - attributes #0 = { alwaysinline } - """ -end - -const FFE_IR = _simd_scan_ir("i64", "eq") - -function _findfirstequal(vpivot::Int64, ptr::Ptr{Int64}, len::Int64) - return Base.llvmcall( - (FFE_IR, "entry"), - Int64, - Tuple{Int64, Ptr{Int64}, Int64}, - vpivot, - ptr, - len - ) -end - -""" - findfirstequal(x, A) -> Union{Int, Nothing} - -Find the first index in `A` where the value equals `x`. Returns `nothing` -if `x` does not occur in `A`. - -This function does **not** assume `A` is sorted. For sorted vectors, see -[`findfirstsortedequal`](@ref) (a bisect-then-SIMD specialization on -`DenseVector{Int64}`) or [`findequal`](@ref) (the strategy-framework -equality wrapper that returns an `Int` with a sentinel). - -The `(x::Int64, A::DenseVector{Int64})` method uses a custom LLVM IR SIMD -scan (load 8 lanes, `icmp eq`, `cttz` on the mask) — about 8× faster than -the scalar `findfirst(==(x), v)` on modern x86-64. Every other element-type -and array-storage combination falls back to `findfirst(isequal(x), A)`. -""" -findfirstequal(vpivot, ivars) = findfirst(isequal(vpivot), ivars) -function findfirstequal(vpivot::Int64, ivars::DenseVector{Int64}) - GC.@preserve ivars begin - ret = _findfirstequal(vpivot, pointer(ivars), length(ivars)) - end - return ret < 0 ? nothing : ret + 1 -end - -const _SIMD_GT_I64_IR = _simd_scan_ir("i64", "sgt") -const _SIMD_GE_I64_IR = _simd_scan_ir("i64", "sge") -const _SIMD_GT_F64_IR = _simd_scan_ir("double", "ogt") -const _SIMD_GE_F64_IR = _simd_scan_ir("double", "oge") - -# Backing primitives for SIMDLinearScan. Each returns the 0-based offset of -# the first lane satisfying the predicate, or -1 if none. Caveat: NaN inputs -# always compare false under the ordered `o*` float predicates, so NaN in `v` -# or `x` produces "no match" rather than an exception — consistent with the -# undefined-input contract for sorted Float64 vectors containing NaN. -function _simd_first_gt(x::Int64, ptr::Ptr{Int64}, len::Int64) - return Base.llvmcall( - (_SIMD_GT_I64_IR, "entry"), - Int64, Tuple{Int64, Ptr{Int64}, Int64}, - x, ptr, len - ) -end -function _simd_first_ge(x::Int64, ptr::Ptr{Int64}, len::Int64) - return Base.llvmcall( - (_SIMD_GE_I64_IR, "entry"), - Int64, Tuple{Int64, Ptr{Int64}, Int64}, - x, ptr, len - ) -end -function _simd_first_gt(x::Float64, ptr::Ptr{Float64}, len::Int64) - return Base.llvmcall( - (_SIMD_GT_F64_IR, "entry"), - Int64, Tuple{Float64, Ptr{Float64}, Int64}, - x, ptr, len - ) -end -function _simd_first_ge(x::Float64, ptr::Ptr{Float64}, len::Int64) - return Base.llvmcall( - (_SIMD_GE_F64_IR, "entry"), - Int64, Tuple{Float64, Ptr{Float64}, Int64}, - x, ptr, len - ) -end - -""" - findfirstsortedequal(var::Int64, vars::DenseVector{Int64}) -> Union{Int64, Nothing} - -Find the index of the first occurrence of `var` in the sorted vector -`vars`. Returns `nothing` if `var` does not occur. Specialized for -`DenseVector{Int64}` via a branchless binary bisection down to a small -basecase, followed by the same SIMD equality scan that backs -[`findfirstequal`](@ref) — faster than plain `findfirst(==(var), vars)` -or `searchsortedfirst` + post-check for typical Int64 vectors. - -The strategy-framework equivalent is -[`findequal(BisectThenSIMD(), vars, var)`](@ref findequal); that wrapper -returns an `Int` with a sentinel (`firstindex(v) - 1`) for "not found", -which is type-stable and composes with the rest of the strategy -dispatch. Prefer `findequal` for new code; `findfirstsortedequal` remains -as the dedicated `Union{Int64, Nothing}`-returning name. -""" -function findfirstsortedequal( - var::Int64, - vars::DenseVector{Int64}, - ::Val{basecase} = Base.libllvm_version >= v"17" ? Val(8) : Val(128) - ) where {basecase} - len = length(vars) - offset = 0 - @inbounds while len > basecase - # Bisect with the predicate `vars[mid] < var` (strict). When true, - # `var` is past the midpoint — drop the left half *and* the - # midpoint itself. When false (`vars[mid] >= var`), `var` may be - # at the midpoint, so keep `offset` and shrink the window to - # `vars[offset+1 .. offset+half+1]` (inclusive of the midpoint). - # The earlier `<=` predicate would have advanced past matching - # midpoints, masking earlier duplicates of `var`. - half = len >>> 1 - mid = offset + half + 1 - is_left_strictly_less = vars[mid] < var - offset = ifelse(is_left_strictly_less, offset + half + 1, offset) - len = ifelse(is_left_strictly_less, len - half - 1, half + 1) - end - # maybe occurs in vars[offset+1:offset+len] - GC.@preserve vars begin - ret = _findfirstequal(var, pointer(vars) + 8offset, len) - end - return ret < 0 ? nothing : ret + offset + 1 -end - -# Internal: expanding-binary-search bracket around a guess. Backs the -# `BracketGallop` strategy. Not part of the public API in 2.x — use -# `searchsortedfirst(BracketGallop(), v, x, guess)` / -# `searchsortedlast(BracketGallop(), v, x, guess)` instead. -function bracketstrictlymonotonic( - v::AbstractVector, - x, - guess::T, - o::Base.Order.Ordering - )::NTuple{2, keytype(v)} where {T <: Integer} - bottom = firstindex(v) - top = lastindex(v) - if guess < bottom || guess > top - return bottom, top - # # NOTE: for cache efficiency in repeated calls, we avoid accessing the first and last elements of `v` - # # on each call to this function. This should only result in significant slow downs for calls with - # # out-of-bounds values of `x` *and* bad `guess`es. - # elseif lt(o, x, v[bottom]) - # return bottom, bottom - # elseif lt(o, v[top], x) - # return top, top - else - u = T(1) - lo, hi = guess, min(guess + u, top) - @inbounds if Base.Order.lt(o, x, v[lo]) - while lo > bottom && Base.Order.lt(o, x, v[lo]) - lo, hi = max(bottom, lo - u), lo - u += u - end - else - while hi < top && !Base.Order.lt(o, x, v[hi]) - lo, hi = hi, min(top, hi + u) - u += u - end - end - end - return lo, hi -end - -# Internal: companion to `bracketstrictlymonotonic` for the `searchsortedfirst` -# polarity. The original galloping uses `lt(o, x, v[lo])` (i.e., `x < v[lo]`) -# to choose direction, which is the right test for `searchsortedlast`: when -# `x == v[lo]`, the answer is `>= lo` so we gallop right. For -# `searchsortedfirst`, when `x == v[lo]` the answer is `<= lo` (look for -# earlier duplicates) — so we need the inverted polarity `lt(o, v[lo], x)` -# (i.e., `v[lo] < x`). Without this, BracketGallop.searchsortedfirst returns -# the wrong index when the hint lands on a run of duplicates. -function bracketstrictlymonotonic_first( - v::AbstractVector, - x, - guess::T, - o::Base.Order.Ordering - )::NTuple{2, keytype(v)} where {T <: Integer} - bottom = firstindex(v) - top = lastindex(v) - if guess < bottom || guess > top - return bottom, top - else - u = T(1) - lo, hi = guess, min(guess + u, top) - @inbounds if !Base.Order.lt(o, v[lo], x) - # v[lo] >= x → answer is <= lo, gallop left. - while lo > bottom && !Base.Order.lt(o, v[lo], x) - lo, hi = max(bottom, lo - u), lo - u += u - end - else - # v[lo] < x → answer is > lo, gallop right. - while hi < top && Base.Order.lt(o, v[hi], x) - lo, hi = hi, min(top, hi + u) - u += u - end - end - end - return lo, hi -end - -# --------------------------------------------------------------------------- -# Sorted-search strategies -# --------------------------------------------------------------------------- - -""" - SearchStrategy - -Abstract supertype for sorted-search strategies. Concrete subtypes select how -[`searchsortedlast`](@ref Base.searchsortedlast) and -[`searchsortedfirst`](@ref Base.searchsortedfirst) should be performed when -called with a strategy as the first positional argument: - - - [`LinearScan`](@ref) walks ±1 from the hint. Cheapest when the target is - within a few positions of the hint; degrades linearly otherwise. - - [`SIMDLinearScan`](@ref) is `LinearScan` with the forward walk lowered to - 8-wide SIMD chunks for `DenseVector{Int64}` and `DenseVector{Float64}`. - Falls back to plain [`LinearScan`](@ref) for any other element type. - - [`BracketGallop`](@ref) expands an exponential bracket bidirectionally - from the hint, then binary-searches inside it. Effectively O(1) when the - target is near the hint; never worse than ~2 log₂ n comparisons. - - [`ExpFromLeft`](@ref) expands rightward from a left-bound hint by - doubling, then binary-searches inside the final bracket. Best for batched - sorted queries where each next query's hint is the previous result. - - [`InterpolationSearch`](@ref) guesses the answer by linearly extrapolating - between `v[lo]` and `v[hi]`, then refines with a bounded binary search. - O(1) per query on uniformly-spaced data; falls back to O(log n) on - irregular data. - - [`BinaryBracket`](@ref) is the standard `Base.searchsortedlast` / - `Base.searchsortedfirst` with no hint. Use it when no useful hint exists. - - [`BisectThenSIMD`](@ref) is an equality-search strategy: binary-bisects - `v` to a small basecase, then SIMD-scans for exact equality. Specialised - for `DenseVector{Int64}`; only meaningful when used with - [`findequal`](@ref). - - [`Auto`](@ref) heuristically picks one of the above based on the size of - `v`, the spacing of `v`, and whether a hint was supplied. Accepts an - optional [`SearchProperties`](@ref) cache to skip per-call probes. - -Strategies can also be passed to the batched -[`searchsortedlast!`](@ref) / [`searchsortedfirst!`](@ref) APIs. -""" -abstract type SearchStrategy end - -""" - LinearScan <: SearchStrategy - -Walk ±1 from the hint. Best when the target is within a few positions of the -hint. Falls back to [`BinaryBracket`](@ref) when no hint is supplied. -""" -struct LinearScan <: SearchStrategy end - -""" - SIMDLinearScan <: SearchStrategy - -Variant of [`LinearScan`](@ref) whose forward walk is lowered to 8-wide -SIMD chunks via custom LLVM IR. Specialized for `DenseVector{Int64}` and -`DenseVector{Float64}`; for any other element type, falls back to plain -[`LinearScan`](@ref). The backward walk (when the hint is past the -answer) uses the scalar `LinearScan` path regardless of element type. - -Wins on long forward walks (≥ 8 elements past the hint). For walks of -1–3 elements `LinearScan` is comparable — the SIMD chunk has constant -setup overhead. Worst case is O(n / 8) which is still linear, so -`SIMDLinearScan` is only `Auto`-relevant for small `n` or small-gap -batches where plain `LinearScan` would have been picked anyway. - -Caveats: - - Element type must be exactly `Int64` or `Float64`. `Int32`, - `UInt64`, `Float32`, and user-defined numeric types all fall back to - scalar. - - Sorted-Float64 vectors containing `NaN` produce undefined results, - same as for any positional search on a vector that isn't totally - ordered. - - Falls back to [`BinaryBracket`](@ref) when no hint is supplied. - - Falls back to [`LinearScan`](@ref) for non-`Forward` orderings. -""" -struct SIMDLinearScan <: SearchStrategy end - -""" - BracketGallop <: SearchStrategy - -Expand an exponential bracket bidirectionally from the hint, then -binary-search inside the bracket. Effectively O(1) when the target is near -the hint; never worse than ~2 log₂ n comparisons. - -Falls back to [`BinaryBracket`](@ref) when no hint is supplied. -""" -struct BracketGallop <: SearchStrategy end - -""" - ExpFromLeft <: SearchStrategy - -Exponential search forward from the hint (interpreted as a left bound), then -binary search in the final bracket. The hint is a *lower* bound rather than a -center guess, which is what batched sorted-search loops typically want: -`hint = previous_result`. - -Specifically: starting at `lo = hint`, check `v[lo], v[lo+1], ..., v[lo+4]` -linearly, then `v[lo+8], v[lo+16], …` exponentially, until `x` is bracketed, -then binary-search inside the bracket. - -Falls back to [`BinaryBracket`](@ref) when no hint is supplied. -""" -struct ExpFromLeft <: SearchStrategy end - -""" - InterpolationSearch <: SearchStrategy - -Guesses an index by linearly extrapolating `x` between `v[lo]` and `v[hi]`, -then refines with a bounded binary search. O(1) per query on uniformly-spaced -data (e.g. `collect(0:0.1:10)`); falls back to O(log n) otherwise. Requires -`x` to be subtractable with elements of `v` (i.e., a numeric ordering). - -Ignores any hint that is supplied — the guess is computed fresh from the -endpoints. Falls back to [`BinaryBracket`](@ref) for non-numeric element -types where subtraction isn't defined. -""" -struct InterpolationSearch <: SearchStrategy end - -""" - BitInterpolationSearch <: SearchStrategy - -Variant of [`InterpolationSearch`](@ref) that reinterprets `DenseVector{Float64}` -as `DenseVector{UInt64}` before computing the extrapolation guess. For -positive IEEE Float64 values, the bit pattern is monotonically increasing -with the float value and is approximately linear in array index when the -underlying data is *log-spaced* (geometric). On such data the bit-domain -guess is far better than the float-domain guess that `InterpolationSearch` -would compute — sometimes O(1) versus O(log n) refinement. - -After computing the bit-domain guess, the bracket and binary refine step -uses the original float values for comparison, so the answer is identical -to `Base.searchsortedlast` / `Base.searchsortedfirst`. - -Constraints: - - `DenseVector{Float64}` only (the IEEE bit-pattern trick is Float64-specific). - - Requires `v[1] > 0` and the query `x > 0` (negative, zero, subnormal, - and non-finite Float64 bit patterns are not monotonic with float value - under raw reinterpret). - - Forward ordering only. - -**This strategy is opt-in only** — `Auto` does not pick it. The bench sweep -shows the per-query division and UInt64↔Float64 conversion overhead -(~60–90 ns/q) costs more than the bracket refinement that the guess -saves at every gap tested; pinning `BitInterpolationSearch` is slower than -letting `Auto` pick `SIMDLinearScan` / `BracketGallop` / `ExpFromLeft`. -The strategy is retained for users with workloads not covered by the -sweep — for instance, very-large `n` (≥ 2²⁰), pathologically log-spaced -data, or hardware where Float64 division is unusually cheap relative to -the scalar walk. - -Falls back to [`InterpolationSearch`](@ref) for non-Float64 dense eltypes -(where the bit pattern equals the value and the two strategies are -equivalent), and to [`BinaryBracket`](@ref) for non-positive or -non-finite Float64 data. -""" -struct BitInterpolationSearch <: SearchStrategy end - -""" - BinaryBracket <: SearchStrategy - -Plain `Base.searchsortedlast` / `Base.searchsortedfirst`. Ignores any hint -that is supplied. -""" -struct BinaryBracket <: SearchStrategy end - -""" - BisectThenSIMD <: SearchStrategy - -Equality-search strategy. Binary-bisects `v` down to a small basecase, then -SIMD-scans the basecase for exact equality with `x`. Specialised for -`DenseVector{Int64}` + `Int64` queries via the same custom LLVM IR that -backs [`findfirstsortedequal`](@ref FindFirstFunctions.findfirstsortedequal); -for other element types, falls back to [`BinaryBracket`](@ref) plus an -equality check. - -This strategy is meant for use with [`findequal`](@ref FindFirstFunctions.findequal), -not with `searchsortedfirst` / `searchsortedlast` — its purpose is to answer -"is `x` present at exactly which index, or not at all?", which is a -different question from positional search. In the -`searchsortedfirst`/`searchsortedlast` dispatch it falls back to -[`BinaryBracket`](@ref). - -Ignores any hint that is supplied. Falls back to [`BinaryBracket`](@ref) for -non-`Forward` orderings. -""" -struct BisectThenSIMD <: SearchStrategy end - -""" - GuesserHint(guesser::Guesser) <: SearchStrategy - -Uses a [`Guesser`](@ref) to produce an integer guess for `x`, then dispatches -to [`BracketGallop`](@ref) from that guess. The `Guesser` already decides -between linear-extrapolation lookup (when `v` looks linear) and using the -previous result as a guess; this strategy plugs that logic into the strategy -dispatch hierarchy, and updates `guesser.idx_prev` on each call. - -Use this strategy with the per-query and batched APIs whenever you have a -`Guesser` attached to a vector. The cost is one `guesser(x)` evaluation -plus one `BracketGallop` call plus one `idx_prev[]` write per call. -""" -struct GuesserHint{G} <: SearchStrategy - guesser::G -end - -""" - SearchProperties - -Cached, non-allocating facts about a sorted vector. Pass to [`Auto`](@ref) -via `Auto(props)` to skip the per-call probes that the default `Auto()` runs -on every batched call. Stored fields are kept to plain `Bool`s so the struct -stays `isbits` and travels in registers. - -Default-constructed (`SearchProperties()`) is the "no information" sentinel: -`has_props` is `false`, the other fields are unspecified and ignored by -`Auto`. Construct via `SearchProperties(v::AbstractVector)` to populate the -fields by running the probes once. - -Currently consumed: `is_linear` and `has_nan` (the latter only on Float64, -to gate `SIMDLinearScan` eligibility in `Auto`). `is_log_linear` is -populated for callers that want to manually pin -[`BitInterpolationSearch`](@ref) based on data shape; `Auto` does not -consume it. The fields are otherwise populated for forward compatibility. -""" -struct SearchProperties - has_props::Bool - is_linear::Bool - has_nan::Bool - is_log_linear::Bool -end - -SearchProperties() = SearchProperties(false, false, false, false) - -# `has_nan` is only meaningful for floating-point eltypes; for other numeric -# types and non-numeric eltypes there is no NaN concept. -@inline _has_nan(v::AbstractVector{<:AbstractFloat}) = any(isnan, v) -@inline _has_nan(::AbstractVector) = false - -""" - SearchProperties(v::AbstractVector; linear_tolerance = 1.0e-3) - -Run the linearity probe and (for floating-point eltypes) the NaN scan on `v`, -returning the populated [`SearchProperties`](@ref). Cost is O(n) on -floating-point vectors because of the NaN scan; for integer and non-numeric -eltypes the cost is O(1) — only the sampled-linearity probe runs. - -`linear_tolerance` controls the maximum relative deviation accepted by the -sampled-linearity probe. The default `1e-3` (0.1%) matches `Auto`'s -un-cached probe behaviour. Loosen it (e.g. to `1e-2`) to accept noisier -"approximately linear" data — this widens the regime where `Auto` will pick -`InterpolationSearch` over `ExpFromLeft`. Tighten it (e.g. to `1e-4`) to be -more conservative. -""" -function SearchProperties( - v::AbstractVector; - linear_tolerance::Real = 1.0e-3, - ) - tol = Float64(linear_tolerance) - return SearchProperties( - true, - _sampled_looks_linear(v, tol), - _has_nan(v), - _sampled_looks_log_linear(v, tol), - ) -end - -""" - Auto <: SearchStrategy - Auto() - Auto(props::SearchProperties) - -Heuristically picks among [`LinearScan`](@ref), [`ExpFromLeft`](@ref), -[`InterpolationSearch`](@ref), [`BracketGallop`](@ref), and -[`BinaryBracket`](@ref). The choice depends on the calling context: - -**Per-query** (`searchsortedlast(Auto(), v, x[, hint])`): - - No hint, or hint outside `axes(v)` → [`BinaryBracket`](@ref). - - Hint in range, `length(v) ≤ 16` → [`LinearScan`](@ref). - - Hint in range, `length(v) > 16` → [`BracketGallop`](@ref). - -**Batched sorted** (`searchsortedlast!(out, v, queries; strategy = Auto())`), -using the expected average gap between consecutive results. For numeric -data the gap is estimated from the span ratio -`(queries[end] - queries[1]) / (v[end] - v[1])` so that dense-burst queries -clustered inside one segment of `v` are recognized as having gap ≈ 0: - - `gap ≤ 4` → [`LinearScan`](@ref) (most queries land in the same - segment or the next; linear-walk overhead is minimal, and `ExpFromLeft` - wastes its 5 initial linear probes when the gap is already 0 or 1). - - `gap ≥ 8`, `length(v) ≥ 1024`, `length(queries) ≥ 2`, and a sampled - linearity probe (~25 ns) accepts → [`InterpolationSearch`](@ref). - On uniformly-spaced data this is ~2× faster than `ExpFromLeft` for - sparse queries; the linearity probe is what keeps `Auto` from picking - `InterpolationSearch` on irregular data where it would lose badly. - - otherwise → [`ExpFromLeft`](@ref) (linear probes for very small - jumps, doubling for medium, bounded binary search for far — always - moving forward from the previous result, which is what - `BracketGallop`'s bidirectional bracketing wastes effort on). - -**Batched unsorted**: falls back to per-element `Base.searchsortedlast` / -`Base.searchsortedfirst` with no hint regardless of strategy. - -**Cached properties.** Passing a populated [`SearchProperties`](@ref) via -`Auto(props)` short-circuits the per-call probes. The cached path is -behaviour-equivalent to `Auto()` when `props` is up to date for `v`; the -caller is responsible for re-computing `props` if `v` mutates. -""" -struct Auto <: SearchStrategy - props::SearchProperties -end - -Auto() = Auto(SearchProperties()) - -# Per-query Auto threshold: under this length, the bracket-search bookkeeping -# costs more than a worst-case linear walk. -const _AUTO_LINEAR_THRESHOLD = 16 - -# Batched-Auto crossover: at gap ≤ 4 LinearScan beats ExpFromLeft (its 5 -# initial linear probes are wasted when the gap is already 0 or 1). -# Above 4, ExpFromLeft handles arbitrary gap sizes via doubling — the -# bench sweep shows it strictly beats BracketGallop for forward-moving -# sorted queries at gap < ~16. -const _AUTO_BATCH_LINEAR_GAP = 4 - -# For sparse queries (gap large) on long vectors, InterpolationSearch can -# beat ExpFromLeft by ~2× on uniformly-spaced data. The sampled-linearity -# check below is O(1) — 9 probes — so it's cheap enough to run inside Auto -# when there's a real chance of unlocking InterpolationSearch. -const _AUTO_INTERP_MIN_GAP = 8 -const _AUTO_INTERP_MIN_N = 1024 -const _AUTO_INTERP_MIN_M = 2 -const _AUTO_LINEAR_REL_TOLERANCE = 1.0e-3 - -# Very-sparse override: when the gap is large enough that ExpFromLeft's -# log₂(gap) doubling levels approach InterpolationSearch's log₂(n) worst-case -# binary refinement, InterpolationSearch's better cache behaviour (one -# extrapolation jump + local refine vs. many doubling probes across the -# array) wins even on non-strictly-linear data — random-sorted vectors -# included, because their order statistics deviate from a straight line by -# O(√n)/n, which is much less than the gap-related cost difference. -# -# At gap ≥ 256, a looser linearity tolerance is used. This still rejects -# genuinely-nonlinear `v` (log-spaced, two-scale), where the bench shows -# InterpolationSearch losing 2–3× to ExpFromLeft, but accepts approximately -# linear data (random_sorted, jittered) where the order-statistic variance -# is well below the loose threshold. -const _AUTO_INTERP_LOOSE_GAP = 256 -const _AUTO_LINEAR_LOOSE_TOLERANCE = 5.0e-2 - -# SIMDLinearScan wins in the medium-gap regime on `DenseVector{Int64}` and -# `DenseVector{Float64}` — 24% of cells in the bench sweep, with median -# 1.94× speedup over plain LinearScan. The threshold is eltype-specific: -# - Float64: gap ∈ (4, 64]. fcmp is heavier than icmp, so SIMD's 8-wide -# vector compare wins over the scalar walk at a higher gap than for -# integers. Bench shows SIMD winning consistently through gap ≈ 64. -# - Int64: gap ∈ (4, 16]. The scalar icmp loop is so tight that SIMD's -# constant per-call setup dominates above gap ≈ 16. Bench shows -# LinearScan recapturing the win above that crossover. -@inline _auto_simd_gap_max(::DenseVector{Int64}) = 64 -@inline _auto_simd_gap_max(::DenseVector{Float64}) = 64 -@inline _auto_simd_gap_max(::AbstractVector) = 0 # not SIMD-eligible - -# When InterpolationSearch isn't eligible and the gap is large, BracketGallop -# beats ExpFromLeft because the 5 linear probes ExpFromLeft does upfront -# are wasted (no chance the answer is within 5 of `hint = prev_result` when -# the gap is hundreds or thousands). BracketGallop just starts doubling -# immediately. The bench sweep shows this crossover at gap ≈ 16. -const _AUTO_GALLOP_GAP_MIN = 16 - -# Sampled linearity check: probes v[1], v[k*n/10] for k = 1..9, v[n] and -# tests whether all interior points sit within `_AUTO_LINEAR_REL_TOLERANCE` -# (default 0.1%) of the straight line between v[1] and v[n]. The tight -# tolerance reliably distinguishes truly-uniform data from random/sorted -# data even at large n (where the order-statistic variance ≈ 1/sqrt(n) -# would fool a looser check). -# -# Cost is ~25 ns regardless of n — 11 reads + 9 comparisons. Used by Auto -# to decide whether to gamble on InterpolationSearch. -# -# InterpolationSearch's downside on non-linear data is large (4-14× slower -# than ExpFromLeft on log/plateau/two-scale spacings), so we err on the -# side of rejecting borderline cases. Truly uniform data — exact ranges, -# evenly-spaced grids, and small-amplitude jittered data — passes; sorted -# random data is rejected at all `n` tested up to ~10⁶. -@inline function _sampled_looks_linear( - v::AbstractVector{<:Number}, - tol::Float64 = _AUTO_LINEAR_REL_TOLERANCE, - ) - n = length(v) - n < 11 && return false - @inbounds begin - v1, vn = v[1], v[n] - span = vn - v1 - (iszero(span) || !isfinite(span)) && return false - abs_span = abs(span) - nm1 = n - 1 - for k in 1:9 - kk = 1 + (k * nm1) ÷ 10 - expected = v1 + (kk - 1) / nm1 * span - rel_err = abs(v[kk] - expected) / abs_span - rel_err > tol && return false - end - end - return true -end - -# Non-numeric eltype: can't sample, never picks InterpolationSearch. -@inline _sampled_looks_linear(::AbstractVector, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = false - -# AbstractRange is definitionally uniform — accept without sampling. -@inline _sampled_looks_linear(::AbstractRange, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = true - -# Sampled "log-linear" probe: same 9-point probe as `_sampled_looks_linear` -# but tests whether `log(v)` is linear in array index. Used to detect -# geometric / log-spaced data where `BitInterpolationSearch` is a win. -# Requires all sampled points to be strictly positive and finite; otherwise -# returns false. The probe runs in ~30 ns (the `log` calls are not cheap -# but only 11 of them, all at fixed index positions). -@inline function _sampled_looks_log_linear( - v::AbstractVector{<:Real}, - tol::Float64 = _AUTO_LINEAR_REL_TOLERANCE, - ) - n = length(v) - n < 11 && return false - @inbounds begin - v1, vn = v[1], v[n] - (v1 <= 0 || vn <= 0 || !isfinite(v1) || !isfinite(vn)) && return false - log_v1 = log(Float64(v1)) - log_vn = log(Float64(vn)) - span = log_vn - log_v1 - (iszero(span) || !isfinite(span)) && return false - abs_span = abs(span) - nm1 = n - 1 - for k in 1:9 - kk = 1 + (k * nm1) ÷ 10 - vk = v[kk] - (vk <= 0 || !isfinite(vk)) && return false - expected = log_v1 + (kk - 1) / nm1 * span - rel_err = abs(log(Float64(vk)) - expected) / abs_span - rel_err > tol && return false - end - end - return true -end - -@inline _sampled_looks_log_linear(::AbstractVector, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = false - -# Strategy: BinaryBracket — ignore any hint. -Base.searchsortedlast( - ::BinaryBracket, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(v, x, order) -Base.searchsortedfirst( - ::BinaryBracket, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(v, x, order) -Base.searchsortedlast( - s::BinaryBracket, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(s, v, x; order = order) -Base.searchsortedfirst( - s::BinaryBracket, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(s, v, x; order = order) - -# Strategy: LinearScan — walk ±1 from the hint until the answer is bracketed. -function Base.searchsortedlast( - ::LinearScan, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - lo, hi = firstindex(v), lastindex(v) - if hi < lo - return lo - 1 # empty vector - end - i = clamp(hint, lo, hi) - @inbounds if Base.Order.lt(order, x, v[i]) - # v[i] > x → retreat - while i > lo - i -= 1 - !Base.Order.lt(order, x, v[i]) && return i - end - return lo - 1 # x precedes all of v - else - # v[i] ≤ x → try to advance - while i < hi - Base.Order.lt(order, x, v[i + 1]) && return i - i += 1 - end - return hi - end -end - -function Base.searchsortedfirst( - ::LinearScan, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - lo, hi = firstindex(v), lastindex(v) - if hi < lo - return lo - end - i = clamp(hint, lo, hi) - @inbounds if Base.Order.lt(order, v[i], x) - # v[i] < x → advance - while i < hi - i += 1 - !Base.Order.lt(order, v[i], x) && return i - end - return hi + 1 # x exceeds all of v - else - # v[i] ≥ x → try to retreat - while i > lo - !Base.Order.lt(order, v[i - 1], x) && (i -= 1; continue) - return i - end - return lo - end -end - -# LinearScan without a hint falls back to BinaryBracket. -Base.searchsortedlast( - s::LinearScan, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(BinaryBracket(), v, x; order = order) -Base.searchsortedfirst( - s::LinearScan, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(BinaryBracket(), v, x; order = order) - -# Strategy: SIMDLinearScan — specialized forward walk for DenseVector{Int64} -# and DenseVector{Float64}. Backward walks reuse the scalar LinearScan path -# (rare from a good hint, and the SIMD primitive only exists for the -# forward-scan direction). - -@inline function _simdscan_last_specialized( - v::Union{DenseVector{Int64}, DenseVector{Float64}}, x, hint::Integer - ) - lo = firstindex(v) - hi = lastindex(v) - hi < lo && return lo - 1 - i = clamp(hint, lo, hi) - @inbounds vi = v[i] - if vi > x - # Backward walk (scalar). - while i > lo - i -= 1 - @inbounds v[i] <= x && return i - end - return lo - 1 - end - i == hi && return hi - start = i + 1 - len = hi - start + 1 - offset = GC.@preserve v _simd_first_gt(x, pointer(v, start), Int64(len)) - return offset < 0 ? hi : (start + offset) - 1 -end - -@inline function _simdscan_first_specialized( - v::Union{DenseVector{Int64}, DenseVector{Float64}}, x, hint::Integer - ) - lo = firstindex(v) - hi = lastindex(v) - hi < lo && return lo - i = clamp(hint, lo, hi) - @inbounds vi = v[i] - if vi < x - i == hi && return hi + 1 - start = i + 1 - len = hi - start + 1 - offset = GC.@preserve v _simd_first_ge(x, pointer(v, start), Int64(len)) - return offset < 0 ? hi + 1 : start + offset - end - while i > lo - @inbounds v[i - 1] >= x && (i -= 1; continue) - return i - end - return lo -end - -function Base.searchsortedlast( - ::SIMDLinearScan, v::DenseVector{Int64}, x::Int64, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - order === Base.Order.Forward || - return searchsortedlast(LinearScan(), v, x, hint; order = order) - return _simdscan_last_specialized(v, x, hint) -end -function Base.searchsortedlast( - ::SIMDLinearScan, v::DenseVector{Float64}, x::Float64, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - order === Base.Order.Forward || - return searchsortedlast(LinearScan(), v, x, hint; order = order) - return _simdscan_last_specialized(v, x, hint) -end -function Base.searchsortedfirst( - ::SIMDLinearScan, v::DenseVector{Int64}, x::Int64, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - order === Base.Order.Forward || - return searchsortedfirst(LinearScan(), v, x, hint; order = order) - return _simdscan_first_specialized(v, x, hint) -end -function Base.searchsortedfirst( - ::SIMDLinearScan, v::DenseVector{Float64}, x::Float64, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - order === Base.Order.Forward || - return searchsortedfirst(LinearScan(), v, x, hint; order = order) - return _simdscan_first_specialized(v, x, hint) -end - -# Other eltypes fall back to the scalar LinearScan walk. -Base.searchsortedlast( - ::SIMDLinearScan, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(LinearScan(), v, x, hint; order = order) -Base.searchsortedfirst( - ::SIMDLinearScan, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(LinearScan(), v, x, hint; order = order) - -# No hint → BinaryBracket. -Base.searchsortedlast( - ::SIMDLinearScan, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(BinaryBracket(), v, x; order = order) -Base.searchsortedfirst( - ::SIMDLinearScan, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(BinaryBracket(), v, x; order = order) - -# Strategy: BracketGallop — bracketstrictlymonotonic + bounded binary search. -function Base.searchsortedlast( - ::BracketGallop, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - lo, hi = bracketstrictlymonotonic(v, x, hint, order) - return searchsortedlast(v, x, lo, hi, order) -end - -function Base.searchsortedfirst( - ::BracketGallop, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - lo, hi = bracketstrictlymonotonic_first(v, x, hint, order) - return searchsortedfirst(v, x, lo, hi, order) -end - -# BracketGallop without a hint falls back to BinaryBracket. -Base.searchsortedlast( - ::BracketGallop, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(BinaryBracket(), v, x; order = order) -Base.searchsortedfirst( - ::BracketGallop, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(BinaryBracket(), v, x; order = order) - -# Strategy: ExpFromLeft — galloping forward from a left-bound hint. -# -# Contract: callers pass `hint` such that the answer is ≥ `hint`. When that -# isn't true (hint is past the answer), we fall back to a full -# `searchsortedlast`/`searchsortedfirst` — the batched-sorted loop sets -# `hint = prev_result`, which always satisfies this for sorted queries, so the -# fallback is only exercised by arbitrary single-query callers. -function Base.searchsortedfirst( - ::ExpFromLeft, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - lo = firstindex(v) - hi = lastindex(v) - if isempty(v) - return lo - end - h = clamp(hint, lo, hi) - # `searchsortedfirst` semantics: smallest i with v[i] >= x. We can only - # gallop forward from `h` when v[h] < x (then the answer is strictly - # > h). When v[h] >= x, the first occurrence of `x` may be at index - # ≤ h (duplicates to the left), so fall back to a full search rather - # than risk skipping past earlier duplicates. - @inbounds if !Base.Order.lt(order, v[h], x) - return searchsortedfirst(v, x, order) - end - return order === Base.Order.Forward ? - searchsortedfirstexp(v, x, h, hi) : - searchsortedfirst(v, x, h, hi, order) -end - -function Base.searchsortedlast( - ::ExpFromLeft, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - lo = firstindex(v) - hi = lastindex(v) - if isempty(v) - return lo - 1 - end - h = clamp(hint, lo, hi) - @inbounds if Base.Order.lt(order, x, v[h]) - return searchsortedlast(v, x, order) - end - if order === Base.Order.Forward - y = searchsortedfirstexp(v, x, h, hi) - return if y > hi - hi - else - @inbounds v[y] == x ? y : y - 1 - end - else - return searchsortedlast(v, x, h, hi, order) - end -end - -# ExpFromLeft without a hint falls back to BinaryBracket. -Base.searchsortedlast( - ::ExpFromLeft, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(BinaryBracket(), v, x; order = order) -Base.searchsortedfirst( - ::ExpFromLeft, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(BinaryBracket(), v, x; order = order) - -# Strategy: InterpolationSearch — extrapolate a guess, then bounded binary search. -@inline function _interp_guess(v::AbstractVector, x, lo::Integer, hi::Integer) - @inbounds vlo = v[lo] - @inbounds vhi = v[hi] - span = vhi - vlo - iszero(span) && return lo - # Linear extrapolation: how far is x along [vlo, vhi]? - f = (x - vlo) / span - if !isfinite(f) - return f > 0 ? hi : lo - end - g = lo + round(Int, f * (hi - lo)) - return clamp(g, lo, hi) -end - -function Base.searchsortedlast( - ::InterpolationSearch, v::AbstractVector{<:Number}, x::Number; - order::Base.Order.Ordering = Base.Order.Forward - ) - if order !== Base.Order.Forward - # Linear interpolation doesn't carry over to reverse order; fall back - return searchsortedlast(v, x, order) - end - lo, hi = firstindex(v), lastindex(v) - hi < lo && return lo - 1 - g = _interp_guess(v, x, lo, hi) - return searchsortedlast(BracketGallop(), v, x, g; order = order) -end - -function Base.searchsortedfirst( - ::InterpolationSearch, v::AbstractVector{<:Number}, x::Number; - order::Base.Order.Ordering = Base.Order.Forward - ) - if order !== Base.Order.Forward - return searchsortedfirst(v, x, order) - end - lo, hi = firstindex(v), lastindex(v) - hi < lo && return lo - g = _interp_guess(v, x, lo, hi) - return searchsortedfirst(BracketGallop(), v, x, g; order = order) -end - -# InterpolationSearch ignores any hint; pass-through. -Base.searchsortedlast( - s::InterpolationSearch, v::AbstractVector{<:Number}, x::Number, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(s, v, x; order = order) -Base.searchsortedfirst( - s::InterpolationSearch, v::AbstractVector{<:Number}, x::Number, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(s, v, x; order = order) - -# InterpolationSearch on non-numeric data falls back to BinaryBracket. -Base.searchsortedlast( - ::InterpolationSearch, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(BinaryBracket(), v, x; order = order) -Base.searchsortedfirst( - ::InterpolationSearch, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(BinaryBracket(), v, x; order = order) -Base.searchsortedlast( - s::InterpolationSearch, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(BinaryBracket(), v, x; order = order) -Base.searchsortedfirst( - s::InterpolationSearch, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(BinaryBracket(), v, x; order = order) - -# Strategy: BitInterpolationSearch — InterpolationSearch on the IEEE bit -# pattern of positive Float64. Cheaper than reinterpret-as-array because we -# only need two endpoint reads and one query bitcast per call. -@inline function _bit_interp_guess_f64( - v::DenseVector{Float64}, x::Float64, lo::Integer, hi::Integer - ) - @inbounds vlo_bits = reinterpret(UInt64, v[lo]) - @inbounds vhi_bits = reinterpret(UInt64, v[hi]) - xu = reinterpret(UInt64, x) - span = vhi_bits - vlo_bits - iszero(span) && return lo - if xu <= vlo_bits - return lo - elseif xu >= vhi_bits - return hi - end - num = xu - vlo_bits - f = Float64(num) / Float64(span) - g = lo + round(Int, f * (hi - lo)) - return clamp(g, lo, hi) -end - -function Base.searchsortedlast( - ::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64; - order::Base.Order.Ordering = Base.Order.Forward - ) - if order !== Base.Order.Forward - return searchsortedlast(v, x, order) - end - lo, hi = firstindex(v), lastindex(v) - hi < lo && return lo - 1 - @inbounds if v[lo] <= 0.0 || !isfinite(v[lo]) || x <= 0.0 || !isfinite(x) - return searchsortedlast(BinaryBracket(), v, x; order = order) - end - g = _bit_interp_guess_f64(v, x, lo, hi) - return searchsortedlast(BracketGallop(), v, x, g; order = order) -end - -function Base.searchsortedfirst( - ::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64; - order::Base.Order.Ordering = Base.Order.Forward - ) - if order !== Base.Order.Forward - return searchsortedfirst(v, x, order) - end - lo, hi = firstindex(v), lastindex(v) - hi < lo && return lo - @inbounds if v[lo] <= 0.0 || !isfinite(v[lo]) || x <= 0.0 || !isfinite(x) - return searchsortedfirst(BinaryBracket(), v, x; order = order) - end - g = _bit_interp_guess_f64(v, x, lo, hi) - return searchsortedfirst(BracketGallop(), v, x, g; order = order) -end - -# Hint pass-through (bit-interp ignores externally-supplied hints). -Base.searchsortedlast( - s::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(s, v, x; order = order) -Base.searchsortedfirst( - s::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(s, v, x; order = order) - -# Non-Float64 / non-dense eltypes: fall back to plain InterpolationSearch -# (bit reinterpret only carries the log-linearity trick for Float64). -Base.searchsortedlast( - ::BitInterpolationSearch, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(InterpolationSearch(), v, x; order = order) -Base.searchsortedfirst( - ::BitInterpolationSearch, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(InterpolationSearch(), v, x; order = order) -Base.searchsortedlast( - ::BitInterpolationSearch, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(InterpolationSearch(), v, x; order = order) -Base.searchsortedfirst( - ::BitInterpolationSearch, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(InterpolationSearch(), v, x; order = order) - -# Strategy: BisectThenSIMD — only meaningful for `findequal`. For the -# positional `searchsortedfirst` / `searchsortedlast` dispatch, fall back to -# BinaryBracket — bisect-then-equality-scan can't answer the positional -# question ("where would x insert?") that searchsortedfirst asks. -Base.searchsortedlast( - ::BisectThenSIMD, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(BinaryBracket(), v, x; order = order) -Base.searchsortedfirst( - ::BisectThenSIMD, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(BinaryBracket(), v, x; order = order) -Base.searchsortedlast( - s::BisectThenSIMD, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(BinaryBracket(), v, x; order = order) -Base.searchsortedfirst( - s::BisectThenSIMD, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(BinaryBracket(), v, x; order = order) - -# Strategy: GuesserHint — Guesser produces an integer hint, BracketGallop runs -# the search and updates the Guesser's prev-result cache. Methods are defined -# below where Guesser is in scope (search the file for "GuesserHint methods"). - -# Strategy: Auto — pick based on hint validity and length(v). -@inline function _auto_pick(v::AbstractVector, hint::Integer) - return if hint < firstindex(v) || hint > lastindex(v) - BinaryBracket() - elseif length(v) <= _AUTO_LINEAR_THRESHOLD - LinearScan() - else - BracketGallop() - end -end - -# Batched Auto: pick based on the expected average gap between consecutive -# results. -# -# For numeric data we can do better than `n / m`: the queries' actual span as -# a fraction of `v`'s span tells us how clustered they really are. e.g. -# 4096 sorted queries crammed into a single segment of a 65k-long `v` have -# n/m = 16 but actual_gap = 0; the span heuristic catches that. -@inline function _auto_pick_batched(v::AbstractVector, queries::AbstractVector) - m = length(queries) - if m == 0 - return BinaryBracket() - end - gap, _ = _estimate_avg_gap(v, queries, m) - return gap <= _AUTO_BATCH_LINEAR_GAP ? LinearScan() : ExpFromLeft() -end - -# Returns `(gap, skewed)`: the estimated average step in `v`'s index space -# between consecutive query results, plus a flag that's true when the -# queries' distribution is non-uniform within their span. The two pieces of -# information serve different roles in Auto's decision tree: -# -# - `gap` is the per-query cost driver. We always use the span-based -# estimate `n * span(queries) / span(v) / m` so that tightly-clustered -# queries (span_q ≈ 0) report gap ≈ 0 regardless of `n/m`. The earlier -# `n / m` fallback for skewed queries was wrong: it caused `SIMDLinearScan` -# to be picked for clustered queries where LinearScan's tiny scalar -# walk is 5× faster (e.g. clustered queries with span_q = 1 over an -# `n = 65536` vector). -# - `skewed` is an InterpolationSearch-suitability flag. When the median -# query sits well off the midpoint of `queries[1]..queries[end]`, the -# queries are clustered within their span and the per-call linear -# extrapolation guess is worse than the previous-result hint that -# `ExpFromLeft` would use. -@inline function _estimate_avg_gap( - v::AbstractVector{<:Number}, queries::AbstractVector{<:Number}, m::Integer - ) - n = length(v) - n <= 1 && return (0, false) - @inbounds span_v = v[end] - v[1] - if iszero(span_v) || !isfinite(span_v) - return (n ÷ max(1, m), false) - end - @inbounds span_q = queries[end] - queries[1] - # Skew detection on small `m` is too noisy — for `m ≈ 4` random uniform - # samples, the median routinely sits 30 %+ off the linear midpoint by - # chance. Gate on `m ≥ 10` where the statistical variance is well below - # the 20 % threshold. - skewed = false - if m >= 10 - @inbounds mid_q = queries[firstindex(queries) + m ÷ 2] - @inbounds expected_mid = ( - queries[firstindex(queries)] + - queries[lastindex(queries)] - ) / 2 - if !iszero(span_q) && - abs(mid_q - expected_mid) > 0.2 * abs(span_q) - skewed = true - end - end - ratio = span_q / span_v - # Clamp ratio: queries may extend outside v's range (extrapolation). - ratio = clamp(ratio, zero(ratio), one(ratio)) - return (floor(Int, n * ratio / max(1, m)), skewed) -end - -# Non-numeric eltypes: no span subtraction possible, fall back to length ratio -# and assume queries are roughly uniform (no skew detection possible). -@inline _estimate_avg_gap( - v::AbstractVector, ::AbstractVector, m::Integer -) = (length(v) ÷ max(1, m), false) - -function Base.searchsortedlast( - ::Auto, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - s = _auto_pick(v, hint) - return s isa BinaryBracket ? - searchsortedlast(s, v, x; order = order) : - searchsortedlast(s, v, x, hint; order = order) -end - -function Base.searchsortedfirst( - ::Auto, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - s = _auto_pick(v, hint) - return s isa BinaryBracket ? - searchsortedfirst(s, v, x; order = order) : - searchsortedfirst(s, v, x, hint; order = order) -end - -Base.searchsortedlast( - ::Auto, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(BinaryBracket(), v, x; order = order) -Base.searchsortedfirst( - ::Auto, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(BinaryBracket(), v, x; order = order) - -# --------------------------------------------------------------------------- -# In-place batched sorted-search API -# --------------------------------------------------------------------------- - -""" - searchsortedlast!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward, - queries_sorted = nothing) - -In-place batched [`searchsortedlast`](@ref Base.searchsortedlast). Writes one -index per element of `queries` into `idx_out` (which must be the same length). - -If `queries` is sorted under `order`, the previous result is used as a hint for -the next query, so the total cost is O(length(v) + length(queries)) under -`strategy = BracketGallop()` (the default `Auto` choice for non-tiny `v`). - -If `queries` is not sorted, falls back to per-element `searchsortedlast` with -no hint regardless of `strategy`. - -The `queries_sorted` kwarg controls the runtime `issorted(queries)` check: - - - `nothing` (default): run `issorted(queries; order = order)` on every call. - O(m) bookkeeping, roughly 1 ns/q on long batches. - - `true`: trust the caller — skip the check and take the sorted-loop path - unconditionally. Use this when you already know your queries are sorted - (you computed them as a range, sorted them yourself, etc.). Wrong-answer - risk: a non-sorted `queries` passed with `queries_sorted = true` will - produce incorrect results, since the inner loop uses the previous result - as a hint and that hint becomes invalid when queries jump backward. - - `false`: skip the check and take the unsorted-loop path unconditionally - (per-query unhinted `Base.searchsortedlast`). Use when you know queries - are not sorted and want to avoid the O(m) probe. - -Returns `idx_out`. -""" -function searchsortedlast!( - idx_out::AbstractVector{<:Integer}, - v::AbstractVector, - queries::AbstractVector; - strategy::SearchStrategy = Auto(), - order::Base.Order.Ordering = Base.Order.Forward, - queries_sorted::Union{Nothing, Bool} = nothing, - ) - if length(idx_out) != length(queries) - throw( - DimensionMismatch( - "idx_out and queries must have the same length" - ) - ) - end - return _searchsortedlast_batched!( - idx_out, v, queries, strategy, order, queries_sorted - ) -end - -""" - searchsortedfirst!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward, - queries_sorted = nothing) - -In-place batched [`searchsortedfirst`](@ref Base.searchsortedfirst). See -[`searchsortedlast!`](@ref) for behavior and for the `queries_sorted` kwarg. -""" -function searchsortedfirst!( - idx_out::AbstractVector{<:Integer}, - v::AbstractVector, - queries::AbstractVector; - strategy::SearchStrategy = Auto(), - order::Base.Order.Ordering = Base.Order.Forward, - queries_sorted::Union{Nothing, Bool} = nothing, - ) - if length(idx_out) != length(queries) - throw( - DimensionMismatch( - "idx_out and queries must have the same length" - ) - ) - end - return _searchsortedfirst_batched!( - idx_out, v, queries, strategy, order, queries_sorted - ) -end - -# Sorted inner loop, parameterized on strategy. Used by both the generic and -# Auto batched entry points so each batch performs at most one issorted check. -function _searchsortedlast_sorted_loop!( - idx_out, v::AbstractVector, queries::AbstractVector, - strategy::SearchStrategy, order::Base.Order.Ordering - ) - hint = firstindex(v) - 1 - @inbounds for k in eachindex(queries) - q = queries[k] - hint = if hint < firstindex(v) - searchsortedlast(strategy, v, q; order = order) - else - searchsortedlast(strategy, v, q, hint; order = order) - end - idx_out[k] = hint - end - return idx_out -end - -function _searchsortedfirst_sorted_loop!( - idx_out, v::AbstractVector, queries::AbstractVector, - strategy::SearchStrategy, order::Base.Order.Ordering - ) - hint = firstindex(v) - 1 - @inbounds for k in eachindex(queries) - q = queries[k] - hint = if hint < firstindex(v) - searchsortedfirst(strategy, v, q; order = order) - else - searchsortedfirst(strategy, v, q, hint; order = order) - end - idx_out[k] = hint - end - return idx_out -end - -function _searchsortedlast_unsorted_loop!( - idx_out, v::AbstractVector, queries::AbstractVector, - order::Base.Order.Ordering - ) - @inbounds for k in eachindex(queries) - idx_out[k] = searchsortedlast(v, queries[k], order) - end - return idx_out -end - -function _searchsortedfirst_unsorted_loop!( - idx_out, v::AbstractVector, queries::AbstractVector, - order::Base.Order.Ordering - ) - @inbounds for k in eachindex(queries) - idx_out[k] = searchsortedfirst(v, queries[k], order) - end - return idx_out -end - -# Decide whether to take the sorted-queries fast path. `queries_sorted` is -# the caller-supplied override: `nothing` means "check at runtime", `true` -# means "trust the caller, skip the O(m) issorted probe", `false` means -# "force the unsorted path". -@inline function _take_sorted_path( - queries, order::Base.Order.Ordering, queries_sorted::Union{Nothing, Bool} - ) - return queries_sorted === nothing ? - issorted(queries; order = order) : queries_sorted -end - -function _searchsortedlast_batched!( - idx_out, v::AbstractVector, queries::AbstractVector, - strategy::SearchStrategy, order::Base.Order.Ordering, - queries_sorted::Union{Nothing, Bool}, - ) - return if _take_sorted_path(queries, order, queries_sorted) - _searchsortedlast_sorted_loop!(idx_out, v, queries, strategy, order) - else - _searchsortedlast_unsorted_loop!(idx_out, v, queries, order) - end -end - -# Specialized batched-Auto: pick an inner strategy from the n/m ratio, then -# call the sorted loop directly (no duplicate `issorted` check, and each -# branch is type-stable so the loop specializes on the concrete strategy). -function _searchsortedlast_batched!( - idx_out, v::AbstractVector, queries::AbstractVector, - s::Auto, order::Base.Order.Ordering, - queries_sorted::Union{Nothing, Bool}, - ) - m = length(queries) - m == 0 && return idx_out - # m == 1: skip the issorted + span heuristic — no batched hint is - # available for a single-element batch, so just dispatch straight to - # the unhinted backing call. Saves ~20 ns of bookkeeping per call. - if m == 1 - @inbounds idx_out[firstindex(idx_out)] = - searchsortedlast(v, queries[firstindex(queries)], order) - return idx_out - end - if !_take_sorted_path(queries, order, queries_sorted) - return _searchsortedlast_unsorted_loop!(idx_out, v, queries, order) - end - gap, skewed = _estimate_avg_gap(v, queries, m) - # Manually dispatch on the picked strategy so each branch is concrete. - if gap <= _AUTO_BATCH_LINEAR_GAP - return _searchsortedlast_sorted_loop!( - idx_out, v, queries, LinearScan(), order - ) - end - # Medium-gap regime: SIMDLinearScan wins on `DenseVector{Int64}` and - # `DenseVector{Float64}` (without NaN). For Float64, NaN presence is - # taken from `s.props.has_nan` if `SearchProperties(v)` was constructed, - # else we assume no NaN (consistent with the existing contract that - # `Base.searchsortedlast` doesn't check sortedness either). - if gap <= _auto_simd_gap_max(v) && - _auto_simd_eligible(v, s.props) - return _searchsortedlast_sorted_loop!( - idx_out, v, queries, SIMDLinearScan(), order - ) - end - # Sparse-on-large-linear: InterpolationSearch wins ~2× over ExpFromLeft - # on uniformly-spaced data — but only when queries are *also* spread - # roughly uniformly within their span. For skewed (clustered) queries, - # `ExpFromLeft` from `prev_idx` wins even on linear v because the next - # query's true index is close to the previous one's. - if !skewed && - gap >= _AUTO_INTERP_MIN_GAP && - length(v) >= _AUTO_INTERP_MIN_N && - m >= _AUTO_INTERP_MIN_M && - _auto_interp_eligible(v, s.props, gap) - return _searchsortedlast_sorted_loop!( - idx_out, v, queries, InterpolationSearch(), order - ) - end - # Sparse fallback: BracketGallop beats ExpFromLeft when the gap is large - # enough that ExpFromLeft's initial 5 linear probes are guaranteed to - # miss. BracketGallop starts doubling from one position past `hint`, so - # it skips the wasted linear preamble. - if gap >= _AUTO_GALLOP_GAP_MIN - return _searchsortedlast_sorted_loop!( - idx_out, v, queries, BracketGallop(), order - ) - end - return _searchsortedlast_sorted_loop!( - idx_out, v, queries, ExpFromLeft(), order - ) -end - -# InterpolationSearch eligibility: two-tier linearity check. For -# `_AUTO_INTERP_MIN_GAP ≤ gap < _AUTO_INTERP_LOOSE_GAP` we require strict -# linearity (`_AUTO_LINEAR_REL_TOLERANCE`, default 0.1%) — InterpolationSearch -# is only worth the per-call cost on truly uniform data when ExpFromLeft is -# also competitive. For `gap ≥ _AUTO_INTERP_LOOSE_GAP` we accept a looser -# tolerance (`_AUTO_LINEAR_LOOSE_TOLERANCE`, default 5%) because the cache -# benefit of one extrapolation jump + local refine compensates for a worse -# guess, but we still reject genuinely nonlinear data (log-spaced, -# two-scale) where InterpolationSearch loses 2–3× to ExpFromLeft. -@inline function _auto_interp_eligible(v, props::SearchProperties, gap::Integer) - if gap >= _AUTO_INTERP_LOOSE_GAP - # Loose probe — even on cached props, the strict `is_linear` bit may - # already reflect a tighter threshold than we need here, so run the - # sampled probe at the loose tolerance regardless of cache state. - return _sampled_looks_linear(v, _AUTO_LINEAR_LOOSE_TOLERANCE) - end - return props.has_props ? props.is_linear : _sampled_looks_linear(v) -end - -# SIMD eligibility check used by Auto's batched dispatch. The static type -# test on `v` discriminates the `DenseVector{Int64}` / `DenseVector{Float64}` -# cases that SIMDLinearScan supports. For Float64, NaN presence is taken -# from cached `SearchProperties.has_nan` when available; otherwise we -# assume no NaN — Base's positional search doesn't check sortedness either, -# and the burden of supplying populated props is on the caller for -# pathological inputs. -@inline _auto_simd_eligible(v::DenseVector{Int64}, ::SearchProperties) = true -@inline function _auto_simd_eligible(v::DenseVector{Float64}, p::SearchProperties) - return p.has_props ? !p.has_nan : true -end -@inline _auto_simd_eligible(::AbstractVector, ::SearchProperties) = false - -function _searchsortedfirst_batched!( - idx_out, v::AbstractVector, queries::AbstractVector, - strategy::SearchStrategy, order::Base.Order.Ordering, - queries_sorted::Union{Nothing, Bool}, - ) - return if _take_sorted_path(queries, order, queries_sorted) - _searchsortedfirst_sorted_loop!(idx_out, v, queries, strategy, order) - else - _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) - end -end - -function _searchsortedfirst_batched!( - idx_out, v::AbstractVector, queries::AbstractVector, - s::Auto, order::Base.Order.Ordering, - queries_sorted::Union{Nothing, Bool}, - ) - m = length(queries) - m == 0 && return idx_out - if m == 1 - @inbounds idx_out[firstindex(idx_out)] = - searchsortedfirst(v, queries[firstindex(queries)], order) - return idx_out - end - if !_take_sorted_path(queries, order, queries_sorted) - return _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) - end - gap, skewed = _estimate_avg_gap(v, queries, m) - if gap <= _AUTO_BATCH_LINEAR_GAP - return _searchsortedfirst_sorted_loop!( - idx_out, v, queries, LinearScan(), order - ) - end - if gap <= _auto_simd_gap_max(v) && - _auto_simd_eligible(v, s.props) - return _searchsortedfirst_sorted_loop!( - idx_out, v, queries, SIMDLinearScan(), order - ) - end - if !skewed && - gap >= _AUTO_INTERP_MIN_GAP && - length(v) >= _AUTO_INTERP_MIN_N && - m >= _AUTO_INTERP_MIN_M && - _auto_interp_eligible(v, s.props, gap) - return _searchsortedfirst_sorted_loop!( - idx_out, v, queries, InterpolationSearch(), order - ) - end - if gap >= _AUTO_GALLOP_GAP_MIN - return _searchsortedfirst_sorted_loop!( - idx_out, v, queries, BracketGallop(), order - ) - end - return _searchsortedfirst_sorted_loop!( - idx_out, v, queries, ExpFromLeft(), order - ) -end - -""" - looks_linear(v; threshold = 1e-2) - -Determine if the abscissae `v` are regularly distributed, taking the standard deviation of -the difference between the array of abscissae with respect to the straight line linking -its first and last elements, normalized by the range of `v`. If this standard deviation is -below the given `threshold`, the vector looks linear (return true). Internal function - -interface may change. -""" -function looks_linear(v; threshold = 1.0e-2) - length(v) <= 2 && return true - x_0, x_f = first(v), last(v) - N = length(v) - x_span = x_f - x_0 - mean_x_dist = x_span / (N - 1) - norm_var = sum((x_i - x_0 - (i - 1) * mean_x_dist)^2 for (i, x_i) in enumerate(v)) / - (N * x_span^2) - return norm_var < threshold^2 -end - -""" - Guesser(v::AbstractVector; looks_linear_threshold = 1e-2) - -Wrapper of the searched vector `v` which makes an informed guess for the next -correlated lookup by either - - - exploiting that `v` is sufficiently evenly spaced (linear-extrapolation guess), or - - using the previous outcome (the cached `idx_prev`). - -Pass a `Guesser` to [`GuesserHint`](@ref) to use it as a search strategy with -the dispatched [`searchsortedlast`](@ref Base.searchsortedlast) / -[`searchsortedfirst`](@ref Base.searchsortedfirst) API. -""" -struct Guesser{T <: AbstractVector} - v::T - idx_prev::Base.RefValue{Int} - linear_lookup::Bool -end - -function Guesser(v::AbstractVector; looks_linear_threshold = 1.0e-2) - return Guesser(v, Ref(1), looks_linear(v; threshold = looks_linear_threshold)) -end - -function (g::Guesser)(x) - (; v, idx_prev, linear_lookup) = g - return if linear_lookup - δx = x - first(v) - iszero(δx) && return firstindex(v) - f = δx / (last(v) - first(v)) - if isinf(f) - f > 0 ? lastindex(v) : firstindex(v) - else - i_0, i_f = firstindex(v), lastindex(v) - i_approx = f * (i_f - i_0) + i_0 - target_type = typeof(firstindex(v)) - if i_approx >= typemax(target_type) - lastindex(v) + 1 - elseif i_approx <= typemin(target_type) - firstindex(v) - 1 - else - round(target_type, i_approx) - end - end - else - idx_prev[] - end -end - -# Note on ranges: `Base.searchsortedlast(r::AbstractRange, x, order)` is -# already O(1) (closed-form), so the strategies' fallback path through -# `BinaryBracket` (which delegates to that Base method) is already optimal -# for ranges. No special-case overlays needed. - -# GuesserHint methods — strategy dispatch wrapper for the `Guesser`-based -# correlated search. Per-call cost: one `guesser(x)` evaluation + one -# `BracketGallop` call + one `idx_prev[]` write. -function Base.searchsortedlast( - s::GuesserHint, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward - ) - @assert v === s.guesser.v - out = searchsortedlast(BracketGallop(), v, x, s.guesser(x); order = order) - s.guesser.idx_prev[] = out - return out -end - -function Base.searchsortedfirst( - s::GuesserHint, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward - ) - @assert v === s.guesser.v - out = searchsortedfirst(BracketGallop(), v, x, s.guesser(x); order = order) - s.guesser.idx_prev[] = out - return out -end - -# GuesserHint ignores any externally-supplied hint (the Guesser carries its own). -Base.searchsortedlast( - s::GuesserHint, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedlast(s, v, x; order = order) -Base.searchsortedfirst( - s::GuesserHint, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = searchsortedfirst(s, v, x; order = order) - -# Internal: exponential search forward from `lo`, then bounded binary search. -# Backs the `ExpFromLeft` strategy. Not part of the public API in 2.x — use -# `searchsortedfirst(ExpFromLeft(), v, x, lo)` instead. -Base.@propagate_inbounds function searchsortedfirstexp( - v::AbstractVector, - x, - lo::Integer = firstindex(v), - hi::Integer = lastindex(v) - ) - # Linear search for first few elements - for i in 0:4 - ind = lo + i - ind > hi && return ind - x <= v[ind] && return ind - end - # Exponential search with doubling steps - n = 3 - tn2 = 2^n - tn2m1 = 2^(n - 1) - ind = lo + tn2 - while ind <= hi - x <= v[ind] && - return searchsortedfirst(v, x, lo + tn2 - tn2m1, ind, Base.Order.Forward) - tn2 *= 2 - tn2m1 *= 2 - ind = lo + tn2 - end - return searchsortedfirst(v, x, lo + tn2 - tn2m1, hi, Base.Order.Forward) -end - -# --------------------------------------------------------------------------- -# Range search through the strategy dispatch -# --------------------------------------------------------------------------- - -""" - searchsortedrange(strategy, v, lo, hi[, hint]; order = Base.Order.Forward) - -> UnitRange{Int} - -Return the index range of all entries `v[i]` satisfying `lo ≤ v[i] ≤ hi` -under `order`. Equivalent to -`searchsortedfirst(strategy, v, lo[, hint]; order) : - searchsortedlast(strategy, v, hi[, hint]; order)` but expressed as a -single call that may share bracket-discovery work between the two -endpoints when the underlying strategy allows it. - -The empty range case (no `v[i]` lies in `[lo, hi]`) returns -`searchsortedfirst(strategy, v, lo) : (searchsortedfirst(strategy, v, lo) - 1)`, -matching `Base.searchsorted(v, lo)` for an absent value. - -When a `hint` is supplied it is used for both endpoint searches. Strategies -that ignore the hint (`BinaryBracket`, `InterpolationSearch`) treat the -hinted form as a pass-through. -""" -@inline function searchsortedrange( - strategy::SearchStrategy, v::AbstractVector, lo, hi; - order::Base.Order.Ordering = Base.Order.Forward - ) - first_idx = searchsortedfirst(strategy, v, lo; order = order) - last_idx = searchsortedlast(strategy, v, hi; order = order) - return first_idx:last_idx -end - -@inline function searchsortedrange( - strategy::SearchStrategy, v::AbstractVector, lo, hi, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - first_idx = searchsortedfirst(strategy, v, lo, hint; order = order) - # `last_idx` searches *forward* from `first_idx` if the hint suggests it - # (lo ≤ hi means the right endpoint is ≥ first_idx). Use first_idx as a - # hint to skip work shared with the left search; falls back to the - # supplied hint for strategies that ignore the integer hint. - last_idx = searchsortedlast( - strategy, v, hi, max(first_idx, hint); order = order - ) - return first_idx:last_idx -end - -# --------------------------------------------------------------------------- -# Equality search through the strategy dispatch -# --------------------------------------------------------------------------- - -""" - findequal(strategy, v, x[, hint]; order = Base.Order.Forward) -> Int - -Return the index of `x` in sorted `v` if present, or the sentinel -`firstindex(v) - 1` if `x` is absent. Type-stable `Int` return — the -sentinel matches the convention `Base.searchsortedlast` already uses for -"x precedes all of v", so callers can test for "not found" with -`i < firstindex(v)`. - -For vectors with 1-based indexing (the Julia default), the sentinel is -exactly `0`, which is also `searchsortedlast`'s "x precedes all" return. -For [OffsetArrays](https://github.com/JuliaArrays/OffsetArrays.jl) and any -other vector whose `firstindex` is not `1`, the sentinel adjusts -accordingly — e.g. for a vector with `firstindex == -3`, the sentinel is -`-4`. Always test against `firstindex(v) - 1` (or equivalently -`i < firstindex(v)`), not against the literal `0`. - -Most strategies are handled generically: run -`searchsortedfirst(strategy, v, x[, hint])` to find the candidate insertion -point, then check whether `v[i]` actually equals `x`. The shortcut method -on [`BisectThenSIMD`](@ref) for `DenseVector{Int64}` skips the -`searchsortedfirst` path entirely and uses the dedicated bisect-then-SIMD -equality scan that backs [`findfirstsortedequal`](@ref). - -For unsorted vectors, use [`findfirstequal`](@ref) — it does not require -a sorted input and falls outside the strategy framework. -""" -@inline function findequal( - strategy::SearchStrategy, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward - ) - return _findequal_generic(strategy, v, x, order) -end - -@inline function findequal( - strategy::SearchStrategy, v::AbstractVector, x, hint::Integer; - order::Base.Order.Ordering = Base.Order.Forward - ) - i = searchsortedfirst(strategy, v, x, hint; order = order) - return _findequal_postcheck(v, x, i) -end - -@inline function _findequal_generic(strategy, v, x, order) - i = searchsortedfirst(strategy, v, x; order = order) - return _findequal_postcheck(v, x, i) -end - -@inline function _findequal_postcheck(v::AbstractVector, x, i::Integer) - if i > lastindex(v) - return firstindex(v) - 1 - end - @inbounds return isequal(v[i], x) ? Int(i) : (firstindex(v) - 1) -end - -# Shortcut: BisectThenSIMD on DenseVector{Int64} uses the dedicated bisect- -# then-SIMD equality scan (same algorithm as `findfirstsortedequal`). -function findequal( - ::BisectThenSIMD, v::DenseVector{Int64}, x::Int64; - order::Base.Order.Ordering = Base.Order.Forward - ) - if order !== Base.Order.Forward - return _findequal_generic(BinaryBracket(), v, x, order) - end - r = findfirstsortedequal(x, v) - return r === nothing ? (firstindex(v) - 1) : r -end -# Hinted form ignores the hint — the bisect-then-SIMD algorithm does not -# benefit from a hint, and probing it would only waste cycles. -findequal( - s::BisectThenSIMD, v::DenseVector{Int64}, x::Int64, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = findequal(s, v, x; order = order) - -# Non-Int64 fallback for BisectThenSIMD: use BinaryBracket + post-check. -function findequal( - ::BisectThenSIMD, v::AbstractVector, x; - order::Base.Order.Ordering = Base.Order.Forward - ) - return _findequal_generic(BinaryBracket(), v, x, order) -end -findequal( - s::BisectThenSIMD, v::AbstractVector, x, ::Integer; - order::Base.Order.Ordering = Base.Order.Forward -) = findequal(s, v, x; order = order) - -using PrecompileTools: @compile_workload, @setup_workload - -@setup_workload begin - # Minimal setup for precompilation workload - vec_int64 = Int64[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] - linear_vec = collect(1.0:0.5:10.0) - - @compile_workload begin - # Precompile the most commonly used functions with typical types. - - # findfirstequal: fast SIMD-based search in Int64 vectors. - findfirstequal(Int64(5), vec_int64) - findfirstequal(Int64(100), vec_int64) - - # findfirstsortedequal: binary search in sorted Int64 vectors. - findfirstsortedequal(Int64(8), vec_int64) - findfirstsortedequal(Int64(100), vec_int64) - - # looks_linear: check if vector is evenly spaced. - looks_linear(linear_vec) - - # Guesser: hint provider for correlated repeated searches. - guesser = Guesser(linear_vec) - guesser(5.0) - - # Strategy dispatch — single-query forms across the standard strategies. - for strategy in ( - LinearScan(), SIMDLinearScan(), BracketGallop(), ExpFromLeft(), - InterpolationSearch(), BinaryBracket(), Auto(), - Auto(SearchProperties(linear_vec)), - ) - searchsortedfirst(strategy, vec_int64, Int64(8), Int64(1)) - searchsortedlast(strategy, vec_int64, Int64(8), Int64(1)) - end - # findequal: generic + BisectThenSIMD shortcut for Int64 dense vectors. - for strategy in ( - BinaryBracket(), BracketGallop(), SIMDLinearScan(), - BisectThenSIMD(), Auto(), - ) - findequal(strategy, vec_int64, Int64(8)) - findequal(strategy, vec_int64, Int64(8), Int64(1)) - end - # SIMDLinearScan's Float64 specialization. - let vec_f64 = collect(1.0:1.0:16.0) - searchsortedfirst(SIMDLinearScan(), vec_f64, 8.0, 1) - searchsortedlast(SIMDLinearScan(), vec_f64, 8.0, 1) - end - searchsortedfirst(GuesserHint(Guesser(vec_int64)), vec_int64, Int64(8)) - searchsortedlast(GuesserHint(Guesser(vec_int64)), vec_int64, Int64(8)) - - # Strategy dispatch — batched in-place forms. - idx_out = Vector{Int}(undef, 4) - queries = Int64[2, 5, 8, 12] - searchsortedfirst!(idx_out, vec_int64, queries) - searchsortedlast!(idx_out, vec_int64, queries) - end -end +# Source layout. Include order matters — each file may depend on names +# defined in earlier files. See the comment block at the top of each file +# for what lives where. +include("simd_ir.jl") # IR template + per-eltype IR constants + SIMD primitives +include("equality.jl") # findfirstequal + findfirstsortedequal +include("strategies.jl") # SearchStrategy + concrete strategy types + SearchProperties + Auto +include("search_properties.jl") # Linearity / NaN probes + populated SearchProperties constructor +include("dispatch.jl") # Per-strategy searchsortedfirst/last methods + their internal helpers +include("auto.jl") # Auto crossover constants + per-query Auto + Auto's batched helpers +include("batched.jl") # Batched API + searchsortedrange + _batched! (incl Auto specialization) +include("guesser.jl") # looks_linear + Guesser + GuesserHint dispatch +include("findequal.jl") # findequal + BisectThenSIMD shortcut +include("precompile.jl") # PrecompileTools workload end # module FindFirstFunctions diff --git a/src/auto.jl b/src/auto.jl new file mode 100644 index 0000000..aebb1c5 --- /dev/null +++ b/src/auto.jl @@ -0,0 +1,168 @@ +# Auto strategy — heuristic dispatch tree + crossover constants + the +# helpers (`_estimate_avg_gap`, `_auto_simd_*`, `_auto_interp_eligible`) it +# consults. Per-query Auto dispatch lives here; batched Auto dispatch lives +# in `batched.jl` (next to the generic `_batched!` it specializes). + +# Per-query Auto threshold: under this length, the bracket-search bookkeeping +# costs more than a worst-case linear walk. +const _AUTO_LINEAR_THRESHOLD = 16 + +# Batched-Auto crossover: at gap ≤ 4 LinearScan beats ExpFromLeft (its 5 +# initial linear probes are wasted when the gap is already 0 or 1). Above 4, +# the SIMD path picks up (where eligible) up to gap = `_auto_simd_gap_max`. +const _AUTO_BATCH_LINEAR_GAP = 4 + +# For sparse queries (gap large) on long vectors, InterpolationSearch can +# beat ExpFromLeft by ~2× on uniformly-spaced data. The sampled-linearity +# check is O(1) — 9 probes — so it's cheap enough to run inside Auto when +# there's a real chance of unlocking InterpolationSearch. +const _AUTO_INTERP_MIN_GAP = 8 +const _AUTO_INTERP_MIN_N = 1024 +const _AUTO_INTERP_MIN_M = 2 + +# Very-sparse override: when the gap is large enough that ExpFromLeft's +# log₂(gap) doubling levels approach InterpolationSearch's log₂(n) worst-case +# binary refinement, InterpolationSearch's better cache behaviour (one +# extrapolation jump + local refine vs. many doubling probes across the +# array) wins even on non-strictly-linear data. +const _AUTO_INTERP_LOOSE_GAP = 256 +const _AUTO_LINEAR_LOOSE_TOLERANCE = 5.0e-2 + +# SIMDLinearScan eligibility window. The threshold is eltype-parameterized +# via the `_auto_simd_gap_max` function below. +@inline _auto_simd_gap_max(::DenseVector{Int64}) = 64 +@inline _auto_simd_gap_max(::DenseVector{Float64}) = 64 +@inline _auto_simd_gap_max(::AbstractVector) = 0 # not SIMD-eligible + +# When InterpolationSearch isn't eligible and the gap is large, BracketGallop +# beats ExpFromLeft because the 5 linear probes ExpFromLeft does upfront are +# wasted (no chance the answer is within 5 of `hint = prev_result` when the +# gap is hundreds or thousands). BracketGallop just starts doubling +# immediately. The bench sweep shows this crossover at gap ≈ 16. +const _AUTO_GALLOP_GAP_MIN = 16 + +# Per-query Auto: pick based on hint validity and length(v). +@inline function _auto_pick(v::AbstractVector, hint::Integer) + return if hint < firstindex(v) || hint > lastindex(v) + BinaryBracket() + elseif length(v) <= _AUTO_LINEAR_THRESHOLD + LinearScan() + else + BracketGallop() + end +end + +# Returns `(gap, skewed)`: the estimated average step in `v`'s index space +# between consecutive query results, plus a flag that's true when the +# queries' distribution is non-uniform within their span. +# +# - `gap` is the per-query cost driver. We always use the span-based +# estimate `n * span(queries) / span(v) / m` so that tightly-clustered +# queries (span_q ≈ 0) report gap ≈ 0 regardless of `n/m`. The earlier +# `n / m` fallback for skewed queries caused `SIMDLinearScan` to be +# picked for clustered queries where LinearScan's tiny scalar walk is +# 5× faster. +# - `skewed` is an InterpolationSearch-suitability flag. When the median +# query sits well off the midpoint of `queries[1]..queries[end]`, the +# queries are clustered within their span and the per-call linear +# extrapolation guess is worse than the previous-result hint that +# `ExpFromLeft` would use. +@inline function _estimate_avg_gap( + v::AbstractVector{<:Number}, queries::AbstractVector{<:Number}, m::Integer, + ) + n = length(v) + n <= 1 && return (0, false) + @inbounds span_v = v[end] - v[1] + if iszero(span_v) || !isfinite(span_v) + return (n ÷ max(1, m), false) + end + @inbounds span_q = queries[end] - queries[1] + # Skew detection on small `m` is too noisy — for `m ≈ 4` random uniform + # samples, the median routinely sits 30%+ off the linear midpoint by + # chance. Gate on `m ≥ 10` where the statistical variance is well below + # the 20% threshold. + skewed = false + if m >= 10 + @inbounds mid_q = queries[firstindex(queries) + m ÷ 2] + @inbounds expected_mid = ( + queries[firstindex(queries)] + + queries[lastindex(queries)] + ) / 2 + if !iszero(span_q) && + abs(mid_q - expected_mid) > 0.2 * abs(span_q) + skewed = true + end + end + ratio = span_q / span_v + # Clamp ratio: queries may extend outside v's range (extrapolation). + ratio = clamp(ratio, zero(ratio), one(ratio)) + return (floor(Int, n * ratio / max(1, m)), skewed) +end + +# Non-numeric eltypes: no span subtraction possible, fall back to length +# ratio and assume queries are roughly uniform (no skew detection possible). +@inline _estimate_avg_gap( + v::AbstractVector, ::AbstractVector, m::Integer, +) = (length(v) ÷ max(1, m), false) + +# SIMD eligibility check used by Auto's batched dispatch. The static type +# test on `v` discriminates the `DenseVector{Int64}` / `DenseVector{Float64}` +# cases that SIMDLinearScan supports. For Float64, NaN presence is taken from +# cached `SearchProperties.has_nan` when available; otherwise we assume no +# NaN — Base's positional search doesn't check sortedness either, and the +# burden of supplying populated props is on the caller for pathological +# inputs. +@inline _auto_simd_eligible(v::DenseVector{Int64}, ::SearchProperties) = true +@inline function _auto_simd_eligible(v::DenseVector{Float64}, p::SearchProperties) + return p.has_props ? !p.has_nan : true +end +@inline _auto_simd_eligible(::AbstractVector, ::SearchProperties) = false + +# InterpolationSearch eligibility: two-tier linearity check. For +# `_AUTO_INTERP_MIN_GAP ≤ gap < _AUTO_INTERP_LOOSE_GAP` we require strict +# linearity (`_AUTO_LINEAR_REL_TOLERANCE`, default 0.1%) — InterpolationSearch +# is only worth the per-call cost on truly uniform data when ExpFromLeft is +# also competitive. For `gap ≥ _AUTO_INTERP_LOOSE_GAP` we accept a looser +# tolerance (`_AUTO_LINEAR_LOOSE_TOLERANCE`, default 5%) because the cache +# benefit of one extrapolation jump + local refine compensates for a worse +# guess, but we still reject genuinely nonlinear data (log-spaced, +# two-scale) where InterpolationSearch loses 2–3× to ExpFromLeft. +@inline function _auto_interp_eligible(v, props::SearchProperties, gap::Integer) + if gap >= _AUTO_INTERP_LOOSE_GAP + # Loose probe — even on cached props, the strict `is_linear` bit may + # already reflect a tighter threshold than we need here, so run the + # sampled probe at the loose tolerance regardless of cache state. + return _sampled_looks_linear(v, _AUTO_LINEAR_LOOSE_TOLERANCE) + end + return props.has_props ? props.is_linear : _sampled_looks_linear(v) +end + +# Per-query Auto dispatch. +function Base.searchsortedlast( + ::Auto, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + s = _auto_pick(v, hint) + return s isa BinaryBracket ? + searchsortedlast(s, v, x; order = order) : + searchsortedlast(s, v, x, hint; order = order) +end + +function Base.searchsortedfirst( + ::Auto, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + s = _auto_pick(v, hint) + return s isa BinaryBracket ? + searchsortedfirst(s, v, x; order = order) : + searchsortedfirst(s, v, x, hint; order = order) +end + +Base.searchsortedlast( + ::Auto, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::Auto, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(BinaryBracket(), v, x; order = order) diff --git a/src/batched.jl b/src/batched.jl new file mode 100644 index 0000000..9dbc82f --- /dev/null +++ b/src/batched.jl @@ -0,0 +1,321 @@ +# In-place batched sorted-search API: `searchsortedfirst!` / `searchsortedlast!` +# and `searchsortedrange`, plus the internal `_batched!` dispatchers and the +# Auto-specific specialization that turns Auto's decision tree into a single +# branchless dispatch on a concrete strategy. + +""" + searchsortedlast!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward, + queries_sorted = nothing) + +In-place batched [`searchsortedlast`](@ref Base.searchsortedlast). Writes one +index per element of `queries` into `idx_out` (which must be the same length). + +If `queries` is sorted under `order`, the previous result is used as a hint for +the next query, so the total cost is O(length(v) + length(queries)) under +`strategy = BracketGallop()` (the default `Auto` choice for non-tiny `v`). + +If `queries` is not sorted, falls back to per-element `searchsortedlast` with +no hint regardless of `strategy`. + +The `queries_sorted` kwarg controls the runtime `issorted(queries)` check: + + - `nothing` (default): run `issorted(queries; order = order)` on every call. + O(m) bookkeeping, roughly 1 ns/q on long batches. + - `true`: trust the caller — skip the check and take the sorted-loop path + unconditionally. Use this when you already know your queries are sorted + (you computed them as a range, sorted them yourself, etc.). Wrong-answer + risk: a non-sorted `queries` passed with `queries_sorted = true` will + produce incorrect results, since the inner loop uses the previous result + as a hint and that hint becomes invalid when queries jump backward. + - `false`: skip the check and take the unsorted-loop path unconditionally + (per-query unhinted `Base.searchsortedlast`). Use when you know queries + are not sorted and want to avoid the O(m) probe. + +Returns `idx_out`. +""" +function searchsortedlast!( + idx_out::AbstractVector{<:Integer}, + v::AbstractVector, + queries::AbstractVector; + strategy::SearchStrategy = Auto(), + order::Base.Order.Ordering = Base.Order.Forward, + queries_sorted::Union{Nothing, Bool} = nothing, + ) + if length(idx_out) != length(queries) + throw( + DimensionMismatch( + "idx_out and queries must have the same length" + ) + ) + end + return _searchsortedlast_batched!( + idx_out, v, queries, strategy, order, queries_sorted + ) +end + +""" + searchsortedfirst!(idx_out, v, queries; strategy = Auto(), order = Base.Order.Forward, + queries_sorted = nothing) + +In-place batched [`searchsortedfirst`](@ref Base.searchsortedfirst). See +[`searchsortedlast!`](@ref) for behavior and for the `queries_sorted` kwarg. +""" +function searchsortedfirst!( + idx_out::AbstractVector{<:Integer}, + v::AbstractVector, + queries::AbstractVector; + strategy::SearchStrategy = Auto(), + order::Base.Order.Ordering = Base.Order.Forward, + queries_sorted::Union{Nothing, Bool} = nothing, + ) + if length(idx_out) != length(queries) + throw( + DimensionMismatch( + "idx_out and queries must have the same length" + ) + ) + end + return _searchsortedfirst_batched!( + idx_out, v, queries, strategy, order, queries_sorted + ) +end + +# Sorted inner loop, parameterized on strategy. Used by both the generic and +# Auto batched entry points so each batch performs at most one issorted check. +function _searchsortedlast_sorted_loop!( + idx_out, v::AbstractVector, queries::AbstractVector, + strategy::SearchStrategy, order::Base.Order.Ordering, + ) + hint = firstindex(v) - 1 + @inbounds for k in eachindex(queries) + q = queries[k] + hint = if hint < firstindex(v) + searchsortedlast(strategy, v, q; order = order) + else + searchsortedlast(strategy, v, q, hint; order = order) + end + idx_out[k] = hint + end + return idx_out +end + +function _searchsortedfirst_sorted_loop!( + idx_out, v::AbstractVector, queries::AbstractVector, + strategy::SearchStrategy, order::Base.Order.Ordering, + ) + hint = firstindex(v) - 1 + @inbounds for k in eachindex(queries) + q = queries[k] + hint = if hint < firstindex(v) + searchsortedfirst(strategy, v, q; order = order) + else + searchsortedfirst(strategy, v, q, hint; order = order) + end + idx_out[k] = hint + end + return idx_out +end + +function _searchsortedlast_unsorted_loop!( + idx_out, v::AbstractVector, queries::AbstractVector, + order::Base.Order.Ordering, + ) + @inbounds for k in eachindex(queries) + idx_out[k] = searchsortedlast(v, queries[k], order) + end + return idx_out +end + +function _searchsortedfirst_unsorted_loop!( + idx_out, v::AbstractVector, queries::AbstractVector, + order::Base.Order.Ordering, + ) + @inbounds for k in eachindex(queries) + idx_out[k] = searchsortedfirst(v, queries[k], order) + end + return idx_out +end + +# Decide whether to take the sorted-queries fast path. `queries_sorted` is +# the caller-supplied override: `nothing` means "check at runtime", `true` +# means "trust the caller, skip the O(m) issorted probe", `false` means +# "force the unsorted path". +@inline function _take_sorted_path( + queries, order::Base.Order.Ordering, queries_sorted::Union{Nothing, Bool}, + ) + return queries_sorted === nothing ? + issorted(queries; order = order) : queries_sorted +end + +function _searchsortedlast_batched!( + idx_out, v::AbstractVector, queries::AbstractVector, + strategy::SearchStrategy, order::Base.Order.Ordering, + queries_sorted::Union{Nothing, Bool}, + ) + return if _take_sorted_path(queries, order, queries_sorted) + _searchsortedlast_sorted_loop!(idx_out, v, queries, strategy, order) + else + _searchsortedlast_unsorted_loop!(idx_out, v, queries, order) + end +end + +# Specialized batched-Auto: pick an inner strategy from the n/m ratio, then +# call the sorted loop directly (no duplicate `issorted` check, and each +# branch is type-stable so the loop specializes on the concrete strategy). +function _searchsortedlast_batched!( + idx_out, v::AbstractVector, queries::AbstractVector, + s::Auto, order::Base.Order.Ordering, + queries_sorted::Union{Nothing, Bool}, + ) + m = length(queries) + m == 0 && return idx_out + # m == 1: skip the issorted + span heuristic — no batched hint is + # available for a single-element batch, so just dispatch straight to + # the unhinted backing call. Saves ~20 ns of bookkeeping per call. + if m == 1 + @inbounds idx_out[firstindex(idx_out)] = + searchsortedlast(v, queries[firstindex(queries)], order) + return idx_out + end + if !_take_sorted_path(queries, order, queries_sorted) + return _searchsortedlast_unsorted_loop!(idx_out, v, queries, order) + end + gap, skewed = _estimate_avg_gap(v, queries, m) + # Manually dispatch on the picked strategy so each branch is concrete. + if gap <= _AUTO_BATCH_LINEAR_GAP + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, LinearScan(), order + ) + end + # Medium-gap regime: SIMDLinearScan wins on `DenseVector{Int64}` and + # `DenseVector{Float64}` (without NaN). + if gap <= _auto_simd_gap_max(v) && _auto_simd_eligible(v, s.props) + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, SIMDLinearScan(), order + ) + end + # Sparse-on-large-linear: InterpolationSearch wins ~2× over ExpFromLeft + # on uniformly-spaced data — but only when queries are *also* spread + # roughly uniformly within their span. + if !skewed && + gap >= _AUTO_INTERP_MIN_GAP && + length(v) >= _AUTO_INTERP_MIN_N && + m >= _AUTO_INTERP_MIN_M && + _auto_interp_eligible(v, s.props, gap) + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, InterpolationSearch(), order + ) + end + # Sparse fallback: BracketGallop beats ExpFromLeft when the gap is large + # enough that ExpFromLeft's initial 5 linear probes are guaranteed to + # miss. BracketGallop starts doubling from one position past `hint`, so + # it skips the wasted linear preamble. + if gap >= _AUTO_GALLOP_GAP_MIN + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, BracketGallop(), order + ) + end + return _searchsortedlast_sorted_loop!( + idx_out, v, queries, ExpFromLeft(), order + ) +end + +function _searchsortedfirst_batched!( + idx_out, v::AbstractVector, queries::AbstractVector, + strategy::SearchStrategy, order::Base.Order.Ordering, + queries_sorted::Union{Nothing, Bool}, + ) + return if _take_sorted_path(queries, order, queries_sorted) + _searchsortedfirst_sorted_loop!(idx_out, v, queries, strategy, order) + else + _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) + end +end + +function _searchsortedfirst_batched!( + idx_out, v::AbstractVector, queries::AbstractVector, + s::Auto, order::Base.Order.Ordering, + queries_sorted::Union{Nothing, Bool}, + ) + m = length(queries) + m == 0 && return idx_out + if m == 1 + @inbounds idx_out[firstindex(idx_out)] = + searchsortedfirst(v, queries[firstindex(queries)], order) + return idx_out + end + if !_take_sorted_path(queries, order, queries_sorted) + return _searchsortedfirst_unsorted_loop!(idx_out, v, queries, order) + end + gap, skewed = _estimate_avg_gap(v, queries, m) + if gap <= _AUTO_BATCH_LINEAR_GAP + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, LinearScan(), order + ) + end + if gap <= _auto_simd_gap_max(v) && _auto_simd_eligible(v, s.props) + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, SIMDLinearScan(), order + ) + end + if !skewed && + gap >= _AUTO_INTERP_MIN_GAP && + length(v) >= _AUTO_INTERP_MIN_N && + m >= _AUTO_INTERP_MIN_M && + _auto_interp_eligible(v, s.props, gap) + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, InterpolationSearch(), order + ) + end + if gap >= _AUTO_GALLOP_GAP_MIN + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, BracketGallop(), order + ) + end + return _searchsortedfirst_sorted_loop!( + idx_out, v, queries, ExpFromLeft(), order + ) +end + +# --------------------------------------------------------------------------- +# Range search through the strategy dispatch +# --------------------------------------------------------------------------- + +""" + searchsortedrange(strategy, v, lo, hi[, hint]; order = Base.Order.Forward) + -> UnitRange{Int} + +Return the index range of all entries `v[i]` satisfying `lo ≤ v[i] ≤ hi` +under `order`. Equivalent to +`searchsortedfirst(strategy, v, lo[, hint]; order) : + searchsortedlast(strategy, v, hi[, hint]; order)` but expressed as a +single call that may share bracket-discovery work between the two +endpoints when the underlying strategy allows it. + +The empty range case (no `v[i]` lies in `[lo, hi]`) returns +`searchsortedfirst(strategy, v, lo) : (searchsortedfirst(strategy, v, lo) - 1)`, +matching `Base.searchsorted(v, lo)` for an absent value. + +When a `hint` is supplied it is used for both endpoint searches. Strategies +that ignore the hint (`BinaryBracket`, `InterpolationSearch`) treat the +hinted form as a pass-through. +""" +@inline function searchsortedrange( + strategy::SearchStrategy, v::AbstractVector, lo, hi; + order::Base.Order.Ordering = Base.Order.Forward, + ) + first_idx = searchsortedfirst(strategy, v, lo; order = order) + last_idx = searchsortedlast(strategy, v, hi; order = order) + return first_idx:last_idx +end + +@inline function searchsortedrange( + strategy::SearchStrategy, v::AbstractVector, lo, hi, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + first_idx = searchsortedfirst(strategy, v, lo, hint; order = order) + last_idx = searchsortedlast( + strategy, v, hi, max(first_idx, hint); order = order + ) + return first_idx:last_idx +end diff --git a/src/dispatch.jl b/src/dispatch.jl new file mode 100644 index 0000000..f2a5575 --- /dev/null +++ b/src/dispatch.jl @@ -0,0 +1,583 @@ +# Per-strategy `Base.searchsortedlast` / `Base.searchsortedfirst` dispatch. +# Each strategy gets one dispatch block plus any internal helpers it needs +# (`bracketstrictlymonotonic*` for `BracketGallop`, `searchsortedfirstexp` +# for `ExpFromLeft`, `_interp_guess` for `InterpolationSearch`, etc.). +# +# `Auto`'s per-query and batched dispatch lives in `auto.jl` / `batched.jl`; +# `GuesserHint`'s lives in `guesser.jl`. + +# =========================================================================== +# Bracket helpers — backing `BracketGallop` +# =========================================================================== + +# Expanding-binary-search bracket around a guess. The `searchsortedlast` +# polarity: when `x == v[guess]`, the answer is `>= guess` (gallop right). +function bracketstrictlymonotonic( + v::AbstractVector, + x, + guess::T, + o::Base.Order.Ordering, + )::NTuple{2, keytype(v)} where {T <: Integer} + bottom = firstindex(v) + top = lastindex(v) + if guess < bottom || guess > top + return bottom, top + else + u = T(1) + lo, hi = guess, min(guess + u, top) + @inbounds if Base.Order.lt(o, x, v[lo]) + while lo > bottom && Base.Order.lt(o, x, v[lo]) + lo, hi = max(bottom, lo - u), lo + u += u + end + else + while hi < top && !Base.Order.lt(o, x, v[hi]) + lo, hi = hi, min(top, hi + u) + u += u + end + end + end + return lo, hi +end + +# Companion to `bracketstrictlymonotonic` for the `searchsortedfirst` +# polarity. Original uses `lt(o, x, v[lo])` (i.e., `x < v[lo]`), which is +# right for `searchsortedlast`: when `x == v[lo]`, the answer is `>= lo` so +# we gallop right. For `searchsortedfirst`, when `x == v[lo]` the answer is +# `<= lo` (look for earlier duplicates) — so we need the inverted polarity +# `lt(o, v[lo], x)`. Without this, BracketGallop.searchsortedfirst returns +# the wrong index when the hint lands on a run of duplicates. +function bracketstrictlymonotonic_first( + v::AbstractVector, + x, + guess::T, + o::Base.Order.Ordering, + )::NTuple{2, keytype(v)} where {T <: Integer} + bottom = firstindex(v) + top = lastindex(v) + if guess < bottom || guess > top + return bottom, top + else + u = T(1) + lo, hi = guess, min(guess + u, top) + @inbounds if !Base.Order.lt(o, v[lo], x) + # v[lo] >= x → answer is <= lo, gallop left. + while lo > bottom && !Base.Order.lt(o, v[lo], x) + lo, hi = max(bottom, lo - u), lo + u += u + end + else + # v[lo] < x → answer is > lo, gallop right. + while hi < top && Base.Order.lt(o, v[hi], x) + lo, hi = hi, min(top, hi + u) + u += u + end + end + end + return lo, hi +end + +# =========================================================================== +# Exponential-search helper — backing `ExpFromLeft` +# =========================================================================== + +# Exponential search forward from `lo`, then bounded binary search inside the +# final bracket. Used internally by `ExpFromLeft`. +Base.@propagate_inbounds function searchsortedfirstexp( + v::AbstractVector, + x, + lo::Integer = firstindex(v), + hi::Integer = lastindex(v), + ) + # Linear search for first few elements + for i in 0:4 + ind = lo + i + ind > hi && return ind + x <= v[ind] && return ind + end + # Exponential search with doubling steps + n = 3 + tn2 = 2^n + tn2m1 = 2^(n - 1) + ind = lo + tn2 + while ind <= hi + x <= v[ind] && + return searchsortedfirst(v, x, lo + tn2 - tn2m1, ind, Base.Order.Forward) + tn2 *= 2 + tn2m1 *= 2 + ind = lo + tn2 + end + return searchsortedfirst(v, x, lo + tn2 - tn2m1, hi, Base.Order.Forward) +end + +# =========================================================================== +# Strategy: BinaryBracket — ignore any hint, delegate to `Base` +# =========================================================================== + +Base.searchsortedlast( + ::BinaryBracket, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(v, x, order) +Base.searchsortedfirst( + ::BinaryBracket, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(v, x, order) +Base.searchsortedlast( + s::BinaryBracket, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(s, v, x; order = order) +Base.searchsortedfirst( + s::BinaryBracket, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(s, v, x; order = order) + +# =========================================================================== +# Strategy: LinearScan — walk ±1 from the hint +# =========================================================================== + +function Base.searchsortedlast( + ::LinearScan, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + lo, hi = firstindex(v), lastindex(v) + if hi < lo + return lo - 1 # empty vector + end + i = clamp(hint, lo, hi) + @inbounds if Base.Order.lt(order, x, v[i]) + # v[i] > x → retreat + while i > lo + i -= 1 + !Base.Order.lt(order, x, v[i]) && return i + end + return lo - 1 # x precedes all of v + else + # v[i] ≤ x → try to advance + while i < hi + Base.Order.lt(order, x, v[i + 1]) && return i + i += 1 + end + return hi + end +end + +function Base.searchsortedfirst( + ::LinearScan, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + lo, hi = firstindex(v), lastindex(v) + if hi < lo + return lo + end + i = clamp(hint, lo, hi) + @inbounds if Base.Order.lt(order, v[i], x) + # v[i] < x → advance + while i < hi + i += 1 + !Base.Order.lt(order, v[i], x) && return i + end + return hi + 1 # x exceeds all of v + else + # v[i] ≥ x → try to retreat + while i > lo + !Base.Order.lt(order, v[i - 1], x) && (i -= 1; continue) + return i + end + return lo + end +end + +# LinearScan without a hint falls back to BinaryBracket. +Base.searchsortedlast( + s::LinearScan, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + s::LinearScan, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + +# =========================================================================== +# Strategy: SIMDLinearScan — specialized forward walk for DenseVector{Int64} +# and DenseVector{Float64}. Backward walks reuse the scalar LinearScan path +# (rare from a good hint, and the SIMD primitive only exists for the +# forward-scan direction). +# =========================================================================== + +@inline function _simdscan_last_specialized( + v::Union{DenseVector{Int64}, DenseVector{Float64}}, x, hint::Integer, + ) + lo = firstindex(v) + hi = lastindex(v) + hi < lo && return lo - 1 + i = clamp(hint, lo, hi) + @inbounds vi = v[i] + if vi > x + # Backward walk (scalar). + while i > lo + i -= 1 + @inbounds v[i] <= x && return i + end + return lo - 1 + end + i == hi && return hi + start = i + 1 + len = hi - start + 1 + offset = GC.@preserve v _simd_first_gt(x, pointer(v, start), Int64(len)) + return offset < 0 ? hi : (start + offset) - 1 +end + +@inline function _simdscan_first_specialized( + v::Union{DenseVector{Int64}, DenseVector{Float64}}, x, hint::Integer, + ) + lo = firstindex(v) + hi = lastindex(v) + hi < lo && return lo + i = clamp(hint, lo, hi) + @inbounds vi = v[i] + if vi < x + i == hi && return hi + 1 + start = i + 1 + len = hi - start + 1 + offset = GC.@preserve v _simd_first_ge(x, pointer(v, start), Int64(len)) + return offset < 0 ? hi + 1 : start + offset + end + while i > lo + @inbounds v[i - 1] >= x && (i -= 1; continue) + return i + end + return lo +end + +function Base.searchsortedlast( + ::SIMDLinearScan, v::DenseVector{Int64}, x::Int64, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + order === Base.Order.Forward || + return searchsortedlast(LinearScan(), v, x, hint; order = order) + return _simdscan_last_specialized(v, x, hint) +end +function Base.searchsortedlast( + ::SIMDLinearScan, v::DenseVector{Float64}, x::Float64, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + order === Base.Order.Forward || + return searchsortedlast(LinearScan(), v, x, hint; order = order) + return _simdscan_last_specialized(v, x, hint) +end +function Base.searchsortedfirst( + ::SIMDLinearScan, v::DenseVector{Int64}, x::Int64, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + order === Base.Order.Forward || + return searchsortedfirst(LinearScan(), v, x, hint; order = order) + return _simdscan_first_specialized(v, x, hint) +end +function Base.searchsortedfirst( + ::SIMDLinearScan, v::DenseVector{Float64}, x::Float64, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + order === Base.Order.Forward || + return searchsortedfirst(LinearScan(), v, x, hint; order = order) + return _simdscan_first_specialized(v, x, hint) +end + +# Other eltypes fall back to the scalar LinearScan walk. +Base.searchsortedlast( + ::SIMDLinearScan, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(LinearScan(), v, x, hint; order = order) +Base.searchsortedfirst( + ::SIMDLinearScan, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(LinearScan(), v, x, hint; order = order) + +# No hint → BinaryBracket. +Base.searchsortedlast( + ::SIMDLinearScan, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::SIMDLinearScan, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + +# =========================================================================== +# Strategy: BracketGallop — bracketstrictlymonotonic + bounded binary search +# =========================================================================== + +function Base.searchsortedlast( + ::BracketGallop, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + lo, hi = bracketstrictlymonotonic(v, x, hint, order) + return searchsortedlast(v, x, lo, hi, order) +end + +function Base.searchsortedfirst( + ::BracketGallop, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + lo, hi = bracketstrictlymonotonic_first(v, x, hint, order) + return searchsortedfirst(v, x, lo, hi, order) +end + +# BracketGallop without a hint falls back to BinaryBracket. +Base.searchsortedlast( + ::BracketGallop, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::BracketGallop, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + +# =========================================================================== +# Strategy: ExpFromLeft — galloping forward from a left-bound hint. +# +# Contract: callers pass `hint` such that the answer is ≥ `hint`. When that +# isn't true (hint is past the answer), we fall back to a full +# `searchsortedlast`/`searchsortedfirst` — the batched-sorted loop sets +# `hint = prev_result`, which always satisfies this for sorted queries, so +# the fallback is only exercised by arbitrary single-query callers. +# =========================================================================== + +function Base.searchsortedfirst( + ::ExpFromLeft, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + lo = firstindex(v) + hi = lastindex(v) + if isempty(v) + return lo + end + h = clamp(hint, lo, hi) + # `searchsortedfirst` semantics: smallest i with v[i] >= x. We can only + # gallop forward from `h` when v[h] < x (then the answer is strictly + # > h). When v[h] >= x, the first occurrence of `x` may be at index + # ≤ h (duplicates to the left), so fall back to a full search rather + # than risk skipping past earlier duplicates. + @inbounds if !Base.Order.lt(order, v[h], x) + return searchsortedfirst(v, x, order) + end + return order === Base.Order.Forward ? + searchsortedfirstexp(v, x, h, hi) : + searchsortedfirst(v, x, h, hi, order) +end + +function Base.searchsortedlast( + ::ExpFromLeft, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + lo = firstindex(v) + hi = lastindex(v) + if isempty(v) + return lo - 1 + end + h = clamp(hint, lo, hi) + @inbounds if Base.Order.lt(order, x, v[h]) + return searchsortedlast(v, x, order) + end + if order === Base.Order.Forward + y = searchsortedfirstexp(v, x, h, hi) + return if y > hi + hi + else + @inbounds v[y] == x ? y : y - 1 + end + else + return searchsortedlast(v, x, h, hi, order) + end +end + +# ExpFromLeft without a hint falls back to BinaryBracket. +Base.searchsortedlast( + ::ExpFromLeft, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::ExpFromLeft, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + +# =========================================================================== +# Strategy: InterpolationSearch — extrapolate a guess, then bounded binary +# search around it. +# =========================================================================== + +@inline function _interp_guess(v::AbstractVector, x, lo::Integer, hi::Integer) + @inbounds vlo = v[lo] + @inbounds vhi = v[hi] + span = vhi - vlo + iszero(span) && return lo + # Linear extrapolation: how far is x along [vlo, vhi]? + f = (x - vlo) / span + if !isfinite(f) + return f > 0 ? hi : lo + end + g = lo + round(Int, f * (hi - lo)) + return clamp(g, lo, hi) +end + +function Base.searchsortedlast( + ::InterpolationSearch, v::AbstractVector{<:Number}, x::Number; + order::Base.Order.Ordering = Base.Order.Forward, + ) + if order !== Base.Order.Forward + # Linear interpolation doesn't carry over to reverse order; fall back + return searchsortedlast(v, x, order) + end + lo, hi = firstindex(v), lastindex(v) + hi < lo && return lo - 1 + g = _interp_guess(v, x, lo, hi) + return searchsortedlast(BracketGallop(), v, x, g; order = order) +end + +function Base.searchsortedfirst( + ::InterpolationSearch, v::AbstractVector{<:Number}, x::Number; + order::Base.Order.Ordering = Base.Order.Forward, + ) + if order !== Base.Order.Forward + return searchsortedfirst(v, x, order) + end + lo, hi = firstindex(v), lastindex(v) + hi < lo && return lo + g = _interp_guess(v, x, lo, hi) + return searchsortedfirst(BracketGallop(), v, x, g; order = order) +end + +# InterpolationSearch ignores any hint; pass-through. +Base.searchsortedlast( + s::InterpolationSearch, v::AbstractVector{<:Number}, x::Number, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(s, v, x; order = order) +Base.searchsortedfirst( + s::InterpolationSearch, v::AbstractVector{<:Number}, x::Number, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(s, v, x; order = order) + +# InterpolationSearch on non-numeric data falls back to BinaryBracket. +Base.searchsortedlast( + ::InterpolationSearch, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::InterpolationSearch, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(BinaryBracket(), v, x; order = order) +Base.searchsortedlast( + s::InterpolationSearch, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + s::InterpolationSearch, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(BinaryBracket(), v, x; order = order) + +# =========================================================================== +# Strategy: BitInterpolationSearch — InterpolationSearch on the IEEE bit +# pattern of positive Float64. Cheaper than reinterpret-as-array because we +# only need two endpoint reads and one query bitcast per call. +# =========================================================================== + +@inline function _bit_interp_guess_f64( + v::DenseVector{Float64}, x::Float64, lo::Integer, hi::Integer, + ) + @inbounds vlo_bits = reinterpret(UInt64, v[lo]) + @inbounds vhi_bits = reinterpret(UInt64, v[hi]) + xu = reinterpret(UInt64, x) + span = vhi_bits - vlo_bits + iszero(span) && return lo + if xu <= vlo_bits + return lo + elseif xu >= vhi_bits + return hi + end + num = xu - vlo_bits + f = Float64(num) / Float64(span) + g = lo + round(Int, f * (hi - lo)) + return clamp(g, lo, hi) +end + +function Base.searchsortedlast( + ::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64; + order::Base.Order.Ordering = Base.Order.Forward, + ) + if order !== Base.Order.Forward + return searchsortedlast(v, x, order) + end + lo, hi = firstindex(v), lastindex(v) + hi < lo && return lo - 1 + @inbounds if v[lo] <= 0.0 || !isfinite(v[lo]) || x <= 0.0 || !isfinite(x) + return searchsortedlast(BinaryBracket(), v, x; order = order) + end + g = _bit_interp_guess_f64(v, x, lo, hi) + return searchsortedlast(BracketGallop(), v, x, g; order = order) +end + +function Base.searchsortedfirst( + ::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64; + order::Base.Order.Ordering = Base.Order.Forward, + ) + if order !== Base.Order.Forward + return searchsortedfirst(v, x, order) + end + lo, hi = firstindex(v), lastindex(v) + hi < lo && return lo + @inbounds if v[lo] <= 0.0 || !isfinite(v[lo]) || x <= 0.0 || !isfinite(x) + return searchsortedfirst(BinaryBracket(), v, x; order = order) + end + g = _bit_interp_guess_f64(v, x, lo, hi) + return searchsortedfirst(BracketGallop(), v, x, g; order = order) +end + +# Hint pass-through (bit-interp ignores externally-supplied hints). +Base.searchsortedlast( + s::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(s, v, x; order = order) +Base.searchsortedfirst( + s::BitInterpolationSearch, v::DenseVector{Float64}, x::Float64, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(s, v, x; order = order) + +# Non-Float64 / non-dense eltypes: fall back to plain InterpolationSearch. +Base.searchsortedlast( + ::BitInterpolationSearch, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(InterpolationSearch(), v, x; order = order) +Base.searchsortedfirst( + ::BitInterpolationSearch, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(InterpolationSearch(), v, x; order = order) +Base.searchsortedlast( + ::BitInterpolationSearch, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(InterpolationSearch(), v, x; order = order) +Base.searchsortedfirst( + ::BitInterpolationSearch, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(InterpolationSearch(), v, x; order = order) + +# =========================================================================== +# Strategy: BisectThenSIMD — equality-search; positional dispatch falls back +# to BinaryBracket. (The `findequal(BisectThenSIMD(), v, x)` shortcut lives +# in `findequal.jl`.) +# =========================================================================== + +Base.searchsortedlast( + ::BisectThenSIMD, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + ::BisectThenSIMD, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(BinaryBracket(), v, x; order = order) +Base.searchsortedlast( + s::BisectThenSIMD, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(BinaryBracket(), v, x; order = order) +Base.searchsortedfirst( + s::BisectThenSIMD, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(BinaryBracket(), v, x; order = order) diff --git a/src/equality.jl b/src/equality.jl new file mode 100644 index 0000000..14feb03 --- /dev/null +++ b/src/equality.jl @@ -0,0 +1,73 @@ +# Equality-search public surface. `findfirstequal` handles unsorted vectors +# (with a SIMD specialization for `DenseVector{Int64}`); `findfirstsortedequal` +# handles sorted vectors via bisect-then-SIMD. The strategy-framework +# wrapper `findequal(strategy, v, x)` lives in `findequal.jl`. + +""" + findfirstequal(x, A) -> Union{Int, Nothing} + +Find the first index in `A` where the value equals `x`. Returns `nothing` +if `x` does not occur in `A`. + +This function does **not** assume `A` is sorted. For sorted vectors, see +[`findfirstsortedequal`](@ref) (a bisect-then-SIMD specialization on +`DenseVector{Int64}`) or [`findequal`](@ref) (the strategy-framework +equality wrapper that returns an `Int` with a sentinel). + +The `(x::Int64, A::DenseVector{Int64})` method uses a custom LLVM IR SIMD +scan (load 8 lanes, `icmp eq`, `cttz` on the mask) — about 8× faster than +the scalar `findfirst(==(x), v)` on modern x86-64. Every other element-type +and array-storage combination falls back to `findfirst(isequal(x), A)`. +""" +findfirstequal(vpivot, ivars) = findfirst(isequal(vpivot), ivars) +function findfirstequal(vpivot::Int64, ivars::DenseVector{Int64}) + GC.@preserve ivars begin + ret = _findfirstequal(vpivot, pointer(ivars), length(ivars)) + end + return ret < 0 ? nothing : ret + 1 +end + +""" + findfirstsortedequal(var::Int64, vars::DenseVector{Int64}) -> Union{Int64, Nothing} + +Find the index of the first occurrence of `var` in the sorted vector +`vars`. Returns `nothing` if `var` does not occur. Specialized for +`DenseVector{Int64}` via a branchless binary bisection down to a small +basecase, followed by the same SIMD equality scan that backs +[`findfirstequal`](@ref) — faster than plain `findfirst(==(var), vars)` +or `searchsortedfirst` + post-check for typical Int64 vectors. + +The strategy-framework equivalent is +[`findequal(BisectThenSIMD(), vars, var)`](@ref findequal); that wrapper +returns an `Int` with a sentinel (`firstindex(v) - 1`) for "not found", +which is type-stable and composes with the rest of the strategy +dispatch. Prefer `findequal` for new code; `findfirstsortedequal` remains +as the dedicated `Union{Int64, Nothing}`-returning name. +""" +function findfirstsortedequal( + var::Int64, + vars::DenseVector{Int64}, + ::Val{basecase} = Base.libllvm_version >= v"17" ? Val(8) : Val(128), + ) where {basecase} + len = length(vars) + offset = 0 + @inbounds while len > basecase + # Bisect with the predicate `vars[mid] < var` (strict). When true, + # `var` is past the midpoint — drop the left half *and* the + # midpoint itself. When false (`vars[mid] >= var`), `var` may be + # at the midpoint, so keep `offset` and shrink the window to + # `vars[offset+1 .. offset+half+1]` (inclusive of the midpoint). + # The earlier `<=` predicate would have advanced past matching + # midpoints, masking earlier duplicates of `var`. + half = len >>> 1 + mid = offset + half + 1 + is_left_strictly_less = vars[mid] < var + offset = ifelse(is_left_strictly_less, offset + half + 1, offset) + len = ifelse(is_left_strictly_less, len - half - 1, half + 1) + end + # maybe occurs in vars[offset+1:offset+len] + GC.@preserve vars begin + ret = _findfirstequal(var, pointer(vars) + 8offset, len) + end + return ret < 0 ? nothing : ret + offset + 1 +end diff --git a/src/findequal.jl b/src/findequal.jl new file mode 100644 index 0000000..c7a9807 --- /dev/null +++ b/src/findequal.jl @@ -0,0 +1,91 @@ +# Strategy-framework equality search: `findequal(strategy, v, x[, hint])`. +# Returns an `Int` with the sentinel `firstindex(v) - 1` for "not found" +# (matching `Base.searchsortedlast`'s convention for "x precedes all of v"). +# The `BisectThenSIMD` shortcut for `DenseVector{Int64}` dispatches into +# `findfirstsortedequal` directly; every other strategy composes via +# `searchsortedfirst` + a post-check. + +""" + findequal(strategy, v, x[, hint]; order = Base.Order.Forward) -> Int + +Return the index of `x` in sorted `v` if present, or the sentinel +`firstindex(v) - 1` if `x` is absent. Type-stable `Int` return — the +sentinel matches the convention `Base.searchsortedlast` already uses for +"x precedes all of v", so callers can test for "not found" with +`i < firstindex(v)`. + +For vectors with 1-based indexing (the Julia default), the sentinel is +exactly `0`, which is also `searchsortedlast`'s "x precedes all" return. +For [OffsetArrays](https://github.com/JuliaArrays/OffsetArrays.jl) and any +other vector whose `firstindex` is not `1`, the sentinel adjusts +accordingly — e.g. for a vector with `firstindex == -3`, the sentinel is +`-4`. Always test against `firstindex(v) - 1` (or equivalently +`i < firstindex(v)`), not against the literal `0`. + +Most strategies are handled generically: run +`searchsortedfirst(strategy, v, x[, hint])` to find the candidate insertion +point, then check whether `v[i]` actually equals `x`. The shortcut method +on [`BisectThenSIMD`](@ref) for `DenseVector{Int64}` skips the +`searchsortedfirst` path entirely and uses the dedicated bisect-then-SIMD +equality scan that backs [`findfirstsortedequal`](@ref). + +For unsorted vectors, use [`findfirstequal`](@ref) — it does not require +a sorted input and falls outside the strategy framework. +""" +@inline function findequal( + strategy::SearchStrategy, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, + ) + return _findequal_generic(strategy, v, x, order) +end + +@inline function findequal( + strategy::SearchStrategy, v::AbstractVector, x, hint::Integer; + order::Base.Order.Ordering = Base.Order.Forward, + ) + i = searchsortedfirst(strategy, v, x, hint; order = order) + return _findequal_postcheck(v, x, i) +end + +@inline function _findequal_generic(strategy, v, x, order) + i = searchsortedfirst(strategy, v, x; order = order) + return _findequal_postcheck(v, x, i) +end + +@inline function _findequal_postcheck(v::AbstractVector, x, i::Integer) + if i > lastindex(v) + return firstindex(v) - 1 + end + @inbounds return isequal(v[i], x) ? Int(i) : (firstindex(v) - 1) +end + +# Shortcut: BisectThenSIMD on DenseVector{Int64} uses the dedicated bisect- +# then-SIMD equality scan (same algorithm as `findfirstsortedequal`). +function findequal( + ::BisectThenSIMD, v::DenseVector{Int64}, x::Int64; + order::Base.Order.Ordering = Base.Order.Forward, + ) + if order !== Base.Order.Forward + return _findequal_generic(BinaryBracket(), v, x, order) + end + r = findfirstsortedequal(x, v) + return r === nothing ? (firstindex(v) - 1) : r +end +# Hinted form ignores the hint — the bisect-then-SIMD algorithm does not +# benefit from a hint, and probing it would only waste cycles. +findequal( + s::BisectThenSIMD, v::DenseVector{Int64}, x::Int64, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = findequal(s, v, x; order = order) + +# Non-Int64 fallback for BisectThenSIMD: use BinaryBracket + post-check. +function findequal( + ::BisectThenSIMD, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, + ) + return _findequal_generic(BinaryBracket(), v, x, order) +end +findequal( + s::BisectThenSIMD, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = findequal(s, v, x; order = order) diff --git a/src/guesser.jl b/src/guesser.jl new file mode 100644 index 0000000..e3e4b61 --- /dev/null +++ b/src/guesser.jl @@ -0,0 +1,109 @@ +# `Guesser` correlated-lookup helper + the public `looks_linear` probe it +# uses + the `GuesserHint` strategy dispatch that plugs a `Guesser` into the +# `searchsortedfirst`/`searchsortedlast` API. + +""" + looks_linear(v; threshold = 1e-2) + +Determine if the abscissae `v` are regularly distributed, taking the standard deviation of +the difference between the array of abscissae with respect to the straight line linking +its first and last elements, normalized by the range of `v`. If this standard deviation is +below the given `threshold`, the vector looks linear (return true). Internal function - +interface may change. +""" +function looks_linear(v; threshold = 1.0e-2) + length(v) <= 2 && return true + x_0, x_f = first(v), last(v) + N = length(v) + x_span = x_f - x_0 + mean_x_dist = x_span / (N - 1) + norm_var = sum((x_i - x_0 - (i - 1) * mean_x_dist)^2 for (i, x_i) in enumerate(v)) / + (N * x_span^2) + return norm_var < threshold^2 +end + +""" + Guesser(v::AbstractVector; looks_linear_threshold = 1e-2) + +Wrapper of the searched vector `v` which makes an informed guess for the next +correlated lookup by either + + - exploiting that `v` is sufficiently evenly spaced (linear-extrapolation guess), or + - using the previous outcome (the cached `idx_prev`). + +Pass a `Guesser` to [`GuesserHint`](@ref) to use it as a search strategy with +the dispatched [`searchsortedlast`](@ref Base.searchsortedlast) / +[`searchsortedfirst`](@ref Base.searchsortedfirst) API. +""" +struct Guesser{T <: AbstractVector} + v::T + idx_prev::Base.RefValue{Int} + linear_lookup::Bool +end + +function Guesser(v::AbstractVector; looks_linear_threshold = 1.0e-2) + return Guesser(v, Ref(1), looks_linear(v; threshold = looks_linear_threshold)) +end + +function (g::Guesser)(x) + (; v, idx_prev, linear_lookup) = g + return if linear_lookup + δx = x - first(v) + iszero(δx) && return firstindex(v) + f = δx / (last(v) - first(v)) + if isinf(f) + f > 0 ? lastindex(v) : firstindex(v) + else + i_0, i_f = firstindex(v), lastindex(v) + i_approx = f * (i_f - i_0) + i_0 + target_type = typeof(firstindex(v)) + if i_approx >= typemax(target_type) + lastindex(v) + 1 + elseif i_approx <= typemin(target_type) + firstindex(v) - 1 + else + round(target_type, i_approx) + end + end + else + idx_prev[] + end +end + +# Note on ranges: `Base.searchsortedlast(r::AbstractRange, x, order)` is +# already O(1) (closed-form), so the strategies' fallback path through +# `BinaryBracket` (which delegates to that Base method) is already optimal +# for ranges. No special-case overlays needed. + +# GuesserHint methods — strategy dispatch wrapper for the `Guesser`-based +# correlated search. Per-call cost: one `guesser(x)` evaluation + one +# `BracketGallop` call + one `idx_prev[]` write. +function Base.searchsortedlast( + s::GuesserHint, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, + ) + @assert v === s.guesser.v + out = searchsortedlast(BracketGallop(), v, x, s.guesser(x); order = order) + s.guesser.idx_prev[] = out + return out +end + +function Base.searchsortedfirst( + s::GuesserHint, v::AbstractVector, x; + order::Base.Order.Ordering = Base.Order.Forward, + ) + @assert v === s.guesser.v + out = searchsortedfirst(BracketGallop(), v, x, s.guesser(x); order = order) + s.guesser.idx_prev[] = out + return out +end + +# GuesserHint ignores any externally-supplied hint (the Guesser carries its own). +Base.searchsortedlast( + s::GuesserHint, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedlast(s, v, x; order = order) +Base.searchsortedfirst( + s::GuesserHint, v::AbstractVector, x, ::Integer; + order::Base.Order.Ordering = Base.Order.Forward, +) = searchsortedfirst(s, v, x; order = order) diff --git a/src/precompile.jl b/src/precompile.jl new file mode 100644 index 0000000..93c5ec1 --- /dev/null +++ b/src/precompile.jl @@ -0,0 +1,58 @@ +# PrecompileTools workload — exercises the most commonly used public +# entry points across typical eltypes so `using FindFirstFunctions` is hot +# without a startup compile spike on the first call. + +using PrecompileTools: @compile_workload, @setup_workload + +@setup_workload begin + vec_int64 = Int64[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + linear_vec = collect(1.0:0.5:10.0) + + @compile_workload begin + # findfirstequal: fast SIMD-based search in Int64 vectors. + findfirstequal(Int64(5), vec_int64) + findfirstequal(Int64(100), vec_int64) + + # findfirstsortedequal: binary search in sorted Int64 vectors. + findfirstsortedequal(Int64(8), vec_int64) + findfirstsortedequal(Int64(100), vec_int64) + + # looks_linear: check if vector is evenly spaced. + looks_linear(linear_vec) + + # Guesser: hint provider for correlated repeated searches. + guesser = Guesser(linear_vec) + guesser(5.0) + + # Strategy dispatch — single-query forms across the standard strategies. + for strategy in ( + LinearScan(), SIMDLinearScan(), BracketGallop(), ExpFromLeft(), + InterpolationSearch(), BinaryBracket(), Auto(), + Auto(SearchProperties(linear_vec)), + ) + searchsortedfirst(strategy, vec_int64, Int64(8), Int64(1)) + searchsortedlast(strategy, vec_int64, Int64(8), Int64(1)) + end + # findequal: generic + BisectThenSIMD shortcut for Int64 dense vectors. + for strategy in ( + BinaryBracket(), BracketGallop(), SIMDLinearScan(), + BisectThenSIMD(), Auto(), + ) + findequal(strategy, vec_int64, Int64(8)) + findequal(strategy, vec_int64, Int64(8), Int64(1)) + end + # SIMDLinearScan's Float64 specialization. + let vec_f64 = collect(1.0:1.0:16.0) + searchsortedfirst(SIMDLinearScan(), vec_f64, 8.0, 1) + searchsortedlast(SIMDLinearScan(), vec_f64, 8.0, 1) + end + searchsortedfirst(GuesserHint(Guesser(vec_int64)), vec_int64, Int64(8)) + searchsortedlast(GuesserHint(Guesser(vec_int64)), vec_int64, Int64(8)) + + # Strategy dispatch — batched in-place forms. + idx_out = Vector{Int}(undef, 4) + queries = Int64[2, 5, 8, 12] + searchsortedfirst!(idx_out, vec_int64, queries) + searchsortedlast!(idx_out, vec_int64, queries) + end +end diff --git a/src/search_properties.jl b/src/search_properties.jl new file mode 100644 index 0000000..f0507bf --- /dev/null +++ b/src/search_properties.jl @@ -0,0 +1,120 @@ +# `SearchProperties` populated constructor + the runtime probes it runs at +# construction time. The `SearchProperties` struct itself, the default +# constructor (`SearchProperties()` sentinel), and the `Auto` type that +# carries one as a field all live in `strategies.jl`. + +# `has_nan` is only meaningful for floating-point eltypes; for other numeric +# types and non-numeric eltypes there is no NaN concept. +@inline _has_nan(v::AbstractVector{<:AbstractFloat}) = any(isnan, v) +@inline _has_nan(::AbstractVector) = false + +# Auto's strict linearity tolerance. `SearchProperties(v)` uses the same +# default. Defined here rather than in `auto.jl` because `_sampled_looks_*` +# need it as a default arg; `auto.jl` re-uses the same constant. +const _AUTO_LINEAR_REL_TOLERANCE = 1.0e-3 + +# Sampled linearity check: probes v[1], v[k*n/10] for k = 1..9, v[n] and +# tests whether all interior points sit within `_AUTO_LINEAR_REL_TOLERANCE` +# (default 0.1%) of the straight line between v[1] and v[n]. The tight +# tolerance reliably distinguishes truly-uniform data from random/sorted +# data even at large n (where the order-statistic variance ≈ 1/sqrt(n) +# would fool a looser check). +# +# Cost is ~25 ns regardless of n — 11 reads + 9 comparisons. Used by Auto +# to decide whether to gamble on InterpolationSearch. +# +# InterpolationSearch's downside on non-linear data is large (4-14× slower +# than ExpFromLeft on log/plateau/two-scale spacings), so we err on the +# side of rejecting borderline cases. Truly uniform data — exact ranges, +# evenly-spaced grids, and small-amplitude jittered data — passes; sorted +# random data is rejected at all `n` tested up to ~10⁶. +@inline function _sampled_looks_linear( + v::AbstractVector{<:Number}, + tol::Float64 = _AUTO_LINEAR_REL_TOLERANCE, + ) + n = length(v) + n < 11 && return false + @inbounds begin + v1, vn = v[1], v[n] + span = vn - v1 + (iszero(span) || !isfinite(span)) && return false + abs_span = abs(span) + nm1 = n - 1 + for k in 1:9 + kk = 1 + (k * nm1) ÷ 10 + expected = v1 + (kk - 1) / nm1 * span + rel_err = abs(v[kk] - expected) / abs_span + rel_err > tol && return false + end + end + return true +end + +# Non-numeric eltype: can't sample, never picks InterpolationSearch. +@inline _sampled_looks_linear(::AbstractVector, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = false + +# AbstractRange is definitionally uniform — accept without sampling. +@inline _sampled_looks_linear(::AbstractRange, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = true + +# Sampled "log-linear" probe: same 9-point probe as `_sampled_looks_linear` +# but tests whether `log(v)` is linear in array index. Used to detect +# geometric / log-spaced data where `BitInterpolationSearch` is a win. +# Requires all sampled points to be strictly positive and finite; otherwise +# returns false. The probe runs in ~30 ns (the `log` calls are not cheap +# but only 11 of them, all at fixed index positions). +@inline function _sampled_looks_log_linear( + v::AbstractVector{<:Real}, + tol::Float64 = _AUTO_LINEAR_REL_TOLERANCE, + ) + n = length(v) + n < 11 && return false + @inbounds begin + v1, vn = v[1], v[n] + (v1 <= 0 || vn <= 0 || !isfinite(v1) || !isfinite(vn)) && return false + log_v1 = log(Float64(v1)) + log_vn = log(Float64(vn)) + span = log_vn - log_v1 + (iszero(span) || !isfinite(span)) && return false + abs_span = abs(span) + nm1 = n - 1 + for k in 1:9 + kk = 1 + (k * nm1) ÷ 10 + vk = v[kk] + (vk <= 0 || !isfinite(vk)) && return false + expected = log_v1 + (kk - 1) / nm1 * span + rel_err = abs(log(Float64(vk)) - expected) / abs_span + rel_err > tol && return false + end + end + return true +end + +@inline _sampled_looks_log_linear(::AbstractVector, ::Float64 = _AUTO_LINEAR_REL_TOLERANCE) = false + +""" + SearchProperties(v::AbstractVector; linear_tolerance = 1.0e-3) + +Run the linearity probe and (for floating-point eltypes) the NaN scan on `v`, +returning the populated [`SearchProperties`](@ref). Cost is O(n) on +floating-point vectors because of the NaN scan; for integer and non-numeric +eltypes the cost is O(1) — only the sampled-linearity probe runs. + +`linear_tolerance` controls the maximum relative deviation accepted by the +sampled-linearity probe. The default `1e-3` (0.1%) matches `Auto`'s +un-cached probe behaviour. Loosen it (e.g. to `1e-2`) to accept noisier +"approximately linear" data — this widens the regime where `Auto` will pick +`InterpolationSearch` over `ExpFromLeft`. Tighten it (e.g. to `1e-4`) to be +more conservative. +""" +function SearchProperties( + v::AbstractVector; + linear_tolerance::Real = 1.0e-3, + ) + tol = Float64(linear_tolerance) + return SearchProperties( + true, + _sampled_looks_linear(v, tol), + _has_nan(v), + _sampled_looks_log_linear(v, tol), + ) +end diff --git a/src/simd_ir.jl b/src/simd_ir.jl new file mode 100644 index 0000000..1c543da --- /dev/null +++ b/src/simd_ir.jl @@ -0,0 +1,135 @@ +# SIMD LLVM IR scaffolding shared by every "find first lane matching +# predicate" routine in the package: +# +# - `FFE_IR` / `_findfirstequal` — exact equality scan, Int64 +# (predicate `icmp eq`) +# - `_SIMD_GT_I64_IR` / `_simd_first_gt(::Int64, …)` — `icmp sgt` +# - `_SIMD_GE_I64_IR` / `_simd_first_ge(::Int64, …)` — `icmp sge` +# - `_SIMD_GT_F64_IR` / `_simd_first_gt(::Float64, …)` — `fcmp ogt` +# - `_SIMD_GE_F64_IR` / `_simd_first_ge(::Float64, …)` — `fcmp oge` +# +# All five IR strings are generated from the same template, keyed on scalar +# LLVM type (`i64`, `double`) and compare predicate. Adding a new predicate +# is a single `_simd_scan_ir(t, pred)` call plus a corresponding +# `Base.llvmcall` wrapper. + +# Generate the SIMD "find first lane matching predicate" IR for an arbitrary +# scalar type and LLVM compare predicate. Load 8 lanes at a time, compare +# against a broadcast of the search value, bitcast the i1×8 mask to i8, +# `cttz` to find the first set bit. The tail past the last full chunk is +# handled scalar-wise. +function _simd_scan_ir(t, pred) + cmp = pred[1] in ('o', 'u') ? "fcmp" : "icmp" + return """ + declare i8 @llvm.cttz.i8(i8, i1); + define i64 @entry($t %0, $(USE_PTR ? "ptr" : "i64") %1, i64 %2) #0 { + top: + $(USE_PTR ? "" : "%ivars = inttoptr i64 %1 to $t*") + %btmp = insertelement <8 x $t> undef, $t %0, i64 0 + %var = shufflevector <8 x $t> %btmp, <8 x $t> undef, <8 x i32> zeroinitializer + %lenm7 = add nsw i64 %2, -7 + %dosimditer = icmp ugt i64 %2, 7 + br i1 %dosimditer, label %L9.lr.ph, label %L32 + + L9.lr.ph: + %len8 = and i64 %2, 9223372036854775800 + br label %L9 + + L9: + %i = phi i64 [ 0, %L9.lr.ph ], [ %vinc, %L30 ] + %ivarsi = getelementptr inbounds $t, $(USE_PTR ? "ptr %1" : "$t* %ivars"), i64 %i + $(USE_PTR ? "" : "%vpvi = bitcast $t* %ivarsi to <8 x $t>*") + %v = load <8 x $t>, $(USE_PTR ? "ptr %ivarsi" : "<8 x $t> * %vpvi"), align 8 + %m = $cmp $pred <8 x $t> %v, %var + %mu = bitcast <8 x i1> %m to i8 + %matchnotfound = icmp eq i8 %mu, 0 + br i1 %matchnotfound, label %L30, label %L17 + + L17: + %tz8 = call i8 @llvm.cttz.i8(i8 %mu, i1 true) + %tz64 = zext i8 %tz8 to i64 + %vis = add nuw i64 %i, %tz64 + br label %common.ret + + common.ret: + %retval = phi i64 [ %vis, %L17 ], [ -1, %L32 ], [ %si, %L51 ], [ -1, %L67 ] + ret i64 %retval + + L30: + %vinc = add nuw nsw i64 %i, 8 + %continue = icmp slt i64 %vinc, %lenm7 + br i1 %continue, label %L9, label %L32 + + L32: + %cumi = phi i64 [ 0, %top ], [ %len8, %L30 ] + %done = icmp eq i64 %cumi, %2 + br i1 %done, label %common.ret, label %L51 + + L51: + %si = phi i64 [ %inc, %L67 ], [ %cumi, %L32 ] + %spi = getelementptr inbounds $t, $(USE_PTR ? "ptr %1" : "$t* %ivars"), i64 %si + %svi = load $t, $(USE_PTR ? "ptr" : "$t*") %spi, align 8 + %match = $cmp $pred $t %svi, %0 + br i1 %match, label %common.ret, label %L67 + + L67: + %inc = add i64 %si, 1 + %dobreak = icmp eq i64 %inc, %2 + br i1 %dobreak, label %common.ret, label %L51 + + } + attributes #0 = { alwaysinline } + """ +end + +const FFE_IR = _simd_scan_ir("i64", "eq") + +function _findfirstequal(vpivot::Int64, ptr::Ptr{Int64}, len::Int64) + return Base.llvmcall( + (FFE_IR, "entry"), + Int64, + Tuple{Int64, Ptr{Int64}, Int64}, + vpivot, + ptr, + len + ) +end + +const _SIMD_GT_I64_IR = _simd_scan_ir("i64", "sgt") +const _SIMD_GE_I64_IR = _simd_scan_ir("i64", "sge") +const _SIMD_GT_F64_IR = _simd_scan_ir("double", "ogt") +const _SIMD_GE_F64_IR = _simd_scan_ir("double", "oge") + +# Backing primitives for SIMDLinearScan. Each returns the 0-based offset of +# the first lane satisfying the predicate, or -1 if none. Caveat: NaN inputs +# always compare false under the ordered `o*` float predicates, so NaN in `v` +# or `x` produces "no match" rather than an exception — consistent with the +# undefined-input contract for sorted Float64 vectors containing NaN. +function _simd_first_gt(x::Int64, ptr::Ptr{Int64}, len::Int64) + return Base.llvmcall( + (_SIMD_GT_I64_IR, "entry"), + Int64, Tuple{Int64, Ptr{Int64}, Int64}, + x, ptr, len + ) +end +function _simd_first_ge(x::Int64, ptr::Ptr{Int64}, len::Int64) + return Base.llvmcall( + (_SIMD_GE_I64_IR, "entry"), + Int64, Tuple{Int64, Ptr{Int64}, Int64}, + x, ptr, len + ) +end +function _simd_first_gt(x::Float64, ptr::Ptr{Float64}, len::Int64) + return Base.llvmcall( + (_SIMD_GT_F64_IR, "entry"), + Int64, Tuple{Float64, Ptr{Float64}, Int64}, + x, ptr, len + ) +end +function _simd_first_ge(x::Float64, ptr::Ptr{Float64}, len::Int64) + return Base.llvmcall( + (_SIMD_GE_F64_IR, "entry"), + Int64, Tuple{Float64, Ptr{Float64}, Int64}, + x, ptr, len + ) +end diff --git a/src/strategies.jl b/src/strategies.jl new file mode 100644 index 0000000..e70263c --- /dev/null +++ b/src/strategies.jl @@ -0,0 +1,268 @@ +# Sorted-search strategy type hierarchy. All concrete strategies live here; +# their `Base.searchsortedfirst` / `Base.searchsortedlast` method definitions +# live in `dispatch.jl` and `auto.jl`. The `SearchProperties` cache type +# is defined here too because `Auto` carries one as a field; its populated +# constructor lives in `search_properties.jl`. + +""" + SearchStrategy + +Abstract supertype for sorted-search strategies. Concrete subtypes select how +[`searchsortedlast`](@ref Base.searchsortedlast) and +[`searchsortedfirst`](@ref Base.searchsortedfirst) should be performed when +called with a strategy as the first positional argument: + + - [`LinearScan`](@ref) walks ±1 from the hint. Cheapest when the target is + within a few positions of the hint; degrades linearly otherwise. + - [`SIMDLinearScan`](@ref) is `LinearScan` with the forward walk lowered to + 8-wide SIMD chunks for `DenseVector{Int64}` and `DenseVector{Float64}`. + Falls back to plain [`LinearScan`](@ref) for any other element type. + - [`BracketGallop`](@ref) expands an exponential bracket bidirectionally + from the hint, then binary-searches inside it. Effectively O(1) when the + target is near the hint; never worse than ~2 log₂ n comparisons. + - [`ExpFromLeft`](@ref) expands rightward from a left-bound hint by + doubling, then binary-searches inside the final bracket. Best for batched + sorted queries where each next query's hint is the previous result. + - [`InterpolationSearch`](@ref) guesses the answer by linearly extrapolating + between `v[lo]` and `v[hi]`, then refines with a bounded binary search. + O(1) per query on uniformly-spaced data; falls back to O(log n) on + irregular data. + - [`BinaryBracket`](@ref) is the standard `Base.searchsortedlast` / + `Base.searchsortedfirst` with no hint. Use it when no useful hint exists. + - [`BisectThenSIMD`](@ref) is an equality-search strategy: binary-bisects + `v` to a small basecase, then SIMD-scans for exact equality. Specialised + for `DenseVector{Int64}`; only meaningful when used with + [`findequal`](@ref). + - [`Auto`](@ref) heuristically picks one of the above based on the size of + `v`, the spacing of `v`, and whether a hint was supplied. Accepts an + optional [`SearchProperties`](@ref) cache to skip per-call probes. + +Strategies can also be passed to the batched +[`searchsortedlast!`](@ref) / [`searchsortedfirst!`](@ref) APIs. +""" +abstract type SearchStrategy end + +""" + LinearScan <: SearchStrategy + +Walk ±1 from the hint. Best when the target is within a few positions of the +hint. Falls back to [`BinaryBracket`](@ref) when no hint is supplied. +""" +struct LinearScan <: SearchStrategy end + +""" + SIMDLinearScan <: SearchStrategy + +Variant of [`LinearScan`](@ref) whose forward walk is lowered to 8-wide +SIMD chunks via custom LLVM IR. Specialized for `DenseVector{Int64}` and +`DenseVector{Float64}`; for any other element type, falls back to plain +[`LinearScan`](@ref). The backward walk (when the hint is past the +answer) uses the scalar `LinearScan` path regardless of element type. + +Wins on long forward walks (≥ 8 elements past the hint). For walks of +1–3 elements `LinearScan` is comparable — the SIMD chunk has constant +setup overhead. Worst case is O(n / 8) which is still linear, so +`SIMDLinearScan` is only `Auto`-relevant for small `n` or small-gap +batches where plain `LinearScan` would have been picked anyway. + +Caveats: + - Element type must be exactly `Int64` or `Float64`. `Int32`, + `UInt64`, `Float32`, and user-defined numeric types all fall back to + scalar. + - Sorted-Float64 vectors containing `NaN` produce undefined results, + same as for any positional search on a vector that isn't totally + ordered. + - Falls back to [`BinaryBracket`](@ref) when no hint is supplied. + - Falls back to [`LinearScan`](@ref) for non-`Forward` orderings. +""" +struct SIMDLinearScan <: SearchStrategy end + +""" + BracketGallop <: SearchStrategy + +Expand an exponential bracket bidirectionally from the hint, then +binary-search inside the bracket. Effectively O(1) when the target is near +the hint; never worse than ~2 log₂ n comparisons. + +Falls back to [`BinaryBracket`](@ref) when no hint is supplied. +""" +struct BracketGallop <: SearchStrategy end + +""" + ExpFromLeft <: SearchStrategy + +Exponential search forward from the hint (interpreted as a left bound), then +binary search in the final bracket. The hint is a *lower* bound rather than a +center guess, which is what batched sorted-search loops typically want: +`hint = previous_result`. + +Specifically: starting at `lo = hint`, check `v[lo], v[lo+1], ..., v[lo+4]` +linearly, then `v[lo+8], v[lo+16], …` exponentially, until `x` is bracketed, +then binary-search inside the bracket. + +Falls back to [`BinaryBracket`](@ref) when no hint is supplied. +""" +struct ExpFromLeft <: SearchStrategy end + +""" + InterpolationSearch <: SearchStrategy + +Guesses an index by linearly extrapolating `x` between `v[lo]` and `v[hi]`, +then refines with a bounded binary search. O(1) per query on uniformly-spaced +data (e.g. `collect(0:0.1:10)`); falls back to O(log n) otherwise. Requires +`x` to be subtractable with elements of `v` (i.e., a numeric ordering). + +Ignores any hint that is supplied — the guess is computed fresh from the +endpoints. Falls back to [`BinaryBracket`](@ref) for non-numeric element +types where subtraction isn't defined. +""" +struct InterpolationSearch <: SearchStrategy end + +""" + BitInterpolationSearch <: SearchStrategy + +Variant of [`InterpolationSearch`](@ref) that reinterprets `DenseVector{Float64}` +as `DenseVector{UInt64}` before computing the extrapolation guess. For +positive IEEE Float64 values, the bit pattern is monotonically increasing +with the float value and is approximately linear in array index when the +underlying data is *log-spaced* (geometric). On such data the bit-domain +guess is far better than the float-domain guess that `InterpolationSearch` +would compute — sometimes O(1) versus O(log n) refinement. + +After computing the bit-domain guess, the bracket and binary refine step +uses the original float values for comparison, so the answer is identical +to `Base.searchsortedlast` / `Base.searchsortedfirst`. + +Constraints: + - `DenseVector{Float64}` only (the IEEE bit-pattern trick is Float64-specific). + - Requires `v[1] > 0` and the query `x > 0` (negative, zero, subnormal, + and non-finite Float64 bit patterns are not monotonic with float value + under raw reinterpret). + - Forward ordering only. + +**This strategy is opt-in only** — `Auto` does not pick it. The bench sweep +shows the per-query division and UInt64↔Float64 conversion overhead +(~60–90 ns/q) costs more than the bracket refinement that the guess +saves at every gap tested; pinning `BitInterpolationSearch` is slower than +letting `Auto` pick `SIMDLinearScan` / `BracketGallop` / `ExpFromLeft`. +The strategy is retained for users with workloads not covered by the +sweep — for instance, very-large `n` (≥ 2²⁰), pathologically log-spaced +data, or hardware where Float64 division is unusually cheap relative to +the scalar walk. + +Falls back to [`InterpolationSearch`](@ref) for non-Float64 dense eltypes +(where the bit pattern equals the value and the two strategies are +equivalent), and to [`BinaryBracket`](@ref) for non-positive or +non-finite Float64 data. +""" +struct BitInterpolationSearch <: SearchStrategy end + +""" + BinaryBracket <: SearchStrategy + +Plain `Base.searchsortedlast` / `Base.searchsortedfirst`. Ignores any hint +that is supplied. +""" +struct BinaryBracket <: SearchStrategy end + +""" + BisectThenSIMD <: SearchStrategy + +Equality-search strategy. Binary-bisects `v` down to a small basecase, then +SIMD-scans the basecase for exact equality with `x`. Specialised for +`DenseVector{Int64}` + `Int64` queries via the same custom LLVM IR that +backs [`findfirstsortedequal`](@ref FindFirstFunctions.findfirstsortedequal); +for other element types, falls back to [`BinaryBracket`](@ref) plus an +equality check. + +This strategy is meant for use with [`findequal`](@ref FindFirstFunctions.findequal), +not with `searchsortedfirst` / `searchsortedlast` — its purpose is to answer +"is `x` present at exactly which index, or not at all?", which is a +different question from positional search. In the +`searchsortedfirst`/`searchsortedlast` dispatch it falls back to +[`BinaryBracket`](@ref). + +Ignores any hint that is supplied. Falls back to [`BinaryBracket`](@ref) for +non-`Forward` orderings. +""" +struct BisectThenSIMD <: SearchStrategy end + +""" + GuesserHint(guesser::Guesser) <: SearchStrategy + +Uses a [`Guesser`](@ref) to produce an integer guess for `x`, then dispatches +to [`BracketGallop`](@ref) from that guess. The `Guesser` already decides +between linear-extrapolation lookup (when `v` looks linear) and using the +previous result as a guess; this strategy plugs that logic into the strategy +dispatch hierarchy, and updates `guesser.idx_prev` on each call. + +Use this strategy with the per-query and batched APIs whenever you have a +`Guesser` attached to a vector. The cost is one `guesser(x)` evaluation +plus one `BracketGallop` call plus one `idx_prev[]` write per call. +""" +struct GuesserHint{G} <: SearchStrategy + guesser::G +end + +""" + SearchProperties + +Cached, non-allocating facts about a sorted vector. Pass to [`Auto`](@ref) +via `Auto(props)` to skip the per-call probes that the default `Auto()` runs +on every batched call. Stored fields are kept to plain `Bool`s so the struct +stays `isbits` and travels in registers. + +Default-constructed (`SearchProperties()`) is the "no information" sentinel: +`has_props` is `false`, the other fields are unspecified and ignored by +`Auto`. Construct via `SearchProperties(v::AbstractVector)` to populate the +fields by running the probes once. + +Currently consumed: `is_linear` and `has_nan` (the latter only on Float64, +to gate `SIMDLinearScan` eligibility in `Auto`). `is_log_linear` is +populated for callers that want to manually pin +[`BitInterpolationSearch`](@ref) based on data shape; `Auto` does not +consume it. The fields are otherwise populated for forward compatibility. +""" +struct SearchProperties + has_props::Bool + is_linear::Bool + has_nan::Bool + is_log_linear::Bool +end + +SearchProperties() = SearchProperties(false, false, false, false) + +""" + Auto <: SearchStrategy + Auto() + Auto(props::SearchProperties) + +Heuristically picks among [`LinearScan`](@ref), [`SIMDLinearScan`](@ref), +[`ExpFromLeft`](@ref), [`InterpolationSearch`](@ref), +[`BracketGallop`](@ref), and [`BinaryBracket`](@ref). The choice depends on +the calling context: + +**Per-query** (`searchsortedlast(Auto(), v, x[, hint])`): + - No hint, or hint outside `axes(v)` → [`BinaryBracket`](@ref). + - Hint in range, `length(v) ≤ 16` → [`LinearScan`](@ref). + - Hint in range, `length(v) > 16` → [`BracketGallop`](@ref). + +**Batched sorted** (`searchsortedlast!(out, v, queries; strategy = Auto())`) +chooses by the expected average gap in `v`'s index space between +consecutive query results. See the package's `auto.md` documentation for +the full decision tree and the crossover constants the bench sweep +determined. + +**Batched unsorted**: falls back to per-element `Base.searchsortedlast` / +`Base.searchsortedfirst` with no hint regardless of strategy. + +**Cached properties.** Passing a populated [`SearchProperties`](@ref) via +`Auto(props)` short-circuits the per-call probes. The cached path is +behaviour-equivalent to `Auto()` when `props` is up to date for `v`; the +caller is responsible for re-computing `props` if `v` mutates. +""" +struct Auto <: SearchStrategy + props::SearchProperties +end + +Auto() = Auto(SearchProperties())