Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make behavior of ^(::Matrix{<:Integer},::Integer) consistent with behavior of ^(::Integer, ::Integer) #23368

Merged
merged 16 commits into from
Aug 24, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
added specialized domain error message for
`^(::Matrix{<:Integer},::Integer)`,
added `@inferred` and comments to test
afniedermayer committed Aug 22, 2017
commit 56f50914785e3e34a522c8f8fb21ef2b220cf659
11 changes: 8 additions & 3 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
@@ -160,10 +160,15 @@ invmod(n::Integer, m::Integer) = invmod(promote(n,m)...)

# ^ for any x supporting *
to_power_type(x) = convert(Base.promote_op(*, typeof(x), typeof(x)), x)
@noinline throw_domerr_powbysq(p) = throw(DomainError(p,
@noinline throw_domerr_powbysq(::Any, p) = throw(DomainError(p,
string("Cannot raise an integer x to a negative power ", p, '.',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is generic function, it might make sense to make this message generic if it doesn't make it (much) less informative. What about just writing "Cannot raise an integer x to a negative power. Try converting input to float". We could keep this version but restrict the inputs to Integers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you mean three versions of throw_domerr_powbysq: for ::Any (short message), ::Integer (message above), and ::AbstractMatrix (message below)?

"\nMake x a float by adding a zero decimal (e.g., 2.0^$p instead ",
"of 2^$p), or write 1/x^$(-p), float(x)^$p, or (x//1)^$p")))
@noinline throw_domerr_powbysq(::AbstractMatrix, p) = throw(DomainError(p,
string("Cannot raise an integer matrix x to a negative power ", p, '.',
"\nMake x a float matrix by adding a zero decimal ",
"(e.g., [2.0 1.0;1.0 0.0]^$p instead ",
"of [2 1;1 0]^$p), or write float(x)^$p or Rational.(x)^$p")))
function power_by_squaring(x_, p::Integer)
x = to_power_type(x_)
if p == 1
@@ -175,7 +180,7 @@ function power_by_squaring(x_, p::Integer)
elseif p < 0
isone(x) && return copy(x)
isone(-x) && return iseven(p) ? one(x) : copy(x)
throw_domerr_powbysq(p)
throw_domerr_powbysq(x, p)
end
t = trailing_zeros(p) + 1
p >>= t
@@ -195,7 +200,7 @@ function power_by_squaring(x_, p::Integer)
end
power_by_squaring(x::Bool, p::Unsigned) = ((p==0) | x)
function power_by_squaring(x::Bool, p::Integer)
p < 0 && !x && throw_domerr_powbysq(p)
p < 0 && !x && throw_domerr_powbysq(x, p)
return (p==0) | x
end

12 changes: 8 additions & 4 deletions test/linalg/dense.jl
Original file line number Diff line number Diff line change
@@ -587,16 +587,20 @@ end
UInt128, UInt16, UInt32, UInt64, UInt8,
BigInt)
@test_throws DomainError elty[1 1;1 0]^-2
@test elty[1 1;1 0]^2 == elty[2 1;1 1]
@test (@inferred elty[1 1;1 0]^2) == elty[2 1;1 1]
I_ = elty[1 0;0 1]
@test I_^-1 == I_
if !(elty<:Unsigned)
@test (-I_)^-1 == -I_
@test (-I_)^-2 == I_
@test (@inferred (-I_)^-1) == -I_
@test (@inferred (-I_)^-2) == I_
end
# make sure that type promotion for ^(::Matrix{<:Integer}, ::Integer)
# is analogous to type promotion for ^(::Integer, ::Integer)
# e.g. [1 1;1 0]^big(10000) should return Matrix{BigInt}, the same
# way as 2^big(10000) returns BigInt
for elty2 = (Int64, BigInt)
TT = Base.promote_op(^, elty, elty2)
@test Base.return_types(^, (Array{elty,2}, elty2)) == [Array{TT,2}]
@test (@inferred elty[1 1;1 0]^elty2(1))::Matrix{TT} == [1 1;1 0]
end
end
end