Skip to content

reinterpret SVector as Vector{SVector} #634

Open
@halleysfifthinc

Description

@halleysfifthinc

Last year, I had code to reinterpret an SVector with length N*3 as a Vector{SVector{3}} like reinterpret(SVector{3, Float64}, SVector{12}(1.0:12.0)). However this now errors:

julia> reinterpret(SVector{3, Float64}, SVector{12}(1.0:12.0))
DimensionMismatch("1:4 is inconsistent with SOneTo{12}")

Stacktrace:
 [1] (::getfield(StaticArrays, Symbol("#errmsg#1")){12})(::UnitRange{Int64}) at ~/.julia/packages/StaticArrays/3KEjZ/src/SOneTo.jl:14
 [2] Type at ~/.julia/packages/StaticArrays/3KEjZ/src/SOneTo.jl:15 [inlined]
 [3] convert at ./range.jl:143 [inlined]
 [4] oftype at ./essentials.jl:370 [inlined]
 [5] axes at ./reinterpretarray.jl:112 [inlined]
 [6] summary at ./show.jl:1863 [inlined]
 [7] show(::IOContext{Base.GenericIOBuffer{Array{UInt8,1}}}, ::MIME{Symbol("text/plain")}, ::Base.ReinterpretArray{SArray{Tuple{3},Float64,1,3},1,Float64,SArray{Tuple{12},Float64,1,12}}) at ./arrayshow.jl:316
 [8] limitstringmime(::MIME{Symbol("text/plain")}, ::Base.ReinterpretArray{SArray{Tuple{3},Float64,1,3},1,Float64,SArray{Tuple{12},Float64,1,12}}) at ~/.julia/packages/IJulia/gI2uA/src/inline.jl:37
 [9] display_mimestring(::MIME{Symbol("text/plain")}, ::Base.ReinterpretArray{SArray{Tuple{3},Float64,1,3},1,Float64,SArray{Tuple{12},Float64,1,12}}) at ~/.julia/packages/IJulia/gI2uA/src/display.jl:67
 [10] display_dict(::Base.ReinterpretArray{SArray{Tuple{3},Float64,1,3},1,Float64,SArray{Tuple{12},Float64,1,12}}) at ~/.julia/packages/IJulia/gI2uA/src/display.jl:96
 [11] #invokelatest#1 at ./essentials.jl:790 [inlined]
 [12] invokelatest at ./essentials.jl:789 [inlined]

The issue being that SOneTo will only convert identical UnitRanges (e.g. SOneTo{4} == 1:4, this is due to a requirement in the constructor at src/SOneTo.jl:12), so the axes are unable to be properly constructed. It seems reasonable to me that if somebody is trying to convert a unit range to an SOneTo, the range of the argument is most likely the intentional one, so relaxing the constructor to something like:

diff --git a/src/SOneTo.jl b/src/SOneTo.jl
index 96c1ad2..3dd29ba 100644
--- a/src/SOneTo.jl
+++ b/src/SOneTo.jl
@@ -9,10 +9,7 @@ end

 SOneTo(n::Int) = SOneTo{n}()
 function SOneTo{n}(r::AbstractUnitRange) where n
-    ((first(r) == 1) & (last(r) == n)) && return SOneTo{n}()
-
-    errmsg(r) = throw(DimensionMismatch("$r is inconsistent with SOneTo{$n}")) # avoid GC frame
-    errmsg(r)
+    (first(r) == 1) && return SOneTo{last(r)}()
 end

 Base.axes(s::SOneTo) = (s,)

Such a change makes my original example work again, and I will note that my example is also quite similar to the example given in #554. I wonder what the original intent behind this restriction was and/or if there are possible negatives to relaxing this? pinging @timholy as the author of that PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    fix-in-baseFix needs some work in Base

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions