Skip to content

Commit b975b7c

Browse files
authored
Derivative calls diff (#153)
* Derivative -> diff overloads * tests pass, diff(T) === diff(T; dims=1) * Move more diff * Introduce gram matrix * diff defaults * mapped diff should pull out coeffiicients * Update bases.jl * Update test_chebyshev.jl * Increase coverage * Update test_chebyshev.jl * mapped gram matrix * Update test_chebyshev.jl * AdjointMappedBasisLayouts
1 parent 449a39d commit b975b7c

File tree

9 files changed

+138
-129
lines changed

9 files changed

+138
-129
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ContinuumArrays"
22
uuid = "7ae1f121-cc2c-504b-ac30-9b923412ae5c"
3-
version = "0.13"
3+
version = "0.14"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
@@ -30,7 +30,7 @@ InfiniteArrays = "0.12"
3030
Infinities = "0.1"
3131
IntervalSets = "0.7"
3232
LazyArrays = "1.0"
33-
QuasiArrays = "0.10"
33+
QuasiArrays = "0.11"
3434
RecipesBase = "1.0"
3535
StaticArrays = "1.0"
3636
julia = "1.9"

src/ContinuumArrays.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import QuasiArrays: cardinality, checkindex, QuasiAdjoint, QuasiTranspose, Inclu
1818
QuasiDiagonal, MulQuasiArray, MulQuasiMatrix, MulQuasiVector, QuasiMatMulMat, QuasiArrayLayout,
1919
ApplyQuasiArray, ApplyQuasiMatrix, LazyQuasiArrayApplyStyle, AbstractQuasiArrayApplyStyle, AbstractQuasiLazyLayout,
2020
LazyQuasiArray, LazyQuasiVector, LazyQuasiMatrix, LazyLayout, LazyQuasiArrayStyle, _factorize, _cutdim,
21-
AbstractQuasiFill, UnionDomain, sum_size, sum_layout, _cumsum, cumsum_layout, applylayout, _equals, layout_broadcasted, PolynomialLayout, _dot
21+
AbstractQuasiFill, UnionDomain, sum_size, sum_layout, _cumsum, cumsum_layout, applylayout, _equals, layout_broadcasted, PolynomialLayout, dot_size,
22+
diff_layout, diff_size
2223
import InfiniteArrays: Infinity, InfAxes
2324
import AbstractFFTs: Plan
2425

@@ -104,7 +105,8 @@ include("plotting.jl")
104105
###
105106

106107
sum_size(::Tuple{InfiniteCardinal{1}}, a, dims) = _sum(expand(a), dims)
107-
_dot(::InfiniteCardinal{1}, a, b) = dot(expand(a), expand(b))
108+
dot_size(::InfiniteCardinal{1}, a, b) = dot(expand(a), expand(b))
109+
diff_size(::Tuple{InfiniteCardinal{1}}, a, dims) = diff(expand(a); dims=dims)
108110
function copy(d::Dot{<:ExpansionLayout,<:ExpansionLayout,<:AbstractQuasiArray,<:AbstractQuasiArray})
109111
a,b = d.A,d.B
110112
P,c = basis(a),coefficients(a)

src/bases/bases.jl

Lines changed: 72 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ abstract type Basis{T} <: LazyQuasiMatrix{T} end
22
abstract type Weight{T} <: LazyQuasiVector{T} end
33

44

5-
struct WeightLayout <: AbstractQuasiLazyLayout end
5+
abstract type AbstractWeightLayout <: AbstractQuasiLazyLayout end
6+
struct WeightLayout <: AbstractWeightLayout end
7+
struct MappedWeightLayout <: AbstractWeightLayout end
68
abstract type AbstractBasisLayout <: AbstractQuasiLazyLayout end
79
abstract type AbstractWeightedBasisLayout <: AbstractBasisLayout end
810
struct BasisLayout <: AbstractBasisLayout end
@@ -12,22 +14,22 @@ struct WeightedBasisLayout{Basis} <: AbstractWeightedBasisLayout end
1214
const SubWeightedBasisLayout = WeightedBasisLayout{SubBasisLayout}
1315
const MappedWeightedBasisLayout = WeightedBasisLayout{MappedBasisLayout}
1416

17+
struct AdjointBasisLayout{Basis} <: AbstractQuasiLazyLayout end
18+
const AdjointSubBasisLayout = AdjointBasisLayout{SubBasisLayout}
19+
1520
SubBasisLayouts = Union{SubBasisLayout,SubWeightedBasisLayout}
1621
WeightedBasisLayouts = Union{WeightedBasisLayout,SubWeightedBasisLayout,MappedWeightedBasisLayout}
1722
MappedBasisLayouts = Union{MappedBasisLayout,MappedWeightedBasisLayout}
18-
19-
struct AdjointBasisLayout{Basis} <: AbstractQuasiLazyLayout end
20-
const AdjointSubBasisLayout = AdjointBasisLayout{SubBasisLayout}
21-
const AdjointMappedBasisLayout = AdjointBasisLayout{MappedBasisLayout}
23+
AdjointMappedBasisLayouts = AdjointBasisLayout{<:MappedBasisLayouts}
2224

2325
MemoryLayout(::Type{<:Basis}) = BasisLayout()
2426
MemoryLayout(::Type{<:Weight}) = WeightLayout()
2527

2628
adjointlayout(::Type, ::Basis) where Basis<:AbstractBasisLayout = AdjointBasisLayout{Basis}()
27-
broadcastlayout(::Type{typeof(*)}, ::WeightLayout, ::Basis) where Basis<:AbstractBasisLayout = WeightedBasisLayout{Basis}()
29+
broadcastlayout(::Type{typeof(*)}, ::AbstractWeightLayout, ::Basis) where Basis<:AbstractBasisLayout = WeightedBasisLayout{Basis}()
2830

29-
# A sub of a weight is still a weight
30-
sublayout(::WeightLayout, _) = WeightLayout()
31+
sublayout(::AbstractWeightLayout, _) = WeightLayout()
32+
sublayout(::AbstractWeightLayout, ::Type{<:Tuple{Map}}) = MappedWeightLayout()
3133
sublayout(::AbstractBasisLayout, ::Type{<:Tuple{Map,AbstractVector}}) = MappedBasisLayout()
3234

3335
# copy with an Inclusion can not be materialized
@@ -39,6 +41,7 @@ unweighted(P::BroadcastQuasiMatrix{<:Any,typeof(*),<:Tuple{AbstractQuasiVector,A
3941
unweighted(V::SubQuasiArray) = view(unweighted(parent(V)), parentindices(V)...)
4042
weight(P::BroadcastQuasiMatrix{<:Any,typeof(*),<:Tuple{AbstractQuasiVector,AbstractQuasiMatrix}}) = first(P.args)
4143
weight(V::SubQuasiArray) = weight(parent(V))[parentindices(V)[1]]
44+
weight(V::SubQuasiArray{<:Any,2,<:Any, <:Tuple{Inclusion,Any}}) = weight(parent(V))
4245

4346
unweighted(a::AbstractQuasiArray) = unweighted(MemoryLayout(a), a)
4447
# Default is lazy
@@ -109,7 +112,7 @@ copy(L::Ldiv{<:MappedBasisLayouts,ApplyLayout{typeof(*)},<:Any,<:AbstractQuasiVe
109112
end
110113

111114
# default to transform for expanding weights
112-
copy(L::Ldiv{<:AbstractBasisLayout,WeightLayout}) = transform_ldiv(L.A, L.B)
115+
copy(L::Ldiv{<:AbstractBasisLayout,<:AbstractWeightLayout}) = transform_ldiv(L.A, L.B)
113116

114117
# multiplication operators, reexpand in basis A
115118
@inline function _broadcast_mul_ldiv(::Tuple{Any,AbstractBasisLayout}, A, B)
@@ -341,6 +344,8 @@ gives a basis for expanding given quasi-vector.
341344
basis(v) = basis_layout(MemoryLayout(v), v)
342345

343346
basis_layout(::ExpansionLayout, v::ApplyQuasiArray{<:Any,N,typeof(*)}) where N = v.args[1]
347+
basis_layout(lay::ApplyLayout{typeof(*)}, v) = basis(first(arguments(lay, v)))
348+
basis_layout(lay::AbstractBasisLayout, v) = v
344349
basis_layout(lay, v) = basis_axes(axes(v,1), v) # allow choosing a basis based on axes
345350
basis_axes(ax, v) = error("Overload for $ax")
346351

@@ -499,43 +504,6 @@ end
499504
# \int_a^b f(y) g(y) dy = \int_{-1}^1 f(p(x))*g(p(x)) * p'(x) dx
500505

501506

502-
_sub_getindex(A, kr, jr) = A[kr, jr]
503-
_sub_getindex(A, ::Slice, ::Slice) = A
504-
505-
@simplify function *(Ac::QuasiAdjoint{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}}},
506-
B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}})
507-
A = Ac'
508-
PA,PB = parent(A),parent(B)
509-
kr,jr = parentindices(B)
510-
_sub_getindex((PA'PB)/kr.A,parentindices(A)[2],jr)
511-
end
512-
513-
514-
# Differentiation of sub-arrays
515-
516-
# avoid stack overflow from unmaterialize Derivative() * parent()
517-
_der_sub(DP, inds...) = DP[inds...]
518-
_der_sub(DP::ApplyQuasiMatrix{T,typeof(*),<:Tuple{Derivative,Any}}, kr, jr) where T = ApplyQuasiMatrix{T}(*, DP.args[1], view(DP.args[2], kr, jr))
519-
520-
# need to customise simplifiable so can't use @simplify
521-
simplifiable(::typeof(*), A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:Inclusion,<:Any}})= simplifiable(*, Derivative(axes(parent(B),1)), parent(B))
522-
simplifiable(::typeof(*), Ac::QuasiAdjoint{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:Inclusion,<:Any}}}, Bc::QuasiAdjoint{<:Any,<:Derivative}) = simplifiable(*, Bc', Ac')
523-
function mul(A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:Inclusion,<:Any}})
524-
axes(A,2) == axes(B,1) || throw(DimensionMismatch())
525-
P = parent(B)
526-
_der_sub(Derivative(axes(P,1))*P, parentindices(B)...)
527-
end
528-
mul(Ac::QuasiAdjoint{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:Inclusion,<:Any}}}, Bc::QuasiAdjoint{<:Any,<:Derivative}) = mul(Bc', Ac')'
529-
530-
simplifiable(::typeof(*), A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}}) = simplifiable(*, Derivative(axes(parent(B),1)), parent(B))
531-
simplifiable(::typeof(*), Ac::QuasiAdjoint{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}}}, Bc::QuasiAdjoint{<:Any,<:Derivative}) = simplifiable(*, Bc', Ac')
532-
function mul(A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}})
533-
axes(A,2) == axes(B,1) || throw(DimensionMismatch())
534-
P = parent(B)
535-
kr,jr = parentindices(B)
536-
(Derivative(axes(P,1))*P*kr.A)[kr,jr]
537-
end
538-
mul(Ac::QuasiAdjoint{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}}}, Bc::QuasiAdjoint{<:Any,<:Derivative}) = mul(Bc', Ac')'
539507

