Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,18 +191,26 @@ almostbandedrank
finish_part_setindex!
```

Because the documented constructor is `AlmostBandedMatrix(bands::BandedMatrix, fill)`,
`using FastAlmostBandedMatrices` also brings along the
[BandedMatrices.jl](https://github.com/JuliaLinearAlgebra/BandedMatrices.jl) names needed to
build, populate and query that `bands` argument. They remain owned and documented by
BandedMatrices.jl:

```
BandedMatrix brand brandn
Band BandRange band bandrange
bandwidth bandwidths colrange rowrange
BandError
```
### Reexported from BandedMatrices.jl

`AlmostBandedMatrix(bands::BandedMatrix, fill)` is the documented constructor and the
examples above build `bands` with `brand`, so `using FastAlmostBandedMatrices` also brings
in the [BandedMatrices.jl](https://juliaLinearAlgebra.github.io/BandedMatrices.jl/stable/)
names needed to build that banded argument, populate it and query it:

- Building the bands: `BandedMatrix`, `brand`, `brandn`
- Populating them: `Band`, `BandRange`, `band`, `bandrange`
- Querying them: `bandwidth`, `bandwidths`, `colrange`, `rowrange`
- Errors: `BandError`

These names are owned and documented by
[BandedMatrices.jl](https://juliaLinearAlgebra.github.io/BandedMatrices.jl/stable/);
FastAlmostBandedMatrices.jl only re-exports them and does not document them. Anything else
from BandedMatrices.jl must be imported from BandedMatrices.jl directly. In particular,
the FillArrays.jl names it reexports in turn (`Fill`, `Ones`, `Zeros`, `Eye`), the
`BandedMatrices` module binding itself, and `symrcm` are deliberately not passed along.
See the [API page](https://docs.sciml.ai/FastAlmostBandedMatrices/stable/api/) for the
details.

## Some Considerations

Expand Down
52 changes: 36 additions & 16 deletions docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,40 @@ finish_part_setindex!

## Reexported from BandedMatrices.jl

The documented constructor is `AlmostBandedMatrix(bands::BandedMatrix, fill)`, and the
`AlmostBandedMatrix(bands::BandedMatrix, fill)` is the documented constructor, and the
examples on the home page build `bands` with `brand`. So `using FastAlmostBandedMatrices`
also brings the
[BandedMatrices.jl](https://github.com/JuliaLinearAlgebra/BandedMatrices.jl) names needed to
construct, populate and query that banded argument:

| Purpose | Names |
|:--------|:------|
| Construction | `BandedMatrix`, `brand`, `brandn` |
| Band indexing | `Band`, `BandRange`, `band`, `bandrange` |
| Structure queries | `bandwidth`, `bandwidths`, `colrange`, `rowrange` |
| Errors | `BandError` |

These names are owned and documented by BandedMatrices.jl; see its documentation for their
full behaviour. Nothing else from BandedMatrices.jl is reexported, and neither are the
names it reexports from its own dependencies (for example the FillArrays.jl names `Fill`,
`Ones`, `Zeros` and `Eye`). Use `using BandedMatrices` or `using FillArrays` for those.
also brings in the [BandedMatrices.jl](https://juliaLinearAlgebra.github.io/BandedMatrices.jl/stable/)
names needed to build that banded argument, populate it and query it, so they do not have
to be imported separately:

- Building the bands: `BandedMatrix`, `brand`, `brandn`
- Populating them: `Band`, `BandRange`, `band`, `bandrange`
- Querying them: `bandwidth`, `bandwidths`, `colrange`, `rowrange`
- Errors: `BandError`

These names are owned and documented by
[BandedMatrices.jl](https://juliaLinearAlgebra.github.io/BandedMatrices.jl/stable/).
FastAlmostBandedMatrices.jl only re-exports them; it does not document them and does not
define their behaviour, so BandedMatrices.jl's own documentation is the reference for what
each one does.

Anything else from BandedMatrices.jl must be imported from BandedMatrices.jl directly.
In particular, the following are deliberately **not** reexported:

- The [FillArrays.jl](https://juliaarrays.github.io/FillArrays.jl/stable/) names
`Fill`, `Ones`, `Zeros` and `Eye`. BandedMatrices.jl reexports those from a
dependency of its own, so passing them along here would be reexporting a whole
dependency chain; none of them is needed to build an `AlmostBandedMatrix`. Use
`using FillArrays`.
- The `BandedMatrices` module binding itself. Use `import BandedMatrices` if you want
the qualified form.
- `symrcm`, a sparse-matrix reordering unrelated to this package.

`Band` and `BandError` have no docstring upstream in BandedMatrices.jl, so they are listed
in the `api_docs_kwargs` ignore list in `test/qa/qa.jl` rather than documented here; that
docstring is owed by BandedMatrices.jl. Every other reexported name above carries its own
upstream docstring, reachable from the REPL help mode.

The list above is kept in sync with the reexport `export` block in
`src/FastAlmostBandedMatrices.jl` and with `REEXPORTED_API` in `test/qa/qa.jl`, and the
Core test suite asserts that all three agree.
70 changes: 68 additions & 2 deletions test/core_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ using SafeTestsets
using FastAlmostBandedMatrices
import BandedMatrices

# Kept in sync with the reexport `export` block in src/FastAlmostBandedMatrices.jl and
# with `REEXPORTED_API` in test/qa/qa.jl.
# Kept in sync with the reexport `export` block in src/FastAlmostBandedMatrices.jl,
# `REEXPORTED_API` in test/qa/qa.jl, and the reexport section of docs/src/api.md.
reexports = (
:Band, :BandError, :BandRange, :BandedMatrix, :band, :bandrange, :bandwidth,
:bandwidths, :brand, :brandn, :colrange, :rowrange,
Expand All @@ -26,6 +26,72 @@ using SafeTestsets
@test name ∉ exported
end

# The same list lives in three places: the `export` block in src (checked above via
# `names`), `REEXPORTED_API` in test/qa/qa.jl, and the "Reexported from
# BandedMatrices.jl" section of docs/src/api.md. They must not drift apart.
#
# Both files are read line-wise after normalising the line endings: git checks these
# files out with CRLF on Windows, so nothing here may assume "\n".
readlines_lf(path) = split(replace(read(path, String), "\r\n" => "\n", "\r" => "\n"), '\n')

qa_file = joinpath(@__DIR__, "qa", "qa.jl")
if isfile(qa_file)
qa_source = join(readlines_lf(qa_file), '\n')
block = match(r"REEXPORTED_API = \((.*?)\)"s, qa_source)
block === nothing &&
@error "reexport sync: no `REEXPORTED_API = (...)` found" file = qa_file
@test block !== nothing
if block !== nothing
declared = Set(Symbol(m[1]) for m in eachmatch(r":(\w+)", block[1]))
declared == Set(reexports) || @error(
"reexport sync: REEXPORTED_API disagrees with the exports",
file = qa_file, only_in_file = setdiff(declared, Set(reexports)),
only_in_exports = setdiff(Set(reexports), declared)
)
@test declared == Set(reexports)
end
end

docs_file = joinpath(@__DIR__, "..", "docs", "src", "api.md")
if isfile(docs_file)
heading = "## Reexported from BandedMatrices.jl"
lines = readlines_lf(docs_file)
# Structural, not prose-anchored: the section runs from its heading to the next
# `## ` heading (or the end of the file).
is_bullet(line) = startswith(line, " - ")
start = findfirst(line -> rstrip(line) == heading, lines)
start === nothing &&
@error "reexport sync: heading not found in docs" file = docs_file heading
@test start !== nothing
if start !== nothing
stop = findnext(line -> startswith(line, "## "), lines, start + 1)
section = lines[start:(stop === nothing ? lastindex(lines) : stop - 1)]
# Only the first contiguous run of bullets under the heading is the list of
# reexported names (" - Building the bands: `BandedMatrix`, ..."); the later
# bullet list in the same section is the deliberate *exclusions*.
bullets = String[]
idx = findfirst(is_bullet, section)
while idx !== nothing && idx <= lastindex(section) && is_bullet(section[idx])
push!(bullets, String(section[idx]))
idx += 1
end
isempty(bullets) && @error(
"reexport sync: no ` - ` role bullets under the heading",
file = docs_file, heading
)
@test !isempty(bullets)
documented = Set(
Symbol(m[1]) for line in bullets for m in eachmatch(r"`(\w+)`", line)
)
documented == Set(reexports) || @error(
"reexport sync: the docs section disagrees with the exports",
file = docs_file, only_in_docs = setdiff(documented, Set(reexports)),
only_in_exports = setdiff(Set(reexports), documented)
)
@test documented == Set(reexports)
end
end

# The documented construction path works with `using FastAlmostBandedMatrices` alone.
A = AlmostBandedMatrix(brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
B = AlmostBandedMatrix(BandedMatrix(fill(1.0, 10, 10), (3, 2)), rand(Float64, 2, 10))
Expand Down
Loading