-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Improve linalg error messages and coverage reports, round 2 #12434
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
Conversation
@@ -35,7 +35,9 @@ end | |||
Bidiagonal(A::AbstractMatrix, isupper::Bool)=Bidiagonal(diag(A), diag(A, isupper?1:-1), isupper) | |||
|
|||
function getindex{T}(A::Bidiagonal{T}, i::Integer, j::Integer) | |||
(1<=i<=size(A,2) && 1<=j<=size(A,2)) || throw(BoundsError()) | |||
if !(1<=i<=size(A,2) && 1<=j<=size(A,2)) | |||
return throw(BoundsError()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does it have a return?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh god. Thanks for the catch. I guess we know this path isn't tested!
f33fa4a
to
04ad48f
Compare
setindex!(A::LowerTriangular, x, i::Integer, j::Integer) = i >= j ? (A.data[i,j] = x; A) : throw(BoundsError()) | ||
setindex!(A::UnitLowerTriangular, x, i::Integer, j::Integer) = i > j ? (A.data[i,j] = x; A) : throw(BoundsError()) | ||
function setindex!(A::UpperTriangular, x, i::Integer, j::Integer) | ||
if i <= j |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be:
i <= j && throw(BoundsError("($i,$j) indices not in upper triangle"))
A.data[i,j] = x
return A
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that doesn't fix the coverage reporting issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that had been solved?
I got in trouble for changing the expr && throw's if's, remember? 😀
Even so, changing it to an if, I think it is better to have the errors first, and what you return at the end, instead of the other way around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK we are not computing partial coverage on each line yet for Codecov. Until that happens it won't be clear that parts of the line are not covered. Moving the code right of &&
or ||
to the next line did not fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, then I hope nobody will complain if I go back to changing things to if's in the string code! 😀 (but I still think the pattern of having the throws first, then the computations, finally return value, is clearer)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be:
if i > j
throw(BoundsError(A, i)
end
A.data[i,j] = x
return A
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't think these 4 would be easier to understand as above (but with (i,j)
as you did for the second arg to BoundsError
)?
Having two things on one line, without the return, now that you've expanded the functions, seems confusing.
Don't we normal try to have error messages without starting capital letter? Also we should probably be consistent in usage of "should have", "needs a", "must have" in error messages. That can be decided on at some other time though. |
@@ -35,7 +35,9 @@ end | |||
Bidiagonal(A::AbstractMatrix, isupper::Bool)=Bidiagonal(diag(A), diag(A, isupper?1:-1), isupper) | |||
|
|||
function getindex{T}(A::Bidiagonal{T}, i::Integer, j::Integer) | |||
(1<=i<=size(A,2) && 1<=j<=size(A,2)) || throw(BoundsError()) | |||
if !(1<=i<=size(A,2) && 1<=j<=size(A,2)) | |||
throw(BoundsError()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this have more information about the subscript(s) that were out of bounds? Would that be BoundsError(A,i,j)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, you'd need to have two separate ones, BoundsError(A,i)
, or BoundsError(A,j)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if !(1 <= i <= size(A,2))
throw(BoundsError(A,i))
elseif !(1 <= j <= size(A,2))
throw(BoundsError(A,j))
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think this should be addressed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that BoundsError(A,(i,j))
is the right one here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that would work also, it just shouldn't be left BoundsError()
with no information.
Unfortunately, I think all of the ones with |
@KristofferC is correct, with a few exceptions, all of the DimensionError messages start with lower-case. |
BTW, this is great stuff, and the linalg reorg looks very nice when I did |
04ad48f
to
e51e0dd
Compare
I pulled out the strings from the |
@@ -71,7 +71,7 @@ vecnorm2{T<:BlasFloat}(x::Union{Array{T},StridedVector{T}}) = | |||
function triu!(M::AbstractMatrix, k::Integer) | |||
m, n = size(M) | |||
if (k > 0 && k > n) || (k < 0 && -k > m) | |||
throw(BoundsError()) | |||
throw(BoundsError("Requested diagonal, $k, out of bounds in matrix of size ($m,$n)")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These haven't been addressed yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think BoundsError
should take an array and index tuple as arguments. You could just use an ArgumentError
. It's more flexible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That can cause problems, if there is any code with try/catch expecting the BoundsError
(had to deal with that when I was dealing with trying to improve the messages in AbstractArray
)
I've added a few comments, but only minor things. I think it makes the source more readable which is a nice bonus from your test coverage mission. |
SymTridiagonal(A.d, A.dl) | ||
end | ||
|
||
function convert(::Type{Diagonal}, A::AbstractTriangular) | ||
full(A) == diagm(diag(A)) || throw(ArgumentError("Matrix cannot be represented as Diagonal")) | ||
if full(A) != diagm(diag(A)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@andreasnoack it seems terribly inefficient to do a full conversion here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. That is bananas. Allocating three arrays for an operation that doesn't require a single is not efficient. I'll prepare a fix when this is merged.
e51e0dd
to
b07fe3e
Compare
Updated! I added a bunch of |
@kshyatt looks good, a nitpick but maybe stick with the convention that all error messages are lowercased (when appropriate). |
I tried to! Did I miss somewhere? It's not a nitpick - stylistic consistency is important :). |
|
CURSES! Can we wait to see if CI passes, and if so, I'll correct that then merge? |
There's enough of a queue ATM that it wont make much difference if you fix now, the pending jobs will automatically fail fast and if you fix it quickly you'll have the same place in line. |
Boss. On the case! |
matmul's also not the only case with still-uppercase errors, also |
b07fe3e
to
f08cd7e
Compare
Ok! I fixed |
f08cd7e
to
69de1fd
Compare
Just a personal remark but I don't like the word |
We should open an issue to decide on a common syntax for these messages. |
length(rx)==length(ry) || throw(DimensionMismatch()) | ||
if length(rx) != length(ry) | ||
throw(DimensionMismatch("length of rx, $(length(rx)), does not equal length of ry, $(length(ry))")) | ||
end | ||
if minimum(rx) < 1 || maximum(rx) > length(x) || minimum(ry) < 1 || maximum(ry) > length(y) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one still has no information in the BoundsError
Lines 163 and 180 in bidiag.jl still have "Size" instead of "size" in |
dense.jl has an empty |
Did something dumb, fixing now. |
I still see the following problems: |
I'm going to merge this once CI passes and then you can submit the fixes you see as a separate PR, ok? |
Improve linalg error messages and coverage reports, round 2
Now that it's merged, @ScottPJones, feel free to make whatever fixes seem necessary in a new PR. |
@StefanKarpinski Done. There probably needs to be some more coverage tests, because the changes in #12434 would have actually gotten errors from the places where julia> throw(BoundsError("foobar"))
ERROR: BoundsError: attempt to access "foobar" |
More coverage is always good. |
I expanded a bunch of functions so that we can see if all branch paths are followed for coverage purposes. I also tried to improve a bunch of error messages, by replacing
error
withthrow(ArgumentErrror())
in relevant spots and improving the text of the message.