Skip to content

Commit c1dea17

Browse files
committed
work on hvcat macro
1 parent d062189 commit c1dea17

File tree

7 files changed

+69
-31
lines changed

7 files changed

+69
-31
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ script:
77
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
88
- julia -e 'Pkg.clone(pwd()); Pkg.build("ControlSystems")'
99
#- julia -e 'ENV["PYTHON"] = ""; Pkg.clone("PyPlot"); Pkg.build("PyPlot")'
10-
- julia -e 'Pkg.clone("https://github.com/JuliaControl/ControlExamplePlots.jl.git");'
10+
#- julia -e 'Pkg.clone("https://github.com/JuliaControl/ControlExamplePlots.jl.git");'
1111
- julia -e 'Pkg.test("ControlSystems"; coverage=true)'
1212
after_success:
1313
- julia -e 'cd(Pkg.dir("ControlSystems")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'

src/connections.jl

+20-12
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,15 @@ end
4343

4444
append(systems::LTISystem...) = append(promote(systems...)...)
4545

46-
function Base.vcat(systems::StateSpace...)
46+
macro sys(ex)
47+
if ex.head == :vcat
48+
# vcat or hvcat
49+
elseif ex.head == :hcat
50+
# hcat only
51+
end
52+
end
53+
54+
function vcatsys(systems::StateSpace...)
4755
# Perform checks
4856
nu = systems[1].nu
4957
if !all(s.nu == nu for s in systems)
@@ -61,7 +69,7 @@ function Base.vcat(systems::StateSpace...)
6169
return StateSpace(A, B, C, D, Ts)
6270
end
6371

64-
function Base.vcat(systems::TransferFunction...)
72+
function vcatsys(systems::TransferFunction...)
6573
# Perform checks
6674
nu = systems[1].nu
6775
if !all(s.nu == nu for s in systems)
@@ -75,17 +83,17 @@ function Base.vcat(systems::TransferFunction...)
7583
return TransferFunction(mat, Ts)
7684
end
7785

78-
Base.vcat(systems::LTISystem...) = vcat(promote(systems...)...)
86+
vcatsys(systems::LTISystem...) = vcat(promote(systems...)...)
7987

80-
function Base.vcat{T<:Real}(systems::Union{VecOrMat{T},T,TransferFunction}...)
88+
function vcatsys{T<:Real}(systems::Union{VecOrMat{T},T,TransferFunction}...)
8189
if Base.promote_typeof(systems...) <: TransferFunction
8290
vcat(map(e->convert(TransferFunction,e),systems)...)
8391
else
8492
cat(1,systems...)
8593
end
8694
end
8795

88-
function Base.hcat(systems::StateSpace...)
96+
function hcatsys(systems::StateSpace...)
8997
# Perform checks
9098
ny = systems[1].ny
9199
if !all(s.ny == ny for s in systems)
@@ -103,7 +111,7 @@ function Base.hcat(systems::StateSpace...)
103111
return StateSpace(A, B, C, D, Ts)
104112
end
105113

106-
function Base.hcat(systems::TransferFunction...)
114+
function hcatsys(systems::TransferFunction...)
107115
# Perform checks
108116
ny = systems[1].ny
109117
if !all(s.ny == ny for s in systems)
@@ -117,30 +125,30 @@ function Base.hcat(systems::TransferFunction...)
117125
return TransferFunction(mat, Ts)
118126
end
119127

120-
Base.hcat(systems::LTISystem...) = hcat(promote(systems...)...)
128+
hcatsys(systems::LTISystem...) = hcat(promote(systems...)...)
121129

122130

123131
# TODO: Fix this
124-
function Base.hcat(systems::Union{Number,AbstractVecOrMat{<:Number},LTISystem}...)
132+
function hcatsys(systems::Union{Number,AbstractVecOrMat{<:Number},LTISystem}...)
125133
S = Base.promote_typeof(systems...)
126134
if S <: LTISystem
127-
hcat(map(e->convert(S,e),systems)...)
135+
hcatsys(map(e->convert(S,e),systems)...)
128136
else
129137
cat(Val{2},systems...)
130138
end
131139
end
132140

