Skip to content

Commit d63f02c

Browse files
committed
Adjoint/Transpose -> QuasiAdjoint/QuasiTranspose
Add QuasiDiagonal
1 parent 503f0fe commit d63f02c

File tree

10 files changed

+299
-88
lines changed

10 files changed

+299
-88
lines changed

REQUIRE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
julia 0.7
22
IntervalSets 0.3.1
3+
DomainSets 0.0.1
34
LazyArrays 0.4
45
BandedMatrices 0.7.2
6+
InfiniteArrays 0.0.2

src/ContinuumArrays.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module ContinuumArrays
2-
using IntervalSets, LinearAlgebra, LazyArrays, BandedMatrices
2+
using IntervalSets, LinearAlgebra, LazyArrays, BandedMatrices, InfiniteArrays, DomainSets
33
import Base: @_inline_meta, axes, getindex, convert, prod, *, /, \, +, -,
44
IndexStyle, IndexLinear, ==
55
import Base.Broadcast: materialize
@@ -8,7 +8,7 @@ import BandedMatrices: AbstractBandedLayout
88

99
include("QuasiArrays/QuasiArrays.jl")
1010
using .QuasiArrays
11-
import .QuasiArrays: cardinality, checkindex, Adjoint, Transpose, slice, QSlice, SubQuasiArray
11+
import .QuasiArrays: cardinality, checkindex, QuasiAdjoint, QuasiTranspose, slice, QSlice, SubQuasiArray
1212

1313
export Spline, LinearSpline, HeavisideSpline, DiracDelta, Derivative
1414

src/QuasiArrays/QuasiArrays.jl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,17 @@ import Base: ViewIndex, Slice, ScalarIndex, RangeIndex, view, viewindexing, ensu
1111
check_parent_index_match, reindex, _isdisjoint, unsafe_indices,
1212
parentindices
1313
import Base: *, /, \, +, -, inv
14+
import Base: exp, log, sqrt,
15+
cos, sin, tan, csc, sec, cot,
16+
cosh, sinh, tanh, csch, sech, coth,
17+
acos, asin, atan, acsc, asec, acot,
18+
acosh, asinh, atanh, acsch, asech, acoth
19+
import Base: Array, Matrix, Vector
1420

1521
import Base.Broadcast: materialize
1622

17-
import LinearAlgebra: transpose, adjoint, checkeltype_adjoint, checkeltype_transpose
23+
import LinearAlgebra: transpose, adjoint, checkeltype_adjoint, checkeltype_transpose, Diagonal,
24+
AbstractTriangular
1825

1926
import LazyArrays: MemoryLayout, UnknownLayout, Mul2
2027

@@ -37,6 +44,7 @@ include("multidimensional.jl")
3744
include("subquasiarray.jl")
3845
include("matmul.jl")
3946

40-
include("adjtrans.jl")
47+
include("quasiadjtrans.jl")
48+
include("quasidiagonal.jl")
4149

4250
end

src/QuasiArrays/adjtrans.jl renamed to src/QuasiArrays/quasiadjtrans.jl

Lines changed: 61 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,30 @@
44

55
### basic definitions (types, aliases, constructors, abstractarray interface, sundry similar)
66

7-
# note that Adjoint and Transpose must be able to wrap not only vectors and matrices
7+
# note that QuasiAdjoint and QuasiTranspose must be able to wrap not only vectors and matrices
88
# but also factorizations, rotations, and other linear algebra objects, including
99
# user-defined such objects. so do not restrict the wrapped type.
10-
struct Adjoint{T,S} <: AbstractQuasiMatrix{T}
10+
struct QuasiAdjoint{T,S} <: AbstractQuasiMatrix{T}
1111
parent::S
12-
function Adjoint{T,S}(A::S) where {T,S}
12+
function QuasiAdjoint{T,S}(A::S) where {T,S}
1313
checkeltype_adjoint(T, eltype(A))
1414
new(A)
1515
end
1616
end
17-
struct Transpose{T,S} <: AbstractQuasiMatrix{T}
17+
struct QuasiTranspose{T,S} <: AbstractQuasiMatrix{T}
1818
parent::S
19-
function Transpose{T,S}(A::S) where {T,S}
19+
function QuasiTranspose{T,S}(A::S) where {T,S}
2020
checkeltype_transpose(T, eltype(A))
2121
new(A)
2222
end
2323
end
2424

