Skip to content

Commit

Permalink
Merge pull request JuliaLang#31615 from JuliaLang/sgj/parseinf
Browse files Browse the repository at this point in the history
fix parse(ComplexF64, "inf")
  • Loading branch information
StefanKarpinski committed Apr 12, 2019
2 parents 6308ebd + c36e70b commit 4d4091d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 11 deletions.
2 changes: 1 addition & 1 deletion base/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
17 changes: 9 additions & 8 deletions src/support/strtod.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 == '-') {
Expand Down
18 changes: 16 additions & 2 deletions test/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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

0 comments on commit 4d4091d

Please sign in to comment.