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
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ repository.
### Basic Construction and Usage

```julia
using BandedMatrices, FastAlmostBandedMatrices, LinearAlgebra
using FastAlmostBandedMatrices, LinearAlgebra

m = 2 # Fill rank
n = 10 # Matrix dimension
Expand Down Expand Up @@ -58,7 +58,7 @@ Q, R = fact.Q, fact.R
<p>

```julia
using BandedMatrices, BenchmarkTools, FastAlmostBandedMatrices, SparseArrays, FillArrays, LinearAlgebra
using BenchmarkTools, FastAlmostBandedMatrices, SparseArrays, FillArrays, LinearAlgebra
import SemiseparableMatrices

m = 5
Expand Down Expand Up @@ -191,6 +191,19 @@ 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
```

## Some Considerations

1. Not all operations are meant to be fast. Currently only the following operations are
Expand Down
20 changes: 20 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,23 @@ almostbandedrank
```@docs
finish_part_setindex!
```

## Reexported from BandedMatrices.jl

The documented constructor is `AlmostBandedMatrix(bands::BandedMatrix, fill)`, 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.
2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Pkg.add("FastAlmostBandedMatrices")
## Basic Construction and Usage

```julia
using BandedMatrices, FastAlmostBandedMatrices, LinearAlgebra
using FastAlmostBandedMatrices, LinearAlgebra

m = 2 # Fill rank
n = 10 # Matrix dimension
Expand Down
44 changes: 27 additions & 17 deletions src/FastAlmostBandedMatrices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ import PrecompileTools: @setup_workload, @compile_workload

using ArrayInterface, ArrayLayouts, ConcreteStructs, LazyArrays, LinearAlgebra,
MatrixFactorizations
import BandedMatrices
using BandedMatrices: bandwidth, bandwidths

# The BandedMatrices.jl surface that FastAlmostBandedMatrices reexports (see the second
# `export` below), so that `using FastAlmostBandedMatrices` on its own is enough to build
# the `bands` argument of an `AlmostBandedMatrix`, populate it, and query its band
# structure. Everything stays owned and documented upstream in BandedMatrices.jl.
using BandedMatrices: Band, BandError, BandRange, BandedMatrix, band, bandrange, bandwidth,
bandwidths, brand, brandn, colrange, rowrange

import ArrayLayouts: MemoryLayout, sublayout, MatLdivVec, materialize!,
triangularlayout, triangulardata, colsupport,
Expand Down Expand Up @@ -95,7 +100,7 @@ abstract type AbstractAlmostBandedLayout <: MemoryLayout end
struct AlmostBandedLayout <: AbstractAlmostBandedLayout end

"""
AlmostBandedMatrix(bands::BandedMatrices.BandedMatrix, fill)
AlmostBandedMatrix(bands::BandedMatrix, fill)
AlmostBandedMatrix{T}(bands, fill)
AlmostBandedMatrix(::UndefInitializer, [::Type{T} = Float64], mn::NTuple{2, Integer},
lu::NTuple{2, Integer}, rank::Integer)
Expand Down Expand Up @@ -149,7 +154,7 @@ part.
# Example

```julia
bands = BandedMatrices.brand(Float64, 8, 8, 3, 2)
bands = brand(Float64, 8, 8, 3, 2)
fill = rand(2, 8)
A = AlmostBandedMatrix(bands, fill)
```
Expand All @@ -170,7 +175,7 @@ function AlmostBandedMatrix(
) where {T}
@assert lu[2] ≥ rank - 1
@assert rank ≥ 1 "Rank 0 fill array makes it a BandedMatrix."
bands = BandedMatrices.BandedMatrix{T}(undef, mn, lu)
bands = BandedMatrix{T}(undef, mn, lu)
fill = Matrix{T}(undef, rank, mn[2])
return AlmostBandedMatrix{T}(bands, fill)
end
Expand All @@ -190,7 +195,7 @@ function AlmostBandedMatrix(
return AlmostBandedMatrix(undef, Float64, mn, lu, rank)
end

function AlmostBandedMatrix(bands::BandedMatrices.BandedMatrix, fill::AbstractMatrix)
function AlmostBandedMatrix(bands::BandedMatrix, fill::AbstractMatrix)
@assert size(fill, 2) == size(bands, 2)
@assert size(fill, 1) ≥ 1 "Rank 0 fill array makes it a BandedMatrix."
T = promote_type(eltype(fill), eltype(bands))
Expand Down Expand Up @@ -228,7 +233,7 @@ not mutated.
# Example

```julia
A = AlmostBandedMatrix(BandedMatrices.brand(Float64, 8, 8, 3, 2), rand(2, 8))
A = AlmostBandedMatrix(brand(Float64, 8, 8, 3, 2), rand(2, 8))
fillpart(A)[1, 1] = 1
finish_part_setindex!(A)
```
Expand Down Expand Up @@ -262,7 +267,7 @@ Returns the mutable `BandedMatrix` stored by `A`; it is not a copy.

# Example
```julia
A = AlmostBandedMatrix(BandedMatrices.brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
A = AlmostBandedMatrix(brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
B = bandpart(A) # Returns the BandedMatrix component
```
"""
Expand All @@ -286,7 +291,7 @@ Returns the mutable fill matrix stored by `A`; it is not a copy. Call

