Skip to content

Commit 184150e

Browse files
authored
Merge branch 'JuliaArrays:master' into master
2 parents 9374c65 + 19ecce7 commit 184150e

File tree

16 files changed

+191
-22
lines changed

16 files changed

+191
-22
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "StaticArrays"
22
uuid = "90137ffa-7385-5640-81b9-e52037218182"
3-
version = "1.9.8"
3+
version = "1.9.13"
44

55
[deps]
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

ext/StaticArraysStatisticsExt.jl

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
module StaticArraysStatisticsExt
22

3-
import Statistics: mean
3+
import Statistics: mean, median
4+
5+
using Base.Order: Forward, ord
6+
using Statistics: median!, middle
47

58
using StaticArrays
6-
using StaticArrays: _InitialValue, _reduce, _mapreduce
9+
using StaticArrays: BitonicSort, _InitialValue, _reduce, _mapreduce, _bitonic_sort_limit, _sort
710

811
_mean_denom(a, ::Colon) = length(a)
912
_mean_denom(a, dims::Int) = size(a, dims)
@@ -12,4 +15,37 @@ _mean_denom(a, ::Val{D}) where {D} = size(a, D)
1215
@inline mean(a::StaticArray; dims=:) = _reduce(+, a, dims) / _mean_denom(a, dims)
1316
@inline mean(f::Function, a::StaticArray; dims=:) = _mapreduce(f, +, dims, _InitialValue(), Size(a), a) / _mean_denom(a, dims)
1417

18+
@inline function median(a::StaticArray; dims = :)
19+
if dims == Colon()
20+
median(vec(a))
21+
else
22+
# FIXME: Implement `mapslices` correctly on `StaticArray` to remove
23+
# this fallback.
24+
median(Array(a); dims)
25+
end
26+
end
27+
28+
@inline function median(a::StaticVector)
29+
(isimmutable(a) && length(a) <= _bitonic_sort_limit) ||
30+
return median!(Base.copymutable(a))
31+
32+
# following Statistics.median
33+
isempty(a) &&
34+
throw(ArgumentError("median of empty vector is undefined, $(repr(a))"))
35+
eltype(a) >: Missing && any(ismissing, a) &&
36+
return missing
37+
nanix = findfirst(x -> x isa Number && isnan(x), a)
38+
isnothing(nanix) ||
39+
return a[nanix]
40+
41+
order = ord(isless, identity, nothing, Forward)
42+
sa = _sort(Tuple(a), BitonicSort, order)
43+
44+
n = length(a)
45+
# sa is 1-indexed
46+
return isodd(n) ?
47+
middle(sa[n ÷ 2 + 1]) :
48+
middle(sa[n ÷ 2], sa[n ÷ 2 + 1])
49+
end
50+
1551
end # module

src/MArray.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ end
4242
return v
4343
end
4444

45-
@inline Tuple(v::MArray) = getfield(v,:data)
45+
@inline Base.Tuple(v::MArray) = getfield(v,:data)
4646

4747
Base.dataids(ma::MArray) = (UInt(pointer(ma)),)
4848

src/MVector.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ end
1818
let dimension_names = QuoteNode.([:x, :y, :z, :w])
1919
body = :(getfield(v, name))
2020
for (i,dim_name) in enumerate(dimension_names)
21+
@eval @inline function Base.propertynames(v::Union{SVector{$i},MVector{$i}}, private::Bool = false)
22+
named_dims = ($(first(dimension_names, i)...),)
23+
private ? (named_dims..., :data) : named_dims
24+
end
25+
2126
body = :(name === $(dimension_names[i]) ? getfield(v, :data)[$i] : $body)
2227
@eval @inline function Base.getproperty(v::Union{SVector{$i},MVector{$i}},
2328
name::Symbol)
@@ -33,3 +38,6 @@ let dimension_names = QuoteNode.([:x, :y, :z, :w])
3338
end
3439
end
3540
end
41+
42+
# for longer S/MVectors and other S/MArrays, the only property is data, and it's private
43+
Base.propertynames(::Union{SArray,MArray}, private::Bool = false) = private ? (:data,) : ()

src/SArray.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ sacollect
6565
getfield(v,:data)[i]
6666
end
6767

68-
@inline Tuple(v::SArray) = getfield(v,:data)
68+
@inline Base.Tuple(v::SArray) = getfield(v,:data)
6969

7070
Base.dataids(::SArray) = ()
7171

