Skip to content

Commit 5723a05

Browse files
authored
Fix infinite loop when inputs are Inf (#51554)
1 parent 7916b73 commit 5723a05

File tree

2 files changed

+17
-9
lines changed

2 files changed

+17
-9
lines changed

src/givens.jl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ floatmin2(::Type{T}) where {T} = (twopar = 2one(T); twopar^trunc(Integer,log(flo
7676
# NAG Ltd.
7777
function givensAlgorithm(f::T, g::T) where T<:AbstractFloat
7878
onepar = one(T)
79-
twopar = 2one(T)
8079
T0 = typeof(onepar) # dimensionless
8180
zeropar = T0(zero(T)) # must be dimensionless
8281

@@ -105,7 +104,7 @@ function givensAlgorithm(f::T, g::T) where T<:AbstractFloat
105104
f1 *= safmn2
106105
g1 *= safmn2
107106
scalepar = max(abs(f1), abs(g1))
108-
if scalepar < safmx2u break end
107+
if scalepar < safmx2u || count >= 20 break end
109108
end
110109
r = sqrt(f1*f1 + g1*g1)
111110
cs = f1/r
@@ -149,7 +148,7 @@ end
149148
# Univ. of Colorado Denver
150149
# NAG Ltd.
151150
function givensAlgorithm(f::Complex{T}, g::Complex{T}) where T<:AbstractFloat
152-
twopar, onepar = 2one(T), one(T)
151+
onepar = one(T)
153152
T0 = typeof(onepar) # dimensionless
154153
zeropar = T0(zero(T)) # must be dimensionless
155154
czero = complex(zeropar)
@@ -170,7 +169,7 @@ function givensAlgorithm(f::Complex{T}, g::Complex{T}) where T<:AbstractFloat
170169
fs *= safmn2
171170
gs *= safmn2
172171
scalepar *= safmn2
173-
if scalepar < safmx2u break end
172+
if scalepar < safmx2u || count >= 20 break end
174173
end
175174
elseif scalepar <= safmn2u
176175
if g == 0
@@ -193,13 +192,13 @@ function givensAlgorithm(f::Complex{T}, g::Complex{T}) where T<:AbstractFloat
193192
# This is a rare case: F is very small.
194193
if f == 0
195194
cs = zero(T)
196-
r = complex(hypot(real(g), imag(g)))
195+
r = complex(abs(g))
197196
# do complex/real division explicitly with two real divisions
198-
d = hypot(real(gs), imag(gs))
197+
d = abs(gs)
199198
sn = complex(real(gs)/d, -imag(gs)/d)
200199
return cs, sn, r
201200
end
202-
f2s = hypot(real(fs), imag(fs))
201+
f2s = abs(fs)
203202
# g2 and g2s are accurate
204203
# g2 is at least safmin, and g2s is at least safmn2
205204
g2s = sqrt(g2)
@@ -214,7 +213,7 @@ function givensAlgorithm(f::Complex{T}, g::Complex{T}) where T<:AbstractFloat
214213
# make sure abs(ff) = 1
215214
# do complex/real division explicitly with 2 real divisions
216215
if abs1(f) > 1
217-
d = hypot(real(f), imag(f))
216+
d = abs(f)
218217
ff = complex(real(f)/d, imag(f)/d)
219218
else
220219
dr = safmx2*real(f)

test/givens.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module TestGivens
44

55
using Test, LinearAlgebra, Random
6-
using LinearAlgebra: Givens, Rotation
6+
using LinearAlgebra: Givens, Rotation, givensAlgorithm
77

88
# Test givens rotations
99
@testset "Test Givens for $elty" for elty in (Float32, Float64, ComplexF32, ComplexF64)
@@ -112,4 +112,13 @@ oneunit(::Type{<:MockUnitful{T}}) where T = MockUnitful(one(T))
112112
@test r.data 5.0
113113
end
114114

115+
# 51554
116+
# avoid infinite loop on Inf inputs
117+
@testset "givensAlgorithm - Inf inputs" for T in (Float64, ComplexF64)
118+
cs, sn, r = givensAlgorithm(T(Inf), T(1.0))
119+
@test !isfinite(r)
120+
cs, sn, r = givensAlgorithm(T(1.0), T(Inf))
121+
@test !isfinite(r)
122+
end
123+
115124
end # module TestGivens

0 commit comments

Comments
 (0)