# Example
```julia
A = AlmostBandedMatrix(BandedMatrices.brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
A = AlmostBandedMatrix(brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
F = fillpart(A) # Returns the fill matrix (2×10)
```
"""
Expand All @@ -309,7 +314,7 @@ Returns a view into `bandpart(A)`, not a copy.

# Example
```julia
A = AlmostBandedMatrix(BandedMatrices.brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
A = AlmostBandedMatrix(brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
E = exclusive_bandpart(A) # Returns a view of rows 3:10 of the banded part
```
"""
Expand All @@ -335,7 +340,7 @@ Returns `(l, u)`, where `l` is the lower bandwidth and `u` is the upper bandwidt

# Example
```julia
A = AlmostBandedMatrix(BandedMatrices.brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
A = AlmostBandedMatrix(brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
almostbandwidths(A) # Returns (3, 2)
```
"""
Expand All @@ -361,7 +366,7 @@ Returns the number of rows in `fillpart(A)`.

# Example
```julia
A = AlmostBandedMatrix(BandedMatrices.brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
A = AlmostBandedMatrix(brand(Float64, 10, 10, 3, 2), rand(Float64, 2, 10))
almostbandedrank(A) # Returns 2
```
"""
Expand Down Expand Up @@ -539,17 +544,15 @@ function _almostbanded_qr(_, A)
# Expand the bandsize for the QR factorization
## Bypass the safety checks in `AlmostBandedMatrix`
return almostbanded_qr!(
AlmostBandedMatrix{eltype(A)}(
BandedMatrices.BandedMatrix(copy(B), (l, l + u)), copy(L)
), Val(true)
AlmostBandedMatrix{eltype(A)}(BandedMatrix(copy(B), (l, l + u)), copy(L)), Val(true)
)
end

# Band size not yet expanded!
function almostbanded_qr!(R::AbstractMatrix{T}, ::Val{false}) where {T}
l, u = almostbandwidths(R)
B, L = bandpart(R), fillpart(R)
R′ = AlmostBandedMatrix{eltype(R)}(BandedMatrices.BandedMatrix(B, (l, l + u)), L)
R′ = AlmostBandedMatrix{eltype(R)}(BandedMatrix(B, (l, l + u)), L)
return almostbanded_qr!(R′, Val(true))
end

Expand Down Expand Up @@ -766,7 +769,7 @@ end
m = 2
n = 10
for T in (Float32, Float64)
B = BandedMatrices.brand(T, n, n, m + 1, m)
B = brand(T, n, n, m + 1, m)
F = rand(T, m, n)

@compile_workload begin
Expand All @@ -784,4 +787,11 @@ end
export AlmostBandedMatrix, bandpart, fillpart, exclusive_bandpart, finish_part_setindex!,
almostbandwidths, almostbandedrank

# Reexported BandedMatrices.jl names; approved via `reexports_allow` in test/qa/qa.jl.
# `AlmostBandedMatrix(bands::BandedMatrix, fill)` is the documented constructor and every
# documented example builds `bands` with `brand`, so these must keep coming along with
# `using FastAlmostBandedMatrices`.
export Band, BandError, BandRange, BandedMatrix, band, bandrange, bandwidth, bandwidths,
brand, brandn, colrange, rowrange

end
54 changes: 37 additions & 17 deletions test/core_tests.jl
Original file line number Diff line number Diff line change
@@ -1,25 +1,45 @@
using SafeTestsets

@safetestset "Documented construction API" begin
using BandedMatrices, FastAlmostBandedMatrices

exported = Set(names(FastAlmostBandedMatrices; all = false))
@test :brand ∉ exported
@test all(name ∉ exported for name in (:Band, :BandedMatrix, :Fill, :band, :bandwidth, :brandn))

@safetestset "Reexported BandedMatrices API" begin
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.
reexports = (
:Band, :BandError, :BandRange, :BandedMatrix, :band, :bandrange, :bandwidth,
:bandwidths, :brand, :brandn, :colrange, :rowrange,
)

exported = Set(names(FastAlmostBandedMatrices))
for name in reexports
# Exported, in scope from a bare `using FastAlmostBandedMatrices`, and still the
# upstream binding rather than a copy.
@test name in exported
@test isdefined(@__MODULE__, name)
@test getfield(FastAlmostBandedMatrices, name) === getfield(BandedMatrices, name)
end

