diff --git a/base/parse.jl b/base/parse.jl index b21d85f7faf99..a652e1f7387ab 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -319,7 +319,7 @@ function tryparse_internal(::Type{Complex{T}}, s::Union{String,SubString{String} end if i₊ == 0 # purely real or imaginary value - if iᵢ > 0 # purely imaginary + if iᵢ > i && !(iᵢ == i+1 && s[i] in ('+','-')) # purely imaginary (not "±inf") x = tryparse_internal(T, s, i, iᵢ-1, raise) x === nothing && return nothing return Complex{T}(zero(x),x) diff --git a/src/support/strtod.c b/src/support/strtod.c index 047d404d90cda..225f2dbd4c933 100644 --- a/src/support/strtod.c +++ b/src/support/strtod.c @@ -118,9 +118,16 @@ JL_DLLEXPORT double jl_strtod_c(const char *nptr, char **endptr) decimal_point_pos = NULL; + p = nptr; + + /* parse leading spaces */ + while (isspace((unsigned char)*p)) { + p++; + } + /* Parse infinities and nans */ - val = parse_inf_or_nan(nptr, endptr); - if (*endptr != nptr) + val = parse_inf_or_nan(p, endptr); + if (*endptr != p) return val; /* 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) /* We process the optional sign manually, then pass the remainder to the system strtod. This ensures that the result of an underflow has the correct sign. */ - p = nptr; - - /* parse leading spaces */ - while (isspace((unsigned char)*p)) { - p++; - } /* Process leading sign, if present */ if (*p == '-') { diff --git a/test/parse.jl b/test/parse.jl index 45e13a95b7f90..1d3e064823cf4 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -278,8 +278,8 @@ end # parsing complex numbers (#22250) @testset "complex parsing" begin - for r in (1,0,-1), i in (1,0,-1), sign in ('-','+'), Im in ("i","j","im") - for s1 in (""," "), s2 in (""," "), s3 in (""," "), s4 in (""," ") + for sign in ('-','+'), Im in ("i","j","im"), s1 in (""," "), s2 in (""," "), s3 in (""," "), s4 in (""," ") + for r in (1,0,-1), i in (1,0,-1), n = Complex(r, sign == '+' ? i : -i) s = string(s1, r, s2, sign, s3, i, Im, s4) @test n === parse(Complex{Int}, s) @@ -293,6 +293,13 @@ end @test n*parse(T,"1e-3") == parse(Complex{T}, string(s1, r, "e-3", s2, sign, s3, i, "e-3", Im, s4)) end end + for r in (-1.0,-1e-9,Inf,-Inf,NaN), i in (-1.0,-1e-9,Inf,NaN) + n = Complex(r, sign == '+' ? i : -i) + s = lowercase(string(s1, r, s2, sign, s3, i, Im, s4)) + @test n === parse(ComplexF64, s) + @test Complex(r) === parse(ComplexF64, string(s1, r, s2)) + @test Complex(0,i) === parse(ComplexF64, string(s3, i, Im, s4)) + end end @test parse(Complex{Float16}, "3.3+4i") === Complex{Float16}(3.3+4im) @test parse(Complex{Int}, SubString("xxxxxx1+2imxxxx", 7, 10)) === 1+2im @@ -338,3 +345,10 @@ end # Ensure dotting binary doesn't break dotting unary @test Meta.parse(".~[1,2]") == Expr(:call, :.~, Expr(:vect, 1, 2)) end + +@testset "inf and nan parsing" begin + for (v,vs) in ((NaN,"nan"), (Inf,"inf"), (Inf,"infinity")), sbefore in ("", " "), safter in ("", " "), sign in (+, -), case in (lowercase, uppercase) + s = case(string(sbefore, sign, vs, safter)) + @test isequal(parse(Float64, s), sign(v)) + end +end