From 959eb4cb8ed2a9bfc0fba1e3ea65e8873efa7bb0 Mon Sep 17 00:00:00 2001 From: Felipe Noronha Date: Thu, 27 Aug 2015 00:25:44 -0300 Subject: [PATCH] Raise informative error for float/integer exponentiation that yields Complex Same as #3024 --- base/replutil.jl | 23 +++++++++++++---------- test/math.jl | 5 +++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/base/replutil.jl b/base/replutil.jl index 4b0ca4437cc01..e5c8f4e3f4a73 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -106,11 +106,14 @@ function showerror(io::IO, ex::DomainError, bt; backtrace=true) code = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), b-1, true) if length(code) == 5 && !code[4] # code[4] == fromC if code[1] in (:log, :log2, :log10, :sqrt) # TODO add :besselj, :besseli, :bessely, :besselk - println(io,"\n$(code[1]) will only return a complex result if called with a complex argument.") - print(io, "try $(code[1]) (complex(x))") - elseif (code[1] == :^ && code[2] == symbol("intfuncs.jl")) || code[1] == :power_by_squaring - println(io, "\nCannot raise an integer x to a negative power -n. Make x a float by adding") - print(io, "a zero decimal (e.g. 2.0^-n instead of 2^-n), or write 1/x^n, float(x)^-n, or (x//1)^-n") + println(io,"\n$(code[1]) will only return a complex result if called with a complex argument. ", + "Try $(code[1]) (complex(x)).") + elseif (code[1] == :^ && code[2] == symbol("intfuncs.jl")) || code[1] == :power_by_squaring #3024 + println(io, "\nCannot raise an integer x to a negative power -n. \nMake x a float by adding ", + "a zero decimal (e.g. 2.0^-n instead of 2^-n), or write 1/x^n, float(x)^-n, or (x//1)^-n.") + elseif code[1] == :^ && (code[2] == symbol("promotion.jl") || code[2] == symbol("math.jl")) + println(io, "\nExponentiation yielding a complex result requires a complex argument. ", + "\nReplace x^y with (x+0im)^y, Complex(x)^y, or similar.") end break end @@ -173,9 +176,9 @@ function showerror(io::IO, ex::MethodError) push!(vec_args, isrow ? vec(arg) : arg) end if hasrows && applicable(f, vec_args...) - print(io, "\n\nYou might have used a 2d row vector where a 1d column vector was required.") - print(io, "\nNote the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].") - print(io, "\nYou can convert to a column vector with the vec() function.") + print(io, "\n\nYou might have used a 2d row vector where a 1d column vector was required.", + "\nNote the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].", + "\nYou can convert to a column vector with the vec() function.") end end # Give a helpful error message if the user likely called a type constructor @@ -185,8 +188,8 @@ function showerror(io::IO, ex::MethodError) arg_types_param[1].name === Type.name) construct_type = arg_types_param[1].parameters[1] println(io) - print(io, "This may have arisen from a call to the constructor $construct_type(...),") - print(io, "\nsince type constructors fall back to convert methods.") + print(io, "This may have arisen from a call to the constructor $construct_type(...),", + "\nsince type constructors fall back to convert methods.") end show_method_candidates(io, ex) end diff --git a/test/math.jl b/test/math.jl index 9413df6ea4b1d..f8d3f7f1a8095 100644 --- a/test/math.jl +++ b/test/math.jl @@ -542,3 +542,8 @@ for f in binary_math_functions @test f(x,[y]) == v @test f([x],[y]) == v end + +# #3024, #12822 +@test_throws DomainError 2 ^ -2 +@test_throws DomainError (-2)^(2.2) +@test_throws DomainError (-2.0)^(2.2)