# Whole dependencies are not reexported: BandedMatrices' own reexports (FillArrays)
# and unrelated names stay out.
for name in (:Fill, :Ones, :Zeros, :Eye, :symrcm, :BandedMatrices)
@test name ∉ exported
end

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

@test A isa AlmostBandedMatrix
@test bandpart(A) isa BandedMatrices.BandedMatrix
@test B isa AlmostBandedMatrix
@test bandpart(A) isa BandedMatrix
@test bandwidths(bandpart(A)) == (3, 2)
@test almostbandwidths(A) == (3, 2)
@test almostbandedrank(A) == 2
@test B isa AlmostBandedMatrix
end

@safetestset "Constructors" begin
using BandedMatrices, FastAlmostBandedMatrices
using FastAlmostBandedMatrices

A = AlmostBandedMatrix{Float64}(undef, (10, 11), (2, 1), 2)
A[1, 1] = 2
Expand All @@ -35,7 +55,7 @@ end
end

@safetestset "similar" begin
using BandedMatrices, FastAlmostBandedMatrices
using FastAlmostBandedMatrices

A = AlmostBandedMatrix(brand(Float64, 10, 10, 2, 1), rand(Float64, 2, 10))

Expand All @@ -48,7 +68,7 @@ end
end

@safetestset "Copy" begin
using BandedMatrices, FastAlmostBandedMatrices
using FastAlmostBandedMatrices

n = 5
m = 2
Expand All @@ -66,7 +86,7 @@ end
end

@safetestset "QR" begin
using BandedMatrices, LinearAlgebra, FastAlmostBandedMatrices
using LinearAlgebra, FastAlmostBandedMatrices
import MatrixFactorizations: QRPackedQ

n = 80
Expand Down Expand Up @@ -94,7 +114,7 @@ end
end

@safetestset "Triangular" begin
using BandedMatrices, LinearAlgebra, ArrayLayouts, FastAlmostBandedMatrices
using LinearAlgebra, ArrayLayouts, FastAlmostBandedMatrices
import FastAlmostBandedMatrices: AlmostBandedLayout

n = 80
Expand All @@ -110,7 +130,7 @@ end

# https://github.com/SciML/FastAlmostBandedMatrices.jl/issues/19
@safetestset "fill! on sparse array with BigFloat" begin
using BandedMatrices, FastAlmostBandedMatrices, SparseArrays
using FastAlmostBandedMatrices, SparseArrays

A = sparse([1, 2], [1, 5], big.([1.0, 1.0]))
A1 = AlmostBandedMatrix(brand(BigFloat, 5, 5, 1, 1), A)
Expand Down
1 change: 0 additions & 1 deletion test/qa/alloc_tests.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using AllocCheck
using BandedMatrices
using FastAlmostBandedMatrices
using FastAlmostBandedMatrices: DisjointRange
using ArrayLayouts: colsupport, rowsupport
Expand Down
17 changes: 15 additions & 2 deletions test/qa/qa.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
using SciMLTesting, FastAlmostBandedMatrices

# The BandedMatrices.jl names FastAlmostBandedMatrices intentionally reexports, because they
# are needed for its own documented use: `AlmostBandedMatrix(bands::BandedMatrix, fill)` is
# the documented constructor and the documented examples build `bands` with `brand`.
# Kept in sync with the reexport `export` block in src/FastAlmostBandedMatrices.jl.
const REEXPORTED_API = (
:Band, :BandError, :BandRange, :BandedMatrix,
:band, :bandrange, :bandwidth, :bandwidths, :brand, :brandn, :colrange, :rowrange,
)

run_qa(
FastAlmostBandedMatrices;
reexports_allow = REEXPORTED_API,
# `Band` and `BandError` are reexported but carry no docstring upstream in
# BandedMatrices.jl, so the public-API docstring check has nothing to find for them.
api_docs_kwargs = (; ignore = (:Band, :BandError)),
# 19 method ambiguities, all in FastAlmostBandedMatrices' own ldiv!/__arguments
# against ArrayLayouts/LinearAlgebra Triangular/Factorization methods.
# https://github.com/SciML/FastAlmostBandedMatrices.jl/issues/71
Expand Down Expand Up @@ -30,8 +43,8 @@ run_qa(
),
),
# 31 names implicitly imported via the package's `using ArrayInterface, ArrayLayouts,
# BandedMatrices, ConcreteStructs, LazyArrays, LinearAlgebra, ...`; explicit-import
# conversion tracked separately.
# ConcreteStructs, LazyArrays, LinearAlgebra, ...`; explicit-import conversion tracked
# separately.
# https://github.com/SciML/FastAlmostBandedMatrices.jl/issues/71
ei_broken = (:no_implicit_imports,),
)
Loading