2525
# basic outer constructors
26-
Adjoint(A) = Adjoint{Base.promote_op(adjoint,eltype(A)),typeof(A)}(A)
27-
Transpose(A) = Transpose{Base.promote_op(transpose,eltype(A)),typeof(A)}(A)
26+
QuasiAdjoint(A) = QuasiAdjoint{Base.promote_op(adjoint,eltype(A)),typeof(A)}(A)
27+
QuasiTranspose(A) = QuasiTranspose{Base.promote_op(transpose,eltype(A)),typeof(A)}(A)
2828

29-
Base.dataids(A::Union{Adjoint, Transpose}) = Base.dataids(A.parent)
30-
Base.unaliascopy(A::Union{Adjoint,Transpose}) = typeof(A)(Base.unaliascopy(A.parent))
29+
Base.dataids(A::Union{QuasiAdjoint, QuasiTranspose}) = Base.dataids(A.parent)
30+
Base.unaliascopy(A::Union{QuasiAdjoint,QuasiTranspose}) = typeof(A)(Base.unaliascopy(A.parent))
3131

3232
# wrapping lowercase quasi-constructors
3333
"""
@@ -47,18 +47,18 @@ julia> A = [3+2im 9+2im; 8+7im 4+6im]
4747
8+7im 4+6im
4848
4949
julia> adjoint(A)
50-
2×2 Adjoint{Complex{Int64},Array{Complex{Int64},2}}:
50+
2×2 QuasiAdjoint{Complex{Int64},Array{Complex{Int64},2}}:
5151
3-2im 8-7im
5252
9-2im 4-6im
5353
```
5454
"""
55-
adjoint(A::AbstractQuasiVecOrMat) = Adjoint(A)
55+
adjoint(A::AbstractQuasiVecOrMat) = QuasiAdjoint(A)
5656

5757
"""
5858
transpose(A)
5959
6060
Lazy transpose. Mutating the returned object should appropriately mutate `A`. Often,
61-
but not always, yields `Transpose(A)`, where `Transpose` is a lazy transpose wrapper. Note
61+
but not always, yields `QuasiTranspose(A)`, where `QuasiTranspose` is a lazy transpose wrapper. Note
6262
that this operation is recursive.
6363
6464
This operation is intended for linear algebra usage - for general data manipulation see
@@ -72,30 +72,30 @@ julia> A = [3+2im 9+2im; 8+7im 4+6im]
7272
8+7im 4+6im
7373
7474
julia> transpose(A)
75-
2×2 Transpose{Complex{Int64},Array{Complex{Int64},2}}:
75+
2×2 QuasiTranspose{Complex{Int64},Array{Complex{Int64},2}}:
7676
3+2im 8+7im
7777
9+2im 4+6im
7878
```
7979
"""
80-
transpose(A::AbstractQuasiVecOrMat) = Transpose(A)
80+
transpose(A::AbstractQuasiVecOrMat) = QuasiTranspose(A)
8181

8282
# unwrapping lowercase quasi-constructors
83-
adjoint(A::Adjoint) = A.parent
84-
transpose(A::Transpose) = A.parent
85-
adjoint(A::Transpose{<:Real}) = A.parent
86-
transpose(A::Adjoint{<:Real}) = A.parent
83+
adjoint(A::QuasiAdjoint) = A.parent
84+
transpose(A::QuasiTranspose) = A.parent
85+
adjoint(A::QuasiTranspose{<:Real}) = A.parent
86+
transpose(A::QuasiAdjoint{<:Real}) = A.parent
8787

8888

8989
# some aliases for internal convenience use
90-
const AdjOrTrans{T,S} = Union{Adjoint{T,S},Transpose{T,S}} where {T,S}
91-
const AdjointAbsVec{T} = Adjoint{T,<:AbstractQuasiVector}
92-
const TransposeAbsVec{T} = Transpose{T,<:AbstractQuasiVector}
90+
const AdjOrTrans{T,S} = Union{QuasiAdjoint{T,S},QuasiTranspose{T,S}} where {T,S}
91+
const QuasiAdjointAbsVec{T} = QuasiAdjoint{T,<:AbstractQuasiVector}
92+
const QuasiTransposeAbsVec{T} = QuasiTranspose{T,<:AbstractQuasiVector}
9393
const AdjOrTransAbsVec{T} = AdjOrTrans{T,<:AbstractQuasiVector}
9494
const AdjOrTransAbsMat{T} = AdjOrTrans{T,<:AbstractQuasiMatrix}
9595