540508
# we represent as a Mul with a banded matrix
541509
sublayout(::AbstractBasisLayout, ::Type{<:Tuple{<:Inclusion,<:AbstractVector}}) = SubBasisLayout()
@@ -600,7 +568,7 @@ end
600568
# sum
601569
####
602570
function sum_layout(::SubBasisLayout, Vm, dims)
603-
@assert dims == 1
571+
dims == 1 || error("not implemented")
604572
sum(parent(Vm); dims=dims)[:,parentindices(Vm)[2]]
605573
end
606574

@@ -616,6 +584,63 @@ end
616584
sum_layout(::ExpansionLayout, A, dims) = sum_layout(ApplyLayout{typeof(*)}(), A, dims)
617585
cumsum_layout(::ExpansionLayout, A, dims) = cumsum_layout(ApplyLayout{typeof(*)}(), A, dims)
618586

587+
###
588+
# diff
589+
###
590+
591+
function diff_layout(::SubBasisLayout, Vm, dims::Integer)
592+
dims == 1 || error("not implemented")
593+
diff(parent(Vm); dims=dims)[:,parentindices(Vm)[2]]
594+
end
595+
596+
function diff_layout(::WeightedBasisLayout{<:SubBasisLayout}, Vm, dims::Integer)
597+
dims == 1 || error("not implemented")
598+
w = weight(Vm)
599+
V = unweighted(Vm)
600+
view(diff(w .* parent(V)), parentindices(V)...)
601+
end
602+
603+
function diff_layout(::MappedBasisLayouts, V, dims)
604+
kr = basismap(V)
605+
@assert kr isa AbstractAffineQuasiVector
606+
D = diff(demap(V); dims=dims)
607+
view(basis(D), kr, :) * (kr.A*coefficients(D))
608+
end
609+
610+
diff_layout(::ExpansionLayout, A, dims...) = diff_layout(ApplyLayout{typeof(*)}(), A, dims...)
611+
612+
613+
####
614+
# Gram matrix
615+
####
616+
617+
simplifiable(::Mul{<:AdjointBasisLayout, <:AbstractBasisLayout}) = Val(true)
618+
function copy(M::Mul{<:AdjointBasisLayout, <:AbstractBasisLayout})
619+
A = (M.A)'
620+
A == M.B && return grammatrix(A)
621+
error("Not implemented")
622+
end
623+
624+
grammatrix(A) = grammatrix_layout(MemoryLayout(A), A)
625+
grammatrix_layout(_, A) = error("Not implemented")
626+
627+
function grammatrix_layout(::MappedBasisLayouts, P)
628+
Q = demap(P)
629+
kr = basismap(P)
630+
@assert kr isa AbstractAffineQuasiVector
631+
grammatrix(Q)/kr.A
632+
end
633+
634+
function copy(M::Mul{<:AdjointMappedBasisLayouts, <:MappedBasisLayouts})
635+
A = M.A'
636+
kr = basismap(A)
637+
@assert kr isa AbstractAffineQuasiVector
638+
@assert kr == basismap(M.B)
639+
demap(A)'demap(M.B) / kr.A
640+
end
641+
642+
643+
619644
include("basisconcat.jl")
620645
include("basiskron.jl")
621646
include("splines.jl")