133141

134-
function Base.hvcat(rows::Tuple{Vararg{Int}}, systems::Union{Number,AbstractVecOrMat{<:Number},LTISystem}...)
142+
function hvcatsys(rows::Tuple{Vararg{Int}}, systems::Union{Number,AbstractVecOrMat{<:Number},LTISystem}...)
135143
T = Base.promote_typeof(systems...)
136144
nbr = length(rows) # number of block rows
137145
rs = Array{T,1}(nbr)
138146
a = 1
139147
for i = 1:nbr
140-
rs[i] = hcat(convert.(T,systems[a:a-1+rows[i]])...)
148+
rs[i] = hcatsys(convert.(T,systems[a:a-1+rows[i]])...)
141149
a += rows[i]
142150
end
143-
vcat(rs...)
151+
vcatsys(rs...)
144152
end
145153

146154
# function _get_common_sampling_time(sys_vec::Union{AbstractVector{LTISystem},AbstractVecOrMat{<:Number},Number})

src/types/SisoTfTypes/SisoZpk.jl

+15-9
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function SisoZpk{T}(z::Vector, p::Vector, k::Number) where T
2525
SisoZpk{T,TR}(Vector{TR}(z), Vector{TR}(p), T(k))
2626
end
2727
function SisoZpk(z::AbstractVector{TZ}, p::AbstractVector{TP}, k::T) where {T<:Number, TZ<:Number, TP<:Number} # NOTE: is this constructor really needed?
28-
TR = promote_type(TZ,TP,T)
28+
TR = promote_type(TZ,TP)
2929
# Could check if complex roots come with their conjugates,
3030
# i.e., if the SisoZpk corresponds to a real-valued system
3131

@@ -50,8 +50,8 @@ Base.zero(f::SisoZpk) = zero(typeof(f))
5050

5151

5252
# tzero is not meaningful for transfer function element? But both zero and zeros are taken...
53-
tzero(sys::SisoZpk) = f.z # Do minreal first?,
54-
pole(sys::SisoZpk) = f.p # Do minreal first?
53+
tzero(f::SisoZpk) = f.z # Do minreal first?,
54+
pole(f::SisoZpk) = f.p # Do minreal first?
5555

5656
numpoly(f::SisoZpk{<:Real}) = f.k*prod(roots2real_poly_factors(f.z))
5757
denpoly(f::SisoZpk{<:Real}) = prod(roots2real_poly_factors(f.p))
@@ -198,14 +198,19 @@ end
198198
function +(f1::SisoZpk{T1,TR1}, f2::SisoZpk{T2,TR2}) where {T1<:Number,T2<:Number,TR1<:Number,TR2<:Number}
199199
numPoly = numpoly(f1)*denpoly(f2) + numpoly(f2)*denpoly(f1)
200200

201-
TR = promote_type(TR1, TR2)
202-
z = convert(Vector{TR}, roots(numPoly))
201+
TRtmp = promote_type(TR1, TR2)
202+
# Calculating roots can make integers floats
203+
TRnew = Base.promote_op(/, TRtmp, TRtmp)
204+
z = convert(Vector{TRnew}, roots(numPoly))
205+
#TODO gains could remain integers, but numerical precision inhibits this
206+
Ttmp = promote_type(T1,T2)
207+
Tnew = Base.promote_op(/, Ttmp, Ttmp)
203208
if length(numPoly) > 0
204-
k = numPoly[end]
205-
p = convert(Vector{TR}, [f1.p;f2.p])
209+
k = convert(Tnew, numPoly[end])
210+
p = convert(Vector{TRnew}, [f1.p;f2.p])
206211
else
207-
k = 0
208-
p = TR[]
212+
k = zero(Tnew)
213+
p = TRnew[]
209214
end
210215

211216
# FIXME:
@@ -231,6 +236,7 @@ end
231236

232237

233238
*(f1::SisoZpk, f2::SisoZpk) = SisoZpk([f1.z;f2.z], [f1.p;f2.p], f1.k*f2.k)
239+
234240
*(f::SisoZpk, n::Number) = SisoZpk(f.z, f.p, f.k*n)
235241
*(n::Number, f::SisoZpk) = *(f, n)
236242
#.*(f1::SisoZpk, f2::SisoZpk) = *(f1, f2)