9696
# for internal use below
97-
wrapperop(A::Adjoint) = adjoint
98-
wrapperop(A::Transpose) = transpose
97+
wrapperop(A::QuasiAdjoint) = adjoint
98+
wrapperop(A::QuasiTranspose) = transpose
9999

100100
# AbstractQuasiArray interface, basic definitions
101101
length(A::AdjOrTrans) = length(A.parent)
@@ -114,8 +114,8 @@ IndexStyle(::Type{<:AdjOrTransAbsMat}) = IndexCartesian()
114114
@propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, ::Colon) = wrapperop(v)(v.parent[:])
115115

116116
# conversion of underlying storage
117-
convert(::Type{Adjoint{T,S}}, A::Adjoint) where {T,S} = Adjoint{T,S}(convert(S, A.parent))
118-
convert(::Type{Transpose{T,S}}, A::Transpose) where {T,S} = Transpose{T,S}(convert(S, A.parent))
117+
convert(::Type{QuasiAdjoint{T,S}}, A::QuasiAdjoint) where {T,S} = QuasiAdjoint{T,S}(convert(S, A.parent))
118+
convert(::Type{QuasiTranspose{T,S}}, A::QuasiTranspose) where {T,S} = QuasiTranspose{T,S}(convert(S, A.parent))
119119

120120
# for vectors, the semantics of the wrapped and unwrapped types differ
121121
# so attempt to maintain both the parent and wrapper type insofar as possible
@@ -135,82 +135,82 @@ cmp(A::AdjOrTransAbsVec, B::AdjOrTransAbsVec) = cmp(parent(A), parent(B))
135135
isless(A::AdjOrTransAbsVec, B::AdjOrTransAbsVec) = isless(parent(A), parent(B))
136136

137137
### concatenation
138-
# preserve Adjoint/Transpose wrapper around vectors
138+
# preserve QuasiAdjoint/QuasiTranspose wrapper around vectors
139139
# to retain the associated semantics post-concatenation
140-
hcat(avs::Union{Number,AdjointAbsVec}...) = _adjoint_hcat(avs...)
141-
hcat(tvs::Union{Number,TransposeAbsVec}...) = _transpose_hcat(tvs...)
142-
_adjoint_hcat(avs::Union{Number,AdjointAbsVec}...) = adjoint(vcat(map(adjoint, avs)...))
143-
_transpose_hcat(tvs::Union{Number,TransposeAbsVec}...) = transpose(vcat(map(transpose, tvs)...))
144-
typed_hcat(::Type{T}, avs::Union{Number,AdjointAbsVec}...) where {T} = adjoint(typed_vcat(T, map(adjoint, avs)...))
145-
typed_hcat(::Type{T}, tvs::Union{Number,TransposeAbsVec}...) where {T} = transpose(typed_vcat(T, map(transpose, tvs)...))
140+
hcat(avs::Union{Number,QuasiAdjointAbsVec}...) = _adjoint_hcat(avs...)
141+
hcat(tvs::Union{Number,QuasiTransposeAbsVec}...) = _transpose_hcat(tvs...)
142+
_adjoint_hcat(avs::Union{Number,QuasiAdjointAbsVec}...) = adjoint(vcat(map(adjoint, avs)...))
143+
_transpose_hcat(tvs::Union{Number,QuasiTransposeAbsVec}...) = transpose(vcat(map(transpose, tvs)...))
144+
typed_hcat(::Type{T}, avs::Union{Number,QuasiAdjointAbsVec}...) where {T} = adjoint(typed_vcat(T, map(adjoint, avs)...))
145+
typed_hcat(::Type{T}, tvs::Union{Number,QuasiTransposeAbsVec}...) where {T} = transpose(typed_vcat(T, map(transpose, tvs)...))
146146
# otherwise-redundant definitions necessary to prevent hitting the concat methods in sparse/sparsevector.jl
147-
hcat(avs::Adjoint{<:Any,<:Vector}...) = _adjoint_hcat(avs...)
148-
hcat(tvs::Transpose{<:Any,<:Vector}...) = _transpose_hcat(tvs...)
149-
hcat(avs::Adjoint{T,Vector{T}}...) where {T} = _adjoint_hcat(avs...)
150-
hcat(tvs::Transpose{T,Vector{T}}...) where {T} = _transpose_hcat(tvs...)
147+
hcat(avs::QuasiAdjoint{<:Any,<:Vector}...) = _adjoint_hcat(avs...)
148+
hcat(tvs::QuasiTranspose{<:Any,<:Vector}...) = _transpose_hcat(tvs...)
149+
hcat(avs::QuasiAdjoint{T,Vector{T}}...) where {T} = _adjoint_hcat(avs...)
150+
hcat(tvs::QuasiTranspose{T,Vector{T}}...) where {T} = _transpose_hcat(tvs...)
151151
# TODO unify and allow mixed combinations
152152

