Skip to content

Commit d2ccf89

Browse files
committed
added BroadCast
1 parent cd52268 commit d2ccf89

File tree

4 files changed

+176
-0
lines changed

4 files changed

+176
-0
lines changed

docs/src/calculus.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ NonLinearCompose
2020
```@docs
2121
Scale
2222
Transpose
23+
BroadCast
2324
Reshape
2425
Jacobian
2526
```

src/AbstractOperators.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ include("calculus/HCAT.jl")
5353
include("calculus/VCAT.jl")
5454
include("calculus/Compose.jl")
5555
include("calculus/Reshape.jl")
56+
include("calculus/BroadCast.jl")
5657
include("calculus/Sum.jl")
5758
include("calculus/Transpose.jl")
5859
include("calculus/Jacobian.jl")

src/calculus/BroadCast.jl

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
export BroadCast
2+
3+
"""
4+
`BroadCast(A::AbstractOperator, dim_out...)`
5+
6+
7+
BroadCast the codomain dimensions of an `AbstractOperator`.
8+
9+
```julia
10+
julia> A = Eye(2)
11+
I ℝ^2 -> ℝ^2
12+
13+
julia> B = BroadCast(A,(2,3))
14+
.I ℝ^2 -> ℝ^(2, 3)
15+
16+
julia> B*[1.;2.]
17+
2×3 Array{Float64,2}:
18+
1.0 1.0 1.0
19+
2.0 2.0 2.0
20+
21+
```
22+
23+
"""
24+
struct BroadCast{N,
25+
L <: AbstractOperator,
26+
T <: AbstractArray,
27+
D <: AbstractArray,
28+
M,
29+
C <: NTuple{M,Colon},
30+
I <: CartesianRange
31+
} <: AbstractOperator
32+
A::L
33+
dim_out::NTuple{N,Int}
34+
bufC::T
35+
bufD::D
36+
cols::C
37+
idxs::I
38+
39+
function BroadCast(A::L,dim_out::NTuple{N,Int},bufC::T, bufD::D) where {N,
40+
L<:AbstractOperator,
41+
T<:AbstractArray,
42+
D<:AbstractArray
43+
}
44+
Base.Broadcast.check_broadcast_shape(dim_out,size(A,1))
45+
if size(A,1) != (1,)
46+
M = length(size(A,1))
47+
cols = ([Colon() for i = 1:M]...)
48+
idxs = CartesianRange((dim_out[M+1:end]...))
49+
new{N,L,T,D,M,typeof(cols),typeof(idxs)}(A,dim_out,bufC,bufD,cols,idxs)
50+
else #singleton case
51+
M = 0
52+
idxs = CartesianRange((1,))
53+
new{N,L,T,D,M,NTuple{0,Colon},typeof(idxs)}(A,dim_out,bufC,bufD,(),idxs)
54+
end
55+
56+
end
57+
end
58+
59+
# Constructors
60+
61+
BroadCast(A::L, dim_out::NTuple{N,Int}) where {N,L<:AbstractOperator} =
62+
BroadCast(A, dim_out, zeros(codomainType(A),size(A,1)), zeros(domainType(A),size(A,2)) )
63+
64+
# Mappings
65+
66+
function A_mul_B!(y::C, R::BroadCast{N,L}, b::D) where {N,L,C,D}
67+
A_mul_B!(R.bufC, R.A, b)
68+
y .= R.bufC
69+
end
70+
71+
function Ac_mul_B!(y::C, R::BroadCast{N,L}, b::D) where {N,L,C,D}
72+
fill!(y, 0.)
73+
for i in R.idxs
74+
@views Ac_mul_B!(R.bufD, R.A, b[R.cols...,i.I...])
75+
y .+= R.bufD
76+
end
77+
return y
78+
end
79+
80+
#singleton
81+
function Ac_mul_B!(y::CC, R::BroadCast{N,L,T,D,0}, b::DD) where {N,L,T,D,CC,DD}
82+
fill!(y, 0.)
83+
bii = zeros(eltype(b),1)
84+
for bi in b
85+
bii[1] = bi
86+
Ac_mul_B!(R.bufD, R.A, bii)
87+
y .+= R.bufD
88+
end
89+
return y
90+
end
91+
92+
#singleton Eye
93+
function Ac_mul_B!(y::CC, R::BroadCast{N,L,T,D,0}, b::DD) where {N,L<:Eye,T,D,CC,DD}
94+
y .= sum(b)
95+
end
96+
97+
# Properties
98+
99+
size(R::BroadCast) = (R.dim_out, size(R.A,2))
100+
101+
domainType( R::BroadCast) = domainType(R.A)
102+
codomainType( R::BroadCast) = codomainType(R.A)
103+
104+
is_linear( R::BroadCast) = is_linear(R.A)
105+
is_null( R::BroadCast) = is_null(R.A)
106+
107+
fun_name(R::BroadCast) = "."fun_name(R.A)