src/types/SisoTfTypes/promotion.jl

-2
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,3 @@ function Base.promote_rule(::Type{SisoZpk{T1,TR1}}, ::Type{T2}) where {T1<:Numbe
1616
# TODO Not obvious that we want to promote to complex poles?
1717
SisoZpk{Tnew, TRnew}
1818
end
19-
20-
Base.promote_op(::Any, ::Type{T}, ::Type{T}) where {T<:SisoTf} = T

src/types/TransferFunction.jl

+1-7
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ function +(G1::TransferFunction, G2::TransferFunction)
122122
error("Sampling time mismatch")
123123
end
124124

125-
G1, G2 = promote(G1, G2)
126125
matrix = G1.matrix + G2.matrix
127126
return TransferFunction(matrix, G1.Ts)
128127
end
@@ -146,15 +145,10 @@ function *(G1::TransferFunction, G2::TransferFunction)
146145
elseif G1.Ts != G2.Ts
147146
error("Sampling time mismatch")
148147
end
149-
S = promote_type(eltype(G1), eltype(G2)) # FIXME: Should be done analogusly to +
150-
151-
#matrix = convert(Matrix{S}, G1.matrix) * convert(Matrix{S}, G2.matrix)
152-
G1, G2 = promote(G1, G2)
153148

154149
matrix = G1.matrix * G2.matrix
155-
convert(Matrix{S}, matrix)
156150

157-
return TransferFunction{S}(matrix, G1.Ts)
151+
return TransferFunction{eltype(matrix)}(matrix, G1.Ts)
158152
end
159153

160154
*(G::TransferFunction, n::Number) = TransferFunction(n*G.matrix, G.Ts)

test/runtests.jl

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ my_tests = ["test_statespace",
1010
"test_connections",
1111
"test_discrete",
1212
"test_conversion",
13+
"test_complex",
1314
"test_linalg",
1415
"test_simplification",
1516
"test_freqresp",

test/test_complex.jl

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
@testset "test_complex_systems" begin
2+
3+
C_1 = zpk([], [-1+im], 1.0+1im)
4+
C_2 = zpk([-1+im], [], 1.0+1im)
5+
6+
# Basic arittmetic
7+
@test C_1 + C_1 == zpk([], [-1+im], 2+2im)
8+
@test (1.0+im)*C_1 == zpk([], [-1+im], 2.0im)
9+
@test C_2 + C_2 == zpk([-1+im], [], 2+2im)
10+
11+
@test C_1 * C_1 == zpk([], [-1+im,-1+im], 2.0im)
12+
@test C_2 * C_2 zpk([-1+im,-1+im], [], 2.0im)
13+
14+
15+
@test pole(zpk([], [-1+im,-1+im,0], 2.0im)) == [-1+im,-1+im,0]
16+
@test tzero(zpk([-1+im,-1+im,0], [-2], 2.0im)) == [-1+im,-1+im,0]
17+
18+
@test zpk( tf([1.0, 1+im], [1.0, 2+im]) ) == zpk( [-1-im], [-2-im], 1.0+0im)
19+
20+
@test minreal(zpk([-1+im], [-1+im,-1+im],1+0im)) == zpk([], [-1+im],1+0im)
21+
@test minreal(zpk([-1+im, -1+im], [-1+im],1+1im)) == zpk([-1+im], [], 1+1im)
22+
23+
24+
@test_throws AssertionError zpk([-1+im], [-1+im,-1+im],1) # Given the type of k this should be a real-coefficient system, but poles and zeros don't come in conjugate pairs
25+
26+
@test zpk([-2+im], [-1+im],1+0im)*zpk([], [-1+im],1+0im) == zpk([-2+im], [-1+im, -1+im], 1+0im)
27+
@test zpk([], [-2], 2) + zpk([], [-1], 1) == zpk([-4/3], [-2,-1], 3)
28+
29+
@test_broken tf(zpk([-2+im], [-1+im],1+0im))
30+
31+
end

0 commit comments

Comments
 (0)