153153

154154
### higher order functions
155-
# preserve Adjoint/Transpose wrapper around vectors
155+
# preserve QuasiAdjoint/QuasiTranspose wrapper around vectors
156156
# to retain the associated semantics post-map/broadcast
157157
#
158158
# note that the caller's operation f operates in the domain of the wrapped vectors' entries.
159159
# hence the adjoint->f->adjoint shenanigans applied to the parent vectors' entries.
160-
map(f, avs::AdjointAbsVec...) = adjoint(map((xs...) -> adjoint(f(adjoint.(xs)...)), parent.(avs)...))
161-
map(f, tvs::TransposeAbsVec...) = transpose(map((xs...) -> transpose(f(transpose.(xs)...)), parent.(tvs)...))
160+
map(f, avs::QuasiAdjointAbsVec...) = adjoint(map((xs...) -> adjoint(f(adjoint.(xs)...)), parent.(avs)...))
161+
map(f, tvs::QuasiTransposeAbsVec...) = transpose(map((xs...) -> transpose(f(transpose.(xs)...)), parent.(tvs)...))
162162

163163

164164
### linear algebra
165165

166-
(-)(A::Adjoint) = Adjoint( -A.parent)
167-
(-)(A::Transpose) = Transpose(-A.parent)
166+
(-)(A::QuasiAdjoint) = QuasiAdjoint( -A.parent)
167+
(-)(A::QuasiTranspose) = QuasiTranspose(-A.parent)
168168

169169
## multiplication *
170170

171-
# Adjoint/Transpose-vector * vector
172-
*(u::AdjointAbsVec, v::AbstractQuasiVector) = dot(u.parent, v)
173-
*(u::TransposeAbsVec{T}, v::AbstractQuasiVector{T}) where {T<:Real} = dot(u.parent, v)
174-
function *(u::TransposeAbsVec, v::AbstractQuasiVector)
171+
# QuasiAdjoint/QuasiTranspose-vector * vector
172+
*(u::QuasiAdjointAbsVec, v::AbstractQuasiVector) = dot(u.parent, v)
173+
*(u::QuasiTransposeAbsVec{T}, v::AbstractQuasiVector{T}) where {T<:Real} = dot(u.parent, v)
174+
function *(u::QuasiTransposeAbsVec, v::AbstractQuasiVector)
175175
@assert !has_offset_axes(u, v)
176176
@boundscheck length(u) == length(v) || throw(DimensionMismatch())
177177
return sum(@inbounds(u[k]*v[k]) for k in 1:length(u))
178178
end
179-
# vector * Adjoint/Transpose-vector
179+
# vector * QuasiAdjoint/QuasiTranspose-vector
180180
*(u::AbstractQuasiVector, v::AdjOrTransAbsVec) = broadcast(*, u, v)
181-
# Adjoint/Transpose-vector * Adjoint/Transpose-vector
181+
# QuasiAdjoint/QuasiTranspose-vector * QuasiAdjoint/QuasiTranspose-vector
182182
# (necessary for disambiguation with fallback methods in linalg/matmul)
183-
*(u::AdjointAbsVec, v::AdjointAbsVec) = throw(MethodError(*, (u, v)))
184-
*(u::TransposeAbsVec, v::TransposeAbsVec) = throw(MethodError(*, (u, v)))
183+
*(u::QuasiAdjointAbsVec, v::QuasiAdjointAbsVec) = throw(MethodError(*, (u, v)))
184+
*(u::QuasiTransposeAbsVec, v::QuasiTransposeAbsVec) = throw(MethodError(*, (u, v)))
185185