src/bases/basisconcat.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ abstract type AbstractConcatBasis{T} <: Basis{T} end
88

99
copy(S::AbstractConcatBasis) = S
1010

11-
@simplify function *(D::Derivative, S::AbstractConcatBasis)
12-
axes(D,2) == axes(S,1) || throw(DimensionMismatch())
13-
args = arguments.(Ref(ApplyLayout{typeof(*)}()), Derivative.(axes.(S.args,1)) .* S.args)
11+
function diff(S::AbstractConcatBasis; dims::Integer)
12+
dims == 1 || error("not implemented")
13+
args = arguments.(Ref(ApplyLayout{typeof(*)}()), diff.(S.args; dims=dims))
1414
all(length.(args) .== 2) || error("Not implemented")
1515
concatbasis(S, map(first, args)...) * mortar(Diagonal([map(last, args)...]))
1616
end
@@ -112,4 +112,4 @@ function QuasiArrays._getindex(::Type{IND}, A::HvcatBasis{T}, (x,j)::IND) where
112112
end
113113

114114

115-
@simplify *(D::Derivative, H::ApplyQuasiMatrix{<:Any,typeof(hcat)}) = hcat((Ref(D) .* H.args)...)
115+
diff(H::ApplyQuasiMatrix{<:Any,typeof(hcat)}; dims::Integer) = hcat((diff.(H.args; dims=dims))...)