test/test_linear_operators_calculus.jl

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,3 +682,70 @@ x = randn(m1)
682682
y1 = test_op(opS, x, randn(m3), verb)
683683
y2 = coeff*(A2*A1*x)
684684
@test all(vecnorm.(y1 .- y2) .<= 1e-12)
685+
686+
##########################
687+
##### test BroadCast #####
688+
##########################
689+
690+
m, n = 8, 4
691+
dim_out = (m, 10)
692+
A1 = randn(m, n)
693+
opA1 = MatrixOp(A1)
694+
opR = BroadCast(opA1, dim_out)
695+
x1 = randn(n)
696+
y1 = test_op(opR, x1, randn(dim_out), verb)
697+
y2 = zeros(dim_out)
698+
y2 .= A1*x1
699+
@test vecnorm(y1-y2) <= 1e-12
700+
701+
m, n, l, k = 8, 4, 5, 7
702+
dim_out = (m, n, l, k)
703+
opA1 = Eye(m,n)
704+
opR = BroadCast(opA1, dim_out)
705+
x1 = randn(m,n)
706+
y1 = test_op(opR, x1, randn(dim_out), verb)
707+
y2 = zeros(dim_out)
708+
y2 .= x1
709+
@test vecnorm(y1-y2) <= 1e-12
710+
711+
@test_throws Exception BroadCast(opA1,(m,m))
712+
713+
m, l = 1, 5
714+
dim_out = (m, l)
715+
opA1 = Eye(m)
716+
opR = BroadCast(opA1, dim_out)
717+
x1 = randn(m)
718+
y1 = test_op(opR, x1, randn(dim_out), verb)
719+
y2 = zeros(dim_out)
720+
y2 .= x1
721+
@test vecnorm(y1-y2) <= 1e-12
722+
723+
m, n, l = 2, 5, 8
724+
dim_out = (m, n, l)
725+
opA1 = Eye(m)
726+
opR = BroadCast(opA1, dim_out)
727+
x1 = randn(m)
728+
y1 = test_op(opR, x1, randn(dim_out), verb)
729+
y2 = zeros(dim_out)
730+
y2 .= x1
731+
@test vecnorm(y1-y2) <= 1e-12
732+
733+
m, n, l = 1, 5, 8
734+
dim_out = (m, n, l)
735+
opA1 = Eye(m)
736+
opR = BroadCast(opA1, dim_out)
737+
x1 = randn(m)
738+
y1 = test_op(opR, x1, randn(dim_out), verb)
739+
y2 = zeros(dim_out)
740+
y2 .= x1
741+
@test vecnorm(y1-y2) <= 1e-12
742+
743+
@test is_null(opR) == is_null(opA1)
744+
@test is_eye(opR) == false
745+
@test is_diagonal(opR) == false
746+
@test is_AcA_diagonal(opR) == false
747+
@test is_AAc_diagonal(opR) == false
748+
@test is_orthogonal(opR) == false
749+
@test is_invertible(opR) == false
750+
@test is_full_row_rank(opR) == false
751+
@test is_full_column_rank(opR) == false

0 commit comments

Comments
 (0)