From 5541c02e8da4bcd84f9ce76d70563c1761830b86 Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Thu, 27 Feb 2020 16:25:42 +1000 Subject: [PATCH 1/3] setindex! for non-isbits MArrays Implement this for the sake of people using MArray in generic code, even though it's unlikely to be fast. --- src/MArray.jl | 11 ++++++++--- test/MArray.jl | 9 ++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/MArray.jl b/src/MArray.jl index a9f452e8..ebe82322 100644 --- a/src/MArray.jl +++ b/src/MArray.jl @@ -94,9 +94,14 @@ end if isbitstype(T) GC.@preserve v unsafe_store!(Base.unsafe_convert(Ptr{T}, pointer_from_objref(v)), convert(T, val), i) else - # This one is unsafe (#27) - # unsafe_store!(Base.unsafe_convert(Ptr{Ptr{Nothing}}, pointer_from_objref(v.data)), pointer_from_objref(val), i) - error("setindex!() with non-isbitstype eltype is not supported by StaticArrays. Consider using SizedArray.") + # This is inherently slow because we've got to rebuild a new Tuple to + # reassign to data.v. + # + # However it seems not possible to make fast without having some kind + # of mutable pseudo-container which is inlined as a part of the parent + # struct such that you can't access it separately. (A mutable + # FieldArray achieves this, but can't be parameterized on the size.) + @inbounds v.data = setindex(v.data, val, i) end return val diff --git a/test/MArray.jl b/test/MArray.jl index 3a15eda8..d37e20fb 100644 --- a/test/MArray.jl +++ b/test/MArray.jl @@ -142,9 +142,12 @@ @test_throws BoundsError setindex!(mm, 4, -1) @test_throws BoundsError setindex!(mm, 4, 82) - # setindex with non-elbits type - m = MArray{Tuple{2,2,2}, String}(undef) - @test_throws ErrorException setindex!(m, "a", 1, 1, 1) + # setindex with non-bits eltype + m = fill("a", MMatrix{2,2, String}) + m[1,1] = "b" + m[1,2] = "c" + @test m == ["b" "c"; + "a" "a"] end @testset "promotion" begin From 102686014b6bad85f566322fb3c98ee51c198a36 Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Thu, 27 Feb 2020 20:20:34 +1000 Subject: [PATCH 2/3] Fix and consolidate tests for MVector / MMatrix into MArray There's not a lot of point testing MVector/MMatrix separately, as they're now the same struct (since Julia 0.6 or so) --- test/MArray.jl | 12 ++++++++++++ test/MMatrix.jl | 20 -------------------- test/MVector.jl | 19 ------------------- 3 files changed, 12 insertions(+), 39 deletions(-) diff --git a/test/MArray.jl b/test/MArray.jl index d37e20fb..63c81865 100644 --- a/test/MArray.jl +++ b/test/MArray.jl @@ -137,6 +137,18 @@ m[4] = 14 @test m.data === (11, 12, 13, 14) + m = @MMatrix [0 0; 0 0] + m[1] = Int8(11) + m[2] = Int8(12) + m[3] = Int8(13) + m[4] = Int8(14) + @test m.data === (11, 12, 13, 14) + + v = @MVector [1.,2.,3.] + v[1] = Float16(11) + @test v.data === (11., 2., 3.) + + v = @MArray [1,2,3] @test_throws BoundsError setindex!(v, 4, -1) mm = @MArray zeros(3,3,3,3) @test_throws BoundsError setindex!(mm, 4, -1) diff --git a/test/MMatrix.jl b/test/MMatrix.jl index aa85e765..e5a2ce0f 100644 --- a/test/MMatrix.jl +++ b/test/MMatrix.jl @@ -89,24 +89,4 @@ @test length(m) === 4 end - - @testset "setindex!" begin - m = @MMatrix [0 0; 0 0] - m[1] = 11 - m[2] = 12 - m[3] = 13 - m[4] = 14 - @test m.data === (11, 12, 13, 14) - - m = @MMatrix [0 0; 0 0] - m[1] = Int8(11) - m[2] = Int8(12) - m[3] = Int8(13) - m[4] = Int8(14) - @test m.data === (11, 12, 13, 14) - - # setindex with non-elbits type - m = MMatrix{2,2,String}(undef) - @test_throws ErrorException setindex!(m, "a", 1, 1) - end end diff --git a/test/MVector.jl b/test/MVector.jl index bdc430a7..3dc1638a 100644 --- a/test/MVector.jl +++ b/test/MVector.jl @@ -69,23 +69,4 @@ @test length(v) === 3 end - - @testset "setindex!" begin - v = @MVector [1,2,3] - v[1] = 11 - v[2] = 12 - v[3] = 13 - @test v.data === (11, 12, 13) - - v = @MVector [1.,2.,3.] - v[1] = Float16(11) - @test v.data === (11., 2., 3.) - - @test_throws BoundsError setindex!(v, 4., -1) - @test_throws BoundsError setindex!(v, 4., 4) - - # setindex with non-elbits type - v = MVector{2,String}(undef) - @test_throws ErrorException setindex!(v, "a", 1) - end end From c6033573ede8ac1c8522a16eaa3b56215bda46f4 Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Fri, 17 Apr 2020 20:29:06 +1000 Subject: [PATCH 3/3] Tweak comment to point to julia compiler inlining issue --- src/MArray.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/MArray.jl b/src/MArray.jl index ebe82322..c2b99ae4 100644 --- a/src/MArray.jl +++ b/src/MArray.jl @@ -97,10 +97,8 @@ end # This is inherently slow because we've got to rebuild a new Tuple to # reassign to data.v. # - # However it seems not possible to make fast without having some kind - # of mutable pseudo-container which is inlined as a part of the parent - # struct such that you can't access it separately. (A mutable - # FieldArray achieves this, but can't be parameterized on the size.) + # However it seems not possible to make fast, at least in julia 1.4 + # TODO: Revisit if https://github.com/JuliaLang/julia/pull/34126 is merged @inbounds v.data = setindex(v.data, val, i) end