src/bases/splines.jl

Lines changed: 14 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,10 @@ grid(L::LinearSpline, n...) = L.points
5353
## Sub-bases
5454

5555

56-
## Mass matrix
57-
function similar(AB::QMul2{<:QuasiAdjoint{<:Any,<:LinearSpline},<:LinearSpline}, ::Type{T}) where T
58-
n = size(AB,1)
59-
SymTridiagonal(Vector{T}(undef, n), Vector{T}(undef, n-1))
60-
end
61-
#
62-
@simplify function *(Ac::QuasiAdjoint{<:Any,<:LinearSpline}, B::LinearSpline)
63-
M = Mul(Ac, B)
64-
copyto!(similar(M, eltype(M)), M)
65-
end
66-
67-
function copyto!(dest::SymTridiagonal,
68-
AB::QMul2{<:QuasiAdjoint{<:Any,<:LinearSpline},<:LinearSpline})
69-
Ac,B = AB.A,AB.B
70-
A = parent(Ac)
71-
A.points == B.points || throw(ArgumentError())
72-
dv,ev = dest.dv,dest.ev
56+
## Gram matrix
57+
function grammatrix(A::LinearSpline{T}) where T
7358
x = A.points; n = length(x)
74-
length(dv) == n || throw(DimensionMismatch())
59+
dv,ev = Vector{T}(undef, n), Vector{T}(undef, n-1)
7560