186186
# AdjOrTransAbsVec{<:Any,<:AdjOrTransAbsVec} is a lazy conj vectors
187187
# We need to expand the combinations to avoid ambiguities
188-
(*)(u::TransposeAbsVec, v::AdjointAbsVec{<:Any,<:TransposeAbsVec}) =
188+
(*)(u::QuasiTransposeAbsVec, v::QuasiAdjointAbsVec{<:Any,<:QuasiTransposeAbsVec}) =
189189
sum(uu*vv for (uu, vv) in zip(u, v))
190-
(*)(u::AdjointAbsVec, v::AdjointAbsVec{<:Any,<:TransposeAbsVec}) =
190+
(*)(u::QuasiAdjointAbsVec, v::QuasiAdjointAbsVec{<:Any,<:QuasiTransposeAbsVec}) =
191191
sum(uu*vv for (uu, vv) in zip(u, v))
192-
(*)(u::TransposeAbsVec, v::TransposeAbsVec{<:Any,<:AdjointAbsVec}) =
192+
(*)(u::QuasiTransposeAbsVec, v::QuasiTransposeAbsVec{<:Any,<:QuasiAdjointAbsVec}) =
193193
sum(uu*vv for (uu, vv) in zip(u, v))
194-
(*)(u::AdjointAbsVec, v::TransposeAbsVec{<:Any,<:AdjointAbsVec}) =
194+
(*)(u::QuasiAdjointAbsVec, v::QuasiTransposeAbsVec{<:Any,<:QuasiAdjointAbsVec}) =
195195
sum(uu*vv for (uu, vv) in zip(u, v))
196196

197197
## pseudoinversion
198-
pinv(v::AdjointAbsVec, tol::Real = 0) = pinv(v.parent, tol).parent
199-
pinv(v::TransposeAbsVec, tol::Real = 0) = pinv(conj(v.parent)).parent
198+
pinv(v::QuasiAdjointAbsVec, tol::Real = 0) = pinv(v.parent, tol).parent
199+
pinv(v::QuasiTransposeAbsVec, tol::Real = 0) = pinv(conj(v.parent)).parent
200200

201201

202202
## left-division \
203203
\(u::AdjOrTransAbsVec, v::AdjOrTransAbsVec) = pinv(u) * v
204204

205205

206206
## right-division \
207-
/(u::AdjointAbsVec, A::AbstractQuasiMatrix) = adjoint(adjoint(A) \ u.parent)
208-
/(u::TransposeAbsVec, A::AbstractQuasiMatrix) = transpose(transpose(A) \ u.parent)
209-
/(u::AdjointAbsVec, A::Transpose{<:Any,<:AbstractQuasiMatrix}) = adjoint(conj(A.parent) \ u.parent) # technically should be adjoint(copy(adjoint(copy(A))) \ u.parent)
210-
/(u::TransposeAbsVec, A::Adjoint{<:Any,<:AbstractQuasiMatrix}) = transpose(conj(A.parent) \ u.parent) # technically should be transpose(copy(transpose(copy(A))) \ u.parent)
207+
/(u::QuasiAdjointAbsVec, A::AbstractQuasiMatrix) = adjoint(adjoint(A) \ u.parent)
208+
/(u::QuasiTransposeAbsVec, A::AbstractQuasiMatrix) = transpose(transpose(A) \ u.parent)
209+
/(u::QuasiAdjointAbsVec, A::QuasiTranspose{<:Any,<:AbstractQuasiMatrix}) = adjoint(conj(A.parent) \ u.parent) # technically should be adjoint(copy(adjoint(copy(A))) \ u.parent)
210+
/(u::QuasiTransposeAbsVec, A::QuasiAdjoint{<:Any,<:AbstractQuasiMatrix}) = transpose(conj(A.parent) \ u.parent) # technically should be transpose(copy(transpose(copy(A))) \ u.parent)
211211

212212

213-
function materialize(M::Mul2{<:Any,<:Any,<:Adjoint,<:Adjoint})
213+
function materialize(M::Mul2{<:Any,<:Any,<:QuasiAdjoint,<:QuasiAdjoint})
214214
Ac,Bc = M.factors
215215
materialize(Mul(parent(Bc),parent(Ac)))'
216216
end
@@ -219,4 +219,4 @@ function adjoint(M::Mul)
219219
Mul(reverse(adjoint.(M.factors))...)
220220
end
221221

222-
==(A::Adjoint, B::Adjoint) = parent(A) == parent(B)
222+
==(A::QuasiAdjoint, B::QuasiAdjoint) = parent(A) == parent(B)

0 commit comments

Comments
 (0)