Skip to content

Commit 4d4091d

Browse files
Merge pull request #31615 from JuliaLang/sgj/parseinf
fix parse(ComplexF64, "inf")
2 parents 6308ebd + c36e70b commit 4d4091d

File tree

3 files changed

+26
-11
lines changed

3 files changed

+26
-11
lines changed

base/parse.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ function tryparse_internal(::Type{Complex{T}}, s::Union{String,SubString{String}
319319
end
320320

321321
if i₊ == 0 # purely real or imaginary value
322-
if iᵢ > 0 # purely imaginary
322+
if iᵢ > i && !(iᵢ == i+1 && s[i] in ('+','-')) # purely imaginary (not "±inf")
323323
x = tryparse_internal(T, s, i, iᵢ-1, raise)
324324
x === nothing && return nothing
325325
return Complex{T}(zero(x),x)

src/support/strtod.c

+9-8
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,16 @@ JL_DLLEXPORT double jl_strtod_c(const char *nptr, char **endptr)
118118

119119
decimal_point_pos = NULL;
120120

121+
p = nptr;
122+
123+
/* parse leading spaces */
124+
while (isspace((unsigned char)*p)) {
125+
p++;
126+
}
127+
121128
/* Parse infinities and nans */
122-
val = parse_inf_or_nan(nptr, endptr);
123-
if (*endptr != nptr)
129+
val = parse_inf_or_nan(p, endptr);
130+
if (*endptr != p)
124131
return val;
125132

126133
/* Set errno to zero, so that we can distinguish zero results
@@ -130,12 +137,6 @@ JL_DLLEXPORT double jl_strtod_c(const char *nptr, char **endptr)
130137
/* We process the optional sign manually, then pass the remainder to
131138
the system strtod. This ensures that the result of an underflow
132139
has the correct sign. */
133-
p = nptr;
134-
135-
/* parse leading spaces */
136-
while (isspace((unsigned char)*p)) {
137-
p++;
138-
}
139140

140141
/* Process leading sign, if present */
141142
if (*p == '-') {

test/parse.jl

+16-2
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ end
278278

279279
# parsing complex numbers (#22250)
280280
@testset "complex parsing" begin
281-
for r in (1,0,-1), i in (1,0,-1), sign in ('-','+'), Im in ("i","j","im")
282-
for s1 in (""," "), s2 in (""," "), s3 in (""," "), s4 in (""," ")
281+
for sign in ('-','+'), Im in ("i","j","im"), s1 in (""," "), s2 in (""," "), s3 in (""," "), s4 in (""," ")
282+
for r in (1,0,-1), i in (1,0,-1),
283283
n = Complex(r, sign == '+' ? i : -i)
284284
s = string(s1, r, s2, sign, s3, i, Im, s4)
285285
@test n === parse(Complex{Int}, s)
@@ -293,6 +293,13 @@ end
293293
@test n*parse(T,"1e-3") == parse(Complex{T}, string(s1, r, "e-3", s2, sign, s3, i, "e-3", Im, s4))
294294
end
295295
end
296+
for r in (-1.0,-1e-9,Inf,-Inf,NaN), i in (-1.0,-1e-9,Inf,NaN)
297+
n = Complex(r, sign == '+' ? i : -i)
298+
s = lowercase(string(s1, r, s2, sign, s3, i, Im, s4))
299+
@test n === parse(ComplexF64, s)
300+
@test Complex(r) === parse(ComplexF64, string(s1, r, s2))
301+
@test Complex(0,i) === parse(ComplexF64, string(s3, i, Im, s4))
302+
end
296303
end
297304
@test parse(Complex{Float16}, "3.3+4i") === Complex{Float16}(3.3+4im)
298305
@test parse(Complex{Int}, SubString("xxxxxx1+2imxxxx", 7, 10)) === 1+2im
@@ -338,3 +345,10 @@ end
338345
# Ensure dotting binary doesn't break dotting unary
339346
@test Meta.parse(".~[1,2]") == Expr(:call, :.~, Expr(:vect, 1, 2))
340347
end
348+
349+
@testset "inf and nan parsing" begin
350+
for (v,vs) in ((NaN,"nan"), (Inf,"inf"), (Inf,"infinity")), sbefore in ("", " "), safter in ("", " "), sign in (+, -), case in (lowercase, uppercase)
351+
s = case(string(sbefore, sign, vs, safter))
352+
@test isequal(parse(Float64, s), sign(v))
353+
end
354+
end

0 commit comments

Comments
 (0)