src/convert.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ AbstractArray{T}(sa::StaticArray{S,U}) where {S,T,U} = similar_type(typeof(sa),T
198198
AbstractArray{T,N}(sa::StaticArray{S,U,N}) where {S,T,U,N} = similar_type(typeof(sa),T,Size(sa))(sa)
199199

200200
# Constructing a Tuple from a StaticArray
201-
@inline Tuple(a::StaticArray) = unroll_tuple(a, Length(a))
201+
@inline Base.Tuple(a::StaticArray) = unroll_tuple(a, Length(a))
202202

203203
@noinline function dimension_mismatch_fail(::Type{SA}, a::AbstractArray) where {SA <: StaticArray}
204204
throw(DimensionMismatch("expected input array of length $(length(SA)), got length $(length(a))"))

src/eigen.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,8 @@ end
400400
@inline eigen(A::Symmetric{<:Complex,<:StaticMatrix}; kwargs...) = _eigen(A; kwargs...)
401401

402402
@inline function _eigen(A::LinearAlgebra.HermOrSym; permute::Bool=true, scale::Bool=true)
403-
_eig(Size(A), A, permute, scale)
403+
B = convert(AbstractArray{float(eltype(A))}, A)
404+
_eig(Size(A), B, permute, scale)
404405
end
405406

406407
# NOTE: The following Boost Software License applies to parts of the method:

src/expm.jl

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ end
1414
(newtype)((exp(A[1]), ))
1515
end
1616

17+
# Bernstein, D. S. & So, W. 1993. "Some Explicit Formulas for the Matrix Exponential"
1718
@inline function _exp(::Size{(2,2)}, A::StaticMatrix{<:Any,<:Any,<:Real})
1819
T = typeof(exp(zero(eltype(A))))
1920
newtype = similar_type(A,T)
@@ -25,25 +26,50 @@ end
2526

2627
v = (a-d)^2 + 4*b*c
2728

29+
m = (a + d) / 2
30+
2831
if v > 0
29-
z = sqrt(v)
30-
z1 = cosh(z / 2)
31-
z2 = sinh(z / 2) / z
32+
# In this case the formulas in the entries of the matrix
33+
# are a function of cosh and sinh, and could (in theory)
34+
# follow the same code pattern of the other branches (v ≤ 0).
35+
# However, cosh and sinh explode with large arguments and
36+
# we use the following identity to avoid numerical issues:
37+
#
38+
# exp(m) * [c₁ * cohs(δ) + c₂ * sinh(δ)] =
39+
# c₁ * (e₊ + e₋) / 2 + c₂ * (e₊ - e₋) / 2
40+
#
41+
# where e₊ = exp(m + δ) and e₋ = exp(m - δ).
42+
#
43+
# See https://github.com/JuliaArrays/StaticArrays.jl/issues/1295
44+
δ = sqrt(v) / 2
45+
e₊ = exp(m + δ)
46+
e₋ = exp(m - δ)
47+
e₁ = (e₊ + e₋) / 2
48+
e₂ = (e₊ - e₋) / 2
49+
c₂ = (a - d) / 2δ
50+
m11 = (e₁ + c₂ * e₂)
51+
m12 = (b / δ) * e₂
52+
m21 = (c / δ) * e₂
53+
m22 = (e₁ - c₂ * e₂)
3254
elseif v < 0
3355
z = sqrt(-v)
56+
r = exp(m)
3457
z1 = cos(z / 2)
3558
z2 = sin(z / 2) / z
59+
m11 = r * (z1 + (a - d) * z2)
60+
m12 = r * 2b * z2
61+
m21 = r * 2c * z2
62+
m22 = r * (z1 - (a - d) * z2)
3663
else # if v == 0
64+
r = exp(m)
3765
z1 = T(1.0)
3866
z2 = T(0.5)
67+
m11 = r * (z1 + (a - d) * z2)
68+
m12 = r * 2b * z2
69+
m21 = r * 2c * z2
70+
m22 = r * (z1 - (a - d) * z2)
3971
end
4072

41-
r = exp((a + d) / 2)
42-
m11 = r * (z1 + (a - d) * z2)
43-
m12 = r * 2b * z2
44-
m21 = r * 2c * z2
45-
m22 = r * (z1 - (a - d) * z2)
46-
4773
(newtype)((m11, m21, m12, m22))
4874
end
4975

src/linalg.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ end
301301
$(Expr(:meta, :inline))
302302
scale = maxabs_nested(a)
303303

304-
scale==0 && return _init_zero(a)
304+
iszero(scale) && return _init_zero(a)
305305
p == 1 && return @inbounds scale * $expr_p1
306306
return @inbounds scale * ($expr)^(inv(p))
307307
end
@@ -328,7 +328,7 @@ end
328328
p == Inf && return mapreduce(norm, max, a) # no need for scaling
329329

330330
l = p==1 ? @inbounds($expr_p1) : @inbounds(($expr)^(inv(p)))
331-
0<l<Inf && return l
331+
zero(l) < l && isfinite(l) && return l
332332
return _norm_scaled(Size(a), a, p) # p != 0, 2, Inf
333333
end
334334
end

src/matrix_multiply.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ end
114114
b::Union{Transpose{Tb, <:StaticVector}, Adjoint{Tb, <:StaticVector}}) where {sa, sb, Ta, Tb}
115115
newsize = (sa[1], sb[2])
116116
exprs = [:(a[$i]*b[$j]) for i = 1:sa[1], j = 1:sb[2]]
117-
117+
118118
return quote
119119
@_inline_meta
120120
T = promote_op(*, Ta, Tb)
@@ -208,7 +208,7 @@ end
208208
while m < M
209209
mu = min(M, m + M_r)
210210
mrange = m+1:mu
211-
211+
212212
atemps_init = [:($(atemps[k1]) = a[$k1]) for k1 = mrange]
213213
exprs_init = [:($(tmps[k1,k2]) = $(atemps[k1]) * b[$(1 + (k2-1) * sb[1])]) for k1 = mrange, k2 = nrange]
214214
atemps_loop_init = [:($(atemps[k1]) = a[$(k1-sa[1]) + $(sa[1])*j]) for k1 = mrange]
@@ -246,7 +246,7 @@ end
246246
T = promote_op(matprod, Ta, Tb)
247247
a = mul_parent(wrapped_a)
248248
b = mul_parent(wrapped_b)
249-
return (mul_result_structure(wrapped_a, wrapped_b))(similar_type(a, T, $S)(invoke(*, Tuple{$(_unstatic_array(a)),$(_unstatic_array(b))}, a, b)))
249+
return (mul_result_structure(wrapped_a, wrapped_b))(similar_type(a, T, $S)(invoke(*, Tuple{$_unstatic_array(a),$_unstatic_array(b)}, a, b)))
250250
end
251251
end
252252

0 commit comments

Comments
 (0)