-
Notifications
You must be signed in to change notification settings - Fork 149
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
Rewrite all @pure
functions
#105
Conversation
* Now we use `Size` more consistently and rely less on `@pure` implementations of `similar_type`. * `similar` and `similar_type` both use `Size` not integers to discuss size * `similar` and `similar_type` are now streamlined. Users only need to override one definition, just like in Base. * Associated documentation and test changes.
cff869b
to
5177a27
Compare
This was a little tricky to get inference working well on v0.5. I had to use But in general I think this reorganization is a very good thing. |
Test failure is caused by JuliaLang/julia#20620 on Julia master (v0.5 works). (Ideally we would deal with this more fully but it seems orthogonal to this PR). |
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.
Great effort Andy, this looks like a fair bit of work.
The result is a nice improvement, I think. I like how Size
is fitting in here.
@pure Size{S}(::Type{MArray{S}}) = Size(S) | ||
@pure Size{S,T}(::Type{MArray{S,T}}) = Size(S) | ||
@pure Size{S,T,N}(::Type{MArray{S,T,N}}) = Size(S) | ||
@pure Size{S,T,N,L}(::Type{MArray{S,T,N,L}}) = Size(S) |
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.
Do you know whether this kind of repetition go away with the new type system work in 0.6?
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 Size(::Type{T} where T <: MArray{S}) where S = Size(S)
might be sufficient for all of the above, but I'd like to check. We could probably successfully move the @pure
to the Size
constructor and drop it from here, also.
@inline similar{SV <: StaticVector}(::SV) = MVector{length(SV),eltype(SV)}() | ||
@inline similar{SV <: StaticVector, T}(::SV, ::Type{T}) = MVector{length(SV),T}() | ||
similar{SA<:StaticArray,T}(::SA,::Type{T}) = similar(SA,T,Size(SA)) | ||
similar{SA<:StaticArray,T}(::Type{SA},::Type{T}) = similar(SA,T,Size(SA)) |
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.
So now we've got similar
based on input StaticArray
type as well as value. I guess that makes sense as they all still return a value which can be written into. Did did we have it before anywhere?
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 so (or we should have) but it was all a bit dodgier...
src/core.jl
Outdated
a `MVector`, `MMatrix` or `MArray`. You will benefit from overloading this if | ||
your container is already mutable! | ||
- `setindex!` on mutable arrays (e.g. those returned by `similar`) | ||
- `setindex!` for a single elmenent (linear indexing). |
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.
elmenent
src/deque.jl
Outdated
@generated function push(vec::StaticVector, x) | ||
newtype = similar_type(vec, (length(vec) + 1 ,)) | ||
newtype = similar_type(vec, Size(length(vec) + 1 ,)) |
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.
Minor tidy up: trailing comma no longer required here and in the rest of deque.jl
.
@@ -54,7 +54,7 @@ end | |||
error("Dimension mismatch") | |||
end | |||
|
|||
exprs = [i == j ? :(a.λ + b[$(sub2ind(size(a), i, j))]) : :(b[$(sub2ind(size(a), i, j))]) for i = 1:n, j = 1:n] | |||
exprs = [i == j ? :(a.λ + b[$(sub2ind(size(b), i, j))]) : :(b[$(sub2ind(size(b), i, j))]) for i = 1:n, j = 1: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.
I guess this never worked before?
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.
No... we need to work to improve test coverage.
test/FieldVector.jl
Outdated
@@ -18,19 +18,21 @@ | |||
@test length(p) === 3 | |||
@test eltype(p) === Float64 | |||
|
|||
@test (p + p)::Point3D ≈ Point3D(2.0, 4.0, 6.0) |
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.
Can use ===
here, I think, to check that both the elements and type are the same. (Elements should sum exactly, as the result is exactly representable in Float64
.)
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 never know when to trust floating point arithmetic
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.
The rules say that basic floating point arithmetic operations should be correctly rounded. In particular, this means that if all intermediate results of a computation are exactly representable, then the final result is exact.
This certainly holds true when you're adding, subtracting and multiplying exact integers using floating point arithmetic, up until maxintfloat(Float64) == 9.007199254740992e15
.
The reason I bring this up is that isapprox
uses quite a generous default for rtol
, a lot looser than you'd really want in many tests.
@test @SMatrix([1 2 3; 4 5 6])' === @SMatrix([1 4; 2 5; 3 6]) | ||
@test @inferred(ctranspose(@SVector([1, 2, 3]))) === @SMatrix([1 2 3]) | ||
@test @inferred(ctranspose(@SMatrix([1 2; 0 3]))) === @SMatrix([1 0; 2 3]) | ||
@test @inferred(ctranspose(@SMatrix([1 2 3; 4 5 6]))) === @SMatrix([1 4; 2 5; 3 6]) |
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's a lot of @inferred
. You need a custom @testinferred
macro or some kind of helper to make these easier to look at ;-)
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.
:)
test/linalg.jl
Outdated
@@ -82,4 +114,8 @@ | |||
|
|||
@test normalize(SVector(1,2,3)) ≈ normalize([1,2,3]) | |||
end | |||
|
|||
@testset "trace" begin | |||
@test trace(@SMatrix [1.0 2.0; 3.0 4.0]) ≈ 5.0 |
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.
Can be exact equality, not \approx
I assume the CI failures in latest 0.6 are expected for now? |
e600e89
to
6344b4f
Compare
Now we use
Size
more consistently and rely less on@pure
implementations ofsimilar_type
.similar
andsimilar_type
both useSize
not integers to discuss sizesimilar
andsimilar_type
are now streamlined. Users only need tooverride one definition, just like in Base.
Associated documentation and test changes.