diff --git a/docs/src/strategies.md b/docs/src/strategies.md index d3a9f3a..d2d0924 100644 --- a/docs/src/strategies.md +++ b/docs/src/strategies.md @@ -49,6 +49,18 @@ FindFirstFunctions.strategy_kind | `KIND_UNIFORM_STEP` | `UniformStep` | `_kernel_last_uniform_step` / `_kernel_first_uniform_step` | | `KIND_BISECT_THEN_SIMD` | `BisectThenSIMD` | (positional dispatch falls back to BinaryBracket; equality dispatch goes through `findfirstsortedequal`) | +```@docs +FindFirstFunctions.KIND_BINARY_BRACKET +FindFirstFunctions.KIND_LINEAR_SCAN +FindFirstFunctions.KIND_SIMD_LINEAR_SCAN +FindFirstFunctions.KIND_BRACKET_GALLOP +FindFirstFunctions.KIND_EXP_FROM_LEFT +FindFirstFunctions.KIND_INTERPOLATION_SEARCH +FindFirstFunctions.KIND_BIT_INTERPOLATION_SEARCH +FindFirstFunctions.KIND_UNIFORM_STEP +FindFirstFunctions.KIND_BISECT_THEN_SIMD +``` + Stateful strategies that do **not** have an enum tag and stay on the multimethod path: diff --git a/src/kinds.jl b/src/kinds.jl index 55a9753..d9442df 100644 --- a/src/kinds.jl +++ b/src/kinds.jl @@ -49,6 +49,78 @@ that carries it. KIND_BISECT_THEN_SIMD end +# Julia 1.10's `@enum` does not accept inline docstrings for individual +# values, so keep per-kind docs immediately next to the enum definition. +@doc """ + KIND_BINARY_BRACKET::StrategyKind + +Select [`BinaryBracket`](@ref FindFirstFunctions.BinaryBracket), the plain +binary-search fallback for positional sorted searches. +""" KIND_BINARY_BRACKET + +@doc """ + KIND_LINEAR_SCAN::StrategyKind + +Select [`LinearScan`](@ref FindFirstFunctions.LinearScan), the hinted +strategy that walks linearly from a nearby index. +""" KIND_LINEAR_SCAN + +@doc """ + KIND_SIMD_LINEAR_SCAN::StrategyKind + +Select [`SIMDLinearScan`](@ref FindFirstFunctions.SIMDLinearScan), the +hinted linear scan with SIMD-specialized forward walks for supported dense +vectors. +""" KIND_SIMD_LINEAR_SCAN + +@doc """ + KIND_BRACKET_GALLOP::StrategyKind + +Select [`BracketGallop`](@ref FindFirstFunctions.BracketGallop), the hinted +strategy that expands a bidirectional exponential bracket before binary +searching inside it. +""" KIND_BRACKET_GALLOP + +@doc """ + KIND_EXP_FROM_LEFT::StrategyKind + +Select [`ExpFromLeft`](@ref FindFirstFunctions.ExpFromLeft), the hinted +strategy that treats the hint as a left bound and searches forward +exponentially. +""" KIND_EXP_FROM_LEFT + +@doc """ + KIND_INTERPOLATION_SEARCH::StrategyKind + +Select [`InterpolationSearch`](@ref FindFirstFunctions.InterpolationSearch), +the strategy that guesses from linear extrapolation across the vector +endpoints. +""" KIND_INTERPOLATION_SEARCH + +@doc """ + KIND_BIT_INTERPOLATION_SEARCH::StrategyKind + +Select +[`BitInterpolationSearch`](@ref FindFirstFunctions.BitInterpolationSearch), +the opt-in interpolation strategy that guesses from Float64 bit patterns. +""" KIND_BIT_INTERPOLATION_SEARCH + +@doc """ + KIND_UNIFORM_STEP::StrategyKind + +Select [`UniformStep`](@ref FindFirstFunctions.UniformStep), the direct +arithmetic lookup strategy for uniformly-spaced vectors and ranges. +""" KIND_UNIFORM_STEP + +@doc """ + KIND_BISECT_THEN_SIMD::StrategyKind + +Select [`BisectThenSIMD`](@ref FindFirstFunctions.BisectThenSIMD), the +sorted-equality strategy used by [`findequal`](@ref FindFirstFunctions.findequal). +The positional sorted-search dispatch falls back to +[`BinaryBracket`](@ref FindFirstFunctions.BinaryBracket). +""" KIND_BISECT_THEN_SIMD + """ searchsorted_last(kind::StrategyKind, v, x[, hint]; order = Base.Order.Forward) searchsorted_last(s, v, x[, hint]; order = Base.Order.Forward) diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 3e47319..4fd4159 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -20,3 +20,36 @@ run_qa( ), ), ) + +@testset "Public API documentation coverage" begin + public_names = setdiff( + Set(names(FindFirstFunctions; all = false, imported = false)), + Set((nameof(FindFirstFunctions),)), + ) + + documented_names = Set{Symbol}() + for binding in keys(Base.Docs.meta(FindFirstFunctions)) + binding.mod === FindFirstFunctions && push!(documented_names, binding.var) + end + + docs_names = Set{Symbol}() + docs_dir = joinpath(pkgdir(FindFirstFunctions), "docs", "src") + for file in readdir(docs_dir; join = true) + endswith(file, ".md") || continue + in_docs_block = false + for line in eachline(file) + stripped = strip(line) + if startswith(stripped, "```@docs") + in_docs_block = true + elseif in_docs_block && startswith(stripped, "```") + in_docs_block = false + elseif in_docs_block + m = match(r"^FindFirstFunctions\.([A-Za-z_][A-Za-z_0-9!]*$)", stripped) + m === nothing || push!(docs_names, Symbol(m.captures[1])) + end + end + end + + @test isempty(setdiff(public_names, documented_names)) + @test isempty(setdiff(public_names, docs_names)) +end