7661
dv[1] = (x[2]-x[1])/3
7762
@inbounds for k = 2:n-1
@@ -83,45 +68,23 @@ function copyto!(dest::SymTridiagonal,
8368
ev[k] = (x[k+1]-x[k])/6
8469
end
8570

86-
dest
71+
SymTridiagonal(dv, ev)
8772
end
8873

8974

90-
@simplify function *(Ac::QuasiAdjoint{<:Any,<:HeavisideSpline}, B::HeavisideSpline)
91-
A = parent(Ac)
92-
A.points == B.points || throw(ArgumentError("Cannot multiply incompatible splines"))
93-
Diagonal(diff(A.points))
94-
end
75+
grammatrix(A::HeavisideSpline) = Diagonal(diff(A.points))
9576

9677

9778
## Differentiation
98-
function copyto!(dest::MulQuasiMatrix{<:Any,<:Tuple{<:HeavisideSpline,<:Any}},
99-
M::QMul2{<:Derivative,<:LinearSpline})
100-
D, L = M.A, M.B
101-
H, A = dest.args
102-
x = H.points
103-
104-
axes(dest) == axes(M) || throw(DimensionMismatch("axes must be same"))
105-
x == L.points || throw(ArgumentError("Cannot multiply incompatible splines"))
106-
bandwidths(A) == (0,1) || throw(ArgumentError("Not implemented"))
107-
79+
function diff(L::LinearSpline{T}; dims::Integer=1) where T
80+
dims == 1 || error("not implemented")
81+
n = size(L,2)
82+
x = L.points
83+
D = BandedMatrix{T}(undef, (n-1,n), (0,1))
10884
d = diff(x)
109-
A[band(0)] .= inv.((-).(d))
110-
A[band(1)] .= inv.(d)
111-
112-
dest
113-
end
114-
115-
function similar(M::QMul2{<:Derivative,<:LinearSpline}, ::Type{T}) where T
116-
D, B = M.A, M.B
117-
n = size(B,2)
118-
ApplyQuasiMatrix(*, HeavisideSpline{T}(B.points),
119-
BandedMatrix{T}(undef, (n-1,n), (0,1)))
120-
end
121-
122-
@simplify function *(D::Derivative, L::LinearSpline)
123-
M = Mul(D, L)
124-
copyto!(similar(M, eltype(M)), M)
85+
D[band(0)] .= inv.((-).(d))
86+
D[band(1)] .= inv.(d)
87+
ApplyQuasiMatrix(*, HeavisideSpline{T}(x), D)
12588
end
12689

12790

@@ -130,7 +93,7 @@ end
13093
##
13194

13295
function _sum(A::HeavisideSpline, dims)
133-
@assert dims == 1
96+
dims == 1 || error("not implemented")
13497
permutedims(diff(A.points))
13598
end
13699

src/operators.jl

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -122,19 +122,19 @@ axes(D::Derivative) = (D.axis, D.axis)
122122
==(a::Derivative, b::Derivative) = a.axis == b.axis
123123
copy(D::Derivative) = Derivative(copy(D.axis))
124124

125-
function diff(d::AbstractQuasiVector)
126-
x = axes(d,1)
127-
Derivative(x)*d
125+
@simplify function *(D::Derivative, B::AbstractQuasiMatrix)
126+
T = typeof(zero(eltype(D)) * zero(eltype(B)))
127+
diff(convert(AbstractQuasiMatrix{T}, B); dims=1)
128128
end
129129

130-
function diff(A::AbstractQuasiArray; dims::Integer)
131-
if dims == 1
132-
Derivative(axes(A,1)) * A
133-
else
134-
error("Not implemented")
135-
end
130+
@simplify function *(D::Derivative, B::AbstractQuasiVector)
131+
T = typeof(zero(eltype(D)) * zero(eltype(B)))
132+
diff(convert(AbstractQuasiVector{T}, B))
136133
end
137134

135+
136+
137+
138138
^(D::Derivative, k::Integer) = ApplyQuasiArray(^, D, k)
139139

140140

@@ -153,10 +153,6 @@ const Identity{T,D} = QuasiDiagonal{T,Inclusion{T,D}}
153153

154154
Identity(d::Inclusion) = QuasiDiagonal(d)
155155

156-
@simplify *(D::Derivative, x::Inclusion) = ones(promote_type(eltype(D),eltype(x)), x)
157-
@simplify *(D::Derivative, c::AbstractQuasiFill) = zeros(promote_type(eltype(D),eltype(c)), axes(c,1))
158-
# @simplify *(D::Derivative, x::AbstractQuasiVector) = D * expand(x)
159-
160156
struct OperatorLayout <: AbstractLazyLayout end
161157
MemoryLayout(::Type{<:Derivative}) = OperatorLayout()
162158
# copy(M::Mul{OperatorLayout, <:ExpansionLayout}) = simplify(M)

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using ContinuumArrays, QuasiArrays, IntervalSets, DomainSets, FillArrays, LinearAlgebra, BandedMatrices, InfiniteArrays, Test, Base64, RecipesBase
22
import ContinuumArrays: ℵ₁, materialize, AffineQuasiVector, BasisLayout, AdjointBasisLayout, SubBasisLayout, ℵ₁,
3-
MappedBasisLayout, AdjointMappedBasisLayout, MappedWeightedBasisLayout, TransformFactorization, Weight, WeightedBasisLayout, SubWeightedBasisLayout, WeightLayout,
3+
MappedBasisLayout, AdjointMappedBasisLayouts, MappedWeightedBasisLayout, TransformFactorization, Weight, WeightedBasisLayout, SubWeightedBasisLayout, WeightLayout,
44
basis, invmap, Map, checkpoints, _plotgrid, mul, plotvalues
55
import QuasiArrays: SubQuasiArray, MulQuasiMatrix, Vec, Inclusion, QuasiDiagonal, LazyQuasiArrayApplyStyle, LazyQuasiArrayStyle
66
import LazyArrays: MemoryLayout, ApplyStyle, Applied, colsupport, arguments, ApplyLayout, LdivStyle, MulStyle

0 commit comments

Comments
 (0)