From 7a167062a7486f82d777eec4577a47c59cd05fa5 Mon Sep 17 00:00:00 2001 From: Peter Ahrens Date: Wed, 6 Feb 2019 20:21:08 -0500 Subject: [PATCH 1/3] update counter in broadcast generated function to handle zero dimensional case --- src/broadcast.jl | 24 ++++++++++++++---------- test/broadcast.jl | 6 ++++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/broadcast.jl b/src/broadcast.jl index a0972a75..844d5b12 100644 --- a/src/broadcast.jl +++ b/src/broadcast.jl @@ -164,19 +164,23 @@ end exprs[current_ind...] = :(dest[$j] = f($(exprs_vals...))) # increment current_ind (maybe use CartesianIndices?) - current_ind[1] += 1 - for i ∈ 1:length(newsize) - if current_ind[i] > newsize[i] - if i == length(newsize) - more = false - break + if length(current_ind) >= 1 + current_ind[1] += 1 + for i ∈ 1:length(newsize) + if current_ind[i] > newsize[i] + if i == length(newsize) + more = false + break + else + current_ind[i] = 1 + current_ind[i+1] += 1 + end else - current_ind[i] = 1 - current_ind[i+1] += 1 + break end - else - break end + else + break end j += 1 end diff --git a/test/broadcast.jl b/test/broadcast.jl index e8e71c93..6f2b919d 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -35,6 +35,12 @@ end @test @inferred(v2 .* 1.0)::typeof(v) == v end + @testset "0-dimensional Array broadcast" begin + x = Array{Int, 0}(undef) + x .= Scalar(4) + @test x[] == 4 + end + @testset "2x2 StaticMatrix with StaticVector" begin m = @SMatrix [1 2; 3 4] v = SVector(1, 4) From 7f95150a68e3273b34aada8bc721658efc882d77 Mon Sep 17 00:00:00 2001 From: Peter Ahrens Date: Wed, 6 Feb 2019 20:49:41 -0500 Subject: [PATCH 2/3] some interesting stuff. --- src/MScalar.jl | 25 +++++++++++++++++++++++++ src/StaticArrays.jl | 3 ++- src/indexing.jl | 6 ++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/MScalar.jl diff --git a/src/MScalar.jl b/src/MScalar.jl new file mode 100644 index 00000000..f5cf1cb3 --- /dev/null +++ b/src/MScalar.jl @@ -0,0 +1,25 @@ +""" + MScalar{T}(x::T) + +Construct a mutable, statically-sized, 0-dimensional array that contains a +single element, `x`. This type is particularly useful for influencing +broadcasting operations. +""" +const MScalar{T} = MArray{Tuple{},T,0,1} + +@inline MScalar(x::Tuple{T}) where {T} = MScalar{T}(x[1]) +@inline MScalar(a::AbstractArray) = MScalar{typeof(a)}((a,)) +@inline MScalar(a::AbstractScalar) = MScalar{eltype(a)}((a[],)) # Do we want this to convert or wrap? +@inline function convert(::Type{SA}, a::AbstractArray) where {SA <: MScalar} + return MScalar((a[],)) +end +@inline convert(::Type{SA}, sa::SA) where {SA <: MScalar} = sa + +getindex(v::MScalar) = v[1] +setindex!(v::MScalar, x) = v[1] = x + +# A lot more compact than the default array show +Base.show(io::IO, ::MIME"text/plain", x::MScalar{T}) where {T} = print(io, "MScalar{$T}(", x.data, ")") + +# Simplified show for the type +show(io::IO, ::Type{MScalar{T}}) where {T} = print(io, "MScalar{T}") diff --git a/src/StaticArrays.jl b/src/StaticArrays.jl index de0b3c73..2459ba57 100644 --- a/src/StaticArrays.jl +++ b/src/StaticArrays.jl @@ -28,7 +28,7 @@ end export SOneTo export StaticScalar, StaticArray, StaticVector, StaticMatrix export Scalar, SArray, SVector, SMatrix -export MArray, MVector, MMatrix +export MScalar, MArray, MVector, MMatrix export FieldVector export SizedArray, SizedVector, SizedMatrix export SDiagonal @@ -108,6 +108,7 @@ include("Scalar.jl") include("MArray.jl") include("MVector.jl") include("MMatrix.jl") +include("MScalar.jl") include("SizedArray.jl") include("SDiagonal.jl") diff --git a/src/indexing.jl b/src/indexing.jl index 21edb874..ac0634d2 100644 --- a/src/indexing.jl +++ b/src/indexing.jl @@ -24,6 +24,9 @@ end end stride *= Size(S)[i] end + if length(inds) < 1 + ind_expr = :(1) + end return quote @_propagate_inbounds_meta a[$ind_expr] @@ -46,6 +49,9 @@ end end stride *= S[i] end + if length(inds) < 1 + ind_expr = :(1) + end return quote @_propagate_inbounds_meta a[$ind_expr] = value From 7827c851ffdfacd0952afb0b8fdcb503b7f2533c Mon Sep 17 00:00:00 2001 From: Peter Ahrens Date: Wed, 6 Feb 2019 21:10:25 -0500 Subject: [PATCH 3/3] added a new `MScalar` type to represent zero-dimensional MArrays. fixed bugs with zero-dimensional MArray getindex. --- src/MScalar.jl | 3 --- test/MScalar.jl | 22 ++++++++++++++++++++++ test/runtests.jl | 1 + 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 test/MScalar.jl diff --git a/src/MScalar.jl b/src/MScalar.jl index f5cf1cb3..20483f4f 100644 --- a/src/MScalar.jl +++ b/src/MScalar.jl @@ -15,9 +15,6 @@ const MScalar{T} = MArray{Tuple{},T,0,1} end @inline convert(::Type{SA}, sa::SA) where {SA <: MScalar} = sa -getindex(v::MScalar) = v[1] -setindex!(v::MScalar, x) = v[1] = x - # A lot more compact than the default array show Base.show(io::IO, ::MIME"text/plain", x::MScalar{T}) where {T} = print(io, "MScalar{$T}(", x.data, ")") diff --git a/test/MScalar.jl b/test/MScalar.jl new file mode 100644 index 00000000..e3ca2045 --- /dev/null +++ b/test/MScalar.jl @@ -0,0 +1,22 @@ +@testset "MScalar" begin + @test MScalar(2) .* [1, 2, 3] == [2, 4, 6] + @test_throws DimensionMismatch (MScalar(2) .= (Scalar(2) .* [1, 2, 3])) == [2, 4, 6] + @test MScalar([1 2; 3 4]) .+ [[1 1; 1 1], [2 2; 2 2]] == [[2 3; 4 5], [3 4; 5 6]] + @test (MScalar(1) + MScalar(1.0))::MScalar{Float64} ≈ MScalar(2.0) + @test_throws BoundsError MScalar(2)[2] + @test MScalar(2)[] == 2 + x = MScalar(2) + x[] = 1 + @test x[] == 1 + @testinf Tuple(MScalar(2)) === (2,) + @testinf Tuple(convert(MScalar{Float64}, [2.0])) === (2.0,) + a = Array{Float64, 0}(undef) + a[] = 2 + @test MScalar(a)[] == 2 + s = MScalar(a) + @test convert(typeof(s), s) === s + s[] = 1 + @test s[] == 1 + s .= 42 + @test s[] == 42 +end diff --git a/test/runtests.jl b/test/runtests.jl index e362b920..8e177542 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -20,6 +20,7 @@ include("SArray.jl") include("MArray.jl") include("FieldVector.jl") include("Scalar.jl") +include("MScalar.jl") include("SUnitRange.jl") include("SizedArray.jl") include("SDiagonal.jl")